diff --git a/.gitmodules b/.gitmodules index 8954edd9..b89555a8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "build-system/bazel-rules/apple_support"] path = build-system/bazel-rules/apple_support url = https://github.com/bazelbuild/apple_support.git +[submodule "submodules/ton/tonlib-src"] + path = submodules/ton/tonlib-src + url = https://github.com/trm-dev/ton.git diff --git a/Wallet/Sources/AppDelegate.swift b/Wallet/Sources/AppDelegate.swift index f23fa75a..df7d53af 100644 --- a/Wallet/Sources/AppDelegate.swift +++ b/Wallet/Sources/AppDelegate.swift @@ -997,8 +997,8 @@ private extension MergedLocalWalletConfiguration { resolved: nil),*/ testNet: MergedLocalBlockchainConfiguration( configuration: LocalBlockchainConfiguration( - source: .url("https://newton-blockchain.github.io/global.config.json"), - customId: "testnet2" + source: .url("https://ton.org/global-config-wallet.json"), + customId: "mainnet" ), resolved: nil ), diff --git a/submodules/WalletUI/Sources/ItemList/Items/ItemListSingleLineInputItem.swift b/submodules/WalletUI/Sources/ItemList/Items/ItemListSingleLineInputItem.swift index eb0ea6c8..68873cb7 100644 --- a/submodules/WalletUI/Sources/ItemList/Items/ItemListSingleLineInputItem.swift +++ b/submodules/WalletUI/Sources/ItemList/Items/ItemListSingleLineInputItem.swift @@ -422,7 +422,7 @@ class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDelegate, It } } - if string.count > 1, let item = self.item, let processPaste = item.processPaste { + if string.count >= 1, let item = self.item, let processPaste = item.processPaste { let result = processPaste(string) if result != string { var text = textField.text ?? "" diff --git a/submodules/WalletUI/Sources/WalletConfgurationScreen.swift b/submodules/WalletUI/Sources/WalletConfgurationScreen.swift index b534828c..6e167c5e 100644 --- a/submodules/WalletUI/Sources/WalletConfgurationScreen.swift +++ b/submodules/WalletUI/Sources/WalletConfgurationScreen.swift @@ -157,7 +157,7 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable { case let .blockchainName(theme, strings, title, value): return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: value, placeholder: title, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in arguments.updateBlockchainName(value) - }, action: {}) + }, processPaste: { $0.lowercased() }, action: {}) case let .blockchainNameInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) } @@ -224,9 +224,9 @@ private struct WalletConfigurationScreenState: Equatable { } } - if self.configuration.testNet.customId == "mainnet" { - return nil - } +// if self.configuration.testNet.customId == "mainnet" { +// return nil +// } return LocalWalletConfiguration( //mainNet: LocalBlockchainConfiguration(source: mainSource, customId: nil), @@ -244,7 +244,8 @@ private struct WalletConfigurationScreenState: Equatable { blockchainConfiguration = self.configuration.testNet } - if self.configuration.testNet.customId == "mainnet" { + if let id = self.configuration.testNet.customId, + id.isEmpty { return true } diff --git a/submodules/ton/README.md b/submodules/ton/README.md new file mode 100644 index 00000000..d6110d3f --- /dev/null +++ b/submodules/ton/README.md @@ -0,0 +1,11 @@ +0. make sure you have installed openssl and cmake(optional ninja) +1. git submodule update --init --recursive +2. cd tonlib-src +3. mkdir build +4. cd build +5. cmake --DOPENSSL_ROOT_DIR=*openssl_path* .. (optional -GNinja) +6. cmake --build . --target prepare_cross_compiling (optional ninja prepare_cross_compiling) +7. cd .. +8. rm -rf build +9. cd .. +10. profit=) diff --git a/submodules/ton/build-ton-bazel.sh b/submodules/ton/build-ton-bazel.sh index 069aab7b..a445a867 100755 --- a/submodules/ton/build-ton-bazel.sh +++ b/submodules/ton/build-ton-bazel.sh @@ -26,6 +26,7 @@ mkdir -p "$OUT_DIR" mkdir -p "$OUT_DIR/build" cd "$OUT_DIR/build" +git_executable_path="/usr/bin/git" openssl_path="$openssl_base_path" echo "OpenSSL path = ${openssl_path}" openssl_crypto_library="${openssl_path}/lib/libcrypto.a" @@ -35,6 +36,7 @@ options="$options -DOPENSSL_CRYPTO_LIBRARY=${openssl_crypto_library}" options="$options -DOPENSSL_INCLUDE_DIR=${openssl_path}/include" options="$options -DOPENSSL_LIBRARIES=${openssl_crypto_library}" options="$options -DCMAKE_BUILD_TYPE=Release" +options="$options -DGIT_EXECUTABLE=${git_executable_path}" build="build-${arch}" install="install-${arch}" @@ -54,7 +56,7 @@ rm -rf $build mkdir -p $build mkdir -p $install cd $build -cmake $td_path $options -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" -DIOS_PLATFORM=${ios_platform} -DTON_ARCH= -DCMAKE_INSTALL_PREFIX=../${install} +cmake $td_path $options -DTON_ONLY_TONLIB=ON -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" -DIOS_PLATFORM=${ios_platform} -DTON_ARCH= -DCMAKE_INSTALL_PREFIX=../${install} CORE_COUNT=`sysctl -n hw.logicalcpu` make -j$CORE_COUNT install || exit cd .. diff --git a/submodules/ton/tonlib-src b/submodules/ton/tonlib-src new file mode 160000 index 00000000..93d3c921 --- /dev/null +++ b/submodules/ton/tonlib-src @@ -0,0 +1 @@ +Subproject commit 93d3c921e632ba73e3569e4fd25e580afc0f2d01 diff --git a/submodules/ton/tonlib-src/CMake/AddCXXCompilerFlag.cmake b/submodules/ton/tonlib-src/CMake/AddCXXCompilerFlag.cmake deleted file mode 100644 index 6fb615a1..00000000 --- a/submodules/ton/tonlib-src/CMake/AddCXXCompilerFlag.cmake +++ /dev/null @@ -1,74 +0,0 @@ -# - Adds a compiler flag if it is supported by the compiler -# -# This function checks that the supplied compiler flag is supported and then -# adds it to the corresponding compiler flags -# -# add_cxx_compiler_flag( []) -# -# - Example -# -# include(AddCXXCompilerFlag) -# add_cxx_compiler_flag(-Wall) -# add_cxx_compiler_flag(-no-strict-aliasing RELEASE) -# Requires CMake 2.6+ - -if (__add_cxx_compiler_flag) - return() -endif() -set(__add_cxx_compiler_flag INCLUDED) - -include(CheckCXXCompilerFlag) - -function(mangle_compiler_flag FLAG OUTPUT) - string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG) - string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG}) - string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) - string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) - set(${OUTPUT} "${SANITIZED_FLAG}" PARENT_SCOPE) -endfunction(mangle_compiler_flag) - -function(add_cxx_compiler_flag FLAG) - string(REPLACE "-Wno-" "-W" MAIN_FLAG ${FLAG}) - mangle_compiler_flag("${MAIN_FLAG}" MANGLED_FLAG_NAME) - if (DEFINED CMAKE_REQUIRED_FLAGS) - set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}") - else() - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - endif() - check_cxx_compiler_flag("${MAIN_FLAG}" ${MANGLED_FLAG_NAME}) - if (DEFINED OLD_CMAKE_REQUIRED_FLAGS) - set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") - else() - unset(CMAKE_REQUIRED_FLAGS) - endif() - if (${MANGLED_FLAG_NAME}) - set(VARIANT ${ARGV1}) - if (ARGV1) - string(TOUPPER "_${VARIANT}" VARIANT) - endif() - set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) - endif() -endfunction() - -function(add_required_cxx_compiler_flag FLAG) - string(REPLACE "-Wno-" "-W" MAIN_FLAG ${FLAG}) - mangle_compiler_flag("${MAIN_FLAG}" MANGLED_FLAG_NAME) - set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}") - check_cxx_compiler_flag("${MAIN_FLAG}" ${MANGLED_FLAG_NAME}) - set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") - if (${MANGLED_FLAG_NAME}) - set(VARIANT ${ARGV1}) - if (ARGV1) - string(TOUPPER "_${VARIANT}" VARIANT) - endif() - set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE) - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}" PARENT_SCOPE) - else() - message(FATAL_ERROR "Required flag '${FLAG}' is not supported by the compiler") - endif() -endfunction() diff --git a/submodules/ton/tonlib-src/CMake/FindJeMalloc.cmake b/submodules/ton/tonlib-src/CMake/FindJeMalloc.cmake deleted file mode 100644 index 7911f77c..00000000 --- a/submodules/ton/tonlib-src/CMake/FindJeMalloc.cmake +++ /dev/null @@ -1,21 +0,0 @@ -# - Find JeMalloc library -# Find the native JeMalloc includes and library -# -# JEMALLOC_INCLUDE_DIR - where to find jemalloc.h, etc. -# JEMALLOC_LIBRARIES - List of libraries when using jemalloc. -# JEMALLOC_FOUND - True if jemalloc found. - -find_path(JEMALLOC_INCLUDE_DIR - NAMES jemalloc/jemalloc.h - HINTS ${JEMALLOC_ROOT_DIR}/include) - -find_library(JEMALLOC_LIBRARIES - NAMES jemalloc - HINTS ${JEMALLOC_ROOT_DIR}/lib) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(jemalloc DEFAULT_MSG JEMALLOC_LIBRARIES JEMALLOC_INCLUDE_DIR) - -mark_as_advanced( - JEMALLOC_LIBRARIES - JEMALLOC_INCLUDE_DIR) diff --git a/submodules/ton/tonlib-src/CMake/FindMHD.cmake b/submodules/ton/tonlib-src/CMake/FindMHD.cmake deleted file mode 100644 index 822714a2..00000000 --- a/submodules/ton/tonlib-src/CMake/FindMHD.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# - Try to find MHD -# Once done this will define -# -# MHD_FOUND - system has MHD -# MHD_INCLUDE_DIRS - the MHD include directory -# MHD_LIBRARY - Link these to use MHD - -find_path( - MHD_INCLUDE_DIR - NAMES microhttpd.h - DOC "microhttpd include dir" -) - -find_library( - MHD_LIBRARY - NAMES microhttpd microhttpd-10 libmicrohttpd libmicrohttpd-dll - DOC "microhttpd library" -) - -set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR}) -set(MHD_LIBRARIES ${MHD_LIBRARY}) - -# debug library on windows -# same naming convention as in qt (appending debug library with d) -# boost is using the same "hack" as us with "optimized" and "debug" -# official MHD project actually uses _d suffix -if (MSVC) - find_library( - MHD_LIBRARY_DEBUG - NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d - DOC "mhd debug library" - ) - set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG}) -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(mhd DEFAULT_MSG MHD_INCLUDE_DIR MHD_LIBRARY) -mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY) diff --git a/submodules/ton/tonlib-src/CMake/FindReadline.cmake b/submodules/ton/tonlib-src/CMake/FindReadline.cmake deleted file mode 100644 index 3b1892cb..00000000 --- a/submodules/ton/tonlib-src/CMake/FindReadline.cmake +++ /dev/null @@ -1,25 +0,0 @@ -if (APPLE) - find_path(READLINE_INCLUDE_DIR readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH) -endif() -find_path(READLINE_INCLUDE_DIR readline/readline.h) - -if (APPLE) - find_library(READLINE_LIBRARY readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH) -endif() -find_library(READLINE_LIBRARY readline) - -if (READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NOT GNU_READLINE_FOUND) - set(CMAKE_REQUIRED_INCLUDES "${READLINE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_LIBRARIES "${READLINE_LIBRARY}") - include(CheckCXXSourceCompiles) - unset(GNU_READLINE_FOUND CACHE) - check_cxx_source_compiles("#include \n#include \nint main() { rl_replace_line(\"\", 0); }" GNU_READLINE_FOUND) - if (NOT GNU_READLINE_FOUND) - unset(READLINE_INCLUDE_DIR CACHE) - unset(READLINE_LIBRARY CACHE) - endif() -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Readline DEFAULT_MSG READLINE_INCLUDE_DIR READLINE_LIBRARY) -mark_as_advanced(READLINE_INCLUDE_DIR READLINE_LIBRARY) diff --git a/submodules/ton/tonlib-src/CMake/UseLATEX.cmake b/submodules/ton/tonlib-src/CMake/UseLATEX.cmake deleted file mode 100644 index 53805225..00000000 --- a/submodules/ton/tonlib-src/CMake/UseLATEX.cmake +++ /dev/null @@ -1,1936 +0,0 @@ -# File: UseLATEX.cmake -# CMAKE commands to actually use the LaTeX compiler -# Version: 2.4.6 -# Author: Kenneth Moreland -# -# Copyright 2004, 2015 Sandia Corporation. -# Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive -# license for use of this work by or on behalf of the U.S. Government. -# -# This software is released under the BSD 3-Clause License. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# -# The following function is defined: -# -# add_latex_document( -# [BIBFILES ] -# [INPUTS ] -# [IMAGE_DIRS] -# [IMAGES] -# [CONFIGURE] -# [DEPENDS] -# [MULTIBIB_NEWCITES] -# [USE_BIBLATEX] -# [USE_INDEX] -# [INDEX_NAMES ] -# [USE_GLOSSARY] [USE_NOMENCL] -# [FORCE_PDF] [FORCE_DVI] [FORCE_HTML] -# [TARGET_NAME] -# [EXCLUDE_FROM_ALL] -# [EXCLUDE_FROM_DEFAULTS]) -# Adds targets that compile . The latex output is placed -# in LATEX_OUTPUT_PATH or CMAKE_CURRENT_BINARY_DIR if the former is -# not set. The latex program is picky about where files are located, -# so all input files are copied from the source directory to the -# output directory. This includes the target tex file, any tex file -# listed with the INPUTS option, the bibliography files listed with -# the BIBFILES option, and any .cls, .bst, .clo, .sty, .ist, and .fd -# files found in the current source directory. Images found in the -# IMAGE_DIRS directories or listed by IMAGES are also copied to the -# output directory and converted to an appropriate format if necessary. -# Any tex files also listed with the CONFIGURE option are also processed -# with the CMake CONFIGURE_FILE command (with the @ONLY flag). Any file -# listed in CONFIGURE but not the target tex file or listed with INPUTS -# has no effect. DEPENDS can be used to specify generated files that are -# needed to compile the latex target. -# -# The following targets are made. The name prefix is based off of the -# base name of the tex file unless TARGET_NAME is specified. If -# TARGET_NAME is specified, then that name is used for the targets. -# -# name_dvi: Makes .dvi -# name_pdf: Makes .pdf using pdflatex. -# name_safepdf: Makes .pdf using ps2pdf. If using the -# default program arguments, this will ensure all fonts -# are embedded and no lossy compression has been -# performed on images. -# name_ps: Makes .ps -# name_html: Makes .html -# name_auxclean: Deletes .aux and other auxiliary files. -# This is sometimes necessary if a LaTeX error occurs -# and writes a bad aux file. Unlike the regular clean -# target, it does not delete other input files, such as -# converted images, to save time on the rebuild. -# -# Unless the EXCLUDE_FROM_ALL option is given, one of these targets -# is added to the ALL target and built by default. Which target is -# determined by the LATEX_DEFAULT_BUILD CMake variable. See the -# documentation of that variable for more details. -# -# Unless the EXCLUDE_FROM_DEFAULTS option is given, all these targets -# are added as dependencies to targets named dvi, pdf, safepdf, ps, -# html, and auxclean, respectively. -# -# USE_BIBLATEX enables the use of biblatex/biber as an alternative to -# bibtex. Bibtex remains the default if USE_BIBLATEX is not -# specified. -# -# If the argument USE_INDEX is given, then commands to build an index -# are made. If the argument INDEX_NAMES is given, an index file is -# generated for each name in this list. See the LaTeX package multind -# for more information about how to generate multiple indices. -# -# If the argument USE_GLOSSARY is given, then commands to -# build a glossary are made. If the argument MULTIBIB_NEWCITES is -# given, then additional bibtex calls are added to the build to -# support the extra auxiliary files created with the \newcite command -# in the multibib package. -# -# History: -# -# 2.4.6 Fix parse issue with older versions of CMake. -# -# 2.4.5 Fix issues with files and paths containing spaces. -# -# 2.4.4 Improve error reporting message when LaTeX fails. -# -# When LaTeX fails, delete the output file, which is invalid. -# -# Add warnings for "missing characters." These usually mean that a -# non-ASCII character is in the document and will not be printed -# correctly. -# -# 2.4.3 Check for warnings from the natbib package. When using natbib, -# warnings for missing bibliography references look different. So -# far, natbib seems to be quiet unless something is important, so -# look for all natbib warnings. (We can change this later if -# necessary.) -# -# 2.4.2 Fix an issue where new versions of ImageMagick expect the order of -# options in command line execution of magick/convert. (See, for -# example, http://www.imagemagick.org/Usage/basics/#why.) -# -# 2.4.1 Add ability to dump LaTeX log file when using batch mode. Batch -# mode suppresses most output, often including error messages. To -# make sure critical error messages get displayed, show the full log -# on failures. -# -# 2.4.0 Remove "-r 600" from the default PDFTOPS_CONVERTER_FLAGS. The -r flag -# is available from the Poppler version of pdftops, but not the Xpdf -# version. -# -# Fix an issue with the flags for the different programs not being -# properly separated. -# -# Fix an issue on windows where the = character is not allowed for -# ps2pdf arguments. -# -# Change default arguments for latex and pdflatex commands. Makes the -# output more quiet and prints out the file/line where errors occur. -# (Thanks to Nikos Koukis.) -# -# After a LaTeX build, check the log file for warnings that are -# indicative of problems with the build. -# -# Remove support for latex2html. Instead, use the htlatex program. -# This is now part of TeX Live and most other distributions. It also -# behaves much more like the other LaTeX programs. Also fixed some -# nasty issues with the htlatex arguments. -# -# 2.3.2 Declare LaTeX input files as sources for targets so that they show -# up in IDEs like QtCreator. -# -# Fix issue where main tex files in subdirectories were creating -# invalid targets for building HTML. Just disable the HTML targets in -# this case. -# -# 2.3.1 Support use of magick command instead of convert command for -# ImageMagick 7. -# -# 2.3.0 Add USE_BIBLATEX option to support the biblatex package, which -# requires using the program biber as a replacement for bibtex -# (thanks to David Tracey). -# -# 2.2.1 Add STRINGS property to LATEX_DEFAULT_BUILD to make it easier to -# select the default build in the CMake GUI. -# -# 2.2.0 Add TARGET_NAME option. -# -# 2.1.1 Support for finding bmp, ppm, and other image files. -# -# 2.1.0 Fix an error where the pdf target and others were defined multiple -# times if UseLATEX.cmake was included multiple times. -# -# Added INDEX_NAMES option to support multiple indexes in a single -# document from the multind package (thanks to Dan Lipsa). -# -# 2.0.0 First major revision of UseLATEX.cmake updates to more recent features -# of CMake and some non-backward compatible changes. -# -# Changed all function and macro names to lower case. CMake's identifiers -# are case insensitive, but the convention moved from all upper case to -# all lower case somewhere around the release of CMake 2. (The original -# version of UseLATEX.cmake predates that.) -# -# Remove condition matching in if statements. They are no longer necessary -# and are even discouraged (because else clauses get confusing). -# -# Use "new" features available in CMake such as list and argument parsing. -# -# Remove some code that has been deprecated for a while. -# -# Mark variables for compiler and converter executables as advanced to -# match the more conventional CMake behavior. -# -# Changed how default builds are specified and add the ability to force -# a particular build. -# -# Made the base targets (pdf, dvi, etc.) global. add_latex_document -# always mangles its target names and these base targets depend on -# the targets with mangled names. -# -# 1.10.5 Fix for Window's convert check (thanks to Martin Baute). -# -# 1.10.4 Copy font files to binary directory for packages that come with -# their own fonts. -# -# 1.10.3 Check for Windows version of convert being used instead of -# ImageMagick's version (thanks to Martin Baute). -# -# 1.10.2 Use htlatex as a fallback when latex2html is not available (thanks -# to Tomasz Grzegurzko). -# -# 1.10.1 Make convert program mandatory only if actually used (thanks to -# Julien Schueller). -# -# 1.10.0 Added NO_DEFAULT and DEFAULT_PS options. -# Fixed issue with cleaning files for LaTeX documents originating in -# a subdirectory. -# -# 1.9.6 Fixed problem with LATEX_SMALL_IMAGES. -# Strengthened check to make sure the output directory does not contain -# the source files. -# -# 1.9.5 Add support for image types not directly supported by either latex -# or pdflatex. (Thanks to Jorge Gerardo Pena Pastor for SVG support.) -# -# 1.9.4 Fix issues with filenames containing multiple periods. -# -# 1.9.3 Hide some variables that are now cached but should not show up in -# the ccmake list of variables. -# -# 1.9.2 Changed MACRO declarations to FUNCTION declarations. The better -# FUNCTION scoping will hopefully avoid some common but subtle bugs. -# This implicitly increases the minimum CMake version to 4.6 (although -# I honestly only test it with the latest 4.8 version). -# -# Since we are updating the minimum CMake version, I'm going to start -# using the builtin LIST commands that are now available. -# -# Favor using pdftops from the Poppler package to convert from pdf to -# eps. It does a much better job than ImageMagick or ghostscript. -# -# 1.9.1 Fixed typo that caused the LATEX_SMALL_IMAGES option to fail to -# activate. -# -# 1.9.0 Add support for the multibib package (thanks to Antonio LaTorre). -# -# 1.8.2 Fix corner case when an argument name was also a variable containing -# the text of an argument. In this case, the CMake IF was matching -# the argument text with the contents of the variable with the same -# argument name. -# -# 1.8.1 Fix problem where ps2pdf was not getting the appropriate arguments. -# -# 1.8.0 Add support for synctex. -# -# 1.7.7 Support calling xindy when making glossaries. -# -# Improved make clean support. -# -# 1.7.6 Add support for the nomencl package (thanks to Myles English). -# -# 1.7.5 Fix issue with bibfiles being copied two different ways, which causes -# Problems with dependencies (thanks to Edwin van Leeuwen). -# -# 1.7.4 Added the DEFAULT_SAFEPDF option (thanks to Raymond Wan). -# -# Added warnings when image directories are not found (and were -# probably not given relative to the source directory). -# -# 1.7.3 Fix some issues with interactions between makeglossaries and bibtex -# (thanks to Mark de Wever). -# -# 1.7.2 Use ps2pdf to convert eps to pdf to get around the problem with -# ImageMagick dropping the bounding box (thanks to Lukasz Lis). -# -# 1.7.1 Fixed some dependency issues. -# -# 1.7.0 Added DEPENDS options (thanks to Theodore Papadopoulo). -# -# 1.6.1 Ported the makeglossaries command to CMake and embedded the port -# into UseLATEX.cmake. -# -# 1.6.0 Allow the use of the makeglossaries command. Thanks to Oystein -# S. Haaland for the patch. -# -# 1.5.0 Allow any type of file in the INPUTS lists, not just tex file -# (suggested by Eric Noulard). As a consequence, the ability to -# specify tex files without the .tex extension is removed. The removed -# function is of dubious value anyway. -# -# When copying input files, skip over any file that exists in the -# binary directory but does not exist in the source directory with the -# assumption that these files were added by some other mechanism. I -# find this useful when creating large documents with multiple -# chapters that I want to build separately (for speed) as I work on -# them. I use the same boilerplate as the starting point for all -# and just copy it with different configurations. This was what the -# separate ADD_LATEX_DOCUMENT method was supposed to originally be for. -# Since its external use is pretty much deprecated, I removed that -# documentation. -# -# 1.4.1 Copy .sty files along with the other class and package files. -# -# 1.4.0 Added a MANGLE_TARGET_NAMES option that will mangle the target names. -# -# Fixed problem with copying bib files that became apparent with -# CMake 2.4. -# -# 1.3.0 Added a LATEX_OUTPUT_PATH variable that allows you or the user to -# specify where the built latex documents to go. This is especially -# handy if you want to do in-source builds. -# -# Removed the ADD_LATEX_IMAGES macro and absorbed the functionality -# into ADD_LATEX_DOCUMENT. The old interface was always kind of -# clunky anyway since you had to specify the image directory in both -# places. It also made supporting LATEX_OUTPUT_PATH problematic. -# -# Added support for jpeg files. -# -# 1.2.0 Changed the configuration options yet again. Removed the NO_CONFIGURE -# Replaced it with a CONFIGURE option that lists input files for which -# configure should be run. -# -# The pdf target no longer depends on the dvi target. This allows you -# to build latex documents that require pdflatex. Also added an option -# to make the pdf target the default one. -# -# 1.1.1 Added the NO_CONFIGURE option. The @ character can be used when -# specifying table column separators. If two or more are used, then -# will incorrectly substitute them. -# -# 1.1.0 Added ability include multiple bib files. Added ability to do copy -# sub-tex files for multipart tex files. -# -# 1.0.0 If both ps and pdf type images exist, just copy the one that -# matches the current render mode. Replaced a bunch of STRING -# commands with GET_FILENAME_COMPONENT commands that were made to do -# the desired function. -# -# 0.4.0 First version posted to CMake Wiki. -# - -if(__USE_LATEX_INCLUDED) - return() -endif() -set(__USE_LATEX_INCLUDED TRUE) - -############################################################################# -# Find the location of myself while originally executing. If you do this -# inside of a macro, it will recode where the macro was invoked. -############################################################################# -set(LATEX_USE_LATEX_LOCATION ${CMAKE_CURRENT_LIST_FILE} - CACHE INTERNAL "Location of UseLATEX.cmake file." FORCE - ) - -############################################################################# -# Generic helper functions -############################################################################# - -include(CMakeParseArguments) - -function(latex_list_contains var value) - set(input_list ${ARGN}) - list(FIND input_list "${value}" index) - if(index GREATER -1) - set(${var} TRUE PARENT_SCOPE) - else() - set(${var} PARENT_SCOPE) - endif() -endfunction(latex_list_contains) - -# Match the contents of a file to a regular expression. -function(latex_file_match variable filename regexp default) - # The FILE STRINGS command would be a bit better, but I'm not totally sure - # the match will always be to a whole line, and I don't want to break things. - file(READ ${filename} file_contents) - string(REGEX MATCHALL "${regexp}" - match_result ${file_contents} - ) - if(match_result) - set(${variable} "${match_result}" PARENT_SCOPE) - else() - set(${variable} "${default}" PARENT_SCOPE) - endif() -endfunction(latex_file_match) - -# A version of GET_FILENAME_COMPONENT that treats extensions after the last -# period rather than the first. To the best of my knowledge, all filenames -# typically used by LaTeX, including image files, have small extensions -# after the last dot. -function(latex_get_filename_component varname filename type) - set(result) - if("${type}" STREQUAL "NAME_WE") - get_filename_component(name ${filename} NAME) - string(REGEX REPLACE "\\.[^.]*\$" "" result "${name}") - elseif("${type}" STREQUAL "EXT") - get_filename_component(name ${filename} NAME) - string(REGEX MATCH "\\.[^.]*\$" result "${name}") - else() - get_filename_component(result ${filename} ${type}) - endif() - set(${varname} "${result}" PARENT_SCOPE) -endfunction(latex_get_filename_component) - -############################################################################# -# Functions that perform processing during a LaTeX build. -############################################################################# -function(latex_execute_latex) - if(NOT LATEX_TARGET) - message(SEND_ERROR "Need to define LATEX_TARGET") - endif() - - if(NOT LATEX_WORKING_DIRECTORY) - message(SEND_ERROR "Need to define LATEX_WORKING_DIRECTORY") - endif() - - if(NOT LATEX_FULL_COMMAND) - message(SEND_ERROR "Need to define LATEX_FULL_COMMAND") - endif() - - if(NOT LATEX_OUTPUT_FILE) - message(SEND_ERROR "Need to define LATEX_OUTPUT_FILE") - endif() - - set(full_command_original "${LATEX_FULL_COMMAND}") - - # Chose the native method for parsing command arguments. Newer versions of - # CMake allow you to just use NATIVE_COMMAND. - if (CMAKE_VERSION VERSION_GREATER 3.8) - set(separate_arguments_mode NATIVE_COMMAND) - else() - if (WIN32) - set(separate_arguments_mode WINDOWS_COMMAND) - else() - set(separate_arguments_mode UNIX_COMMAND) - endif() - endif() - - # Preps variables for use in execute_process. - # Even though we expect LATEX_WORKING_DIRECTORY to have a single "argument," - # we also want to make sure that we strip out any escape characters that can - # foul up the WORKING_DIRECTORY argument. - separate_arguments(LATEX_FULL_COMMAND UNIX_COMMAND "${LATEX_FULL_COMMAND}") - separate_arguments(LATEX_WORKING_DIRECTORY UNIX_COMMAND "${LATEX_WORKING_DIRECTORY}") - - execute_process( - COMMAND ${LATEX_FULL_COMMAND} - WORKING_DIRECTORY ${LATEX_WORKING_DIRECTORY} - RESULT_VARIABLE execute_result - ) - - if(NOT ${execute_result} EQUAL 0) - # LaTeX tends to write a file when a failure happens. Delete that file so - # that LaTeX will run again. - file(REMOVE "${LATEX_WORKING_DIRECTORY}/${LATEX_OUTPUT_FILE}") - - message("\n\nLaTeX command failed") - message("${full_command_original}") - message("Log output:") - file(READ ${LATEX_WORKING_DIRECTORY}/${LATEX_TARGET}.log log_output) - message("${log_output}") - message(FATAL_ERROR - "Successfully executed LaTeX, but LaTeX returned an error.") - endif() -endfunction(latex_execute_latex) - -function(latex_makeglossaries) - # This is really a bare bones port of the makeglossaries perl script into - # CMake scripting. - message("**************************** In makeglossaries") - if(NOT LATEX_TARGET) - message(SEND_ERROR "Need to define LATEX_TARGET") - endif() - - set(aux_file ${LATEX_TARGET}.aux) - - if(NOT EXISTS ${aux_file}) - message(SEND_ERROR "${aux_file} does not exist. Run latex on your target file.") - endif() - - latex_file_match(newglossary_lines ${aux_file} - "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}" - "@newglossary{main}{glg}{gls}{glo}" - ) - - latex_file_match(istfile_line ${aux_file} - "@istfilename[ \t]*{([^}]*)}" - "@istfilename{${LATEX_TARGET}.ist}" - ) - string(REGEX REPLACE "@istfilename[ \t]*{([^}]*)}" "\\1" - istfile ${istfile_line} - ) - - string(REGEX MATCH ".*\\.xdy" use_xindy "${istfile}") - if(use_xindy) - message("*************** Using xindy") - if(NOT XINDY_COMPILER) - message(SEND_ERROR "Need to define XINDY_COMPILER") - endif() - else() - message("*************** Using makeindex") - if(NOT MAKEINDEX_COMPILER) - message(SEND_ERROR "Need to define MAKEINDEX_COMPILER") - endif() - endif() - - foreach(newglossary ${newglossary_lines}) - string(REGEX REPLACE - "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}" - "\\1" glossary_name ${newglossary} - ) - string(REGEX REPLACE - "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}" - "${LATEX_TARGET}.\\2" glossary_log ${newglossary} - ) - string(REGEX REPLACE - "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}" - "${LATEX_TARGET}.\\3" glossary_out ${newglossary} - ) - string(REGEX REPLACE - "@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}" - "${LATEX_TARGET}.\\4" glossary_in ${newglossary} - ) - - if(use_xindy) - latex_file_match(xdylanguage_line ${aux_file} - "@xdylanguage[ \t]*{${glossary_name}}{([^}]*)}" - "@xdylanguage{${glossary_name}}{english}" - ) - string(REGEX REPLACE - "@xdylanguage[ \t]*{${glossary_name}}{([^}]*)}" - "\\1" - language - ${xdylanguage_line} - ) - # What crazy person makes a LaTeX index generator that uses different - # identifiers for language than babel (or at least does not support - # the old ones)? - if(${language} STREQUAL "frenchb") - set(language "french") - elseif(${language} MATCHES "^n?germanb?$") - set(language "german") - elseif(${language} STREQUAL "magyar") - set(language "hungarian") - elseif(${language} STREQUAL "lsorbian") - set(language "lower-sorbian") - elseif(${language} STREQUAL "norsk") - set(language "norwegian") - elseif(${language} STREQUAL "portuges") - set(language "portuguese") - elseif(${language} STREQUAL "russianb") - set(language "russian") - elseif(${language} STREQUAL "slovene") - set(language "slovenian") - elseif(${language} STREQUAL "ukraineb") - set(language "ukrainian") - elseif(${language} STREQUAL "usorbian") - set(language "upper-sorbian") - endif() - if(language) - set(language_flags "-L ${language}") - else() - set(language_flags "") - endif() - - latex_file_match(codepage_line ${aux_file} - "@gls@codepage[ \t]*{${glossary_name}}{([^}]*)}" - "@gls@codepage{${glossary_name}}{utf}" - ) - string(REGEX REPLACE - "@gls@codepage[ \t]*{${glossary_name}}{([^}]*)}" - "\\1" - codepage - ${codepage_line} - ) - if(codepage) - set(codepage_flags "-C ${codepage}") - else() - # Ideally, we would check that the language is compatible with the - # default codepage, but I'm hoping that distributions will be smart - # enough to specify their own codepage. I know, it's asking a lot. - set(codepage_flags "") - endif() - - message("${XINDY_COMPILER} ${MAKEGLOSSARIES_COMPILER_ARGS} ${language_flags} ${codepage_flags} -I xindy -M ${glossary_name} -t ${glossary_log} -o ${glossary_out} ${glossary_in}" - ) - exec_program(${XINDY_COMPILER} - ARGS ${MAKEGLOSSARIES_COMPILER_ARGS} - ${language_flags} - ${codepage_flags} - -I xindy - -M ${glossary_name} - -t ${glossary_log} - -o ${glossary_out} - ${glossary_in} - OUTPUT_VARIABLE xindy_output - ) - message("${xindy_output}") - - # So, it is possible (perhaps common?) for aux files to specify a - # language and codepage that are incompatible with each other. Check - # for that condition, and if it happens run again with the default - # codepage. - if("${xindy_output}" MATCHES "^Cannot locate xindy module for language (.+) in codepage (.+)\\.$") - message("*************** Retrying xindy with default codepage.") - exec_program(${XINDY_COMPILER} - ARGS ${MAKEGLOSSARIES_COMPILER_ARGS} - ${language_flags} - -I xindy - -M ${glossary_name} - -t ${glossary_log} - -o ${glossary_out} - ${glossary_in} - ) - endif() - - else() - message("${MAKEINDEX_COMPILER} ${MAKEGLOSSARIES_COMPILER_ARGS} -s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in}") - exec_program(${MAKEINDEX_COMPILER} ARGS ${MAKEGLOSSARIES_COMPILER_ARGS} - -s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in} - ) - endif() - - endforeach(newglossary) -endfunction(latex_makeglossaries) - -function(latex_makenomenclature) - message("**************************** In makenomenclature") - if(NOT LATEX_TARGET) - message(SEND_ERROR "Need to define LATEX_TARGET") - endif() - - if(NOT MAKEINDEX_COMPILER) - message(SEND_ERROR "Need to define MAKEINDEX_COMPILER") - endif() - - set(nomencl_out ${LATEX_TARGET}.nls) - set(nomencl_in ${LATEX_TARGET}.nlo) - - exec_program(${MAKEINDEX_COMPILER} ARGS ${MAKENOMENCLATURE_COMPILER_ARGS} - ${nomencl_in} -s "nomencl.ist" -o ${nomencl_out} - ) -endfunction(latex_makenomenclature) - -function(latex_correct_synctex) - message("**************************** In correct SyncTeX") - if(NOT LATEX_TARGET) - message(SEND_ERROR "Need to define LATEX_TARGET") - endif() - - if(NOT GZIP) - message(SEND_ERROR "Need to define GZIP") - endif() - - if(NOT LATEX_SOURCE_DIRECTORY) - message(SEND_ERROR "Need to define LATEX_SOURCE_DIRECTORY") - endif() - - if(NOT LATEX_BINARY_DIRECTORY) - message(SEND_ERROR "Need to define LATEX_BINARY_DIRECTORY") - endif() - - set(synctex_file ${LATEX_BINARY_DIRECTORY}/${LATEX_TARGET}.synctex) - set(synctex_file_gz ${synctex_file}.gz) - - if(EXISTS ${synctex_file_gz}) - - message("Making backup of synctex file.") - configure_file(${synctex_file_gz} ${synctex_file}.bak.gz COPYONLY) - - message("Uncompressing synctex file.") - exec_program(${GZIP} - ARGS --decompress ${synctex_file_gz} - ) - - message("Reading synctex file.") - file(READ ${synctex_file} synctex_data) - - message("Replacing relative with absolute paths.") - string(REGEX REPLACE - "(Input:[0-9]+:)([^/\n][^\n]*)" - "\\1${LATEX_SOURCE_DIRECTORY}/\\2" - synctex_data - "${synctex_data}" - ) - - message("Writing synctex file.") - file(WRITE ${synctex_file} "${synctex_data}") - - message("Compressing synctex file.") - exec_program(${GZIP} - ARGS ${synctex_file} - ) - - else() - - message(SEND_ERROR "File ${synctex_file_gz} not found. Perhaps synctex is not supported by your LaTeX compiler.") - - endif() - -endfunction(latex_correct_synctex) - -function(latex_check_important_warnings) - set(log_file ${LATEX_TARGET}.log) - - message("\nChecking ${log_file} for important warnings.") - if(NOT LATEX_TARGET) - message(SEND_ERROR "Need to define LATEX_TARGET") - endif() - - if(NOT EXISTS ${log_file}) - message("Could not find log file: ${log_file}") - return() - endif() - - set(found_error) - - file(READ ${log_file} log) - - # Check for undefined references - string(REGEX MATCHALL - "\n[^\n]*Reference[^\n]*undefined[^\n]*" - reference_warnings - "${log}") - if(reference_warnings) - set(found_error TRUE) - message("\nFound missing reference warnings.") - foreach(warning ${reference_warnings}) - string(STRIP "${warning}" warning_no_newline) - message("${warning_no_newline}") - endforeach(warning) - endif() - - # Check for natbib warnings - string(REGEX MATCHALL - "\nPackage natbib Warning:[^\n]*" - natbib_warnings - "${log}") - if(natbib_warnings) - set(found_error TRUE) - message("\nFound natbib package warnings.") - foreach(warning ${natbib_warnings}) - string(STRIP "${warning}" warning_no_newline) - message("${warning_no_newline}") - endforeach(warning) - endif() - - # Check for overfull - string(REGEX MATCHALL - "\nOverfull[^\n]*" - overfull_warnings - "${log}") - if(overfull_warnings) - set(found_error TRUE) - message("\nFound overfull warnings. These are indicative of layout errors.") - foreach(warning ${overfull_warnings}) - string(STRIP "${warning}" warning_no_newline) - message("${warning_no_newline}") - endforeach(warning) - endif() - - # Check for invalid characters - string(REGEX MATCHALL - "\nMissing character:[^\n]*" - invalid_character_warnings - "${log}") - if(invalid_character_warnings) - set(found_error TRUE) - message("\nFound invalid character warnings. These characters are likely not printed correctly.") - foreach(warning ${invalid_character_warnings}) - string(STRIP "${warning}" warning_no_newline) - message("${warning_no_newline}") - endforeach(warning) - endif() - - if(found_error) - latex_get_filename_component(log_file_path ${log_file} ABSOLUTE) - message("\nConsult ${log_file_path} for more information on LaTeX build.") - else() - message("No known important warnings found.") - endif(found_error) -endfunction(latex_check_important_warnings) - -############################################################################# -# Helper functions for establishing LaTeX build. -############################################################################# - -function(latex_needit VAR NAME) - if(NOT ${VAR}) - message(SEND_ERROR "I need the ${NAME} command.") - endif() -endfunction(latex_needit) - -function(latex_wantit VAR NAME) - if(NOT ${VAR}) - message(STATUS "I could not find the ${NAME} command.") - endif() -endfunction(latex_wantit) - -function(latex_setup_variables) - set(LATEX_OUTPUT_PATH "${LATEX_OUTPUT_PATH}" - CACHE PATH "If non empty, specifies the location to place LaTeX output." - ) - - find_package(LATEX) - - find_program(XINDY_COMPILER - NAME xindy - PATHS ${MIKTEX_BINARY_PATH} /usr/bin - ) - - find_package(UnixCommands) - - find_program(PDFTOPS_CONVERTER - NAMES pdftops - DOC "The pdf to ps converter program from the Poppler package." - ) - - find_program(HTLATEX_COMPILER - NAMES htlatex - PATHS ${MIKTEX_BINARY_PATH} - /usr/bin - ) - - mark_as_advanced( - LATEX_COMPILER - PDFLATEX_COMPILER - BIBTEX_COMPILER - BIBER_COMPILER - MAKEINDEX_COMPILER - XINDY_COMPILER - DVIPS_CONVERTER - PS2PDF_CONVERTER - PDFTOPS_CONVERTER - LATEX2HTML_CONVERTER - HTLATEX_COMPILER - ) - - latex_needit(LATEX_COMPILER latex) - latex_wantit(PDFLATEX_COMPILER pdflatex) - latex_wantit(HTLATEX_COMPILER htlatex) - latex_needit(BIBTEX_COMPILER bibtex) - latex_wantit(BIBER_COMPILER biber) - latex_needit(MAKEINDEX_COMPILER makeindex) - latex_wantit(DVIPS_CONVERTER dvips) - latex_wantit(PS2PDF_CONVERTER ps2pdf) - latex_wantit(PDFTOPS_CONVERTER pdftops) - - set(LATEX_COMPILER_FLAGS "-interaction=batchmode -file-line-error" - CACHE STRING "Flags passed to latex.") - set(PDFLATEX_COMPILER_FLAGS ${LATEX_COMPILER_FLAGS} - CACHE STRING "Flags passed to pdflatex.") - set(HTLATEX_COMPILER_TEX4HT_FLAGS "html" - CACHE STRING "Options for the tex4ht.sty and *.4ht style files.") - set(HTLATEX_COMPILER_TEX4HT_POSTPROCESSOR_FLAGS "" - CACHE STRING "Options for the text4ht postprocessor.") - set(HTLATEX_COMPILER_T4HT_POSTPROCESSOR_FLAGS "" - CACHE STRING "Options for the t4ht postprocessor.") - set(HTLATEX_COMPILER_LATEX_FLAGS ${LATEX_COMPILER_FLAGS} - CACHE STRING "Flags passed from htlatex to the LaTeX compiler.") - set(LATEX_SYNCTEX_FLAGS "-synctex=1" - CACHE STRING "latex/pdflatex flags used to create synctex file.") - set(BIBTEX_COMPILER_FLAGS "" - CACHE STRING "Flags passed to bibtex.") - set(BIBER_COMPILER_FLAGS "" - CACHE STRING "Flags passed to biber.") - set(MAKEINDEX_COMPILER_FLAGS "" - CACHE STRING "Flags passed to makeindex.") - set(MAKEGLOSSARIES_COMPILER_FLAGS "" - CACHE STRING "Flags passed to makeglossaries.") - set(MAKENOMENCLATURE_COMPILER_FLAGS "" - CACHE STRING "Flags passed to makenomenclature.") - set(DVIPS_CONVERTER_FLAGS "-Ppdf -G0 -t letter" - CACHE STRING "Flags passed to dvips.") - if(NOT WIN32) - set(PS2PDF_CONVERTER_FLAGS "-dMaxSubsetPct=100 -dCompatibilityLevel=1.3 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoFilterColorImages=false -dAutoFilterGrayImages=false -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode -dMonoImageFilter=/FlateEncode" - CACHE STRING "Flags passed to ps2pdf.") - else() - # Most windows ports of ghostscript utilities use .bat files for ps2pdf - # commands. bat scripts interpret "=" as a special character and separate - # those arguments. To get around this, the ghostscript utilities also - # support using "#" in place of "=". - set(PS2PDF_CONVERTER_FLAGS "-dMaxSubsetPct#100 -dCompatibilityLevel#1.3 -dSubsetFonts#true -dEmbedAllFonts#true -dAutoFilterColorImages#false -dAutoFilterGrayImages#false -dColorImageFilter#/FlateEncode -dGrayImageFilter#/FlateEncode -dMonoImageFilter#/FlateEncode" - CACHE STRING "Flags passed to ps2pdf.") - endif() - set(PDFTOPS_CONVERTER_FLAGS "" - CACHE STRING "Flags passed to pdftops.") - mark_as_advanced( - LATEX_COMPILER_FLAGS - PDFLATEX_COMPILER_FLAGS - HTLATEX_COMPILER_TEX4HT_FLAGS - HTLATEX_COMPILER_TEX4HT_POSTPROCESSOR_FLAGS - HTLATEX_COMPILER_T4HT_POSTPROCESSOR_FLAGS - HTLATEX_COMPILER_LATEX_FLAGS - LATEX_SYNCTEX_FLAGS - BIBTEX_COMPILER_FLAGS - BIBER_COMPILER_FLAGS - MAKEINDEX_COMPILER_FLAGS - MAKEGLOSSARIES_COMPILER_FLAGS - MAKENOMENCLATURE_COMPILER_FLAGS - DVIPS_CONVERTER_FLAGS - PS2PDF_CONVERTER_FLAGS - PDFTOPS_CONVERTER_FLAGS - ) - - # Because it is easier to type, the flags variables are entered as - # space-separated strings much like you would in a shell. However, when - # using a CMake command to execute a program, it works better to hold the - # arguments in semicolon-separated lists (otherwise the whole string will - # be interpreted as a single argument). Use the separate_arguments to - # convert the space-separated strings to semicolon-separated lists. - separate_arguments(LATEX_COMPILER_FLAGS) - separate_arguments(PDFLATEX_COMPILER_FLAGS) - separate_arguments(HTLATEX_COMPILER_LATEX_FLAGS) - separate_arguments(LATEX_SYNCTEX_FLAGS) - separate_arguments(BIBTEX_COMPILER_FLAGS) - separate_arguments(BIBER_COMPILER_FLAGS) - separate_arguments(MAKEINDEX_COMPILER_FLAGS) - separate_arguments(MAKEGLOSSARIES_COMPILER_FLAGS) - separate_arguments(MAKENOMENCLATURE_COMPILER_FLAGS) - separate_arguments(DVIPS_CONVERTER_FLAGS) - separate_arguments(PS2PDF_CONVERTER_FLAGS) - separate_arguments(PDFTOPS_CONVERTER_FLAGS) - - # Not quite done. When you call separate_arguments on a cache variable, - # the result is written to a local variable. That local variable goes - # away when this function returns (which is before any of them are used). - # So, copy these variables with local scope to cache variables with - # global scope. - set(LATEX_COMPILER_ARGS "${LATEX_COMPILER_FLAGS}" CACHE INTERNAL "") - set(PDFLATEX_COMPILER_ARGS "${PDFLATEX_COMPILER_FLAGS}" CACHE INTERNAL "") - set(HTLATEX_COMPILER_ARGS "${HTLATEX_COMPILER_LATEX_FLAGS}" CACHE INTERNAL "") - set(LATEX_SYNCTEX_ARGS "${LATEX_SYNCTEX_FLAGS}" CACHE INTERNAL "") - set(BIBTEX_COMPILER_ARGS "${BIBTEX_COMPILER_FLAGS}" CACHE INTERNAL "") - set(BIBER_COMPILER_ARGS "${BIBER_COMPILER_FLAGS}" CACHE INTERNAL "") - set(MAKEINDEX_COMPILER_ARGS "${MAKEINDEX_COMPILER_FLAGS}" CACHE INTERNAL "") - set(MAKEGLOSSARIES_COMPILER_ARGS "${MAKEGLOSSARIES_COMPILER_FLAGS}" CACHE INTERNAL "") - set(MAKENOMENCLATURE_COMPILER_ARGS "${MAKENOMENCLATURE_COMPILER_FLAGS}" CACHE INTERNAL "") - set(DVIPS_CONVERTER_ARGS "${DVIPS_CONVERTER_FLAGS}" CACHE INTERNAL "") - set(PS2PDF_CONVERTER_ARGS "${PS2PDF_CONVERTER_FLAGS}" CACHE INTERNAL "") - set(PDFTOPS_CONVERTER_ARGS "${PDFTOPS_CONVERTER_FLAGS}" CACHE INTERNAL "") - - find_program(IMAGEMAGICK_CONVERT - NAMES magick convert - DOC "The convert program that comes with ImageMagick (available at http://www.imagemagick.org)." - ) - mark_as_advanced(IMAGEMAGICK_CONVERT) - - if(DEFINED ENV{LATEX_DEFAULT_BUILD}) - set(default_build $ENV{LATEX_DEFAULT_BUILD}) - else() - set(default_build pdf) - endif() - - set(LATEX_DEFAULT_BUILD "${default_build}" CACHE STRING - "Choose the default type of LaTeX build. Valid options are pdf, dvi, ps, safepdf, html" - ) - set_property(CACHE LATEX_DEFAULT_BUILD - PROPERTY STRINGS pdf dvi ps safepdf html - ) - - option(LATEX_USE_SYNCTEX - "If on, have LaTeX generate a synctex file, which WYSIWYG editors can use to correlate output files like dvi and pdf with the lines of LaTeX source that generates them. In addition to adding the LATEX_SYNCTEX_FLAGS to the command line, this option also adds build commands that \"corrects\" the resulting synctex file to point to the original LaTeX files rather than those generated by UseLATEX.cmake." - OFF - ) - - option(LATEX_SMALL_IMAGES - "If on, the raster images will be converted to 1/6 the original size. This is because papers usually require 600 dpi images whereas most monitors only require at most 96 dpi. Thus, smaller images make smaller files for web distribution and can make it faster to read dvi files." - OFF) - if(LATEX_SMALL_IMAGES) - set(LATEX_RASTER_SCALE 16 PARENT_SCOPE) - set(LATEX_OPPOSITE_RASTER_SCALE 100 PARENT_SCOPE) - else() - set(LATEX_RASTER_SCALE 100 PARENT_SCOPE) - set(LATEX_OPPOSITE_RASTER_SCALE 16 PARENT_SCOPE) - endif() - - # Just holds extensions for known image types. They should all be lower case. - # For historical reasons, these are all declared in the global scope. - set(LATEX_DVI_VECTOR_IMAGE_EXTENSIONS .eps CACHE INTERNAL "") - set(LATEX_DVI_RASTER_IMAGE_EXTENSIONS CACHE INTERNAL "") - set(LATEX_DVI_IMAGE_EXTENSIONS - ${LATEX_DVI_VECTOR_IMAGE_EXTENSIONS} - ${LATEX_DVI_RASTER_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) - - set(LATEX_PDF_VECTOR_IMAGE_EXTENSIONS .pdf CACHE INTERNAL "") - set(LATEX_PDF_RASTER_IMAGE_EXTENSIONS .jpeg .jpg .png CACHE INTERNAL "") - set(LATEX_PDF_IMAGE_EXTENSIONS - ${LATEX_PDF_VECTOR_IMAGE_EXTENSIONS} - ${LATEX_PDF_RASTER_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) - - set(LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS .ai .dot .svg CACHE INTERNAL "") - set(LATEX_OTHER_RASTER_IMAGE_EXTENSIONS - .bmp .bmp2 .bmp3 .dcm .dcx .ico .gif .pict .ppm .tif .tiff - CACHE INTERNAL "") - set(LATEX_OTHER_IMAGE_EXTENSIONS - ${LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS} - ${LATEX_OTHER_RASTER_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) - - set(LATEX_VECTOR_IMAGE_EXTENSIONS - ${LATEX_DVI_VECTOR_IMAGE_EXTENSIONS} - ${LATEX_PDF_VECTOR_IMAGE_EXTENSIONS} - ${LATEX_OTHER_VECTOR_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) - set(LATEX_RASTER_IMAGE_EXTENSIONS - ${LATEX_DVI_RASTER_IMAGE_EXTENSIONS} - ${LATEX_PDF_RASTER_IMAGE_EXTENSIONS} - ${LATEX_OTHER_RASTER_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) - set(LATEX_IMAGE_EXTENSIONS - ${LATEX_DVI_IMAGE_EXTENSIONS} - ${LATEX_PDF_IMAGE_EXTENSIONS} - ${LATEX_OTHER_IMAGE_EXTENSIONS} - CACHE INTERNAL "" - ) -endfunction(latex_setup_variables) - -function(latex_setup_targets) - if(NOT TARGET pdf) - add_custom_target(pdf) - endif() - if(NOT TARGET dvi) - add_custom_target(dvi) - endif() - if(NOT TARGET ps) - add_custom_target(ps) - endif() - if(NOT TARGET safepdf) - add_custom_target(safepdf) - endif() - if(NOT TARGET html) - add_custom_target(html) - endif() - if(NOT TARGET auxclean) - add_custom_target(auxclean) - endif() -endfunction(latex_setup_targets) - -function(latex_get_output_path var) - set(latex_output_path) - if(LATEX_OUTPUT_PATH) - get_filename_component( - LATEX_OUTPUT_PATH_FULL "${LATEX_OUTPUT_PATH}" ABSOLUTE - ) - if("${LATEX_OUTPUT_PATH_FULL}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - message(SEND_ERROR "You cannot set LATEX_OUTPUT_PATH to the same directory that contains LaTeX input files.") - else() - set(latex_output_path "${LATEX_OUTPUT_PATH_FULL}") - endif() - else() - if("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - message(SEND_ERROR "LaTeX files must be built out of source or you must set LATEX_OUTPUT_PATH.") - else() - set(latex_output_path "${CMAKE_CURRENT_BINARY_DIR}") - endif() - endif() - set(${var} ${latex_output_path} PARENT_SCOPE) -endfunction(latex_get_output_path) - -function(latex_add_convert_command - output_path - input_path - output_extension - input_extension - flags - ) - set(require_imagemagick_convert TRUE) - set(convert_flags "") - if(${input_extension} STREQUAL ".eps" AND ${output_extension} STREQUAL ".pdf") - # ImageMagick has broken eps to pdf conversion - # use ps2pdf instead - if(PS2PDF_CONVERTER) - set(require_imagemagick_convert FALSE) - set(converter ${PS2PDF_CONVERTER}) - set(convert_flags -dEPSCrop ${PS2PDF_CONVERTER_ARGS}) - else() - message(SEND_ERROR "Using postscript files with pdflatex requires ps2pdf for conversion.") - endif() - elseif(${input_extension} STREQUAL ".pdf" AND ${output_extension} STREQUAL ".eps") - # ImageMagick can also be sketchy on pdf to eps conversion. Not good with - # color spaces and tends to unnecessarily rasterize. - # use pdftops instead - if(PDFTOPS_CONVERTER) - set(require_imagemagick_convert FALSE) - set(converter ${PDFTOPS_CONVERTER}) - set(convert_flags -eps ${PDFTOPS_CONVERTER_ARGS}) - else() - message(STATUS "Consider getting pdftops from Poppler to convert PDF images to EPS images.") - set(convert_flags ${flags}) - endif() - else() - set(convert_flags ${flags}) - endif() - - if(require_imagemagick_convert) - if(IMAGEMAGICK_CONVERT) - string(TOLOWER ${IMAGEMAGICK_CONVERT} IMAGEMAGICK_CONVERT_LOWERCASE) - if(${IMAGEMAGICK_CONVERT_LOWERCASE} MATCHES "system32[/\\\\]convert\\.exe") - message(SEND_ERROR "IMAGEMAGICK_CONVERT set to Window's convert.exe for changing file systems rather than ImageMagick's convert for changing image formats. Please make sure ImageMagick is installed (available at http://www.imagemagick.org). If you have a recent version of ImageMagick (7.0 or higher), use the magick program instead of convert for IMAGEMAGICK_CONVERT.") - else() - set(converter ${IMAGEMAGICK_CONVERT}) - # ImageMagick requires a special order of arguments where resize and - # arguments of that nature must be placed after the input image path. - add_custom_command(OUTPUT ${output_path} - COMMAND ${converter} - ARGS ${input_path} ${convert_flags} ${output_path} - DEPENDS ${input_path} - ) - endif() - else() - message(SEND_ERROR "Could not find convert program. Please download ImageMagick from http://www.imagemagick.org and install.") - endif() - else() # Not ImageMagick convert - add_custom_command(OUTPUT ${output_path} - COMMAND ${converter} - ARGS ${convert_flags} ${input_path} ${output_path} - DEPENDS ${input_path} - ) - endif() -endfunction(latex_add_convert_command) - -# Makes custom commands to convert a file to a particular type. -function(latex_convert_image - output_files_var - input_file - output_extension - convert_flags - output_extensions - other_files - ) - set(output_file_list) - set(input_dir ${CMAKE_CURRENT_SOURCE_DIR}) - latex_get_output_path(output_dir) - - latex_get_filename_component(extension "${input_file}" EXT) - - # Check input filename for potential problems with LaTeX. - latex_get_filename_component(name "${input_file}" NAME_WE) - set(suggested_name "${name}") - if(suggested_name MATCHES ".*\\..*") - string(REPLACE "." "-" suggested_name "${suggested_name}") - endif() - if(suggested_name MATCHES ".* .*") - string(REPLACE " " "-" suggested_name "${suggested_name}") - endif() - if(NOT suggested_name STREQUAL name) - message(WARNING "Some LaTeX distributions have problems with image file names with multiple extensions or spaces. Consider changing ${name}${extension} to something like ${suggested_name}${extension}.") - endif() - - string(REGEX REPLACE "\\.[^.]*\$" ${output_extension} output_file - "${input_file}") - - latex_list_contains(is_type ${extension} ${output_extensions}) - if(is_type) - if(convert_flags) - latex_add_convert_command(${output_dir}/${output_file} - ${input_dir}/${input_file} ${output_extension} ${extension} - "${convert_flags}") - set(output_file_list ${output_dir}/${output_file}) - else() - # As a shortcut, we can just copy the file. - add_custom_command(OUTPUT ${output_dir}/${input_file} - COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${input_dir}/${input_file} ${output_dir}/${input_file} - DEPENDS ${input_dir}/${input_file} - ) - set(output_file_list ${output_dir}/${input_file}) - endif() - else() - set(do_convert TRUE) - # Check to see if there is another input file of the appropriate type. - foreach(valid_extension ${output_extensions}) - string(REGEX REPLACE "\\.[^.]*\$" ${output_extension} try_file - "${input_file}") - latex_list_contains(has_native_file "${try_file}" ${other_files}) - if(has_native_file) - set(do_convert FALSE) - endif() - endforeach(valid_extension) - - # If we still need to convert, do it. - if(do_convert) - latex_add_convert_command(${output_dir}/${output_file} - ${input_dir}/${input_file} ${output_extension} ${extension} - "${convert_flags}") - set(output_file_list ${output_dir}/${output_file}) - endif() - endif() - - set(${output_files_var} ${output_file_list} PARENT_SCOPE) -endfunction(latex_convert_image) - -# Adds custom commands to process the given files for dvi and pdf builds. -# Adds the output files to the given variables (does not replace). -function(latex_process_images dvi_outputs_var pdf_outputs_var) - latex_get_output_path(output_dir) - set(dvi_outputs) - set(pdf_outputs) - foreach(file ${ARGN}) - if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${file}") - latex_get_filename_component(extension "${file}" EXT) - set(convert_flags) - - # Check to see if we need to downsample the image. - latex_list_contains(is_raster "${extension}" - ${LATEX_RASTER_IMAGE_EXTENSIONS}) - if(LATEX_SMALL_IMAGES) - if(is_raster) - set(convert_flags -resize ${LATEX_RASTER_SCALE}%) - endif() - endif() - - # Make sure the output directory exists. - latex_get_filename_component(path "${output_dir}/${file}" PATH) - make_directory("${path}") - - # Do conversions for dvi. - latex_convert_image(output_files "${file}" .eps "${convert_flags}" - "${LATEX_DVI_IMAGE_EXTENSIONS}" "${ARGN}") - list(APPEND dvi_outputs ${output_files}) - - # Do conversions for pdf. - if(is_raster) - latex_convert_image(output_files "${file}" .png "${convert_flags}" - "${LATEX_PDF_IMAGE_EXTENSIONS}" "${ARGN}") - list(APPEND pdf_outputs ${output_files}) - else() - latex_convert_image(output_files "${file}" .pdf "${convert_flags}" - "${LATEX_PDF_IMAGE_EXTENSIONS}" "${ARGN}") - list(APPEND pdf_outputs ${output_files}) - endif() - else() - message(WARNING "Could not find file ${CMAKE_CURRENT_SOURCE_DIR}/${file}. Are you sure you gave relative paths to IMAGES?") - endif() - endforeach(file) - - set(${dvi_outputs_var} ${dvi_outputs} PARENT_SCOPE) - set(${pdf_outputs_var} ${pdf_outputs} PARENT_SCOPE) -endfunction(latex_process_images) - -function(latex_copy_globbed_files pattern dest) - file(GLOB file_list ${pattern}) - foreach(in_file ${file_list}) - latex_get_filename_component(out_file ${in_file} NAME) - configure_file(${in_file} ${dest}/${out_file} COPYONLY) - endforeach(in_file) -endfunction(latex_copy_globbed_files) - -function(latex_copy_input_file file) - latex_get_output_path(output_dir) - - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) - latex_get_filename_component(path ${file} PATH) - file(MAKE_DIRECTORY ${output_dir}/${path}) - - latex_list_contains(use_config ${file} ${LATEX_CONFIGURE}) - if(use_config) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${file} - ${output_dir}/${file} - @ONLY - ) - add_custom_command(OUTPUT ${output_dir}/${file} - COMMAND ${CMAKE_COMMAND} - ARGS ${CMAKE_BINARY_DIR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file} - ) - else() - add_custom_command(OUTPUT ${output_dir}/${file} - COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${output_dir}/${file} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file} - ) - endif() - else() - if(EXISTS ${output_dir}/${file}) - # Special case: output exists but input does not. Assume that it was - # created elsewhere and skip the input file copy. - else() - message("Could not find input file ${CMAKE_CURRENT_SOURCE_DIR}/${file}") - endif() - endif() -endfunction(latex_copy_input_file) - -############################################################################# -# Commands provided by the UseLATEX.cmake "package" -############################################################################# - -function(latex_usage command message) - message(SEND_ERROR - "${message}\n Usage: ${command}(\n [BIBFILES ...]\n [INPUTS ...]\n [IMAGE_DIRS ...]\n [IMAGES \n [CONFIGURE ...]\n [DEPENDS ...]\n [MULTIBIB_NEWCITES] \n [USE_BIBLATEX] [USE_INDEX] [USE_GLOSSARY] [USE_NOMENCL]\n [FORCE_PDF] [FORCE_DVI] [FORCE_HTML]\n [TARGET_NAME] \n [EXCLUDE_FROM_ALL]\n [EXCLUDE_FROM_DEFAULTS])" - ) -endfunction(latex_usage command message) - -# Parses arguments to add_latex_document and ADD_LATEX_TARGETS and sets the -# variables LATEX_TARGET, LATEX_IMAGE_DIR, LATEX_BIBFILES, LATEX_DEPENDS, and -# LATEX_INPUTS. -function(parse_add_latex_arguments command latex_main_input) - set(options - USE_BIBLATEX - USE_INDEX - USE_GLOSSARY - USE_NOMENCL - FORCE_PDF - FORCE_DVI - FORCE_HTML - EXCLUDE_FROM_ALL - EXCLUDE_FROM_DEFAULTS - # Deprecated options - USE_GLOSSARIES - DEFAULT_PDF - DEFAULT_SAFEPDF - DEFAULT_PS - NO_DEFAULT - MANGLE_TARGET_NAMES - ) - set(oneValueArgs - TARGET_NAME - ) - set(multiValueArgs - BIBFILES - MULTIBIB_NEWCITES - INPUTS - IMAGE_DIRS - IMAGES - CONFIGURE - DEPENDS - INDEX_NAMES - ) - cmake_parse_arguments( - LATEX "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - # Handle invalid and deprecated arguments - if(LATEX_UNPARSED_ARGUMENTS) - latex_usage(${command} "Invalid or deprecated arguments: ${LATEX_UNPARSED_ARGUMENTS}") - endif() - if(LATEX_USE_GLOSSARIES) - latex_usage(${command} "USE_GLOSSARIES option removed in version 1.6.1. Use USE_GLOSSARY instead.") - endif() - if(LATEX_DEFAULT_PDF) - latex_usage(${command} "DEFAULT_PDF option removed in version 2.0. Use FORCE_PDF option or LATEX_DEFAULT_BUILD CMake variable instead.") - endif() - if(LATEX_DEFAULT_SAFEPDF) - latex_usage(${command} "DEFAULT_SAFEPDF option removed in version 2.0. Use LATEX_DEFAULT_BUILD CMake variable instead.") - endif() - if(LATEX_DEFAULT_DVI) - latex_usage(${command} "DEFAULT_DVI option removed in version 2.0. Use FORCE_DVI option or LATEX_DEFAULT_BUILD CMake variable instead.") - endif() - if(LATEX_NO_DEFAULT) - latex_usage(${command} "NO_DEFAULT option removed in version 2.0. Use EXCLUDE_FROM_ALL instead.") - endif() - if(LATEX_MANGLE_TARGET_NAMES) - latex_usage(${command} "MANGLE_TARGET_NAMES option removed in version 2.0. All LaTeX targets use mangled names now.") - endif() - - # Capture the first argument, which is the main LaTeX input. - latex_get_filename_component(latex_target ${latex_main_input} NAME_WE) - set(LATEX_MAIN_INPUT ${latex_main_input} PARENT_SCOPE) - set(LATEX_TARGET ${latex_target} PARENT_SCOPE) - - # Propagate the result variables to the caller - foreach(arg_name ${options} ${oneValueArgs} ${multiValueArgs}) - set(var_name LATEX_${arg_name}) - set(${var_name} ${${var_name}} PARENT_SCOPE) - endforeach(arg_name) -endfunction(parse_add_latex_arguments) - -function(add_latex_targets_internal) - latex_get_output_path(output_dir) - - if(LATEX_USE_SYNCTEX) - set(synctex_flags ${LATEX_SYNCTEX_ARGS}) - else() - set(synctex_flags) - endif() - - # The commands to run LaTeX. They are repeated multiple times. - set(latex_build_command - ${LATEX_COMPILER} ${LATEX_COMPILER_ARGS} ${synctex_flags} ${LATEX_MAIN_INPUT} - ) - if(LATEX_COMPILER_ARGS MATCHES ".*batchmode.*") - # Wrap command in script that dumps the log file on error. This makes sure - # errors can be seen. - set(latex_build_command - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=execute_latex - -D LATEX_TARGET=${LATEX_TARGET} - -D LATEX_WORKING_DIRECTORY="${output_dir}" - -D LATEX_FULL_COMMAND="${latex_build_command}" - -D LATEX_OUTPUT_FILE="${LATEX_TARGET}.dvi" - -P "${LATEX_USE_LATEX_LOCATION}" - ) - endif() - set(pdflatex_build_command - ${PDFLATEX_COMPILER} ${PDFLATEX_COMPILER_ARGS} ${synctex_flags} ${LATEX_MAIN_INPUT} - ) - if(PDFLATEX_COMPILER_ARGS MATCHES ".*batchmode.*") - # Wrap command in script that dumps the log file on error. This makes sure - # errors can be seen. - set(pdflatex_build_command - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=execute_latex - -D LATEX_TARGET=${LATEX_TARGET} - -D LATEX_WORKING_DIRECTORY="${output_dir}" - -D LATEX_FULL_COMMAND="${pdflatex_build_command}" - -D LATEX_OUTPUT_FILE="${LATEX_TARGET}.pdf" - -P "${LATEX_USE_LATEX_LOCATION}" - ) - endif() - - if(NOT LATEX_TARGET_NAME) - # Use the main filename (minus the .tex) as the target name. Remove any - # spaces since CMake cannot have spaces in its target names. - string(REPLACE " " "_" LATEX_TARGET_NAME ${LATEX_TARGET}) - endif() - - # Some LaTeX commands may need to be modified (or may not work) if the main - # tex file is in a subdirectory. Make a flag for that. - get_filename_component(LATEX_MAIN_INPUT_SUBDIR ${LATEX_MAIN_INPUT} DIRECTORY) - - # Set up target names. - set(dvi_target ${LATEX_TARGET_NAME}_dvi) - set(pdf_target ${LATEX_TARGET_NAME}_pdf) - set(ps_target ${LATEX_TARGET_NAME}_ps) - set(safepdf_target ${LATEX_TARGET_NAME}_safepdf) - set(html_target ${LATEX_TARGET_NAME}_html) - set(auxclean_target ${LATEX_TARGET_NAME}_auxclean) - - # Probably not all of these will be generated, but they could be. - # Note that the aux file is added later. - set(auxiliary_clean_files - ${output_dir}/${LATEX_TARGET}.aux - ${output_dir}/${LATEX_TARGET}.bbl - ${output_dir}/${LATEX_TARGET}.blg - ${output_dir}/${LATEX_TARGET}-blx.bib - ${output_dir}/${LATEX_TARGET}.glg - ${output_dir}/${LATEX_TARGET}.glo - ${output_dir}/${LATEX_TARGET}.gls - ${output_dir}/${LATEX_TARGET}.idx - ${output_dir}/${LATEX_TARGET}.ilg - ${output_dir}/${LATEX_TARGET}.ind - ${output_dir}/${LATEX_TARGET}.ist - ${output_dir}/${LATEX_TARGET}.log - ${output_dir}/${LATEX_TARGET}.out - ${output_dir}/${LATEX_TARGET}.toc - ${output_dir}/${LATEX_TARGET}.lof - ${output_dir}/${LATEX_TARGET}.xdy - ${output_dir}/${LATEX_TARGET}.synctex.gz - ${output_dir}/${LATEX_TARGET}.synctex.bak.gz - ${output_dir}/${LATEX_TARGET}.dvi - ${output_dir}/${LATEX_TARGET}.ps - ${output_dir}/${LATEX_TARGET}.pdf - ) - - set(image_list ${LATEX_IMAGES}) - - # For each directory in LATEX_IMAGE_DIRS, glob all the image files and - # place them in LATEX_IMAGES. - foreach(dir ${LATEX_IMAGE_DIRS}) - if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}) - message(WARNING "Image directory ${CMAKE_CURRENT_SOURCE_DIR}/${dir} does not exist. Are you sure you gave relative directories to IMAGE_DIRS?") - endif() - foreach(extension ${LATEX_IMAGE_EXTENSIONS}) - file(GLOB files ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*${extension}) - foreach(file ${files}) - latex_get_filename_component(filename ${file} NAME) - list(APPEND image_list ${dir}/${filename}) - endforeach(file) - endforeach(extension) - endforeach(dir) - - latex_process_images(dvi_images pdf_images ${image_list}) - - set(make_dvi_command - ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command}) - set(make_pdf_command - ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command} - ) - - set(make_dvi_depends ${LATEX_DEPENDS} ${dvi_images}) - set(make_pdf_depends ${LATEX_DEPENDS} ${pdf_images}) - foreach(input ${LATEX_MAIN_INPUT} ${LATEX_INPUTS}) - list(APPEND make_dvi_depends ${output_dir}/${input}) - list(APPEND make_pdf_depends ${output_dir}/${input}) - if(${input} MATCHES "\\.tex$") - # Dependent .tex files might have their own .aux files created. Make - # sure these get cleaned as well. This might replicate the cleaning - # of the main .aux file, which is OK. - string(REGEX REPLACE "\\.tex$" "" input_we ${input}) - list(APPEND auxiliary_clean_files - ${output_dir}/${input_we}.aux - ${output_dir}/${input}.aux - ) - endif() - endforeach(input) - - set(all_latex_sources ${LATEX_MAIN_INPUT} ${LATEX_INPUTS} ${image_list}) - - if(LATEX_USE_GLOSSARY) - foreach(dummy 0 1) # Repeat these commands twice. - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=makeglossaries - -D LATEX_TARGET=${LATEX_TARGET} - -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER} - -D XINDY_COMPILER=${XINDY_COMPILER} - -D MAKEGLOSSARIES_COMPILER_ARGS=${MAKEGLOSSARIES_COMPILER_ARGS} - -P ${LATEX_USE_LATEX_LOCATION} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command} - ) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=makeglossaries - -D LATEX_TARGET=${LATEX_TARGET} - -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER} - -D XINDY_COMPILER=${XINDY_COMPILER} - -D MAKEGLOSSARIES_COMPILER_ARGS=${MAKEGLOSSARIES_COMPILER_ARGS} - -P ${LATEX_USE_LATEX_LOCATION} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command} - ) - endforeach(dummy) - endif() - - if(LATEX_USE_NOMENCL) - foreach(dummy 0 1) # Repeat these commands twice. - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=makenomenclature - -D LATEX_TARGET=${LATEX_TARGET} - -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER} - -D MAKENOMENCLATURE_COMPILER_ARGS=${MAKENOMENCLATURE_COMPILER_ARGS} - -P ${LATEX_USE_LATEX_LOCATION} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command} - ) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=makenomenclature - -D LATEX_TARGET=${LATEX_TARGET} - -D MAKEINDEX_COMPILER=${MAKEINDEX_COMPILER} - -D MAKENOMENCLATURE_COMPILER_ARGS=${MAKENOMENCLATURE_COMPILER_ARGS} - -P ${LATEX_USE_LATEX_LOCATION} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command} - ) - endforeach(dummy) - endif() - - if(LATEX_BIBFILES) - if(LATEX_USE_BIBLATEX) - if(NOT BIBER_COMPILER) - message(SEND_ERROR "I need the biber command.") - endif() - set(bib_compiler ${BIBER_COMPILER}) - set(bib_compiler_flags ${BIBER_COMPILER_ARGS}) - else() - set(bib_compiler ${BIBTEX_COMPILER}) - set(bib_compiler_flags ${BIBTEX_COMPILER_ARGS}) - endif() - if(LATEX_MULTIBIB_NEWCITES) - foreach (multibib_auxfile ${LATEX_MULTIBIB_NEWCITES}) - latex_get_filename_component(multibib_target ${multibib_auxfile} NAME_WE) - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${bib_compiler} ${bib_compiler_flags} ${multibib_target}) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${bib_compiler} ${bib_compiler_flags} ${multibib_target}) - set(auxiliary_clean_files ${auxiliary_clean_files} - ${output_dir}/${multibib_target}.aux) - endforeach (multibib_auxfile ${LATEX_MULTIBIB_NEWCITES}) - else() - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${bib_compiler} ${bib_compiler_flags} ${LATEX_TARGET}) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${bib_compiler} ${bib_compiler_flags} ${LATEX_TARGET}) - endif() - - foreach (bibfile ${LATEX_BIBFILES}) - list(APPEND make_dvi_depends ${output_dir}/${bibfile}) - list(APPEND make_pdf_depends ${output_dir}/${bibfile}) - endforeach (bibfile ${LATEX_BIBFILES}) - else() - if(LATEX_MULTIBIB_NEWCITES) - message(WARNING "MULTIBIB_NEWCITES has no effect without BIBFILES option.") - endif() - endif() - - if(LATEX_USE_INDEX) - if(LATEX_INDEX_NAMES) - set(INDEX_NAMES ${LATEX_INDEX_NAMES}) - else() - set(INDEX_NAMES ${LATEX_TARGET}) - endif() - foreach(idx_name ${INDEX_NAMES}) - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${MAKEINDEX_COMPILER} ${MAKEINDEX_COMPILER_ARGS} ${idx_name}.idx) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${MAKEINDEX_COMPILER} ${MAKEINDEX_COMPILER_ARGS} ${idx_name}.idx) - set(auxiliary_clean_files ${auxiliary_clean_files} - ${output_dir}/${idx_name}.idx - ${output_dir}/${idx_name}.ilg - ${output_dir}/${idx_name}.ind) - endforeach() - else() - if(LATEX_INDEX_NAMES) - message(WARNING "INDEX_NAMES has no effect without USE_INDEX option.") - endif() - endif() - - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command}) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command}) - - # Need to run one more time to remove biblatex' warning - # about page breaks that have changed. - if(LATEX_USE_BIBLATEX) - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${latex_build_command}) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${pdflatex_build_command}) - endif() - - if(LATEX_USE_SYNCTEX) - if(NOT GZIP) - message(SEND_ERROR "UseLATEX.cmake: USE_SYNTEX option requires gzip program. Set GZIP variable.") - endif() - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=correct_synctex - -D LATEX_TARGET=${LATEX_TARGET} - -D GZIP=${GZIP} - -D "LATEX_SOURCE_DIRECTORY=${CMAKE_CURRENT_SOURCE_DIR}" - -D "LATEX_BINARY_DIRECTORY=${output_dir}" - -P ${LATEX_USE_LATEX_LOCATION} - ) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=correct_synctex - -D LATEX_TARGET=${LATEX_TARGET} - -D GZIP=${GZIP} - -D "LATEX_SOURCE_DIRECTORY=${CMAKE_CURRENT_SOURCE_DIR}" - -D "LATEX_BINARY_DIRECTORY=${output_dir}" - -P ${LATEX_USE_LATEX_LOCATION} - ) - endif() - - # Check LaTeX output for important warnings at end of build - set(make_dvi_command ${make_dvi_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=check_important_warnings - -D LATEX_TARGET=${LATEX_TARGET} - -P ${LATEX_USE_LATEX_LOCATION} - ) - set(make_pdf_command ${make_pdf_command} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${CMAKE_COMMAND} - -D LATEX_BUILD_COMMAND=check_important_warnings - -D LATEX_TARGET=${LATEX_TARGET} - -P ${LATEX_USE_LATEX_LOCATION} - ) - - # Capture the default build. - string(TOLOWER "${LATEX_DEFAULT_BUILD}" default_build) - - if((NOT LATEX_FORCE_PDF) AND (NOT LATEX_FORCE_DVI) AND (NOT LATEX_FORCE_HTML)) - set(no_force TRUE) - endif() - - # Add commands and targets for building pdf outputs (with pdflatex). - if(LATEX_FORCE_PDF OR no_force) - if(LATEX_FORCE_PDF) - set(default_build pdf) - endif() - - if(PDFLATEX_COMPILER) - add_custom_command(OUTPUT ${output_dir}/${LATEX_TARGET}.pdf - COMMAND ${make_pdf_command} - DEPENDS ${make_pdf_depends} - ) - add_custom_target(${pdf_target} - DEPENDS ${output_dir}/${LATEX_TARGET}.pdf - SOURCES ${all_latex_sources} - ) - if(NOT LATEX_EXCLUDE_FROM_DEFAULTS) - add_dependencies(pdf ${pdf_target}) - endif() - endif() - endif() - - # Add commands and targets for building dvi outputs. - if(LATEX_FORCE_DVI OR LATEX_FORCE_HTML OR no_force) - if(LATEX_FORCE_DVI) - if((NOT default_build STREQUAL dvi) AND - (NOT default_build STREQUAL ps) AND - (NOT default_build STREQUAL safepdf)) - set(default_build dvi) - endif() - endif() - - add_custom_command(OUTPUT ${output_dir}/${LATEX_TARGET}.dvi - COMMAND ${make_dvi_command} - DEPENDS ${make_dvi_depends} - ) - add_custom_target(${dvi_target} - DEPENDS ${output_dir}/${LATEX_TARGET}.dvi - SOURCES ${all_latex_sources} - ) - if(NOT LATEX_EXCLUDE_FROM_DEFAULTS) - add_dependencies(dvi ${dvi_target}) - endif() - - if(DVIPS_CONVERTER) - add_custom_command(OUTPUT ${output_dir}/${LATEX_TARGET}.ps - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${DVIPS_CONVERTER} ${DVIPS_CONVERTER_ARGS} -o ${LATEX_TARGET}.ps ${LATEX_TARGET}.dvi - DEPENDS ${output_dir}/${LATEX_TARGET}.dvi) - add_custom_target(${ps_target} - DEPENDS ${output_dir}/${LATEX_TARGET}.ps - SOURCES ${all_latex_sources} - ) - if(NOT LATEX_EXCLUDE_FROM_DEFAULTS) - add_dependencies(ps ${ps_target}) - endif() - if(PS2PDF_CONVERTER) - # Since both the pdf and safepdf targets have the same output, we - # cannot properly do the dependencies for both. When selecting safepdf, - # simply force a recompile every time. - add_custom_target(${safepdf_target} - ${CMAKE_COMMAND} -E chdir ${output_dir} - ${PS2PDF_CONVERTER} ${PS2PDF_CONVERTER_ARGS} ${LATEX_TARGET}.ps ${LATEX_TARGET}.pdf - DEPENDS ${ps_target} - ) - if(NOT LATEX_EXCLUDE_FROM_DEFAULTS) - add_dependencies(safepdf ${safepdf_target}) - endif() - endif() - endif() - endif() - - if(LATEX_FORCE_HTML OR no_force) - if (LATEX_FORCE_HTML) - set(default_build html) - endif() - - if(HTLATEX_COMPILER AND LATEX_MAIN_INPUT_SUBDIR) - message(STATUS - "Disabling HTML build for ${LATEX_TARGET_NAME}.tex because the main file is in subdirectory ${LATEX_MAIN_INPUT_SUBDIR}" - ) - # The code below to run HTML assumes that LATEX_TARGET.tex is in the - # current directory. I have tried to specify that LATEX_TARGET.tex is - # in a subdirectory. That makes the build targets correct, but the - # HTML build still fails (at least for htlatex) because files are not - # generated where expected. I am getting around the problem by simply - # disabling HTML in this case. If someone really cares, they can fix - # this, but make sure it runs on many platforms and build programs. - elseif(HTLATEX_COMPILER) - # htlatex places the output in a different location - set(HTML_OUTPUT "${output_dir}/${LATEX_TARGET}.html") - add_custom_command(OUTPUT ${HTML_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E chdir ${output_dir} - ${HTLATEX_COMPILER} ${LATEX_MAIN_INPUT} - "${HTLATEX_COMPILER_TEX4HT_FLAGS}" - "${HTLATEX_COMPILER_TEX4HT_POSTPROCESSOR_FLAGS}" - "${HTLATEX_COMPILER_T4HT_POSTPROCESSOR_FLAGS}" - ${HTLATEX_COMPILER_ARGS} - DEPENDS - ${output_dir}/${LATEX_TARGET}.tex - ${output_dir}/${LATEX_TARGET}.dvi - VERBATIM - ) - add_custom_target(${html_target} - DEPENDS ${HTML_OUTPUT} ${dvi_target} - SOURCES ${all_latex_sources} - ) - if(NOT LATEX_EXCLUDE_FROM_DEFAULTS) - add_dependencies(html ${html_target}) - endif() - endif() - endif() - - # Set default targets. - if("${default_build}" STREQUAL "pdf") - add_custom_target(${LATEX_TARGET_NAME} DEPENDS ${pdf_target}) - elseif("${default_build}" STREQUAL "dvi") - add_custom_target(${LATEX_TARGET_NAME} DEPENDS ${dvi_target}) - elseif("${default_build}" STREQUAL "ps") - add_custom_target(${LATEX_TARGET_NAME} DEPENDS ${ps_target}) - elseif("${default_build}" STREQUAL "safepdf") - add_custom_target(${LATEX_TARGET_NAME} DEPENDS ${safepdf_target}) - elseif("${default_build}" STREQUAL "html") - add_custom_target(${LATEX_TARGET_NAME} DEPENDS ${html_target}) - else() - message(SEND_ERROR "LATEX_DEFAULT_BUILD set to an invalid value. See the documentation for that variable.") - endif() - - if(NOT LATEX_EXCLUDE_FROM_ALL) - add_custom_target(_${LATEX_TARGET_NAME} ALL DEPENDS ${LATEX_TARGET_NAME}) - endif() - - set_directory_properties(. - ADDITIONAL_MAKE_CLEAN_FILES "${auxiliary_clean_files}" - ) - - add_custom_target(${auxclean_target} - COMMENT "Cleaning auxiliary LaTeX files." - COMMAND ${CMAKE_COMMAND} -E remove ${auxiliary_clean_files} - ) - add_dependencies(auxclean ${auxclean_target}) -endfunction(add_latex_targets_internal) - -function(add_latex_targets latex_main_input) - latex_get_output_path(output_dir) - parse_add_latex_arguments(ADD_LATEX_TARGETS ${latex_main_input} ${ARGN}) - - add_latex_targets_internal() -endfunction(add_latex_targets) - -function(add_latex_document latex_main_input) - latex_get_output_path(output_dir) - if(output_dir) - parse_add_latex_arguments(add_latex_document ${latex_main_input} ${ARGN}) - - latex_copy_input_file(${LATEX_MAIN_INPUT}) - - foreach (bib_file ${LATEX_BIBFILES}) - latex_copy_input_file(${bib_file}) - endforeach (bib_file) - - foreach (input ${LATEX_INPUTS}) - latex_copy_input_file(${input}) - endforeach(input) - - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.cls ${output_dir}) - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.bst ${output_dir}) - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.clo ${output_dir}) - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.sty ${output_dir}) - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.ist ${output_dir}) - latex_copy_globbed_files(${CMAKE_CURRENT_SOURCE_DIR}/*.fd ${output_dir}) - - add_latex_targets_internal() - endif() -endfunction(add_latex_document) - -############################################################################# -# Actually do stuff -############################################################################# - -if(LATEX_BUILD_COMMAND) - set(command_handled) - - if("${LATEX_BUILD_COMMAND}" STREQUAL execute_latex) - latex_execute_latex() - set(command_handled TRUE) - endif() - - if("${LATEX_BUILD_COMMAND}" STREQUAL makeglossaries) - latex_makeglossaries() - set(command_handled TRUE) - endif() - - if("${LATEX_BUILD_COMMAND}" STREQUAL makenomenclature) - latex_makenomenclature() - set(command_handled TRUE) - endif() - - if("${LATEX_BUILD_COMMAND}" STREQUAL correct_synctex) - latex_correct_synctex() - set(command_handled TRUE) - endif() - - if("${LATEX_BUILD_COMMAND}" STREQUAL check_important_warnings) - latex_check_important_warnings() - set(command_handled TRUE) - endif() - - if(NOT command_handled) - message(SEND_ERROR "Unknown command: ${LATEX_BUILD_COMMAND}") - endif() - -else() - # Must be part of the actual configure (included from CMakeLists.txt). - latex_setup_variables() - latex_setup_targets() -endif() diff --git a/submodules/ton/tonlib-src/CMakeLists.txt b/submodules/ton/tonlib-src/CMakeLists.txt deleted file mode 100644 index c98edaa5..00000000 --- a/submodules/ton/tonlib-src/CMakeLists.txt +++ /dev/null @@ -1,415 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -project(TON VERSION 0.5 LANGUAGES C CXX) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -#set(OPENSSL_USE_STATIC_LIBS TRUE) - -# Prevent in-source build -get_filename_component(TON_REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH) -get_filename_component(TON_REAL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH) - -if (TON_REAL_BINARY_DIR STREQUAL TON_REAL_SOURCE_DIR) - message(" Out-of-source build should be used to build TON.") - message(" You need to remove the files already created by CMake and") - message(" rerun CMake from a new directory:") - message(" rm -rf CMakeFiles CMakeCache.txt") - message(" mkdir build") - message(" cd build") - message(" cmake ..") - message(FATAL_ERROR "In-source build failed.") -endif() - -# HAVE_SSE42 for crc32c and rocksdb -include(CheckCXXSourceCompiles) -# Check for SSE4.2 support in the compiler. -set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX") -else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2") -endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") -check_cxx_source_compiles(" -#if defined(_MSC_VER) -#include -#else // !defined(_MSC_VER) -#include -#include -#endif // defined(_MSC_VER) - -int main() { - _mm_crc32_u8(0, 0); _mm_crc32_u32(0, 0); -#if defined(_M_X64) || defined(__x86_64__) - _mm_crc32_u64(0, 0); -#endif // defined(_M_X64) || defined(__x86_64__) - return 0; -} -" CRC32C_HAVE_SSE42) -set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) - -if(NOT MSVC) - set(CMAKE_REQUIRED_FLAGS "-msse4.2 -mpclmul") -endif() -CHECK_CXX_SOURCE_COMPILES(" -#include -#include -#include -int main() { - volatile uint32_t x = _mm_crc32_u32(0, 0); - const auto a = _mm_set_epi64x(0, 0); - const auto b = _mm_set_epi64x(0, 0); - const auto c = _mm_clmulepi64_si128(a, b, 0x00); - auto d = _mm_cvtsi128_si64(c); -} -" ROCKSDB_HAVE_SSE42) -unset(CMAKE_REQUIRED_FLAGS) - -if (ROCKSDB_HAVE_SSE42 AND CRC32C_HAVE_SSE42) - set(HAVE_SSE42 TRUE) -else() - set(HAVE_SSE42 FALSE) -endif() - - -option(TONLIB_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TonLib API.") -option(TON_USE_ASAN "Use \"ON\" to enable AddressSanitizer." OFF) -option(TON_USE_TSAN "Use \"ON\" to enable ThreadSanitizer." OFF) -option(TON_USE_UBSAN "Use \"ON\" to enable UndefinedBehaviorSanitizer." OFF) -set(TON_ARCH "native" CACHE STRING "Architecture, will be passed to -march=") - -if (TON_USE_ABSEIL) - message("Add abseil-cpp") - add_subdirectory(third-party/abseil-cpp EXCLUDE_FROM_ALL) - set(ABSL_FOUND 1) -endif() - -#add_subdirectory(third-party/libcuckoo EXCLUDE_FROM_ALL) -#add_subdirectory(third-party/junction EXCLUDE_FROM_ALL) - -if (WIN32) - message("Add wingetopt") - add_subdirectory(third-party/wingetopt EXCLUDE_FROM_ALL) - set(WINGETOPT_FOUND 1) - message(STATUS "Use wingetopt") -endif() - -set(CRC32C_BUILD_TESTS OFF CACHE BOOL "Build CRC32C's unit tests") -set(CRC32C_BUILD_BENCHMARKS OFF CACHE BOOL "Build CRC32C's benchmarks") -set(CRC32C_USE_GLOG OFF CACHE BOOL "Build CRC32C's tests with Google Logging") -set(CRC32C_INSTALL OFF CACHE BOOL "Install CRC32C's header and library") -message("Add crc32c") -add_subdirectory(third-party/crc32c EXCLUDE_FROM_ALL) -set(CRC32C_FOUND 1) - -if (TON_USE_ROCKSDB) - if (ANDROID) - set(PORTABLE ON CACHE BOOL "portable") - endif() - set(WITH_GFLAGS OFF CACHE BOOL "build with GFlags") - set(WITH_TESTS OFF CACHE BOOL "build with tests") - set(WITH_TOOLS OFF CACHE BOOL "build with tools") - set(FAIL_ON_WARNINGS OFF CACHE BOOL "fail on warnings") - message("Add rocksdb") - add_subdirectory(third-party/rocksdb EXCLUDE_FROM_ALL) -endif() - -option(USE_COROUTINES "experimental support of coroutines" OFF) -if (USE_COROUTINES) - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(TD_HAVE_COROUTINES 1) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - endif() -endif() - -option(USE_LIBRAPTORQ "use libraptorq for tests" OFF) -if (USE_LIBRAPTORQ) - set(USE_LZ4 OFF CACHE BOOL "use lz4") - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CLANG_STDLIB "ON") # for libraptorq - endif() - message("Add libraptorq") - add_subdirectory(third-party/libraptorq EXCLUDE_FROM_ALL) -endif() - -message("Add ton") -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH}) - -# Configure CCache if available -find_program(CCACHE_FOUND ccache) -#set(CCACHE_FOUND 0) -if (CCACHE_FOUND) - message(STATUS "Found ccache") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) -else() - message(STATUS "Could NOT find ccache") -endif() - -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(GCC 1) -elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CLANG 1) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - set(INTEL 1) -elseif (NOT MSVC) - message(FATAL_ERROR "Compiler isn't supported") -endif() - -include(CheckCXXCompilerFlag) - -if (GCC OR CLANG OR INTEL) - if (WIN32 AND INTEL) - set(STD14_FLAG /Qstd=c++14) - else() - set(STD14_FLAG -std=c++14) - endif() - check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD14) - if (NOT HAVE_STD14) - string(REPLACE "c++14" "c++1y" STD14_FLAG "${STD14_FLAG}") - check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD1Y) - set(HAVE_STD14 ${HAVE_STD1Y}) - endif() -elseif (MSVC) - set(HAVE_STD14 MSVC_VERSION>=1900) -endif() - -if (NOT HAVE_STD14) - message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.") -endif() - -set(CMAKE_THREAD_PREFER_PTHREAD ON) -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) -find_package(ZLIB REQUIRED) - -if (TON_ARCH AND NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TON_ARCH}") -endif() -if (THREADS_HAVE_PTHREAD_ARG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -endif() - -if (TON_USE_JEMALLOC) - find_package(JeMalloc REQUIRED) -endif() - -set(MEMPROF "" CACHE STRING "Use one of \"ON\", \"FAST\" or \"SAFE\" to enable memory profiling. \ -Works under macOS and Linux when compiled using glibc. \ -In FAST mode stack is unwinded only using frame pointers, which may fail. \ -In SAFE mode stack is unwinded using backtrace function from execinfo.h, which may be very slow. \ -By default both methods are used to achieve maximum speed and accuracy") - -if (CLANG OR GCC) - if (MEMPROF) - check_cxx_compiler_flag(-no-pie CXX_NO_PIE_FLAG) - if (CXX_NO_PIE_FLAG) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie") - elseif (APPLE) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie") - endif() - endif() -endif() - -if (MSVC) - if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1") - string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - endif() - add_definitions(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /wd4127 /wd4324 /wd4456 /wd4457 /wd4458 /wd4505 /wd4702") -elseif (CLANG OR GCC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG} -fno-omit-frame-pointer") - if (APPLE) - #use "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/export_list" for exported symbols - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fvisibility=hidden -Wl,-dead_strip,-x,-S") - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fvisibility=hidden -Wl,-dead_strip,-x,-S") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") - if (NOT TON_USE_ASAN AND NOT TON_USE_TSAN AND NOT MEMPROF) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--exclude-libs,ALL") - endif() - endif() -elseif (INTEL) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG}") -endif() - -if (WIN32) - add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DNOMINMAX -DUNICODE -D_UNICODE) -endif() -if (CYGWIN) - add_definitions(-D_DEFAULT_SOURCE=1 -DFD_SETSIZE=4096) -endif() - -if (NOT ANDROID) # _FILE_OFFSET_BITS is broken in ndk r15 and r15b and doesn't work prior to Android 7.0 - add_definitions(-D_FILE_OFFSET_BITS=64) -endif() - -set(INTERNAL_COMPILE "0") - -set(TONLIB_COMPILE "0") -#BEGIN tonlib - add_definitions(-D_TONLIB_COMPILE=1) - set(TONLIB_COMPILE "1") -#END tonlib - -include(AddCXXCompilerFlag) -if (MSVC) - add_cxx_compiler_flag("/experimental:external /external:anglebrackets /external:W0") -endif() -if (NOT MSVC) - add_cxx_compiler_flag("-Wall") -endif() -add_cxx_compiler_flag("-Wextra") -add_cxx_compiler_flag("-Wimplicit-fallthrough=2") -add_cxx_compiler_flag("-Wpointer-arith") -add_cxx_compiler_flag("-Wcast-qual") -add_cxx_compiler_flag("-Wsign-compare") -add_cxx_compiler_flag("-Wduplicated-branches") -add_cxx_compiler_flag("-Wduplicated-cond") -add_cxx_compiler_flag("-Walloc-zero") -add_cxx_compiler_flag("-Wlogical-op") -add_cxx_compiler_flag("-Wno-tautological-compare") -add_cxx_compiler_flag("-Wpointer-arith") -add_cxx_compiler_flag("-Wvla") -add_cxx_compiler_flag("-Wnon-virtual-dtor") -add_cxx_compiler_flag("-Wno-unused-parameter") -add_cxx_compiler_flag("-Wconversion") -add_cxx_compiler_flag("-Wno-sign-conversion") -add_cxx_compiler_flag("-Qunused-arguments") -add_cxx_compiler_flag("-Wno-unused-private-field") -add_cxx_compiler_flag("-Wno-redundant-move") -#add_cxx_compiler_flag("-Werror") - -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/include/c++/v1") -if (CLANG) - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -endif() -if (TON_USE_ASAN) - if (CLANG) - add_cxx_compiler_flag("-stdlib=libc++") - endif() - add_cxx_compiler_flag("-fsanitize=address") - add_definitions(-DTD_USE_ASAN=1) -endif() -if (TON_USE_TSAN) - if (CLANG) - add_cxx_compiler_flag("-stdlib=libc++") - endif() - add_cxx_compiler_flag("-fsanitize=thread") -endif() -if (TON_USE_UBSAN) - if (CLANG) - add_cxx_compiler_flag("-stdlib=libc++") - endif() - add_cxx_compiler_flag("-fsanitize=undefined") -endif() -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finstrument-functions") - -#Compilation database -set(CMAKE_EXPORT_COMPILE_COMMANDS 1) - - -function(target_link_libraries_system target) - set(libs ${ARGN}) - foreach(lib ${libs}) - get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) - target_include_directories(${target} SYSTEM PUBLIC ${lib_include_dirs}) - target_link_libraries(${target} PUBLIC ${lib}) - endforeach(lib) -endfunction(target_link_libraries_system) - -set(TDUTILS_MIME_TYPE OFF CACHE BOOL "Generate mime type conversion") -add_subdirectory(tdutils) -add_subdirectory(memprof) -add_subdirectory(tdactor) -add_subdirectory(tdnet) -if (TON_USE_ROCKSDB) - option(TDDB_USE_ROCKSDB "Use rockdb" ON) -endif() -add_subdirectory(tddb) -add_subdirectory(tdtl) -add_subdirectory(tl) -add_subdirectory(terminal) -add_subdirectory(keys) -add_subdirectory(tl-utils) -add_subdirectory(adnl) -add_subdirectory(crypto) -add_subdirectory(lite-client) - -#BEGIN tonlib -add_subdirectory(tonlib) -#END tonlib - - -if (NOT CMAKE_CROSSCOMPILING) - if (TDUTILS_MIME_TYPE) - set(TDMIME_AUTO tdmime_auto) - endif() - add_custom_target(prepare_cross_compiling DEPENDS tl_generate_common tlb_generate_block gen_fif ${TDMIME_AUTO}) -endif() - -#TESTS -add_executable(test-ed25519 test/test-td-main.cpp ${ED25519_TEST_SOURCE}) -target_link_libraries(test-ed25519 PRIVATE ton_crypto) - -add_executable(test-vm test/test-td-main.cpp ${TONVM_TEST_SOURCE}) -target_link_libraries(test-vm PRIVATE ton_crypto fift-lib) - -add_executable(test-smartcont test/test-td-main.cpp ${SMARTCONT_TEST_SOURCE}) -target_link_libraries(test-smartcont PRIVATE smc-envelope fift-lib ton_db) - -add_executable(test-cells test/test-td-main.cpp ${CELLS_TEST_SOURCE}) -target_link_libraries(test-cells PRIVATE ton_crypto) - -add_executable(test-fift test/test-td-main.cpp ${FIFT_TEST_SOURCE}) -target_link_libraries(test-fift PRIVATE fift-lib) - -add_executable(test-tdutils test/test-td-main.cpp ${TDUTILS_TEST_SOURCE}) -target_link_libraries(test-tdutils PRIVATE tdutils ${CMAKE_THREAD_LIBS_INIT} memprof ${JEMALLOC_LIBRARIES}) -#target_link_libraries_system(test-tdutils absl::base absl::container absl::hash ) -#target_link_libraries_system(test-tdutils libcuckoo) -#target_include_directories(test-tdutils PRIVATE SYSTEM ${JUNCTION_ALL_INCLUDE_DIRS}) -#target_link_libraries(test-tdutils PRIVATE ${JUNCTION_ALL_LIBRARIES}) - -add_executable(test-tdactor test/test-td-main.cpp ${TDACTOR_TEST_SOURCE}) -target_link_libraries(test-tdactor PRIVATE tdactor ${CMAKE_THREAD_LIBS_INIT}) - -add_executable(test-net test/test-td-main.cpp ${NET_TEST_SOURCE}) -target_link_libraries(test-net PRIVATE tdnet tdutils ${CMAKE_THREAD_LIBS_INIT}) - -#BEGIN tonlib -add_executable(test-tonlib ${TONLIB_ONLINE_TEST_SOURCE}) -target_link_libraries(test-tonlib tdutils tdactor adnllite tl_api ton_crypto ton_block tl_tonlib_api tonlib) - -add_executable(test-tonlib-offline test/test-td-main.cpp ${TONLIB_OFFLINE_TEST_SOURCE}) -target_link_libraries(test-tonlib-offline tdutils tdactor adnllite tl_api ton_crypto ton_block fift-lib tl_tonlib_api tonlib) - -if (NOT CMAKE_CROSSCOMPILING) - add_dependencies(test-tonlib-offline gen_fif) -endif() -#END tonlib - - -enable_testing() -set(TEST_OPTIONS "--regression ${CMAKE_CURRENT_SOURCE_DIR}/test/regression-tests.ans --filter -Bench") -separate_arguments(TEST_OPTIONS) -add_test(test-ed25519-crypto crypto/test-ed25519-crypto) -add_test(test-ed25519 test-ed25519) -add_test(test-vm test-vm ${TEST_OPTIONS}) -add_test(test-fift test-fift ${TEST_OPTIONS}) -add_test(test-cells test-cells ${TEST_OPTIONS}) -add_test(test-smartcont test-smartcont) -add_test(test-net test-net) -add_test(test-actors test-tdactor) - -#BEGIN tonlib -add_test(test-tdutils test-tdutils) -add_test(test-tonlib-offline test-tonlib-offline) -#END tonlib - - diff --git a/submodules/ton/tonlib-src/DISCLAIMER b/submodules/ton/tonlib-src/DISCLAIMER deleted file mode 100644 index acddc25d..00000000 --- a/submodules/ton/tonlib-src/DISCLAIMER +++ /dev/null @@ -1,9 +0,0 @@ -Please read the following before you download the TON Blockchain Lite Client and connect to the TON Test Network. By downloading the TON Blockchain Lite Client and associated software and connecting to the TON Test Network, you accept and agree to be bound and abide by the following terms: - - 1. You agree to use the TON Test Network only for lawful purposes and only for testing and development purposes. - - 2. YOUR USE OF THE TON TEST NETWORK IS AT YOUR OWN RISK. THE TON TEST NETWORK IS PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS, WITHOUT ANY WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. YOU UNDERSTAND AND ACKNOWLEDGE THAT THE TON TEST NETWORK IS STILL UNDER DEVELOPMENT AND TESTING. - - 3. NEITHER TELEGRAM NOR ANY PERSON ASSOCIATED WITH TELEGRAM MAKES, AND HEREBY DISCLAIMS, ANY WARRANTY OR REPRESENTATION WITH RESPECT TO THE COMPLETENESS, SECURITY, RELIABILITY, QUALITY, ACCURACY, AVAILABILITY, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT OF THE TON TEST NETWORK. WITHOUT LIMITING THE FOREGOING, NEITHER TELEGRAM NOR ANYONE ASSOCIATED WITH TELEGRAM REPRESENTS OR WARRANTS THAT THE TON TEST NETWORK WILL BE ACCURATE, RELIABLE, ERROR-FREE OR UNINTERRUPTED, THAT DEFECTS WILL BE CORRECTED, THAT THE TON TEST NETWORK IS FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS OR THAT THE TON TEST NETWORK WILL OTHERWISE MEET YOUR NEEDS OR EXPECTATIONS. SOME JURISDICTIONS DO NOT ALLOW EXCLUSION OF WARRANTIES OR LIMITATIONS ON THE DURATION OF IMPLIED WARRANTIES, SO THE ABOVE DISCLAIMER MAY NOT APPLY TO YOU IN ITS ENTIRETY, BUT WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. - - 4. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL TELEGRAM NOR ANY PERSON ASSOCIATED WITH TELEGRAM BE LIABLE FOR ANY LOSS OF USE, LOST DATA, FAILURE OF SECURITY MECHANISMS, INTERRUPTION OF BUSINESS, OR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY KIND (INCLUDING LOST PROFITS), REGARDLESS OF THE FORM OF ACTION, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF INFORMED OF THE POSSIBILITY OF SUCH DAMAGES IN ADVANCE. NOTWITHSTANDING ANY OTHER PROVISION OF THIS TERMS OF USE, NEITHER TELEGRAM NOR ANY PERSON ASSOCIATED WITH TELEGRAM SHALL HAVE ANY LIABILITY UNDER THIS TERMS OF USE. diff --git a/submodules/ton/tonlib-src/HOWTO b/submodules/ton/tonlib-src/HOWTO deleted file mode 100644 index 272c4472..00000000 --- a/submodules/ton/tonlib-src/HOWTO +++ /dev/null @@ -1,556 +0,0 @@ -The aim of this document is to provide step-by-step instructions for compiling and creating a simple smart contract (a simple wallet) in the TON Blockchain Test Network using the TON Blockchain Lite Client and associated software. - -Download and installation instructions may be found in README. We assume here that the Lite Client is already properly downloaded, compiled and installed. - -1. Smart-contract addresses -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Smart-contract addresses in the TON Network consist of two parts: (a) the workchain ID (a signed 32-bit integer) and (b) the address inside the workchain (64-512 bits depending on the workchain). Currently, only the masterchain (workchain_id=-1) and occasionally the basic workchain (workchain_id=0) are running in the TON Blockchain Test Network. Both of them have 256-bit addresses, so we henceforth assume that workchain_id is either 0 or -1 and that the address inside the workchain is exactly 256-bit. - -Under the conditions stated above, the smart-contract address can be represented in the following forms: - -A) "Raw": :<64 hexadecimal digits with address> -B) "User-friendly", which is obtained by first generating: -- one tag byte (0x11 for "bounceable" addresses, 0x51 for "non-bounceable"; add +0x80 if the address should not be accepted by software running in the production network) -- one byte containing a signed 8-bit integer with the workchain_id (0x00 for the basic workchain, 0xff for the masterchain) -- 32 bytes containing 256 bits of the smart-contract address inside the workchain (big-endian) -- 2 bytes containing CRC16-CCITT of the previous 34 bytes - -In case B), the 36 bytes thus obtained are then encoded using base64 (i.e., with digits, upper- and lowercase Latin letters, '/' and '+') or base64url (with '_' and '-' instead of '/' and '+'), yielding 48 printable non-space characters. - -Example: - -The "test giver" (a special smart contract residing in the masterchain of the Test Network that gives up to 20 test Grams to anybody who asks) has the address - --1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 - -in the "raw" form (notice that uppercase Latin letters 'A'..'F' may be used instead of 'a'..'f') - -and - -kf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny (base64) -kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny (base64url) - -in the "user-friendly" form (to be displayed by user-friendly clients). Notice that both forms (base64 and base64url) are valid and must be accepted. - -Incidentally, other binary data related to the TON Blockchain have similar "armored" base64 representations, differing by their first bytes. For example, the ubiquitious 256-bit Ed25519 public keys are represented by first creating a 36-byte sequence as follows: -- one tag byte 0x3E, meaning that this is a public key -- one tag byte 0xE6, meaning that this is a Ed25519 public key -- 32 bytes containing the standard binary representation of the Ed25519 public key -- 2 bytes containing the big-endian representation of CRC16-CCITT of the previous 34 bytes. - -The resulting 36-byte sequence is converted into a 48-character base64 or base64url string in the standard fashion. For example, the Ed25519 public key E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D (usually represented by a sequence of 32 bytes 0xE3, 0x9E, ..., 0x7D) has the following "armored" representation: - -Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2 - -2. Inspecting the state of a smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Inspecting the state of smart contracts with the aid of the TON Lite Client is easy. For the sample smart contract described above, you would run the Lite Client and enter the following commands: - -> last -... -> getaccount -1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 -or -> getaccount kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny - -You will see something like this: - ------------------------------------- -got account state for -1 : FCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260 with respect to blocks (-1,8000000000000000,2075):BFE876CE2085274FEDAF1BD80F3ACE50F42B5A027DF230AD66DCED1F09FB39A7:522C027A721FABCB32574E3A809ABFBEE6A71DE929C1FA2B1CD0DDECF3056505 -account state is (account - addr:(addr_std - anycast:nothing workchain_id:-1 address:xFCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260) - storage_stat:(storage_info - used:(storage_used - cells:(var_uint len:1 value:3) - bits:(var_uint len:2 value:707) - public_cells:(var_uint len:0 value:0)) last_paid:1568899526 - due_payment:nothing) - storage:(account_storage last_trans_lt:2310000003 - balance:(currencies - grams:(nanograms - amount:(var_uint len:6 value:9998859500889)) - other:(extra_currencies - dict:hme_empty)) - state:(account_active - ( - split_depth:nothing - special:nothing - code:(just - value:(raw@^Cell - x{} - x{FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260D31F01ED44D0D31FD166BAF2A1F8000120D74A8E11D307D459821804A817C80073FB0201FB00DED1A4C8CB1FC9ED54} - )) - data:(just - value:(raw@^Cell - x{} - x{00009A15} - )) - library:hme_empty)))) -x{CFFFCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB2923226020680B0C2EC1C0E300000000226BF360D8246029DFF56534_} - x{FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260D31F01ED44D0D31FD166BAF2A1F8000120D74A8E11D307D459821804A817C80073FB0201FB00DED1A4C8CB1FC9ED54} - x{00000003} -last transaction lt = 2310000001 hash = 73F89C6F8910F598AD84504A777E5945C798AC8C847FF861C090109665EAC6BA ------------------------------------- - -The first information line "got account state ... for ..." shows the account address and the masterchain block identifier with respect to which the account state has been dumped. Notice that even if the account state changes in a subsequent block, the `getaccount xxx` command will return the same result until the reference block is updated to a newer value by a `last` command. In this way one can study the state of all accounts and obtain consistent results. - -The "account state is (account ... " line begins the pretty-printed deserialized view of the account state. It is a deserialization of TL-B data type Account, used to represent account states in the TON Blockchain as explained in the TON Blockchain documentation. (You can find the TL-B scheme used for deserialization in the source file crypto/block/block.tlb; notice that if the scheme is out of date, the deserialization may break down.) - -Finally, the last several lines beginning with x{CFF538... (the "raw dump") contain the same information displayed as a tree of cells. In this case, we have one root cell containing the data bits CFF...134_ (the underscore means that the last binary one and all subsequent binary zeroes are to be removed, so hexadecimal "4_" corresponds to binary "0"), and two cells that are its children (displayed with one-space indentation). - -We can see that x{FF0020DD20...} is the code of this smart contract. If we consult the Appendix A of the TON Virtual Machine documentation, we can even disassemble this code: FF00 is SETCP 0, 20 is DUP, DD is IFNOTRET, 20 is DUP, and so on. (Incidentally, you can find the source code of this smartcontract in the source file crypto/block/new-testgiver.fif .) - -We can also see that x{00009A15} (the actual value you see may be different) is the persistent data of this smart contract. It is actually an unsigned 32-bit integer, used by the smart contract as the counter of operations performed so far. Notice that this value is big-endian (i.e., 3 is encoded as x{00000003}, not as x{03000000}), as are all integers inside the TON Blockchain. In this case the counter is equal to 0x9A15 = 39445. - -The current balance of the smart contract is easily seen in the pretty-printed portion of the output. In this case, we see ... balance:(currencies:(grams:(nanograms:(... value:1000000000000000...)))), which is the balance of the account in (test) nanograms (a million test Grams in this example; the actual number you see may be smaller). If you study the TL-B scheme provided in crypto/block/scheme.tlb, you will be able to find this number (10^15) in binary big-endian form in the raw dump portion as well (it is located near the end of the data bits of the root cell). - -3. Compiling a new smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Before uploading a new smart contract into the TON Blockchain, you need to determine its code and data and save them in serialized form into a file (called a "bag-of-cells" or BOC file, usually with a .boc suffix). Let us consider the case of a simple wallet smart contract, which stores a 32-bit operations counter and a 256-bit Ed25519 public key of its owner in its persistent data. - -Obviously, you'll need some tools for developing smart contracts - namely, a TON smart contract compiler. Basically, a TON smart contract compiler is a program that reads the source of a smart contract in a specialized high-level programming language and creates a .boc file from this source. - -One such tool is the Fift interpreter, which is included in this distribution and can help create simple smart contracts. Larger smart contracts should be developed using more sophisticated tools (such as the FunC compiler included in this distribution, that creates Fift assembler files from FunC source files; you can find some FunC smart-contract sources in the directory `crypto/smartcont`). However, Fift is sufficient for demonstration purposes. - -Consider the file `new-wallet.fif` (usually located as `crypto/smartcont/new-wallet.fif` with respect to the source directory) containing the source of a simple wallet smart contract: - ------------------------------------- -#!/usr/bin/env fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new wallet in specified workchain, with private key saved to or loaded from .pk" cr - ."('new-wallet.pk' by default)" cr 1 halt -} : usage -$# 1- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -def? $2 { @' $2 } { "new-wallet" } cond constant file-base - -."Creating new wallet in workchain " wc . cr - -// Create new simple wallet -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt - }> - INC 32 THROWIF // fail unless recv_external - 512 INT LDSLICEX DUP 32 PLDU // sign cs cnt - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk - s1 s2 XCPU // sign cs cnt pubk cnt' cnt - EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - s2 PUSH HASHSU // sign cs cnt pubk hash - s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk - CHKSIGNU // pubk cs cnt ? - 34 THROWIFNOT // signature mismatch - ACCEPT - SWAP 32 LDU NIP - DUP SREFS IF:<{ - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF // pubk cnt mode msg cs - s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent ) - }> - ENDS - INC NEWC 32 STU 256 STU ENDC c4 POPCTR -}>c // >libref -// code - // data -null // no libraries -// Libs{ x{ABACABADABACABA} drop x{AAAA} s>c public_lib x{1234} x{5678} |_ s>c public_lib }Libs - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr --------------------------------------------- - -(The actual source file in your distribution may be slighly different.) Essentially, it is a complete Fift script for creating a new instance of this smart contract controlled by a newly-generated keypair. The script accepts command-line arguments, so you don't need to edit the source file each time you want to create a new wallet. - -Now, provided that you have compiled Fift binary (usually located as "crypto/fift" with respect to the build directory), you can run - -$ crypto/fift -I/crypto/fift/lib -s /crypto/smartcont/new-wallet.fif 0 my_wallet_name - -where 0 is the workchain to contain the new wallet (0 = basechain, -1 = masterchain), `my_wallet_name` is any identifier you wish to be associated with this wallet. The address of the new wallet will be saved into file `my_wallet_name.addr`, its newly-generated private key will be saved to `my_wallet_name.pk` (unless this file already exists; then the key will be loaded from this file instead), and the external message will be saved into my_wallet_name-query.boc. If you do not indicate the name of your wallet (`my_wallet_name` in the example above), the default name `new-wallet` is used. - -You may opt to set the FIFTPATH environment variable to /crypto/fift/lib:/crypto/smartcont, the directories containing Fift.fif and Asm.fif library files, and the sample smart-contract sources, respectively; then you can omit the -I argument to the Fift interpreter. If you install the Fift binary `crypto/fift` to a directory included in your PATH (e.g., /usr/bin/fift), you can simply invoke - -$ fift -s new-wallet.fif 0 my_wallet_name - -instead of indicating the complete search paths in the command line. - -If everything worked, you'll see something like the following - --------------------------------------------- -Creating new wallet in workchain 0 -Saved new private key to file my_wallet_name.pk -StateInit: x{34_} - x{FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54} - x{00000000C59DC52962CC568AC5E72735EABB025C5BDF457D029AEEA6C2FFA5EB2A945446} - -new wallet address = 0:2ee9b4fd4f077c9b223280c35763df9edab0b41ac20d36f4009677df95c3afe2 -(Saving address to file my_wallet_name.addr) -Non-bounceable address (for init): 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb -Bounceable address (for later access): kQAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4rie -signing message: x{00000000} - -External message for initialization is x{88005DD369FA9E0EF93644650186AEC7BF3DB5616835841A6DE8012CEFBF2B875FC41190260D403E40B2EE8BEB2855D0F4447679D9B9519BE64BE421166ABA2C66BEAAAF4EBAF8E162886430243216DDA10FCE68C07B6D7DDAA3E372478D711E3E1041C00000001_} - x{FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54} - x{00000000C59DC52962CC568AC5E72735EABB025C5BDF457D029AEEA6C2FFA5EB2A945446} - -B5EE9C724104030100000000E50002CF88005DD369FA9E0EF93644650186AEC7BF3DB5616835841A6DE8012CEFBF2B875FC41190260D403E40B2EE8BEB2855D0F4447679D9B9519BE64BE421166ABA2C66BEAAAF4EBAF8E162886430243216DDA10FCE68C07B6D7DDAA3E372478D711E3E1041C000000010010200A2FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54004800000000C59DC52962CC568AC5E72735EABB025C5BDF457D029AEEA6C2FFA5EB2A945446BCF59C17 -(Saved wallet creating query to file my_wallet_name-query.boc) --------------------------------------------- - -In a nutshell, the Fift assembler (loaded by the "Asm.fif" include line) is used to compile the source code of the smart contract (contained in <{ SETCP0 ... c4 POPCTR }> lines) into its internal representation. The initial data of the smart contract is also created (by lines), containing a 32-bit sequence number (equal to zero) and a 256-bit public key from a newly-generated Ed25519 keypair. The corresponding private key is saved into the file `my_wallet_name.pk` unless it already exists (if you run this code twice in the same directory, the private key will be loaded from this file instead). - -The code and data for the new smart contract are combined into a StateInit structure (in the next lines), the address of the new smart contract (equal to the hash of this StateInit structure) is computed and output, and then an external message with a destination address equal to that of the new smart contract is created. This external message contains both the correct StateInit for the new smart contract and a non-trivial payload (signed by the correct private key). - -Finally, the external message is serialized into a bag of cells (represented by B5EE...BE63) and saved into the file `my_wallet_name-query.boc`. Essentially, this file is your compiled smart contract with all additional information necessary to upload it into the TON Blockchain. - -4. Transferring some funds to the new smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You might try to upload the new smart contract immediately by running the Lite Client and typing - -> sendfile new-wallet-query.boc - -or - -> sendfile my_wallet_name-query.boc - -if you chose to name your wallet `my_wallet_name`. - -Unfortunately, this won't work, because smart contracts must have a positive balance to be able to pay for storing and processing their data in the blockchain. So you have to transfer some funds to your new smart contract address first, displayed during its generation as -1:60c0...c0d0 (in raw form) and 0f9..EKD (in user-friendly form). - -In a real scenario, you would either transfer some Grams from your already existing wallet, ask a friend to do so, or buy some Grams at a cryptocurrency exchange, indicating 0f9...EKD as the account to transfer the new Grams to. - -In the Test Network, you have another option: you can ask the "test giver" to give you some test Grams (up to 20). Let us explain how to do it. - -5. Using the test giver smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You need to know the address of the test giver smart contract. We'll assume that it is -1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260, or, equivalently, kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny, as indicated in one of the previous examples. You inspect the state of this smart contract in the Lite Client by typing - -> last -> getaccount kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny - -as explained above in Section 2. The only number you need from the output is the 32-bit sequence number stored in the smart contract data (it is 0x9A15 in the example above, but generally it will be different). A simpler way of obtaining the current value of this sequence number is by typing - -> last -> runmethod kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny seqno - -producing the correct value 39445 = 0x9A15: - --------------------------------------------- -got account state for -1 : FCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260 with respect to blocks (-1,8000000000000000,2240):18E6DA7707191E76C71EABBC5277650666B7E2CFA2AEF2CE607EAFE8657A3820:4EFA2540C5D1E4A1BA2B529EE0B65415DF46BFFBD27A8EB74C4C0E17770D03B1 -creating VM -starting VM to run method `seqno` (85143) of smart contract -1:FCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260 -... -arguments: [ 85143 ] -result: [ 39445 ] --------------------------------------------- - -Next, you create an external message to the test giver asking it to send another message to your (uninitialized) smart contract carrying a specified amount of test Grams. There is a special Fift script for generating this external message located at crypto/smartcont/testgiver.fif: - --------------------------------------------- -#!/usr/bin/env fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a request to TestGiver and saves it into .boc" cr - ."('testgiver-query.boc' by default)" cr 1 halt -} : usage - -$# 3 - -2 and ' usage if - -// "testgiver.addr" load-address -Masterchain 0xfcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 -2constant giver_addr - ."Test giver address = " giver_addr 2dup .addr cr 6 .Addr cr - -$1 true parse-load-address =: bounce 2=: dest_addr -$2 parse-int =: seqno -$3 $>GR =: amount -def? $4 { @' $4 } { "testgiver-query" } cond constant savefile - -."Requesting " amount .GR ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."seqno=0x" seqno x. ."bounce=" bounce . cr - -// create a message (NB: 01b00.., b = bounce) - - -dup ."enveloping message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr ---------------------------------------------- - -You can pass the required parameters as command-line arguments to this script - -$ crypto/fift -I -s [] - -For instance, - -$ crypto/fift -I/crypto/fift/lib:/crypto/smartcont -s testgiver.fif 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb 0x9A15 6.666 wallet-query - -or simply - -$ fift -s testgiver.fif 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb 0x9A15 6.666 wallet-query - -provided you have set up the environment variable FIFTPATH to /crypto/fift/lib:/crypto/smartcont and installed the fift binary as /usr/bin/fift (or anywhere else in your PATH). - -The newly-created message to the new smart contract must have its bounce bit clear, otherwise the transfer will be "bounced" to its sender. This is the reason we have passed the "non-bounceable" address 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb of our new wallet smart contract. - -This Fift code creates an internal message from the test giver smart contract to the address of our new smart contract carrying 6.666 test Grams (you can enter any other amount here up to approximately 20 Grams). Then this message is enveloped into an external message addressed to the test giver; this external message must also contain the correct sequence number of the test giver. When the test giver receives such an external message, it checks whether the sequence number matches the one stored in its persistent data, and if it does, sends the embedded internal message with the required amount of test Grams to its destination (our smart contract in this case). - -The external message is serialized and saved into the file `wallet-query.boc`. Some output is generated in the process: - ---------------------------------------------- -Test giver address = -1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 -kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny -Requesting GR$6.666 to account 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb = 0:2ee9b4fd4f077c9b223280c35763df9edab0b41ac20d36f4009677df95c3afe2 seqno=0x9a15 bounce=0 -enveloping message: x{00009A1501} - x{42001774DA7EA783BE4D91194061ABB1EFCF6D585A0D61069B7A004B3BEFCAE1D7F1280C6A98B4000000000000000000000000000047494654} - -resulting external message: x{89FF02ACEEB6F264BCBAC5CE85B372D8616CA2B4B9A5E3EC98BB496327807E0E1C1A000004D0A80C_} - x{42001774DA7EA783BE4D91194061ABB1EFCF6D585A0D61069B7A004B3BEFCAE1D7F1280C6A98B4000000000000000000000000000047494654} - -B5EE9C7241040201000000006600014F89FF02ACEEB6F264BCBAC5CE85B372D8616CA2B4B9A5E3EC98BB496327807E0E1C1A000004D0A80C01007242001774DA7EA783BE4D91194061ABB1EFCF6D585A0D61069B7A004B3BEFCAE1D7F1280C6A98B4000000000000000000000000000047494654AFC17FA4 -(Saved to file wallet-query.boc) ---------------------------------------------- - -6. Uploading the external message to the test giver smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Now we can invoke the Lite Client, check the state of the test giver (if the sequence number has changed, our external message will fail), and then type - -> sendfile wallet-query.boc - -We will see some output: -... external message status is 1 - -which means that the external message has been delivered to the collator pool. Afterwards one of the collators might choose to include this external message in a block, creating a transaction for the test giver smart contract to process this external message. We can check whether the state of the test giver has changed: - -> last -> getaccount kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny - -(If you forget to type `last`, you are likely to see the unchanged state of the test giver smart contract.) The resulting output would be: - ---------------------------------------------- -got account state for -1 : FCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260 with respect to blocks (-1,8000000000000000,2240):18E6DA7707191E76C71EABBC5277650666B7E2CFA2AEF2CE607EAFE8657A3820:4EFA2540C5D1E4A1BA2B529EE0B65415DF46BFFBD27A8EB74C4C0E17770D03B1 -account state is (account - addr:(addr_std - anycast:nothing workchain_id:-1 address:xFCB91A3A3816D0F7B8C2C76108B8A9BC5A6B7A55BD79F8AB101C52DB29232260) - storage_stat:(storage_info - used:(storage_used - cells:(var_uint len:1 value:3) - bits:(var_uint len:2 value:707) - public_cells:(var_uint len:0 value:0)) last_paid:0 - due_payment:nothing) - storage:(account_storage last_trans_lt:10697000003 - balance:(currencies - grams:(nanograms - amount:(var_uint len:7 value:999993280210000)) - other:(extra_currencies - dict:hme_empty)) - state:(account_active - ( - split_depth:nothing - special:nothing - code:(just - value:(raw@^Cell - x{} - x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54} - )) - data:(just - value:(raw@^Cell - x{} - x{00009A16} - )) - library:hme_empty)))) -x{CFF8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D2068086C00000000000000009F65D110DC0E35F450FA914134_} - x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54} - x{00000001} ---------------------------------------------- - -You may notice that the sequence number stored in the persistent data has changed (in our example, to 0x9A16 = 39446), and the last_trans_lt field (the logical time of the last transaction of this account) has been increased. - -Now we can inspect the state of our new smart contract: - -> getaccount 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb -or -> getaccount 0:2ee9b4fd4f077c9b223280c35763df9edab0b41ac20d36f4009677df95c3afe2 -Now we see - ---------------------------------------------- -got account state for 0:2EE9B4FD4F077C9B223280C35763DF9EDAB0B41AC20D36F4009677DF95C3AFE2 with respect to blocks (-1,8000000000000000,16481):890F4D549428B2929F5D5E0C5719FBCDA60B308BA4B907797C9E846E644ADF26:22387176928F7BCEF654411CA820D858D57A10BBF1A0E153E1F77DE2EFB2A3FB and (-1,8000000000000000,16481):890F4D549428B2929F5D5E0C5719FBCDA60B308BA4B907797C9E846E644ADF26:22387176928F7BCEF654411CA820D858D57A10BBF1A0E153E1F77DE2EFB2A3FB -account state is (account - addr:(addr_std - anycast:nothing workchain_id:0 address:x2EE9B4FD4F077C9B223280C35763DF9EDAB0B41AC20D36F4009677DF95C3AFE2) - storage_stat:(storage_info - used:(storage_used - cells:(var_uint len:1 value:1) - bits:(var_uint len:1 value:111) - public_cells:(var_uint len:0 value:0)) last_paid:1553210152 - due_payment:nothing) - storage:(account_storage last_trans_lt:16413000004 - balance:(currencies - grams:(nanograms - amount:(var_uint len:5 value:6666000000)) - other:(extra_currencies - dict:hme_empty)) - state:account_uninit)) -x{CFF60C04141C6A7B96D68615E7A91D265AD0F3A9A922E9AE9C901D4FA83F5D3C0D02025BC2E4A0D9400000000F492A0511406354C5A004_} ---------------------------------------------- - -Our new smart contract has some positive balance (of 6.666 test Grams), but has no code or data (reflected by `state:account_uninit`). - -7. Uploading the code and data of the new smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Now you can finally upload the external message with the StateInit of the new smart contract, containing its code and data: - ---------------------------------------------- -> sendfile my_wallet_name-query.boc -... external message status is 1 -> last -... -> getaccount 0QAu6bT9Twd8myIygMNXY9-e2rC0GsINNvQAlnfflcOv4uVb -... -got account state for 0:2EE9B4FD4F077C9B223280C35763DF9EDAB0B41AC20D36F4009677DF95C3AFE2 with respect to blocks (-1,8000000000000000,16709):D223B25D8D68401B4AA19893C00221CF9AB6B4E5BFECC75FD6048C27E001E0E2:4C184191CE996CF6F91F59CAD9B99B2FD5F3AA6F55B0B6135069AB432264358E and (-1,8000000000000000,16709):D223B25D8D68401B4AA19893C00221CF9AB6B4E5BFECC75FD6048C27E001E0E2:4C184191CE996CF6F91F59CAD9B99B2FD5F3AA6F55B0B6135069AB432264358E -account state is (account - addr:(addr_std - anycast:nothing workchain_id:0 address:x2EE9B4FD4F077C9B223280C35763DF9EDAB0B41AC20D36F4009677DF95C3AFE2) - storage_stat:(storage_info - used:(storage_used - cells:(var_uint len:1 value:3) - bits:(var_uint len:2 value:963) - public_cells:(var_uint len:0 value:0)) last_paid:1553210725 - due_payment:nothing) - storage:(account_storage last_trans_lt:16625000002 - balance:(currencies - grams:(nanograms - amount:(var_uint len:5 value:5983177000)) - other:(extra_currencies - dict:hme_empty)) - state:(account_active - ( - split_depth:nothing - special:nothing - code:(just - value:(raw@^Cell - x{} - x{FF0020DDA4F260810200D71820D70B1FED44D0D7091FD709FFD15112BAF2A122F901541044F910F2A2F80001D7091F3120D74A97D70907D402FB00DED1A4C8CB1FCBFFC9ED54} - )) - data:(just - value:(raw@^Cell - x{} - x{00000001F61CF0BC8E891AD7636E0CD35229D579323AA2DA827EB85D8071407464DC2FA3} - )) - library:hme_empty)))) -x{CFF60C04141C6A7B96D68615E7A91D265AD0F3A9A922E9AE9C901D4FA83F5D3C0D020680F0C2E4A0EB280000000F7BB57909405928024A134_} - x{FF0020DDA4F260810200D71820D70B1FED44D0D7091FD709FFD15112BAF2A122F901541044F910F2A2F80001D7091F3120D74A97D70907D402FB00DED1A4C8CB1FCBFFC9ED54} - x{00000001F61CF0BC8E891AD7636E0CD35229D579323AA2DA827EB85D8071407464DC2FA3} ---------------------------------------------- - -You will see that the smart contract has been initialized using code and data from the StateInit of the external message, and its balance has been slightly decreased because of the processing fees. Now it is up and running, and you can activate it by generating new external messages and uploading them to the TON Blockchain using the "sendfile" command of the Lite Client. - -8. Using the simple wallet smart contract -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Actually, the simple wallet smart contract used in this example can be used to transfer test Grams to any other accounts. It is in this respect similar to the test giver smart contract discussed above, with the difference that it processes only external messages signed by the correct private key (of its owner). In our case, it is the private key saved into the file "my_wallet_name.pk" during the compilation of the smart contract (see Section 3). - -An example of how you might use this smart contract is provided in sample file crypto/smartcont/wallet.fif : - --------------------------------------------------------- -#!/usr/bin/env fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." [-B ] []" cr - ."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file .pk " - ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr 1 halt -} : usage -$# dup 4 < swap 5 > or ' usage if -def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond - @' $# 2- =: $# } if } if - -true constant bounce - -$1 =: file-base -$2 bounce parse-load-address =: bounce 2=: dest_addr -$3 parse-int =: seqno -$4 $>GR =: amount -def? $5 { @' $5 } { "wallet-query" } cond constant savefile - -file-base +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { } cond -constant body-cell - -."Transferring " amount .GR ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."seqno=0x" seqno x. ."bounce=" bounce . cr -."Body of transfer message is " body-cell - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr -------------------------------------- - -You can invoke this script as follows: - -$ fift -I/crypto/fift/lib:/crypto/smartcont -s wallet.fif - -or simply - -$ fift -s wallet.fif - -if you have correctly set up PATH and FIFTPATH. - -For example, - -$ fift -s wallet.fif my_wallet_name kf8Ty2EqAKfAksff0upF1gOptUWRukyI9x5wfgCbh58Pss9j 1 .666 - -Here `my_wallet_name` is the identifier of your wallet used before with new-wallet.fif; the address and the private key of your test wallet will be loaded from files `my_wallet_name.addr` and `my_wallet_name.pk` in the current directory. - -When you run this code (by invoking the Fift interpreter), you create an external message with a destination equal to the address of your wallet smart contract, containing a correct Ed25519 signature, a sequence number, and an enveloped internal message from your wallet smart contract to the smart contract indicated in dest_addr, with an arbitrary value attached and an arbitrary payload. When your smart contract receives and processes this external message, it first checks the signature and the sequence number. If they are correct, it accepts the external message, sends the embedded internal message from itself to the intended destination, and increases the sequence number in its persistent data (this is a simple measure to prevent replay attacks, in case this sample wallet smart contract code ends up used in a real wallet application). - -Of course, a true TON Blockchain wallet application would hide all the intermediate steps explained above. It would first communicate the address of the new smart contract to the user, asking them to transfer some funds to the indicated address (displayed in its non-bounceable user-friendly form) from another wallet or a cryptocurrency exchange, and then would provide a simple interface to display the current balance and to transfer funds to whatever other addresses the user wants. (The aim of this document is to explain how to create new non-trivial smart contracts and experiment with the TON Blockchain Test Network, rather than to explain how one could use the Lite Client instead of a more user-friendly wallet application.) - -One final remark: The above examples used smart contracts in the basic workchain (workchain 0). They would work in exactly the same way in the masterchain (workchain -1), if one passes workchain identifier -1 instead of 0 as the first argument to `new-wallet.fif`. The only difference is that the processing and storage fees in the basic workchain are 100-1000 times lower than in the masterchain. Some smart contracts (such as the validator election smart contract) accept transfers only from masterchain smart contracts, so you'll need a wallet in the masterchain if you wish to make stakes on behalf of your own validator and participate in the elections. diff --git a/submodules/ton/tonlib-src/LGPLv2 b/submodules/ton/tonlib-src/LGPLv2 deleted file mode 100644 index ab2bc125..00000000 --- a/submodules/ton/tonlib-src/LGPLv2 +++ /dev/null @@ -1,18 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ diff --git a/submodules/ton/tonlib-src/LICENSE.LGPL b/submodules/ton/tonlib-src/LICENSE.LGPL deleted file mode 100644 index b482fc4e..00000000 --- a/submodules/ton/tonlib-src/LICENSE.LGPL +++ /dev/null @@ -1,481 +0,0 @@ - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the library, or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link a program with the library, you must provide -complete object files to the recipients so that they can relink them -with the library, after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -General Public License (also called "this License"). Each licensee is -addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also compile or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - c) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - d) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Library General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/submodules/ton/tonlib-src/README b/submodules/ton/tonlib-src/README deleted file mode 100644 index a47456e2..00000000 --- a/submodules/ton/tonlib-src/README +++ /dev/null @@ -1,50 +0,0 @@ -This archive is a distribution of a preliminary version of the TON Blockchain Lite Client along with the relevant portions of the TON Blockchain Library. It is not necessarily representative of the totality of the TON Blockchain code developed so far; rather it is a simplified stable version, containing only those files that are necessary for compiling the Lite Client, and sometimes outdated versions of these files sufficient for this purpose. - -Use this software at your own risk; consult the DISCLAIMER for more information. - -The software is licensed under GNU Lesser General Public License version 2 or later; consult LICENSE.LGPL and LGPL.v2 for more information. If you ever use any of these source files to develop your own versions of this or other software, you must attach a comment with the contents of LGPL.v2 to the beginning of each source file taken from this archive. - -The software is likely to compile and work properly on most Linux systems. It should work on macOS and even Windows; however, we do not guarantee this for this preliminary version. - -BASIC COMPILATION AND INSTALLATION INSTRUCTIONS - -1) Download the newest version of the TON blockchain sources, available at GitHub repository https://github.com/ton-blockchain/ton/ : - -git clone https://github.com/ton-blockchain/ton.git -git submodule update - -The TON Blockchain Test Network is updated quite often, so we cannot guarantee that older versions of the Lite Client will always work. Backward compatibility is not enforced at this development stage. - -2) Install the newest versions of make, cmake (version 3.0.2 or later), OpenSSL (including C header files), and g++ or clang (or another C++14-compatible compiler as appropriate for your operating system). We strongly recommend installing OpenSSL version 1.1.1 or later for better performance, especially if you intend to run a Full Node or a Validator as well. - -3) Suppose that you have fetched the source tree to directory ~/ton, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system: - -cd ~/liteclient-build -cmake ~/ton -cmake --build . --target lite-client - -You might also build some extra utilities useful for smart-contract development: - -cmake --build . --target fift -cmake --build . --target func - -4) Download the newest configuration file from https://test.ton.org/ton-lite-client-test1.config.json : - -wget https://test.ton.org/ton-lite-client-test1.config.json - -5) Run the Lite Client: - -./lite-client/lite-client -C ton-lite-client-test1.config.json - -If everything was installed successfully, the Lite Client will connect to a special server (a full node for the TON Blockchain Test Network #1) and will send some queries to the server. -If you indicate a writeable "database" directory as an extra argument to the client, it will download and save the block and the state corresponding to the newest masterchain block: - -./lite-client/lite-client -C ton-lite-client-test1.config.json -D ~/ton-db-dir - -Basic help info can be obtained by typing "help" into the Lite Client. Type "quit" or press Ctrl-C to exit. - -6) Now you can create new smart contracts, examine the state of existing smart contracts, send external messages to smart contracts and so on. You can also use Fift (if you have compiled it) to compile, execute, and debug your smart contracts locally. - -More details on these activities, including step-by-step instructions for creating a simple wallet smart contract (along with its source code), may be found in the HOWTO file included in this archive. - -7) Some documentation on the TON Blockchain and TON Virtual Machine may be found at the download page https://test.ton.org/download . Be aware that this documentation may not be completely in sync with the version currently employed by the Test Network, because some minor implementation details are likely to be changed during the final development and testing phases. diff --git a/submodules/ton/tonlib-src/adnl/CMakeLists.txt b/submodules/ton/tonlib-src/adnl/CMakeLists.txt deleted file mode 100644 index 06254160..00000000 --- a/submodules/ton/tonlib-src/adnl/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - - -set(ADNL_LITE_SOURCE - adnl-ext-client.cpp - adnl-ext-connection.cpp - adnl-query.cpp - - ${ADNL_LITE_HEADERS} -) - - -add_library(adnllite STATIC ${ADNL_LITE_SOURCE}) - -target_include_directories(adnllite PUBLIC $) -target_link_libraries(adnllite PUBLIC tdactor ton_crypto tl_lite_api tdnet keys ) diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp b/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp deleted file mode 100644 index 9602b521..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl-ext-client.hpp" -#include "adnl-ext-client.h" - -namespace ton { - -namespace adnl { - -void AdnlExtClientImpl::alarm() { - if (is_closing_) { - return; - } - if (conn_.empty() || !conn_.is_alive()) { - next_create_at_ = td::Timestamp::in(10.0); - alarm_timestamp() = next_create_at_; - - auto fd = td::SocketFd::open(dst_addr_); - if (fd.is_error()) { - LOG(INFO) << "failed to connect to " << dst_addr_ << ": " << fd.move_as_error(); - return; - } - - class Cb : public AdnlExtConnection::Callback { - private: - td::actor::ActorId id_; - - public: - void on_ready(td::actor::ActorId conn) { - td::actor::send_closure(id_, &AdnlExtClientImpl::conn_ready, conn); - } - void on_close(td::actor::ActorId conn) { - td::actor::send_closure(id_, &AdnlExtClientImpl::conn_stopped, conn); - } - Cb(td::actor::ActorId id) : id_(id) { - } - }; - - conn_ = td::actor::create_actor(td::actor::ActorOptions().with_name("outconn").with_poll(), - fd.move_as_ok(), std::make_unique(actor_id(this)), dst_, - local_id_, actor_id(this)); - } -} - -void AdnlExtClientImpl::hangup() { - conn_ = {}; - is_closing_ = true; - ref_cnt_--; - for (auto &it : out_queries_) { - td::actor::ActorOwn<>(it.second); // send hangup - } - try_stop(); -} - -void AdnlExtClientImpl::try_stop() { - if (is_closing_ && ref_cnt_ == 0 && out_queries_.empty()) { - stop(); - } -} - -td::Status AdnlOutboundConnection::process_custom_packet(td::BufferSlice &data, bool &processed) { - if (data.size() == 12) { - auto F = fetch_tl_object(data.clone(), true); - if (F.is_ok()) { - processed = true; - return td::Status::OK(); - } - } - if (!local_id_.empty() && nonce_.size() != 0) { - auto F = fetch_tl_object(data.clone(), true); - if (F.is_ok()) { - auto f = F.move_as_ok(); - if (f->nonce_.size() == 0 || f->nonce_.size() > 512) { - return td::Status::Error(ErrorCode::protoviolation, "bad nonce size"); - } - td::SecureString ss{nonce_.size() + f->nonce_.size()}; - ss.as_mutable_slice().copy_from(nonce_.as_slice()); - ss.as_mutable_slice().remove_prefix(nonce_.size()).copy_from(f->nonce_.as_slice()); - - TRY_RESULT(dec, local_id_.create_decryptor()); - TRY_RESULT(B, dec->sign(ss.as_slice())); - - auto obj = - create_tl_object(local_id_.compute_public_key().tl(), std::move(B)); - send(serialize_tl_object(obj, true)); - - nonce_.clear(); - - processed = true; - authorization_complete_ = true; - return td::Status::OK(); - } - } - return td::Status::OK(); -} - -void AdnlOutboundConnection::start_up() { - AdnlExtConnection::start_up(); - auto X = dst_.pubkey().create_encryptor(); - if (X.is_error()) { - LOG(ERROR) << "failed to init encryptor: " << X.move_as_error(); - stop(); - return; - } - auto enc = X.move_as_ok(); - - td::BufferSlice d{256}; - auto id = dst_.compute_short_id(); - auto S = d.as_slice(); - S.copy_from(id.as_slice()); - S.remove_prefix(32); - S.truncate(256 - 64 - 32); - td::Random::secure_bytes(S); - init_crypto(S); - - auto R = enc->encrypt(S); - if (R.is_error()) { - LOG(ERROR) << "failed to encrypt: " << R.move_as_error(); - stop(); - return; - } - auto data = R.move_as_ok(); - LOG_CHECK(data.size() == 256 - 32) << "size=" << data.size(); - S = d.as_slice(); - S.remove_prefix(32); - CHECK(S.size() == data.size()); - S.copy_from(data.as_slice()); - - send_uninit(std::move(d)); - - if (!local_id_.empty()) { - nonce_ = td::SecureString{32}; - td::Random::secure_bytes(nonce_.as_mutable_slice()); - auto obj = create_tl_object(td::BufferSlice{nonce_.as_slice()}); - send(serialize_tl_object(obj, true)); - } -} - -void AdnlExtClientImpl::check_ready(td::Promise promise) { - if (conn_.empty() || !conn_.is_alive()) { - promise.set_error(td::Status::Error(ErrorCode::notready, "not ready")); - return; - } - td::actor::send_closure(td::actor::ActorId{conn_.get()}, &AdnlExtConnection::check_ready_async, - std::move(promise)); -} - -td::actor::ActorOwn AdnlExtClient::create(AdnlNodeIdFull dst, td::IPAddress dst_addr, - std::unique_ptr callback) { - return td::actor::create_actor("extclient", std::move(dst), dst_addr, std::move(callback)); -} - -td::actor::ActorOwn AdnlExtClient::create(AdnlNodeIdFull dst, PrivateKey local_id, - td::IPAddress dst_addr, - std::unique_ptr callback) { - return td::actor::create_actor("extclient", std::move(dst), std::move(local_id), dst_addr, - std::move(callback)); -} - -td::Status AdnlOutboundConnection::process_packet(td::BufferSlice data) { - TRY_RESULT(F, fetch_tl_object(std::move(data), true)); - td::actor::send_closure(ext_client_, &AdnlExtClientImpl::answer_query, F->query_id_, std::move(F->answer_)); - return td::Status::OK(); -} - -void AdnlExtMultiClientImpl::start_up() { - for (auto &id : ids_) { - add_server(id.first, id.second, [](td::Result R) {}); - } - ids_.clear(); -} - -void AdnlExtMultiClientImpl::add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) { - for (auto &c : clients_) { - if (c.second->addr == dst_addr) { - promise.set_error(td::Status::Error(ErrorCode::error, "duplicate ip")); - return; - } - } - - auto g = ++generation_; - auto cli = std::make_unique(AdnlExtClient::create(dst, dst_addr, make_callback(g)), dst, dst_addr, g); - clients_[g] = std::move(cli); -} - -void AdnlExtMultiClientImpl::del_server(td::IPAddress dst_addr, td::Promise promise) { - for (auto &c : clients_) { - if (c.second->addr == dst_addr) { - if (c.second->ready) { - total_ready_--; - if (!total_ready_) { - callback_->on_stop_ready(); - } - } - clients_.erase(c.first); - promise.set_value(td::Unit()); - return; - } - } - promise.set_error(td::Status::Error(ErrorCode::error, "ip not found")); -} - -void AdnlExtMultiClientImpl::send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, - td::Promise promise) { - if (total_ready_ == 0) { - promise.set_error(td::Status::Error(ErrorCode::notready, "conn not ready")); - return; - } - - std::vector vec; - for (auto &c : clients_) { - if (c.second->ready) { - vec.push_back(c.first); - } - } - CHECK(vec.size() == total_ready_); - - auto &c = clients_[vec[td::Random::fast(0, td::narrow_cast(vec.size() - 1))]]; - - td::actor::send_closure(c->client, &AdnlExtClient::send_query, std::move(name), std::move(data), timeout, - std::move(promise)); -} - -void AdnlExtMultiClientImpl::client_ready(td::uint32 idx, bool value) { - auto it = clients_.find(idx); - if (it == clients_.end()) { - return; - } - auto &c = it->second; - if (c->ready == value) { - return; - } - c->ready = value; - if (value) { - total_ready_++; - if (total_ready_ == 1) { - callback_->on_ready(); - } - } else { - total_ready_--; - if (total_ready_ == 0) { - callback_->on_stop_ready(); - } - } -} - -std::unique_ptr AdnlExtMultiClientImpl::make_callback(td::uint32 g) { - class Cb : public Callback { - public: - Cb(td::actor::ActorId id, td::uint32 idx) : id_(id), idx_(idx) { - } - - void on_ready() override { - td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, true); - } - - void on_stop_ready() override { - td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, false); - } - - private: - td::actor::ActorId id_; - td::uint32 idx_; - }; - return std::make_unique(actor_id(this), g); -} - -td::actor::ActorOwn AdnlExtMultiClient::create( - std::vector> ids, std::unique_ptr callback) { - return td::actor::create_actor("extmulticlient", std::move(ids), std::move(callback)); -} - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.h b/submodules/ton/tonlib-src/adnl/adnl-ext-client.h deleted file mode 100644 index b9a5d570..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "adnl-node-id.hpp" -#include "td/utils/port/IPAddress.h" - -namespace ton { - -namespace adnl { - -class AdnlExtClient : public td::actor::Actor { - public: - class Callback { - public: - virtual ~Callback() = default; - virtual void on_ready() = 0; - virtual void on_stop_ready() = 0; - }; - virtual ~AdnlExtClient() = default; - virtual void check_ready(td::Promise promise) = 0; - virtual void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, - td::Promise promise) = 0; - static td::actor::ActorOwn create(AdnlNodeIdFull dst, td::IPAddress dst_addr, - std::unique_ptr callback); - static td::actor::ActorOwn create(AdnlNodeIdFull dst, PrivateKey local_id, td::IPAddress dst_addr, - std::unique_ptr callback); -}; - -class AdnlExtMultiClient : public AdnlExtClient { - public: - virtual void add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) = 0; - virtual void del_server(td::IPAddress dst_addr, td::Promise promise) = 0; - static td::actor::ActorOwn create(std::vector> ids, - std::unique_ptr callback); -}; - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp b/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp deleted file mode 100644 index a4df818e..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "auto/tl/lite_api.h" -#include "adnl-ext-connection.hpp" -#include "tl-utils/lite-utils.hpp" -#include "td/utils/Random.h" -#include "adnl-query.h" -#include "keys/encryptor.h" -#include "adnl-ext-client.h" - -namespace ton { - -namespace adnl { - -class AdnlExtClientImpl; - -class AdnlOutboundConnection : public AdnlExtConnection { - private: - AdnlNodeIdFull dst_; - PrivateKey local_id_; - td::actor::ActorId ext_client_; - td::SecureString nonce_; - bool authorization_complete_ = false; - - public: - AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr callback, AdnlNodeIdFull dst, - td::actor::ActorId ext_client) - : AdnlExtConnection(std::move(fd), std::move(callback), true), dst_(std::move(dst)), ext_client_(ext_client) { - } - AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr callback, AdnlNodeIdFull dst, - PrivateKey local_id, td::actor::ActorId ext_client) - : AdnlExtConnection(std::move(fd), std::move(callback), true) - , dst_(std::move(dst)) - , local_id_(local_id) - , ext_client_(ext_client) { - } - td::Status process_packet(td::BufferSlice data) override; - td::Status process_init_packet(td::BufferSlice data) override { - UNREACHABLE(); - } - td::Status process_custom_packet(td::BufferSlice &data, bool &processed) override; - void start_up() override; - bool authorized() const override { - return local_id_.empty() ? true : authorization_complete_; - } -}; - -class AdnlExtClientImpl : public AdnlExtClient { - public: - AdnlExtClientImpl(AdnlNodeIdFull dst_id, td::IPAddress dst_addr, std::unique_ptr callback) - : dst_(std::move(dst_id)), dst_addr_(dst_addr), callback_(std::move(callback)) { - } - AdnlExtClientImpl(AdnlNodeIdFull dst_id, PrivateKey local_id, td::IPAddress dst_addr, - std::unique_ptr callback) - : dst_(std::move(dst_id)), local_id_(local_id), dst_addr_(dst_addr), callback_(std::move(callback)) { - } - - void start_up() override { - alarm(); - } - void conn_stopped(td::actor::ActorId conn) { - if (!conn_.empty() && conn_.get() == conn) { - callback_->on_stop_ready(); - conn_ = {}; - alarm_timestamp() = next_create_at_; - try_stop(); - } - } - void conn_ready(td::actor::ActorId conn) { - if (!conn_.empty() && conn_.get() == conn) { - callback_->on_ready(); - } - } - void check_ready(td::Promise promise) override; - void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, - td::Promise promise) override { - auto P = [SelfId = actor_id(this)](AdnlQueryId id) { - td::actor::send_closure(SelfId, &AdnlExtClientImpl::destroy_query, id); - }; - auto q_id = generate_next_query_id(); - out_queries_.emplace(q_id, AdnlQuery::create(std::move(promise), std::move(P), name, timeout, q_id)); - if (!conn_.empty()) { - auto obj = create_tl_object(q_id, std::move(data)); - td::actor::send_closure(conn_, &AdnlOutboundConnection::send, serialize_tl_object(obj, true)); - } - } - void destroy_query(AdnlQueryId id) { - out_queries_.erase(id); - try_stop(); - } - void answer_query(AdnlQueryId id, td::BufferSlice data) { - auto it = out_queries_.find(id); - if (it != out_queries_.end()) { - td::actor::send_closure(it->second, &AdnlQuery::result, std::move(data)); - } - } - void alarm() override; - void hangup() override; - AdnlQueryId generate_next_query_id() { - while (true) { - AdnlQueryId q_id = AdnlQuery::random_query_id(); - if (out_queries_.count(q_id) == 0) { - return q_id; - } - } - } - - private: - AdnlNodeIdFull dst_; - PrivateKey local_id_; - td::IPAddress dst_addr_; - - std::unique_ptr callback_; - - td::actor::ActorOwn conn_; - td::Timestamp next_create_at_ = td::Timestamp::now_cached(); - - std::map> out_queries_; - - bool is_closing_{false}; - td::uint32 ref_cnt_{1}; - void try_stop(); -}; - -class AdnlExtMultiClientImpl : public AdnlExtMultiClient { - public: - AdnlExtMultiClientImpl(std::vector> ids, - std::unique_ptr callback) - : ids_(std::move(ids)), callback_(std::move(callback)) { - } - - void start_up() override; - - void add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) override; - void del_server(td::IPAddress dst_addr, td::Promise promise) override; - - void check_ready(td::Promise promise) override { - if (total_ready_ > 0) { - promise.set_value(td::Unit()); - } else { - promise.set_error(td::Status::Error(ErrorCode::notready, "conn not ready")); - } - } - void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, - td::Promise promise) override; - - void client_ready(td::uint32 idx, bool value); - - private: - std::unique_ptr make_callback(td::uint32 g); - - struct Client { - Client(td::actor::ActorOwn client, AdnlNodeIdFull pubkey, td::IPAddress addr, td::uint32 generation) - : client(std::move(client)), pubkey(std::move(pubkey)), addr(addr), generation(generation), ready(false) { - } - td::actor::ActorOwn client; - AdnlNodeIdFull pubkey; - td::IPAddress addr; - td::uint32 generation; - bool ready = false; - }; - td::uint32 total_ready_ = 0; - - td::uint32 generation_ = 0; - std::map> clients_; - - std::vector> ids_; - std::unique_ptr callback_; -}; - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-connection.cpp b/submodules/ton/tonlib-src/adnl/adnl-ext-connection.cpp deleted file mode 100644 index 06926f4d..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-connection.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl-ext-connection.hpp" - -namespace ton { - -namespace adnl { - -void AdnlExtConnection::send_uninit(td::BufferSlice data) { - buffered_fd_.output_buffer().append(std::move(data)); - loop(); -} - -void AdnlExtConnection::send(td::BufferSlice data) { - LOG(DEBUG) << "sending packet of size " << data.size(); - auto data_size = td::narrow_cast(data.size()) + 32 + 32; - if (data_size < 32 || data_size > (1 << 24)) { - LOG(WARNING) << "bad packet size " << data_size; - return; - } - - td::BufferSlice d{data.size() + 4 + 32 + 32}; - auto S = d.as_slice(); - - S.copy_from(td::Slice(reinterpret_cast(&data_size), 4)); - S.remove_prefix(4); - auto Sc = S; - td::Random::secure_bytes(S.copy().truncate(32)); - S.remove_prefix(32); - S.copy_from(data.as_slice()); - S.remove_prefix(data.size()); - - td::sha256(Sc.truncate(32 + data.size()), S); - - td::BufferSlice e{d.size()}; - - out_ctr_.encrypt(d.as_slice(), e.as_slice()); - - buffered_fd_.output_buffer().append(std::move(e)); - loop(); -} - -td::Status AdnlExtConnection::receive(td::ChainBufferReader &input, bool &exit_loop) { - if (stop_read_) { - exit_loop = true; - return td::Status::OK(); - } - if (input.size() > 0) { - received_bytes_ = 1; - } - if (inited_) { - if (!read_len_) { - if (input.size() < 4) { - exit_loop = true; - return td::Status::OK(); - } - - char x[4]; - td::MutableSlice s{x, 4}; - input.advance(4, s); - - td::MutableSlice e{reinterpret_cast(&len_), 4}; - in_ctr_.encrypt(s, e); - LOG(DEBUG) << "len=" << len_; - if (len_ > (1 << 24) || len_ < 32) { - return td::Status::Error("Too big packet"); - } - read_len_ = true; - } - if (input.size() < len_) { - exit_loop = true; - return td::Status::OK(); - } - auto data = input.cut_head(len_).move_as_buffer_slice(); - update_timer(); - - td::BufferSlice dec_data{data.size()}; - in_ctr_.encrypt(data.as_slice(), dec_data.as_slice()); - - exit_loop = false; - read_len_ = false; - len_ = 0; - return receive_packet(std::move(dec_data)); - } else { - if (input.size() < 256) { - exit_loop = true; - return td::Status::OK(); - } - - auto data = input.cut_head(256).move_as_buffer_slice(); - update_timer(); - - exit_loop = false; - return process_init_packet(std::move(data)); - } -} - -void AdnlExtConnection::loop() { - auto status = [&] { - TRY_STATUS(buffered_fd_.flush_read()); - auto &input = buffered_fd_.input_buffer(); - bool exit_loop = false; - while (!exit_loop) { - TRY_STATUS(receive(input, exit_loop)); - } - TRY_STATUS(buffered_fd_.flush_write()); - if (td::can_close(buffered_fd_)) { - stop(); - } - return td::Status::OK(); - }(); - if (status.is_error()) { - LOG(ERROR) << "Client got error " << status; - stop(); - } else { - send_ready(); - } -} - -td::Status AdnlExtConnection::init_crypto(td::Slice S) { - if (S.size() < 96) { - return td::Status::Error(ErrorCode::protoviolation, "too small enc data"); - } - CHECK(S.size() >= 96); - td::SecureString s1(32), s2(32); - td::SecureString v1(16), v2(16); - s1.as_mutable_slice().copy_from(S.copy().truncate(32)); - S.remove_prefix(32); - s2.as_mutable_slice().copy_from(S.copy().truncate(32)); - S.remove_prefix(32); - v1.as_mutable_slice().copy_from(S.copy().truncate(16)); - S.remove_prefix(16); - v2.as_mutable_slice().copy_from(S.copy().truncate(16)); - S.remove_prefix(16); - if (is_client_) { - in_ctr_.init(s1, v1); - out_ctr_.init(s2, v2); - } else { - in_ctr_.init(s2, v2); - out_ctr_.init(s1, v1); - } - inited_ = true; - return td::Status::OK(); -} - -td::Status AdnlExtConnection::receive_packet(td::BufferSlice data) { - LOG(DEBUG) << "received packet of size " << data.size(); - auto S = data.as_slice(); - S.truncate(data.size() - 32); - auto D = data.as_slice(); - D.remove_prefix(data.size() - 32); - - if (td::sha256(S) != D) { - return td::Status::Error(ErrorCode::protoviolation, "sha256 mismatch"); - } - - data.truncate(data.size() - 32); - data.confirm_read(32); - - if (data.size() == 0) { - // keepalive - return td::Status::OK(); - } - - bool processed = false; - TRY_STATUS(process_custom_packet(data, processed)); - if (processed) { - return td::Status::OK(); - } - - return process_packet(std::move(data)); -} - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-connection.hpp b/submodules/ton/tonlib-src/adnl/adnl-ext-connection.hpp deleted file mode 100644 index ce3c29b3..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-connection.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/net/TcpListener.h" -#include "td/utils/crypto.h" -#include "td/utils/BufferedFd.h" -#include "tl-utils/tl-utils.hpp" -#include "td/utils/Random.h" -#include "common/errorcode.h" - -#include -#include - -namespace ton { - -namespace adnl { - -class AdnlExtConnection : public td::actor::Actor, public td::ObserverBase { - public: - class Callback { - public: - virtual ~Callback() = default; - virtual void on_close(td::actor::ActorId conn) = 0; - virtual void on_ready(td::actor::ActorId conn) = 0; - }; - - double timeout() { - return is_client_ ? 20.0 : 60.0; - } - - AdnlExtConnection(td::SocketFd fd, std::unique_ptr callback, bool is_client) - : buffered_fd_(std::move(fd)), callback_(std::move(callback)), is_client_(is_client) { - } - void send(td::BufferSlice data); - void send_uninit(td::BufferSlice data); - td::Status receive(td::ChainBufferReader &input, bool &exit_loop); - virtual td::Status process_packet(td::BufferSlice data) = 0; - td::Status receive_packet(td::BufferSlice data); - virtual td::Status process_custom_packet(td::BufferSlice &data, bool &processed) = 0; - virtual td::Status process_init_packet(td::BufferSlice data) = 0; - virtual bool authorized() const { - return false; - } - td::Status init_crypto(td::Slice data); - void stop_read() { - stop_read_ = true; - } - void resume_read() { - stop_read_ = false; - } - bool check_ready() const { - return received_bytes_ && inited_ && authorized() && !td::can_close(buffered_fd_); - } - void check_ready_async(td::Promise promise) { - if (check_ready()) { - promise.set_value(td::Unit()); - } else { - promise.set_error(td::Status::Error(ErrorCode::notready, "not ready")); - } - } - void send_ready() { - if (check_ready() && !sent_ready_ && callback_) { - callback_->on_ready(actor_id(this)); - sent_ready_ = true; - } - } - - protected: - td::BufferedFd buffered_fd_; - td::actor::ActorId self_; - std::unique_ptr callback_; - bool sent_ready_ = false; - bool is_client_; - - void notify() override { - // NB: Interface will be changed - td::actor::send_closure_later(self_, &AdnlExtConnection::on_net); - } - - void start_up() override { - self_ = actor_id(this); - // Subscribe for socket updates - // NB: Interface will be changed - td::actor::SchedulerContext::get()->get_poll().subscribe(buffered_fd_.get_poll_info().extract_pollable_fd(this), - td::PollFlags::ReadWrite()); - update_timer(); - notify(); - } - - private: - td::AesCtrState in_ctr_; - td::AesCtrState out_ctr_; - bool inited_ = false; - bool stop_read_ = false; - bool read_len_ = false; - td::uint32 len_; - td::uint32 received_bytes_ = 0; - td::Timestamp fail_at_; - td::Timestamp send_ping_at_; - bool ping_sent_ = false; - - void on_net() { - loop(); - } - - void tear_down() override { - if (callback_) { - callback_->on_close(actor_id(this)); - callback_ = nullptr; - } - // unsubscribe from socket updates - // nb: interface will be changed - td::actor::SchedulerContext::get()->get_poll().unsubscribe(buffered_fd_.get_poll_info().get_pollable_fd_ref()); - } - - void update_timer() { - fail_at_ = td::Timestamp::in(timeout()); - alarm_timestamp() = fail_at_; - if (is_client_) { - ping_sent_ = false; - send_ping_at_ = td::Timestamp::in(timeout() / 2); - alarm_timestamp().relax(send_ping_at_); - } - } - - void loop() override; - - void alarm() override { - alarm_timestamp() = fail_at_; - if (fail_at_.is_in_past()) { - stop(); - } else if (is_client_ && !ping_sent_) { - if (send_ping_at_.is_in_past()) { - auto obj = create_tl_object(td::Random::fast_uint64()); - send(serialize_tl_object(obj, true)); - ping_sent_ = true; - } else { - alarm_timestamp().relax(send_ping_at_); - } - } - } -}; - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-node-id.hpp b/submodules/ton/tonlib-src/adnl/adnl-node-id.hpp deleted file mode 100644 index 2d3ade16..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-node-id.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "keys/keys.hpp" -#include "common/io.hpp" - -namespace ton { - -namespace adnl { - -class AdnlNodeIdShort { - public: - explicit AdnlNodeIdShort(const PublicKeyHash &hash) : hash_(hash) { - } - explicit AdnlNodeIdShort(PublicKeyHash &&hash) : hash_(std::move(hash)) { - } - AdnlNodeIdShort() { - } - explicit AdnlNodeIdShort(td::Slice data) : hash_(data) { - } - explicit AdnlNodeIdShort(td::Bits256 value) : hash_(value) { - } - explicit AdnlNodeIdShort(tl_object_ptr obj) : hash_(obj->id_) { - } - - const auto &pubkey_hash() const { - return hash_; - } - - bool operator==(const AdnlNodeIdShort &with) const { - return hash_ == with.hash_; - } - bool operator!=(const AdnlNodeIdShort &with) const { - return hash_ != with.hash_; - } - bool operator<(const AdnlNodeIdShort &with) const { - return hash_ < with.hash_; - } - tl_object_ptr tl() const { - return create_tl_object(hash_.tl()); - } - auto as_slice() { - return hash_.as_slice(); - } - auto as_slice() const { - return hash_.as_slice(); - } - auto uint256_value() const { - return hash_.uint256_value(); - } - auto bits256_value() const { - return hash_.bits256_value(); - } - static AdnlNodeIdShort zero() { - return AdnlNodeIdShort{PublicKeyHash::zero()}; - } - bool is_zero() const { - return hash_.is_zero(); - } - - static td::Result parse(td::Slice key); - - std::string serialize(); - - private: - PublicKeyHash hash_; -}; - -class AdnlNodeIdFull { - private: - explicit AdnlNodeIdFull(const tl_object_ptr &pub) : pub_(pub) { - } - - public: - explicit AdnlNodeIdFull(const PublicKey &pub) : pub_(pub) { - } - explicit AdnlNodeIdFull(PublicKey &&pub) : pub_(std::move(pub)) { - } - static td::Result create(const tl_object_ptr &pub) { - return AdnlNodeIdFull{pub}; - } - AdnlNodeIdFull() { - } - const auto &pubkey() const { - return pub_; - } - bool empty() const { - return pub_.empty(); - } - bool operator==(const AdnlNodeIdFull &with) const { - return pub_ == with.pub_; - } - bool operator!=(const AdnlNodeIdFull &with) const { - return pub_ != with.pub_; - } - auto tl() const { - return pub_.tl(); - } - AdnlNodeIdShort compute_short_id() const { - return AdnlNodeIdShort{pub_.compute_short_id()}; - } - - private: - PublicKey pub_; -}; - -} // namespace adnl - -} // namespace ton - -namespace td { - -inline StringBuilder &operator<<(StringBuilder &stream, const ton::adnl::AdnlNodeIdShort &value) { - return stream << value.bits256_value(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/adnl/adnl-query.cpp b/submodules/ton/tonlib-src/adnl/adnl-query.cpp deleted file mode 100644 index 5bc767d2..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-query.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl-query.h" -#include "common/errorcode.h" -#include "td/utils/Random.h" - -namespace ton { - -namespace adnl { - -void AdnlQuery::alarm() { - promise_.set_error(td::Status::Error(ErrorCode::timeout, "adnl query timeout")); - stop(); -} -void AdnlQuery::result(td::BufferSlice data) { - promise_.set_value(std::move(data)); - stop(); -} - -AdnlQueryId AdnlQuery::random_query_id() { - AdnlQueryId q_id; - td::Random::secure_bytes(q_id.as_slice()); - return q_id; -} - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/adnl/adnl-query.h b/submodules/ton/tonlib-src/adnl/adnl-query.h deleted file mode 100644 index 6e24a49f..00000000 --- a/submodules/ton/tonlib-src/adnl/adnl-query.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" -#include "common/bitstring.h" -#include "common/errorcode.h" -#include "td/utils/buffer.h" - -#include - -namespace ton { - -namespace adnl { - -class AdnlPeerPair; - -using AdnlQueryId = td::Bits256; - -class AdnlQuery : public td::actor::Actor { - public: - static td::actor::ActorId create(td::Promise promise, - std::function destroy, std::string name, - td::Timestamp timeout, AdnlQueryId id) { - return td::actor::create_actor("query", name, std::move(promise), std::move(destroy), timeout, id) - .release(); - } - static AdnlQueryId random_query_id(); - AdnlQuery(std::string name, td::Promise promise, std::function destroy, - td::Timestamp timeout, AdnlQueryId id) - : name_(std::move(name)), timeout_(timeout), promise_(std::move(promise)), destroy_(std::move(destroy)), id_(id) { - } - void alarm() override; - void result(td::BufferSlice data); - void start_up() override { - alarm_timestamp() = timeout_; - } - void tear_down() override { - destroy_(id_); - if (promise_) { - promise_.set_error(td::Status::Error(ErrorCode::cancelled, "Cancelled")); - } - } - - private: - std::string name_; - td::Timestamp timeout_; - td::Promise promise_; - std::function destroy_; - AdnlQueryId id_; -}; - -} // namespace adnl - -} // namespace ton diff --git a/submodules/ton/tonlib-src/common/CMakeLists.txt b/submodules/ton/tonlib-src/common/CMakeLists.txt deleted file mode 100644 index 8fd70f7b..00000000 --- a/submodules/ton/tonlib-src/common/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -set(COMMON_SOURCE - checksum.h - errorcode.h - status.h - io.hpp - - errorlog.h - errorlog.cpp -) - - -add_library(common STATIC ${COMMON_SOURCE}) - -target_include_directories(common PUBLIC - $ - $/.. - ${OPENSSL_INCLUDE_DIR} -) -target_link_libraries(common PRIVATE tdutils ton_crypto ) diff --git a/submodules/ton/tonlib-src/common/checksum.h b/submodules/ton/tonlib-src/common/checksum.h deleted file mode 100644 index ff692239..00000000 --- a/submodules/ton/tonlib-src/common/checksum.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/int_types.h" -#include "crypto/common/bitstring.h" -#include "td/utils/crypto.h" - -namespace td { - -inline Bits256 sha256_bits256(Slice data) { - Bits256 id; - sha256(data, id.as_slice()); - return id; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/common/delay.h b/submodules/ton/tonlib-src/common/delay.h deleted file mode 100644 index 9b98c58e..00000000 --- a/submodules/ton/tonlib-src/common/delay.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" - -namespace ton { - -template -class DelayedAction : public td::actor::Actor { - public: - DelayedAction(T promise) : promise_(std::move(promise)) { - } - void set_timer(td::Timestamp t) { - alarm_timestamp() = t; - } - void alarm() override { - promise_(); - stop(); - } - - static void create(T promise, td::Timestamp t) { - auto A = td::actor::create_actor("delayed", std::move(promise)); - td::actor::send_closure(A, &DelayedAction::set_timer, t); - A.release(); - } - - private: - T promise_; -}; - -template -void delay_action(T promise, td::Timestamp timeout) { - DelayedAction::create(std::move(promise), timeout); -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/common/errorcode.h b/submodules/ton/tonlib-src/common/errorcode.h deleted file mode 100644 index b95e7fc2..00000000 --- a/submodules/ton/tonlib-src/common/errorcode.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace ton { - -enum ErrorCode : int { - failure = 601, - error = 602, - warning = 603, - protoviolation = 621, - notready = 651, - timeout = 652, - cancelled = 653 -}; - -} diff --git a/submodules/ton/tonlib-src/common/errorlog.cpp b/submodules/ton/tonlib-src/common/errorlog.cpp deleted file mode 100644 index a0616698..00000000 --- a/submodules/ton/tonlib-src/common/errorlog.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "errorlog.h" -#include "checksum.h" - -#include "td/utils/port/FileFd.h" -#include "td/utils/filesystem.h" -#include "td/utils/port/path.h" -#include "td/utils/Time.h" - -#include - -namespace ton { - -namespace errorlog { - -td::FileFd fd; -std::mutex init_mutex_; -std::string files_path_; - -void ErrorLog::create(std::string db_root) { - init_mutex_.lock(); - if (!fd.empty()) { - init_mutex_.unlock(); - return; - } - auto path = db_root + "/error"; - td::mkdir(path).ensure(); - files_path_ = path + "/files"; - td::mkdir(files_path_).ensure(); - auto R = td::FileFd::open(path + "/log.txt", - td::FileFd::Flags::Write | td::FileFd::Flags::Append | td::FileFd::Flags::Create); - R.ensure(); - fd = R.move_as_ok(); - init_mutex_.unlock(); -} - -void ErrorLog::log(std::string error) { - error = PSTRING() << "[" << td::Clocks::system() << "] " << error << "\n"; - CHECK(!fd.empty()); - auto s = td::Slice{error}; - while (s.size() > 0) { - auto R = fd.write(s); - R.ensure(); - s.remove_prefix(R.move_as_ok()); - } -} - -void ErrorLog::log_file(td::BufferSlice data) { - auto filename = sha256_bits256(data.as_slice()); - auto path = files_path_ + "/" + filename.to_hex(); - - td::write_file(path, data.as_slice()).ensure(); -} - -} // namespace errorlog - -} // namespace ton diff --git a/submodules/ton/tonlib-src/common/errorlog.h b/submodules/ton/tonlib-src/common/errorlog.h deleted file mode 100644 index 884bfc4d..00000000 --- a/submodules/ton/tonlib-src/common/errorlog.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include "td/utils/buffer.h" - -namespace ton { - -namespace errorlog { - -class ErrorLog { - public: - static void create(std::string db_root); - static void log(std::string error); - static void log_file(td::BufferSlice data); -}; - -} // namespace errorlog - -} // namespace ton diff --git a/submodules/ton/tonlib-src/common/int-to-string.hpp b/submodules/ton/tonlib-src/common/int-to-string.hpp deleted file mode 100644 index 88aecc65..00000000 --- a/submodules/ton/tonlib-src/common/int-to-string.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/int_types.h" -#include "td/utils/Slice.h" - -namespace ton { - -template -typename std::enable_if_t::value, td::MutableSlice> store_int_to_slice(td::MutableSlice S, - const T &v) { - CHECK(S.size() >= sizeof(T)); - S.copy_from(td::Slice(reinterpret_cast(&v), sizeof(T))); - return S.remove_prefix(sizeof(T)); -} - -template -typename std::enable_if_t::value, T> fetch_int_from_slice(td::Slice S) { - CHECK(S.size() >= sizeof(T)); - T v; - td::MutableSlice(reinterpret_cast(&v), sizeof(T)).copy_from(S.truncate(sizeof(T))); - return v; -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/common/io.hpp b/submodules/ton/tonlib-src/common/io.hpp deleted file mode 100644 index e328636f..00000000 --- a/submodules/ton/tonlib-src/common/io.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/misc.h" -#include "td/utils/crypto.h" -#include "td/utils/format.h" -#include "td/utils/base64.h" -#include "tl-utils/tl-utils.hpp" - -#include "common/errorcode.h" -#include "common/status.h" -#include "keys/keys.hpp" - -#include "crypto/common/bitstring.h" - -namespace td { - -template -StringBuilder &operator<<(StringBuilder &stream, const td::BitArray &x) { - return stream << td::base64_encode(as_slice(x)); -} - -inline StringBuilder &operator<<(StringBuilder &stream, const ton::PublicKeyHash &value) { - return stream << value.bits256_value(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/common/status.h b/submodules/ton/tonlib-src/common/status.h deleted file mode 100644 index dacc7ee5..00000000 --- a/submodules/ton/tonlib-src/common/status.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Status.h" - -namespace td { - -inline td::Status status_prefix(td::Status &&status, std::string prefix) { - if (status.is_ok()) { - return std::move(status); - } else { - return td::Status::Error(status.code(), prefix + status.message().str()); - } -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/CMakeLists.txt b/submodules/ton/tonlib-src/crypto/CMakeLists.txt deleted file mode 100644 index d8efc586..00000000 --- a/submodules/ton/tonlib-src/crypto/CMakeLists.txt +++ /dev/null @@ -1,437 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -if (NOT OPENSSL_FOUND) - find_package(OpenSSL REQUIRED) -endif() - -set(TON_CRYPTO_SOURCE - Ed25519.cpp - common/bigint.cpp - common/refcnt.cpp - common/refint.cpp - common/bigexp.cpp - common/bitstring.cpp - common/util.cpp - ellcurve/Ed25519.cpp - ellcurve/Fp25519.cpp - ellcurve/Montgomery.cpp - ellcurve/TwEdwards.cpp - openssl/bignum.cpp - openssl/residue.cpp - openssl/rand.cpp - vm/stack.cpp - vm/atom.cpp - vm/continuation.cpp - vm/dict.cpp - vm/memo.cpp - vm/dispatch.cpp - vm/opctable.cpp - vm/cp0.cpp - vm/stackops.cpp - vm/tupleops.cpp - vm/arithops.cpp - vm/cellops.cpp - vm/contops.cpp - vm/dictops.cpp - vm/debugops.cpp - vm/tonops.cpp - vm/boc.cpp - vm/utils.cpp - vm/vm.cpp - tl/tlblib.cpp - - Ed25519.h - common/AtomicRef.h - common/bigint.hpp - common/bitstring.h - common/refcnt.hpp - common/refint.h - common/bigexp.h - common/util.h - common/linalloc.hpp - common/promiseop.hpp - - ellcurve/Ed25519.h - ellcurve/Fp25519.h - ellcurve/Montgomery.h - ellcurve/TwEdwards.h - - openssl/bignum.h - openssl/digest.hpp - openssl/rand.hpp - openssl/residue.h - - tl/tlbc-aux.h - tl/tlbc-data.h - tl/tlblib.hpp - - vm/arithops.h - vm/atom.h - vm/boc.h - vm/box.hpp - vm/cellops.h - vm/continuation.h - vm/contops.h - vm/cp0.h - vm/debugops.h - vm/dict.h - vm/dictops.h - vm/excno.hpp - vm/fmt.hpp - vm/log.h - vm/memo.h - vm/opctable.h - vm/stack.hpp - vm/stackops.h - vm/tupleops.h - vm/tonops.h - vm/vmstate.h - vm/utils.h - vm/vm.h - - vm/cells.h - vm/cellslice.h - - vm/cells/Cell.cpp - vm/cells/CellBuilder.cpp - vm/cells/CellHash.cpp - vm/cells/CellSlice.cpp - vm/cells/CellString.cpp - vm/cells/CellTraits.cpp - vm/cells/CellUsageTree.cpp - vm/cells/DataCell.cpp - vm/cells/LevelMask.cpp - vm/cells/MerkleProof.cpp - vm/cells/MerkleUpdate.cpp - - vm/cells/Cell.h - vm/cells/CellBuilder.h - vm/cells/CellHash.h - vm/cells/CellSlice.h - vm/cells/CellString.h - vm/cells/CellTraits.h - vm/cells/CellUsageTree.h - vm/cells/CellWithStorage.h - vm/cells/DataCell.h - vm/cells/ExtCell.h - vm/cells/LevelMask.h - vm/cells/MerkleProof.h - vm/cells/MerkleUpdate.h - vm/cells/PrunnedCell.h - vm/cells/UsageCell.h - vm/cells/VirtualCell.h - vm/cells/VirtualizationParameters.h - - vm/db/StaticBagOfCellsDb.h - vm/db/StaticBagOfCellsDb.cpp - - vm/db/BlobView.h - vm/db/BlobView.cpp -) - -set(TON_DB_SOURCE - vm/db/DynamicBagOfCellsDb.cpp - vm/db/CellStorage.cpp - vm/db/TonDb.cpp - - vm/db/DynamicBagOfCellsDb.h - vm/db/CellHashTable.h - vm/db/CellStorage.h - vm/db/TonDb.h -) - -set(FIFT_SOURCE - fift/Dictionary.cpp - fift/Fift.cpp - fift/IntCtx.cpp - fift/SourceLookup.cpp - fift/utils.cpp - fift/words.cpp - - fift/Dictionary.h - fift/Fift.h - fift/IntCtx.h - fift/SourceLookup.h - fift/utils.h - fift/words.h -) - -set(PARSER_SOURCE - parser/srcread.cpp - parser/lexer.cpp - parser/symtable.cpp - - parser/srcread.h - parser/lexer.h - parser/symtable.h -) - -set(FUNC_LIB_SOURCE - func/keywords.cpp - func/unify-types.cpp - func/parse-func.cpp - func/abscode.cpp - func/gen-abscode.cpp - func/analyzer.cpp - func/asmops.cpp - func/builtins.cpp - func/stack-transform.cpp - func/optimize.cpp - func/codegen.cpp -) - -set(TLB_BLOCK_AUTO - ${CMAKE_CURRENT_SOURCE_DIR}/block/block-auto.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/block/block-auto.h -) - -set(BLOCK_SOURCE - block/Binlog.h - block/Binlog.cpp - block/block.cpp - block/block-db.cpp - block/block-parse.cpp - block/check-proof.cpp - block/mc-config.cpp - block/output-queue-merger.cpp - block/transaction.cpp - ${TLB_BLOCK_AUTO} - - block/block-binlog.h - block/block-db-impl.h - block/block-db.h - block/block.h - block/block-parse.h - block/check-proof.h - block/output-queue-merger.h - block/transaction.h -) - -set(SMC_ENVELOPE_SOURCE - smc-envelope/GenericAccount.cpp - smc-envelope/HighloadWallet.cpp - smc-envelope/HighloadWalletV2.cpp - smc-envelope/ManualDns.cpp - smc-envelope/MultisigWallet.cpp - smc-envelope/PaymentChannel.cpp - smc-envelope/SmartContract.cpp - smc-envelope/SmartContractCode.cpp - smc-envelope/TestGiver.cpp - smc-envelope/TestWallet.cpp - smc-envelope/Wallet.cpp - smc-envelope/WalletV3.cpp - - smc-envelope/GenericAccount.h - smc-envelope/HighloadWallet.h - smc-envelope/HighloadWalletV2.h - smc-envelope/ManualDns.h - smc-envelope/MultisigWallet.h - smc-envelope/SmartContract.h - smc-envelope/SmartContractCode.h - smc-envelope/TestGiver.h - smc-envelope/TestWallet.h - smc-envelope/Wallet.h - smc-envelope/WalletInterface.h - smc-envelope/WalletV3.h -) - -set(ED25519_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/Ed25519.cpp - PARENT_SCOPE -) - -set(TONDB_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/test-db.cpp - PARENT_SCOPE -) - -set(CELLS_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/test-cells.cpp - PARENT_SCOPE -) - -set(TONVM_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/vm.cpp - PARENT_SCOPE -) - -set(SMARTCONT_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/test-smartcont.cpp - PARENT_SCOPE -) - -set(FIFT_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/fift.cpp - PARENT_SCOPE -) - -add_library(ton_crypto STATIC ${TON_CRYPTO_SOURCE}) -target_include_directories(ton_crypto PUBLIC $ - $) -target_link_libraries(ton_crypto PUBLIC ${OPENSSL_CRYPTO_LIBRARY} tdutils) -if (NOT WIN32) - target_link_libraries(ton_crypto PUBLIC dl z) -endif() -target_include_directories(ton_crypto SYSTEM PUBLIC $) - -add_library(ton_db STATIC ${TON_DB_SOURCE}) -target_include_directories(ton_db PUBLIC $ - $) -target_link_libraries(ton_db PUBLIC tdutils tddb ton_crypto) - -add_executable(test-ed25519-crypto test/test-ed25519-crypto.cpp) -target_include_directories(test-ed25519-crypto PUBLIC $) -target_link_libraries(test-ed25519-crypto PUBLIC ton_crypto) - -add_library(fift-lib ${FIFT_SOURCE}) -target_include_directories(fift-lib PUBLIC $) -target_link_libraries(fift-lib PUBLIC ton_crypto ton_db tdutils ton_block) -set_target_properties(fift-lib PROPERTIES OUTPUT_NAME fift) - -add_executable(fift fift/fift-main.cpp) -target_link_libraries(fift PUBLIC fift-lib) -if (WINGETOPT_FOUND) - target_link_libraries_system(fift wingetopt) -endif() - -add_library(src_parser ${PARSER_SOURCE}) -target_include_directories(src_parser PUBLIC $) -target_link_libraries(src_parser PUBLIC ton_crypto) - -add_executable(func func/func.cpp ${FUNC_LIB_SOURCE}) -target_include_directories(func PUBLIC $) -target_link_libraries(func PUBLIC ton_crypto src_parser) -if (WINGETOPT_FOUND) - target_link_libraries_system(func wingetopt) -endif() - -add_executable(tlbc tl/tlbc.cpp) -target_include_directories(tlbc PUBLIC $) -target_link_libraries(tlbc PUBLIC ton_crypto src_parser) -if (WINGETOPT_FOUND) - target_link_libraries_system(tlbc wingetopt) -endif() - -add_library(ton_block ${BLOCK_SOURCE}) -target_include_directories(ton_block PUBLIC $ - $ $) -target_link_libraries(ton_block PUBLIC ton_crypto tdutils tdactor tl_api) - -set(TURN_OFF_LSAN cd .) -if (TON_USE_ASAN AND NOT WIN32) - set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0) -endif() - -file(MAKE_DIRECTORY smartcont/auto) -if (NOT CMAKE_CROSSCOMPILING) - set(GENERATE_TLB_CMD tlbc) - add_custom_command( - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/block - COMMAND ${TURN_OFF_LSAN} - COMMAND ${GENERATE_TLB_CMD} -o block-auto -n block::gen -z block.tlb - COMMENT "Generate block tlb source files" - OUTPUT ${TLB_BLOCK_AUTO} - DEPENDS tlbc block/block.tlb - ) - add_custom_target(tlb_generate_block DEPENDS ${TLB_BLOCK_AUTO}) - add_dependencies(ton_block tlb_generate_block) - - add_custom_target(gen_fif ALL) - function(GenFif) - set(options ) - set(oneValueArgs DEST NAME) - set(multiValueArgs SOURCE) - set(FUNC_LIB_SOURCE smartcont/stdlib.fc) - cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - string(REGEX REPLACE "[^0-9a-zA-Z_]" "_" ID ${ARG_DEST}) - set(ARG_DEST_FIF "${ARG_DEST}.fif") - add_custom_command( - COMMENT "Generate ${ARG_DEST_FIF}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND func -PS -o ${ARG_DEST_FIF} ${FUNC_LIB_SOURCE} ${ARG_SOURCE} - MAIN_DEPENDENCY ${ARG_SOURCE} - DEPENDS func ${FUNC_LIB_SOURCE} - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_FIF} - ) - set(ARG_DEST_CPP "${ARG_DEST}.cpp") - add_custom_command( - COMMENT "Generate ${ARG_DEST_CPP}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND fift -Ifift/lib:smartcont -s asm-to-cpp.fif ${ARG_DEST_FIF} ${ARG_DEST_CPP} ${ARG_NAME} - MAIN_DEPENDENCY ${ARG_SOURCE} - DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif fift/lib/Asm.fif - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_CPP} - ) - add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST_FIF} ${ARG_DEST_CPP}) - add_dependencies(gen_fif gen_fif_${ID}) - endfunction() - - GenFif(DEST smartcont/auto/config-code SOURCE smartcont/config-code.fc NAME config) - GenFif(DEST smartcont/auto/wallet-code SOURCE smartcont/wallet-code.fc NAME wallet) - GenFif(DEST smartcont/auto/wallet3-code SOURCE smartcont/wallet3-code.fc NAME wallet3) - GenFif(DEST smartcont/auto/simple-wallet-code SOURCE smartcont/simple-wallet-code.fc NAME simple-wallet) - GenFif(DEST smartcont/auto/highload-wallet-code SOURCE smartcont/highload-wallet-code.fc NAME highload-wallet) - GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highload-wallet-v2) - GenFif(DEST smartcont/auto/elector-code SOURCE smartcont/elector-code.fc NAME elector-code) - GenFif(DEST smartcont/auto/multisig-code SOURCE smartcont/multisig-code.fc NAME multisig) - GenFif(DEST smartcont/auto/restricted-wallet-code SOURCE smartcont/restricted-wallet-code.fc NAME restricted-wallet) - GenFif(DEST smartcont/auto/restricted-wallet2-code SOURCE smartcont/restricted-wallet2-code.fc NAME restricted-wallet2) - GenFif(DEST smartcont/auto/restricted-wallet3-code SOURCE smartcont/restricted-wallet3-code.fc NAME restricted-wallet3) - - GenFif(DEST smartcont/auto/dns-manual-code SOURCE smartcont/dns-manual-code.fc NAME dns-manual) - GenFif(DEST smartcont/auto/dns-auto-code SOURCE smartcont/dns-auto-code.fc NAME dns-auto) - - GenFif(DEST smartcont/auto/payment-channel-code SOURCE smartcont/payment-channel-code.fc NAME payment-channel) - - GenFif(DEST smartcont/auto/simple-wallet-ext-code SOURCE smartcont/simple-wallet-ext-code.fc NAME simple-wallet-ext) -endif() - -add_library(smc-envelope ${SMC_ENVELOPE_SOURCE}) -target_include_directories(smc-envelope PUBLIC $) -target_link_libraries(smc-envelope PUBLIC ton_crypto PRIVATE tdutils ton_block) -if (NOT CMAKE_CROSSCOMPILING) - add_dependencies(smc-envelope gen_fif) -endif() - -add_executable(create-state block/create-state.cpp) -target_include_directories(create-state PUBLIC $ - $) -if (INTERNAL_COMPILE) - target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib) -else() - if (TONLIB_COMPILE) - target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib) - else() - target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block) - endif() -endif() -if (WINGETOPT_FOUND) - target_link_libraries_system(create-state wingetopt) -endif() - -add_executable(dump-block block/dump-block.cpp) -target_include_directories(dump-block PUBLIC $ - $) -target_link_libraries(dump-block PUBLIC ton_crypto fift-lib ton_block) -if (WINGETOPT_FOUND) - target_link_libraries_system(dump-block wingetopt) -endif() - -add_executable(adjust-block block/adjust-block.cpp) -target_include_directories(adjust-block PUBLIC $ - $) -target_link_libraries(adjust-block PUBLIC ton_crypto fift-lib ton_block) -if (WINGETOPT_FOUND) - target_link_libraries_system(dump-block wingetopt) -endif() - -add_executable(test-weight-distr block/test-weight-distr.cpp) -target_include_directories(test-weight-distr PUBLIC $ - $) -target_link_libraries(test-weight-distr PUBLIC ton_crypto fift-lib ton_block) -if (WINGETOPT_FOUND) - target_link_libraries_system(test-weight-distr wingetopt) -endif() - -install(TARGETS fift func RUNTIME DESTINATION bin) -install(DIRECTORY fift/lib/ DESTINATION lib/fift) diff --git a/submodules/ton/tonlib-src/crypto/Ed25519.cpp b/submodules/ton/tonlib-src/crypto/Ed25519.cpp deleted file mode 100644 index c263a0cf..00000000 --- a/submodules/ton/tonlib-src/crypto/Ed25519.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "crypto/Ed25519.h" - -#if TD_HAVE_OPENSSL - -#include - -#if OPENSSL_VERSION_NUMBER >= 0x10101000L && OPENSSL_VERSION_NUMBER != 0x20000000L || defined(OPENSSL_IS_BORINGSSL) - -#include "td/utils/base64.h" -#include "td/utils/BigNum.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/ScopeGuard.h" - -#include -#include -#include - -#else - -#include "crypto/ellcurve/Ed25519.h" - -#endif - -namespace td { - -Ed25519::PublicKey::PublicKey(SecureString octet_string) : octet_string_(std::move(octet_string)) { -} - -SecureString Ed25519::PublicKey::as_octet_string() const { - return octet_string_.copy(); -} - -Ed25519::PrivateKey::PrivateKey(SecureString octet_string) : octet_string_(std::move(octet_string)) { -} - -SecureString Ed25519::PrivateKey::as_octet_string() const { - return octet_string_.copy(); -} - -#if OPENSSL_VERSION_NUMBER >= 0x10101000L && OPENSSL_VERSION_NUMBER != 0x20000000L || defined(OPENSSL_IS_BORINGSSL) - -namespace detail { - -static Result X25519_key_from_PKEY(EVP_PKEY *pkey, bool is_private) { - auto func = is_private ? &EVP_PKEY_get_raw_private_key : &EVP_PKEY_get_raw_public_key; - size_t len = 0; - if (func(pkey, nullptr, &len) == 0) { - return Status::Error("Failed to get raw key length"); - } - CHECK(len == 32); - - SecureString result(len); - if (func(pkey, result.as_mutable_slice().ubegin(), &len) == 0) { - return Status::Error("Failed to get raw key"); - } - return std::move(result); -} - -static EVP_PKEY *X25519_key_to_PKEY(Slice key, bool is_private) { - auto func = is_private ? &EVP_PKEY_new_raw_private_key : &EVP_PKEY_new_raw_public_key; - return func(EVP_PKEY_ED25519, nullptr, key.ubegin(), key.size()); -} - -static Result X25519_pem_from_PKEY(EVP_PKEY *pkey, bool is_private, Slice password) { - BIO *mem_bio = BIO_new(BIO_s_mem()); - SCOPE_EXIT { - BIO_vfree(mem_bio); - }; - if (is_private) { - PEM_write_bio_PrivateKey(mem_bio, pkey, EVP_aes_256_cbc(), const_cast(password.ubegin()), - narrow_cast(password.size()), nullptr, nullptr); - } else { - PEM_write_bio_PUBKEY(mem_bio, pkey); - } - char *data_ptr = nullptr; - auto data_size = BIO_get_mem_data(mem_bio, &data_ptr); - return std::string(data_ptr, data_size); -} - -static int password_cb(char *buf, int size, int rwflag, void *u) { - auto &password = *reinterpret_cast(u); - auto password_size = narrow_cast(password.size()); - if (size < password_size) { - return -1; - } - if (rwflag == 0) { - MutableSlice(buf, size).copy_from(password); - } - return password_size; -} - -static EVP_PKEY *X25519_pem_to_PKEY(Slice pem, Slice password) { - BIO *mem_bio = BIO_new_mem_buf(pem.ubegin(), narrow_cast(pem.size())); - SCOPE_EXIT { - BIO_vfree(mem_bio); - }; - - return PEM_read_bio_PrivateKey(mem_bio, nullptr, password_cb, &password); -} - -} // namespace detail - -Result Ed25519::generate_private_key() { - EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(NID_ED25519, nullptr); - if (pctx == nullptr) { - return Status::Error("Can't create EVP_PKEY_CTX"); - } - SCOPE_EXIT { - EVP_PKEY_CTX_free(pctx); - }; - - if (EVP_PKEY_keygen_init(pctx) <= 0) { - return Status::Error("Can't init keygen"); - } - - EVP_PKEY *pkey = nullptr; - if (EVP_PKEY_keygen(pctx, &pkey) <= 0) { - return Status::Error("Can't generate random private key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey); - }; - - TRY_RESULT(private_key, detail::X25519_key_from_PKEY(pkey, true)); - return std::move(private_key); -} - -Result Ed25519::PrivateKey::get_public_key() const { - auto pkey = detail::X25519_key_to_PKEY(octet_string_, true); - if (pkey == nullptr) { - return Status::Error("Can't import private key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey); - }; - - TRY_RESULT(key, detail::X25519_key_from_PKEY(pkey, false)); - return Ed25519::PublicKey(std::move(key)); -} - -Result Ed25519::PrivateKey::as_pem(Slice password) const { - auto pkey = detail::X25519_key_to_PKEY(octet_string_, true); - if (pkey == nullptr) { - return Status::Error("Can't import private key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey); - }; - - return detail::X25519_pem_from_PKEY(pkey, true, password); -} - -Result Ed25519::PrivateKey::from_pem(Slice pem, Slice password) { - auto pkey = detail::X25519_pem_to_PKEY(pem, password); - if (pkey == nullptr) { - return Status::Error("Can't import private key from pem"); - } - TRY_RESULT(key, detail::X25519_key_from_PKEY(pkey, true)); - return Ed25519::PrivateKey(std::move(key)); -} - -Result Ed25519::PrivateKey::sign(Slice data) const { - auto pkey = detail::X25519_key_to_PKEY(octet_string_, true); - if (pkey == nullptr) { - return Status::Error("Can't import private key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey); - }; - - EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - if (md_ctx == nullptr) { - return Status::Error("Can't create EVP_MD_CTX"); - } - SCOPE_EXIT { - EVP_MD_CTX_free(md_ctx); - }; - - if (EVP_DigestSignInit(md_ctx, nullptr, nullptr, nullptr, pkey) <= 0) { - return Status::Error("Can't init DigestSign"); - } - - SecureString res(64, '\0'); - size_t len = 64; - if (EVP_DigestSign(md_ctx, res.as_mutable_slice().ubegin(), &len, data.ubegin(), data.size()) <= 0) { - return Status::Error("Can't sign data"); - } - return std::move(res); -} - -Status Ed25519::PublicKey::verify_signature(Slice data, Slice signature) const { - auto pkey = detail::X25519_key_to_PKEY(octet_string_, false); - if (pkey == nullptr) { - return Status::Error("Can't import public key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey); - }; - - EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - if (md_ctx == nullptr) { - return Status::Error("Can't create EVP_MD_CTX"); - } - SCOPE_EXIT { - EVP_MD_CTX_free(md_ctx); - }; - - if (EVP_DigestVerifyInit(md_ctx, nullptr, nullptr, nullptr, pkey) <= 0) { - return Status::Error("Can't init DigestVerify"); - } - - if (EVP_DigestVerify(md_ctx, signature.ubegin(), signature.size(), data.ubegin(), data.size())) { - return Status::OK(); - } - return Status::Error("Wrong signature"); -} - -Result Ed25519::compute_shared_secret(const PublicKey &public_key, const PrivateKey &private_key) { - BigNum p = BigNum::from_hex("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed").move_as_ok(); - auto public_y = public_key.as_octet_string(); - public_y.as_mutable_slice()[31] = static_cast(public_y[31] & 127); - BigNum y = BigNum::from_le_binary(public_y); - BigNum y2 = y.clone(); - y += 1; - y2 -= 1; - - BigNumContext context; - - BigNum::mod_sub(y2, p, y2, p, context); - - BigNum inverse_y_plus_1; - BigNum::mod_inverse(inverse_y_plus_1, y2, p, context); - - BigNum u; - BigNum::mod_mul(u, y, inverse_y_plus_1, p, context); - - auto pr_key = private_key.as_octet_string(); - unsigned char buf[64]; - SHA512(Slice(pr_key).ubegin(), 32, buf); - buf[0] &= 248; - buf[31] &= 127; - buf[31] |= 64; - - auto pkey_private = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, nullptr, buf, 32); - if (pkey_private == nullptr) { - return Status::Error("Can't import private key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey_private); - }; - // LOG(ERROR) << buffer_to_hex(Slice(buf, 32)); - - auto pub_key = u.to_le_binary(32); - auto pkey_public = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, nullptr, Slice(pub_key).ubegin(), pub_key.size()); - if (pkey_public == nullptr) { - return Status::Error("Can't import public key"); - } - SCOPE_EXIT { - EVP_PKEY_free(pkey_public); - }; - // LOG(ERROR) << buffer_to_hex(pub_key); - - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey_private, nullptr); - if (ctx == nullptr) { - return Status::Error("Can't create EVP_PKEY_CTX"); - } - SCOPE_EXIT { - EVP_PKEY_CTX_free(ctx); - }; - - if (EVP_PKEY_derive_init(ctx) <= 0) { - return Status::Error("Can't init derive"); - } - if (EVP_PKEY_derive_set_peer(ctx, pkey_public) <= 0) { - return Status::Error("Can't init derive"); - } - - size_t result_len = 0; - if (EVP_PKEY_derive(ctx, nullptr, &result_len) <= 0) { - return Status::Error("Can't get result length"); - } - if (result_len != 32) { - return Status::Error("Unexpected result length"); - } - - SecureString result(result_len, '\0'); - if (EVP_PKEY_derive(ctx, result.as_mutable_slice().ubegin(), &result_len) <= 0) { - return Status::Error("Failed to compute shared secret"); - } - return std::move(result); -} - -int Ed25519::version() { - return OPENSSL_VERSION_NUMBER; -} - -#else - -Result Ed25519::generate_private_key() { - crypto::Ed25519::PrivateKey private_key; - if (!private_key.random_private_key(true)) { - return Status::Error("Can't generate random private key"); - } - SecureString private_key_buf(32); - if (!private_key.export_private_key(private_key_buf.as_mutable_slice())) { - return Status::Error("Failed to export private key"); - } - return PrivateKey(std::move(private_key_buf)); -} - -Result Ed25519::PrivateKey::get_public_key() const { - crypto::Ed25519::PrivateKey private_key; - if (!private_key.import_private_key(Slice(octet_string_).ubegin())) { - return Status::Error("Bad private key"); - } - SecureString public_key(32); - if (!private_key.get_public_key().export_public_key(public_key.as_mutable_slice())) { - return Status::Error("Failed to export public key"); - } - return PublicKey(std::move(public_key)); -} - -Result Ed25519::PrivateKey::as_pem(Slice password) const { - return Status::Error("Not supported"); -} - -Result Ed25519::PrivateKey::from_pem(Slice pem, Slice password) { - return Status::Error("Not supported"); -} - -Result Ed25519::PrivateKey::sign(Slice data) const { - crypto::Ed25519::PrivateKey private_key; - if (!private_key.import_private_key(Slice(octet_string_).ubegin())) { - return Status::Error("Bad private key"); - } - SecureString signature(crypto::Ed25519::sign_bytes, '\0'); - if (!private_key.sign_message(signature.as_mutable_slice(), data)) { - return Status::Error("Failed to sign message"); - } - return std::move(signature); -} - -Status Ed25519::PublicKey::verify_signature(Slice data, Slice signature) const { - if (signature.size() != crypto::Ed25519::sign_bytes) { - return Status::Error("Signature has invalid length"); - } - - crypto::Ed25519::PublicKey public_key; - if (!public_key.import_public_key(Slice(octet_string_).ubegin())) { - return Status::Error("Bad public key"); - } - if (public_key.check_message_signature(signature, data)) { - return Status::OK(); - } - return Status::Error("Wrong signature"); -} - -Result Ed25519::compute_shared_secret(const PublicKey &public_key, const PrivateKey &private_key) { - crypto::Ed25519::PrivateKey tmp_private_key; - if (!tmp_private_key.import_private_key(Slice(private_key.as_octet_string()).ubegin())) { - return Status::Error("Bad private key"); - } - crypto::Ed25519::PublicKey tmp_public_key; - if (!tmp_public_key.import_public_key(Slice(public_key.as_octet_string()).ubegin())) { - return Status::Error("Bad public key"); - } - SecureString shared_secret(32, '\0'); - if (!tmp_private_key.compute_shared_secret(shared_secret.as_mutable_slice(), tmp_public_key)) { - return Status::Error("Failed to compute shared secret"); - } - return std::move(shared_secret); -} - -int Ed25519::version() { - return 0; -} - -#endif - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/crypto/Ed25519.h b/submodules/ton/tonlib-src/crypto/Ed25519.h deleted file mode 100644 index a3340d2e..00000000 --- a/submodules/ton/tonlib-src/crypto/Ed25519.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/SharedSlice.h" -#include "td/utils/Status.h" - -#if TD_HAVE_OPENSSL - -namespace td { - -class Ed25519 { - public: - class PublicKey { - public: - static constexpr size_t LENGTH = 32; - - explicit PublicKey(SecureString octet_string); - - SecureString as_octet_string() const; - - Status verify_signature(Slice data, Slice signature) const; - - private: - SecureString octet_string_; - }; - - class PrivateKey { - public: - static constexpr size_t LENGTH = 32; - - explicit PrivateKey(SecureString octet_string); - - SecureString as_octet_string() const; - - Result get_public_key() const; - - Result sign(Slice data) const; - - Result as_pem(Slice password) const; - - static Result from_pem(Slice pem, Slice password); - - private: - SecureString octet_string_; - }; - - static Result generate_private_key(); - - static Result compute_shared_secret(const PublicKey &public_key, const PrivateKey &private_key); - - static int version(); -}; - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/crypto/block/Binlog.cpp b/submodules/ton/tonlib-src/crypto/block/Binlog.cpp deleted file mode 100644 index b774e693..00000000 --- a/submodules/ton/tonlib-src/crypto/block/Binlog.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "crypto/block/Binlog.h" - -#include "td/utils/as.h" -#include "td/utils/misc.h" -#include "td/utils/port/path.h" - -#include - -namespace block { -/* - * - * GENERIC BINLOG (move to separate file) - * - */ - -BinlogBuffer::BinlogBuffer(std::unique_ptr cb, std::size_t _max_size, td::FileFd fd) - : cb(std::move(cb)) - , need_more_bytes(0) - , eptr(nullptr) - , log_rpos(0) - , log_cpos(0) - , log_wpos(0) - , fd(std::move(fd)) - , replica(false) - , writing(false) - , dirty(false) - , created(false) - , ok(false) { - max_size = _max_size; - start = static_cast(std::malloc(max_size)); - DCHECK(start); - rptr = wptr = cptr = start; - end = start + max_size; -} - -unsigned char* BinlogBuffer::alloc_log_event_force(std::size_t size) { - unsigned char* res = alloc_log_event(size); - if (!res) { - throw LevAllocError{size}; - } - return res; -} - -unsigned char* BinlogBuffer::try_alloc_log_event(std::size_t size) { - if (!eptr) { - if (end - wptr >= (long)size) { - unsigned char* res = wptr; - wptr += size; - log_wpos += size; - return res; - } - eptr = wptr; - wptr = start; - if (rptr == eptr) { - rptr = start; - } - if (cptr == eptr) { - cptr = start; - } - } - if (rptr - wptr > (long)size) { - unsigned char* res = wptr; - wptr += size; - log_wpos += size; - return res; - } - return nullptr; -} - -bool BinlogBuffer::flush(int mode) { - auto r_res = try_flush(mode); - if (r_res.is_ok()) { - return r_res.ok(); - } - std::string msg = PSTRING() << "cannot flush binlog file " << binlog_name << " at position " << log_rpos << " " - << r_res.error(); - LOG(ERROR) << msg; - throw BinlogError{msg}; -} - -td::Result BinlogBuffer::try_flush(int mode) { - LOG(DEBUG) << "in flush: writing=" << writing << " r=" << rptr - start << " c=" << cptr - start - << " w=" << wptr - start << "; rp=" << log_rpos << " cp=" << log_cpos << " wp=" << log_wpos; - if (!writing || rptr == cptr) { - return false; // nothing to flush - } - DCHECK(!fd.empty()); // must have an open binlog file - while (rptr != cptr) { - unsigned char* tptr = (cptr >= rptr ? cptr : eptr); - DCHECK(rptr <= tptr); - auto sz = tptr - rptr; - if (sz) { - LOG(INFO) << "writing " << sz << " bytes to binlog " << binlog_name << " at position " << log_rpos; - TRY_RESULT(res, fd.pwrite(td::Slice(rptr, sz), log_rpos)); - if (static_cast(res) != sz) { - return td::Status::Error(PSLICE() << "written " << res << " bytes instead of " << sz); - } - log_rpos += sz; - rptr += sz; - } - if (rptr == eptr) { - rptr = start; - eptr = nullptr; - } - } - if (mode >= 3) { - LOG(INFO) << "syncing binlog " << binlog_name << " (position " << log_rpos << ")"; - TRY_STATUS(fd.sync()); - } - return true; -} - -unsigned char* BinlogBuffer::alloc_log_event(std::size_t size) { - if (!writing) { - throw BinlogError{"cannot create new binlog event: binlog not open for writing"}; - } - if (size >= max_size || size > max_event_size) { - return nullptr; - } - size = (size + 3) & -4; - unsigned char* res = try_alloc_log_event(size); - if (!res) { - flush(); - return try_alloc_log_event(size); - } else { - return res; - } -} - -bool BinlogBuffer::commit_range(unsigned long long pos_start, unsigned long long pos_end) { - // TODO: make something more clever, with partially committed/uncommitted segments in [cpos..wpos] range - if (pos_start != log_cpos || pos_end < pos_start || pos_end > log_wpos) { - return false; - } - if (!pos_start && pos_end >= pos_start + 4 && td::as(cptr) != 0x0442446b) { - throw BinlogError{"incorrect magic"}; - } - long long size = pos_end - pos_start; - replay_range(cptr, pos_start, pos_end); - log_cpos = pos_end; - cptr += size; - if (eptr && cptr >= eptr) { - cptr -= eptr - start; - } - return true; -} - -bool BinlogBuffer::rollback_range(unsigned long long pos_start, unsigned long long pos_end) { - if (pos_start < log_cpos || pos_end < pos_start || pos_end != log_wpos) { - return false; - } - long long size = pos_end - pos_start; - log_wpos = pos_end; - if (size >= wptr - start) { - wptr -= size; - } else { - DCHECK(eptr); - wptr += eptr - start - size; - } - return true; -} - -void BinlogBuffer::NewBinlogEvent::commit() { - //LOG(DEBUG) << "in NewBinlogEvent::commit (status = " << status << ")"; - if (!(status & 4)) { - throw BinlogError{"cannot commit new binlog event: already committed or rolled back"}; - } - if (!bb.commit_range(pos, pos + size)) { - throw BinlogError{"cannot commit new binlog event: possibly some earlier log events are not committed yet"}; - } - status = 1; - //LOG(DEBUG) << "after NewBinlogEvent::commit (status = " << status << ")"; -} - -void BinlogBuffer::NewBinlogEvent::rollback() { - if (!(status & 4)) { - throw BinlogError{"cannot roll back new binlog event: already committed or rolled back"}; - } - if (!bb.rollback_range(pos, pos + size)) { - throw BinlogError{"cannot roll back new binlog event: possibly some later log event are already committed"}; - } - status = 2; -} - -BinlogBuffer::NewBinlogEvent::~NewBinlogEvent() { - if (status & 4) { - if (status == 5) { - status = 4; - commit(); - } else if (status == 6) { - status = 4; - rollback(); - } else { - LOG(ERROR) << "newly-allocated binlog event is neither committed nor rolled back (automatically rolling back)"; - rollback(); - } - } -} - -void BinlogBuffer::replay_range(unsigned char* ptr, unsigned long long pos_start, unsigned long long pos_end) { - unsigned char* tptr = (ptr <= wptr ? wptr : eptr); - long long avail = tptr - ptr; - while (pos_start < pos_end) { - if (ptr == eptr) { - ptr = start; - tptr = wptr; - avail = tptr - ptr; - if (avail > (long long)(pos_end - pos_start)) { - avail = pos_end - pos_start; - } - } - int res = (avail >= 4 ? cb->replay_log_event(*this, reinterpret_cast(ptr), - td::narrow_cast(avail), pos_start) - : -0x7ffffffc); - if (res <= 0 || res > avail) { - std::ostringstream ss; - ss << "cannot interpret newly-committed binlog event 0x" << std::hex - << (avail >= 4 ? (unsigned)td::as(ptr) : 0u) << std::dec << ": error " << res; - throw BinlogError{ss.str()}; - } - ptr += res; - pos_start += res; - avail -= res; - } -} - -int BinlogBuffer::replay_pending(bool allow_partial) { - if (rptr == cptr) { - return 0; - } - unsigned char* tptr = (rptr <= cptr ? cptr : eptr); - long long avail = tptr - rptr; - DCHECK(tptr && avail >= 0); - while (rptr != cptr) { - int res = (avail >= 4 ? cb->replay_log_event(*this, reinterpret_cast(rptr), - td::narrow_cast(avail), log_rpos) - : -0x7ffffffc); - if (res > 0) { - if (res > avail) { - throw BinlogError{"binlog event used more bytes than available"}; - } - avail -= res; - log_rpos += res; - rptr += res; - if (rptr != eptr) { - continue; - } - rptr = start; - tptr = cptr; - avail = tptr - rptr; - continue; - } - long long prev_need = 0; - while (res < -0x40000000) { - long long need = res - 0x80000000; - need = (need + 3) & -4; - if (need > (long long)max_event_size) { - throw BinlogError{"binlog event requires too many bytes"}; - } - if (need <= avail) { - throw BinlogError{"binlog event requires more bytes, but we already had them"}; - } - if (need <= prev_need) { - throw BinlogError{"binlog event requires more bytes, but we already had them"}; - } - prev_need = need; - long long total_avail = avail + (rptr > cptr ? cptr - start : 0); - if (need > total_avail) { - if (allow_partial) { - need_more_bytes = td::narrow_cast(need - total_avail); - return 2; - } else { - throw BinlogError{"binlog event extends past end of buffer"}; - } - } - if (need <= 1024) { - unsigned char tmp[1024]; - std::memcpy(tmp, rptr, td::narrow_cast(avail)); - std::memcpy(tmp + avail, start, td::narrow_cast(need - avail)); - res = cb->replay_log_event(*this, reinterpret_cast(tmp), td::narrow_cast(need), - log_rpos); - } else { - unsigned char* tmp = static_cast(std::malloc(td::narrow_cast(need))); - std::memcpy(tmp, rptr, td::narrow_cast(avail)); - std::memcpy(tmp + avail, start, td::narrow_cast(need - avail)); - res = cb->replay_log_event(*this, reinterpret_cast(tmp), td::narrow_cast(need), - log_rpos); - std::free(tmp); - } - if (res > need) { - throw BinlogError{"binlog event used more bytes than available"}; - } - } - if (res < 0) { - return res; - } - if (!res) { - throw BinlogError{"unknown error while interpreting binlog event"}; - } - if (res < avail) { - avail -= res; - log_rpos += res; - rptr += res; - continue; - } - DCHECK(eptr); - log_rpos += res; - rptr += res; - rptr = start + (rptr - eptr); - eptr = nullptr; - DCHECK(start <= rptr && rptr <= cptr && cptr <= wptr && wptr <= end); - } - return 1; -} - -BinlogBuffer::~BinlogBuffer() { - if (start) { - if (writing) { - flush(2); - } - std::free(start); - } -} - -td::Status BinlogBuffer::set_binlog(std::string new_binlog_name, int mode) { - if (!binlog_name.empty() || !fd.empty()) { - return td::Status::Error("binlog buffer already attached to a file"); - } - td::int32 flags = td::FileFd::Read; - if ((mode & 1) != 0) { - flags |= td::FileFd::Write; - } - auto r_fd = td::FileFd::open(new_binlog_name, flags, 0640); - if (r_fd.is_error()) { - if (!(~mode & 3)) { - TRY_RESULT(new_fd, td::FileFd::open(new_binlog_name, flags | td::FileFd::CreateNew, 0640)); - fd = std::move(new_fd); - created = true; - } else { - return r_fd.move_as_error(); - } - } else { - fd = r_fd.move_as_ok(); - } - replica = !(mode & 1); - if (!replica) { - TRY_STATUS(fd.lock(td::FileFd::LockFlags::Write, new_binlog_name, 100)); - } - if (created) { - writing = true; - td::Status res; - try { - res = cb->init_new_binlog(*this); - } catch (BinlogBuffer::BinlogError& err) { - res = td::Status::Error(err.msg); - } - if (res.is_error()) { - fd.close(); - td::unlink(new_binlog_name).ignore(); - writing = false; - return res; - } - binlog_name = new_binlog_name; - ok = true; - return td::Status::OK(); - } - binlog_name = new_binlog_name; - auto res = replay_binlog(replica); - if (res.is_error()) { - return res.move_as_error(); - } - if (!replica) { - if (log_rpos != log_wpos || log_rpos != log_cpos || rptr != wptr || rptr != cptr) { - std::string msg = (PSLICE() << "error while interpreting binlog `" << binlog_name << "`: " << log_wpos - log_rpos - << " bytes left uninterpreted at position " << log_rpos << ", truncated binlog?") - .c_str(); - LOG(ERROR) << msg; - return td::Status::Error(msg); - } - //rptr = wptr = cptr = start; - //eptr = nullptr; - LOG(INFO) << "read and interpreted " << res.move_as_ok() << " bytes from binlog `" << binlog_name - << "`, final position " << log_rpos << ", reopening in write mode"; - writing = true; - if (!log_rpos) { - td::Status status; - try { - status = cb->init_new_binlog(*this); - } catch (BinlogBuffer::BinlogError& err) { - status = td::Status::Error(err.msg); - } - if (status.is_error()) { - fd.close(); - td::unlink(new_binlog_name).ignore(); - writing = false; - return status; - } - } - } - ok = true; - return td::Status::OK(); -} - -td::Result BinlogBuffer::replay_binlog(bool allow_partial) { - if (writing) { - return 0; - } - long long total = 0; - while (true) { - auto res = read_file(); - if (res.is_error()) { - return res.move_as_error(); - } - long long sz = res.move_as_ok(); - total += sz; - try { - cptr = wptr; - log_cpos = log_wpos; - if (!log_rpos && rptr == start && wptr >= rptr + 4 && td::as(rptr) != 0x0442446b) { - throw BinlogError{"incorrect magic"}; - } - int r = replay_pending(allow_partial || sz != 0); - if (r < 0 && r >= -0x40000000) { - throw InterpretError{(PSLICE() << "binlog error " << r).c_str()}; - } - } catch (BinlogError err) { - LOG(ERROR) << "error reading binlog " << binlog_name << ": " << err.msg << " at position " << log_rpos; - return td::Status::Error(PSLICE() << "error reading binlog " << binlog_name << ": " << err.msg << " at position " - << log_rpos); - } catch (InterpretError err) { - LOG(ERROR) << "error interpreting binlog " << binlog_name << ": " << err.msg << " at position " << log_rpos; - return td::Status::Error(PSLICE() << "error interpreting binlog " << binlog_name << ": " << err.msg - << " at position " << log_rpos); - } - if (!sz) { - break; - } - }; - return total; -} - -td::Result BinlogBuffer::read_file() { - unsigned char* ptr = wptr; - std::size_t sz = end - wptr; - if (rptr > wptr) { - DCHECK(eptr); - sz = rptr - wptr; - if (sz <= 4) { - return 0; // buffer full - } - sz -= 4; - } else if (!sz) { - DCHECK(!eptr); - if (rptr <= start + 4) { - return 0; // buffer full - } - eptr = end; - ptr = wptr = start; - sz = rptr - start - 4; - } - auto r_res = fd.pread(td::MutableSlice(ptr, sz), log_wpos); - if (r_res.is_error()) { - std::string msg = PSTRING() << "error reading binlog file `" << binlog_name << "` at position " << log_wpos << " : " - << r_res.error(); - LOG(ERROR) << msg; - return td::Status::Error(msg); - } - auto res = r_res.move_as_ok(); - DCHECK(std::size_t(res) <= sz); - LOG(INFO) << "read " << res << " bytes from binlog `" << binlog_name << "` at position " << log_wpos; - log_wpos += res; - wptr += res; - return (int)res; -} -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/Binlog.h b/submodules/ton/tonlib-src/crypto/block/Binlog.h deleted file mode 100644 index 64142fe8..00000000 --- a/submodules/ton/tonlib-src/crypto/block/Binlog.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Status.h" -#include "td/utils/port/FileFd.h" - -namespace block { -/* - * - * BINLOG (BUFFERS) -- move to separate file - * - */ - -class BinlogBuffer; - -class BinlogCallback { - public: - virtual ~BinlogCallback() = default; - virtual td::Status init_new_binlog(BinlogBuffer& bb) = 0; - virtual int replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, unsigned long long pos) = 0; -}; - -class BinlogBuffer { - static constexpr std::size_t max_event_size = 0xfffc; - std::unique_ptr cb; - std::size_t max_size; - std::size_t need_more_bytes; - unsigned char *start, *rptr, *cptr, *wptr, *eptr, *end; - unsigned long long log_rpos, log_cpos, log_wpos; - std::string binlog_name; - td::FileFd fd; - bool replica; - bool writing; - bool dirty; - bool created; - bool ok; - td::Result read_file(); - td::Result replay_binlog(bool allow_partial); - unsigned char* try_alloc_log_event(std::size_t size); - int replay_pending(bool allow_partial = false); - void replay_range(unsigned char* ptr, unsigned long long pos_start, unsigned long long pos_end); - td::Status set_fd(td::FileFd fd); - - public: - struct LevAllocError { - std::size_t size; - explicit LevAllocError(std::size_t _size) : size(_size) { - } - }; - struct InterpretError { - std::string msg; - explicit InterpretError(std::string _msg) : msg(_msg) { - } - }; - struct BinlogError { - std::string msg; - explicit BinlogError(std::string _msg) : msg(_msg) { - } - }; - BinlogBuffer(std::unique_ptr _cb, std::size_t _max_size = (1 << 24), td::FileFd fd = {}); - BinlogBuffer(const BinlogBuffer&) = delete; - BinlogBuffer& operator=(const BinlogBuffer&) = delete; - BinlogBuffer(BinlogBuffer&&) = delete; - BinlogBuffer& operator=(BinlogBuffer&&) = delete; - ~BinlogBuffer(); - td::Status set_binlog(std::string _binlog_name, int mode = 0); - unsigned char* alloc_log_event(std::size_t size); - unsigned char* alloc_log_event_force(std::size_t size); - bool flush(int mode = 0); - td::Result try_flush(int mode); - unsigned long long get_rpos() const { - return log_rpos; - } - // - class NewBinlogEvent { - protected: - BinlogBuffer& bb; - unsigned long long pos; - unsigned size; - int status; - - public: - NewBinlogEvent(BinlogBuffer& _bb, unsigned long long _pos, unsigned _size) - : bb(_bb), pos(_pos), size(_size), status(4) { - } - ~NewBinlogEvent(); - unsigned long long get_log_pos() const { - return pos; - } - void commit(); - void commit_later() { - if (status & 4) { - status = 5; - } - } - void rollback(); - void rollback_later() { - if (status & 4) { - status = 6; - } - }; - }; - template - class NewEvent : public NewBinlogEvent { - T* ptr; - - protected: - friend class BinlogBuffer; - NewEvent(BinlogBuffer& _bb, unsigned long long _pos, unsigned _size, T* _ptr) - : NewBinlogEvent(_bb, _pos, _size), ptr(_ptr) { - } - - public: - T* operator->() const { - return ptr; - } - T& operator*() const { - return *ptr; - } - void commit() { - NewBinlogEvent::commit(); - ptr = nullptr; - } - void rollback() { - NewBinlogEvent::rollback(); - ptr = nullptr; - } - }; - template - NewEvent alloc(Args... args) { - unsigned long long pos = log_wpos; - return NewEvent(*this, pos, sizeof(T), new (alloc_log_event_force(sizeof(T))) T(args...)); - } - - protected: - friend class NewBinlogEvent; - bool commit_range(unsigned long long pos_start, unsigned long long pos_end); - bool rollback_range(unsigned long long pos_start, unsigned long long pos_end); -}; -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/adjust-block.cpp b/submodules/ton/tonlib-src/crypto/block/adjust-block.cpp deleted file mode 100644 index 755d4218..00000000 --- a/submodules/ton/tonlib-src/crypto/block/adjust-block.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "block/block.h" -#include "vm/boc.h" -#include -#include "block-db.h" -#include "block-auto.h" -#include "block-parse.h" -#include "vm/cp0.h" -#include "td/utils/crypto.h" -#include - -using td::Ref; -using namespace std::literals::string_literals; - -int verbosity; - -struct IntError { - std::string err_msg; - IntError(std::string _msg) : err_msg(_msg) { - } - IntError(const char* _msg) : err_msg(_msg) { - } -}; - -int fatal(std::string str) { - std::cerr << "fatal error: " << str << std::endl; - std::exit(2); - return 2; -} - -static inline void fail_unless(td::Status res) { - if (res.is_error()) { - throw IntError{res.to_string()}; - } -} - -td::Ref load_block(std::string filename, ton::BlockIdExt& id) { - std::cerr << "loading block from bag-of-cell file " << filename << std::endl; - auto bytes_res = block::load_binary_file(filename); - if (bytes_res.is_error()) { - throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()}; - } - ton::FileHash fhash; - td::sha256(bytes_res.ok(), fhash.as_slice()); - vm::BagOfCells boc; - auto res = boc.deserialize(bytes_res.move_as_ok()); - if (res.is_error()) { - throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()}; - } - if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) { - throw IntError{"cannot deserialize bag-of-cells"}; - } - auto root = boc.get_root_cell(); - std::vector prev; - ton::BlockIdExt mc_blkid; - bool after_split; - fail_unless(block::unpack_block_prev_blk_try(root, id, prev, mc_blkid, after_split, &id)); - id.file_hash = fhash; - std::cerr << "loaded block " << id.to_str() << std::endl; - return root; -} - -bool save_block(std::string filename, Ref root, ton::BlockIdExt& id) { - std::cerr << "saving block into bag-of-cell file " << filename << std::endl; - if (root.is_null()) { - throw IntError{"new block has no root"}; - } - id.root_hash = root->get_hash().bits(); - auto res = vm::std_boc_serialize(std::move(root), 31); - if (res.is_error()) { - throw IntError{PSTRING() << "cannot serialize modified block as a bag-of-cells: " - << res.move_as_error().to_string()}; - } - auto data = res.move_as_ok(); - td::sha256(data, id.file_hash.as_slice()); - auto res1 = block::save_binary_file(filename, std::move(data)); - if (res1.is_error()) { - throw IntError{PSTRING() << "cannot save file `" << filename << "` : " << res1}; - } - return true; -} - -Ref adjust_block(Ref root, int vseqno_incr, const ton::BlockIdExt& id) { - std::vector prev; - ton::BlockIdExt mc_blkid; - bool after_split; - fail_unless(block::unpack_block_prev_blk_try(root, id, prev, mc_blkid, after_split)); - std::cerr << "unpacked header of block " << id.to_str() << std::endl; - if (!id.is_masterchain()) { - throw IntError{"can modify only masterchain blocks"}; - } - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) { - throw IntError{"cannot unpack block header"}; - } - if (!info.key_block) { - throw IntError{"can modify only key blocks"}; - } - info.vert_seqno_incr = true; - info.vert_seq_no += vseqno_incr; - if (!block::tlb::t_ExtBlkRef.pack_to(info.prev_vert_ref, id, info.end_lt)) { - throw IntError{"cannot pack prev_vert_ref"}; - } - if (!(tlb::pack_cell(blk.info, info) && tlb::pack_cell(root, blk))) { - throw IntError{"cannot pack block header"}; - } - return root; -} - -void usage() { - std::cout << "usage: adjust-block [-i] \n\tor adjust-block -h\n\tAdjusts block " - "loaded from by incrementing vert_seqno by (1 by default)\n"; - std::exit(3); -} - -int main(int argc, char* const argv[]) { - int i, vseqno_incr = 1; - int new_verbosity_level = VERBOSITY_NAME(INFO); - std::string in_fname, out_fname; - while ((i = getopt(argc, argv, "hi:v:")) != -1) { - switch (i) { - case 'h': - usage(); - break; - case 'i': - vseqno_incr = td::to_integer(td::Slice(optarg)); - CHECK(vseqno_incr > 0 && vseqno_incr < 1000); - break; - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer(td::Slice(optarg))); - break; - default: - usage(); - break; - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - if (argc != optind + 2) { - usage(); - return 2; - } - in_fname = argv[optind]; - out_fname = argv[optind + 1]; - try { - ton::BlockIdExt old_id, new_id; - auto root = load_block(in_fname, old_id); - if (root.is_null()) { - return fatal("cannot load BoC from file "s + in_fname); - } - bool ok = block::gen::t_Block.validate_ref(root); - if (!ok) { - return fatal("file `"s + in_fname + " does not contain a valid block"); - } - auto adjusted = adjust_block(root, vseqno_incr, old_id); - if (adjusted.is_null()) { - return fatal("cannot adjust block"); - } - ok = block::gen::t_Block.validate_ref(root); - if (!ok) { - return fatal("modified block is not valid"); - } - new_id = old_id; - if (!save_block(out_fname, adjusted, new_id)) { - return fatal("cannot save modified block to file `"s + out_fname + "`"); - } - std::cout << "old block id: " << old_id.to_str() << std::endl; - std::cout << "new block id: " << new_id.to_str() << std::endl; - } catch (IntError& err) { - std::cerr << "internal error: " << err.err_msg << std::endl; - return 1; - } catch (vm::VmError& err) { - std::cerr << "vm error: " << err.get_msg() << std::endl; - return 1; - } - return 0; -} diff --git a/submodules/ton/tonlib-src/crypto/block/block-auto.cpp b/submodules/ton/tonlib-src/crypto/block/block-auto.cpp deleted file mode 100644 index 9c3c842e..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-auto.cpp +++ /dev/null @@ -1,23793 +0,0 @@ -#include "block-auto.h" -/* - * - * AUTO-GENERATED FROM `block.tlb` - * - */ -// uses built-in type `#` -// uses built-in type `##` -// uses built-in type `#<` -// uses built-in type `#<=` -// uses built-in type `Any` -// uses built-in type `Cell` -// uses built-in type `int` -// uses built-in type `uint` -// uses built-in type `bits` -// uses built-in type `int8` -// uses built-in type `uint8` -// uses built-in type `uint13` -// uses built-in type `uint15` -// uses built-in type `int16` -// uses built-in type `uint16` -// uses built-in type `int32` -// uses built-in type `uint32` -// uses built-in type `uint63` -// uses built-in type `int64` -// uses built-in type `uint64` -// uses built-in type `uint256` -// uses built-in type `int257` -// uses built-in type `bits256` -// uses built-in type `bits512` - -namespace block { - -namespace gen { -using namespace ::tlb; -using td::Ref; -using vm::CellSlice; -using vm::Cell; -using td::RefInt256; - -// -// code for type `Unit` -// - -int Unit::check_tag(const vm::CellSlice& cs) const { - return unit; -} - -bool Unit::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = 0; - return true; -} - -bool Unit::store_enum_from(vm::CellBuilder& cb, int value) const { - return !value; -} - -bool Unit::unpack(vm::CellSlice& cs, Unit::Record& data) const { - return true; -} - -bool Unit::unpack_unit(vm::CellSlice& cs) const { - return true; -} - -bool Unit::cell_unpack(Ref cell_ref, Unit::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Unit::cell_unpack_unit(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_unit(cs) && cs.empty_ext(); -} - -bool Unit::pack(vm::CellBuilder& cb, const Unit::Record& data) const { - return true; -} - -bool Unit::pack_unit(vm::CellBuilder& cb) const { - return true; -} - -bool Unit::cell_pack(Ref& cell_ref, const Unit::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Unit::cell_pack_unit(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_unit(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Unit::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.cons("unit"); -} - -const Unit t_Unit; - -// -// code for type `True` -// - -int True::check_tag(const vm::CellSlice& cs) const { - return true1; -} - -bool True::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = 0; - return true; -} - -bool True::store_enum_from(vm::CellBuilder& cb, int value) const { - return !value; -} - -bool True::unpack(vm::CellSlice& cs, True::Record& data) const { - return true; -} - -bool True::unpack_true1(vm::CellSlice& cs) const { - return true; -} - -bool True::cell_unpack(Ref cell_ref, True::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool True::cell_unpack_true1(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_true1(cs) && cs.empty_ext(); -} - -bool True::pack(vm::CellBuilder& cb, const True::Record& data) const { - return true; -} - -bool True::pack_true1(vm::CellBuilder& cb) const { - return true; -} - -bool True::cell_pack(Ref& cell_ref, const True::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool True::cell_pack_true1(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_true1(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool True::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.cons("true"); -} - -const True t_True; - -// -// code for type `Bool` -// - -int Bool::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bool_false: - return cs.have(1) ? bool_false : -1; - case bool_true: - return cs.have(1) ? bool_true : -1; - } - return -1; -} - -bool Bool::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = (char)cs.fetch_ulong(1); - return value >= 0; -} - -bool Bool::store_enum_from(vm::CellBuilder& cb, int value) const { - return cb.store_long_rchk_bool(value, 1); -} - -bool Bool::unpack(vm::CellSlice& cs, Bool::Record_bool_false& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool Bool::unpack_bool_false(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool Bool::cell_unpack(Ref cell_ref, Bool::Record_bool_false& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Bool::cell_unpack_bool_false(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bool_false(cs) && cs.empty_ext(); -} - -bool Bool::unpack(vm::CellSlice& cs, Bool::Record_bool_true& data) const { - return cs.fetch_ulong(1) == 1; -} - -bool Bool::unpack_bool_true(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 1; -} - -bool Bool::cell_unpack(Ref cell_ref, Bool::Record_bool_true& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Bool::cell_unpack_bool_true(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bool_true(cs) && cs.empty_ext(); -} - -bool Bool::pack(vm::CellBuilder& cb, const Bool::Record_bool_false& data) const { - return cb.store_long_bool(0, 1); -} - -bool Bool::pack_bool_false(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool Bool::cell_pack(Ref& cell_ref, const Bool::Record_bool_false& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Bool::cell_pack_bool_false(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_bool_false(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Bool::pack(vm::CellBuilder& cb, const Bool::Record_bool_true& data) const { - return cb.store_long_bool(1, 1); -} - -bool Bool::pack_bool_true(vm::CellBuilder& cb) const { - return cb.store_long_bool(1, 1); -} - -bool Bool::cell_pack(Ref& cell_ref, const Bool::Record_bool_true& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Bool::cell_pack_bool_true(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_bool_true(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Bool::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bool_false: - return cs.advance(1) - && pp.cons("bool_false"); - case bool_true: - return cs.advance(1) - && pp.cons("bool_true"); - } - return pp.fail("unknown constructor for Bool"); -} - -const Bool t_Bool; - -// -// code for type `BoolFalse` -// - -int BoolFalse::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(1) == 0 ? bool_false : -1; -} - -bool BoolFalse::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(1) == 0; -} - -bool BoolFalse::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = (cs.fetch_ulong(1) == 0) ? 0 : -1; - return !value; -} - -bool BoolFalse::store_enum_from(vm::CellBuilder& cb, int value) const { - return !value && cb.store_long_bool(0, 1); -} - -bool BoolFalse::unpack(vm::CellSlice& cs, BoolFalse::Record& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool BoolFalse::unpack_bool_false(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool BoolFalse::cell_unpack(Ref cell_ref, BoolFalse::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BoolFalse::cell_unpack_bool_false(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bool_false(cs) && cs.empty_ext(); -} - -bool BoolFalse::pack(vm::CellBuilder& cb, const BoolFalse::Record& data) const { - return cb.store_long_bool(0, 1); -} - -bool BoolFalse::pack_bool_false(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool BoolFalse::cell_pack(Ref& cell_ref, const BoolFalse::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BoolFalse::cell_pack_bool_false(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_bool_false(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool BoolFalse::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0 - && pp.cons("bool_false"); -} - -const BoolFalse t_BoolFalse; - -// -// code for type `BoolTrue` -// -constexpr unsigned char BoolTrue::cons_tag[1]; - -int BoolTrue::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(1) == 1 ? bool_true : -1; -} - -bool BoolTrue::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(1) == 1; -} - -bool BoolTrue::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = (cs.fetch_ulong(1) == 1) ? 0 : -1; - return !value; -} - -bool BoolTrue::store_enum_from(vm::CellBuilder& cb, int value) const { - return !value && cb.store_long_bool(1, 1); -} - -bool BoolTrue::unpack(vm::CellSlice& cs, BoolTrue::Record& data) const { - return cs.fetch_ulong(1) == 1; -} - -bool BoolTrue::unpack_bool_true(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 1; -} - -bool BoolTrue::cell_unpack(Ref cell_ref, BoolTrue::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BoolTrue::cell_unpack_bool_true(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bool_true(cs) && cs.empty_ext(); -} - -bool BoolTrue::pack(vm::CellBuilder& cb, const BoolTrue::Record& data) const { - return cb.store_long_bool(1, 1); -} - -bool BoolTrue::pack_bool_true(vm::CellBuilder& cb) const { - return cb.store_long_bool(1, 1); -} - -bool BoolTrue::cell_pack(Ref& cell_ref, const BoolTrue::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BoolTrue::cell_pack_bool_true(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_bool_true(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool BoolTrue::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 1 - && pp.cons("bool_true"); -} - -const BoolTrue t_BoolTrue; - -// -// code for type `Maybe` -// - -int Maybe::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case nothing: - return cs.have(1) ? nothing : -1; - case just: - return cs.have(1) ? just : -1; - } - return -1; -} - -bool Maybe::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case nothing: - return cs.advance(1); - case just: - return cs.advance(1) - && X_.skip(cs); - } - return false; -} - -bool Maybe::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case nothing: - return cs.advance(1); - case just: - return cs.advance(1) - && X_.validate_skip(ops, cs, weak); - } - return false; -} - -bool Maybe::unpack(vm::CellSlice& cs, Maybe::Record_nothing& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool Maybe::unpack_nothing(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool Maybe::cell_unpack(Ref cell_ref, Maybe::Record_nothing& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Maybe::cell_unpack_nothing(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_nothing(cs) && cs.empty_ext(); -} - -bool Maybe::unpack(vm::CellSlice& cs, Maybe::Record_just& data) const { - return cs.fetch_ulong(1) == 1 - && X_.fetch_to(cs, data.value); -} - -bool Maybe::unpack_just(vm::CellSlice& cs, Ref& value) const { - return cs.fetch_ulong(1) == 1 - && X_.fetch_to(cs, value); -} - -bool Maybe::cell_unpack(Ref cell_ref, Maybe::Record_just& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Maybe::cell_unpack_just(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_just(cs, value) && cs.empty_ext(); -} - -bool Maybe::pack(vm::CellBuilder& cb, const Maybe::Record_nothing& data) const { - return cb.store_long_bool(0, 1); -} - -bool Maybe::pack_nothing(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool Maybe::cell_pack(Ref& cell_ref, const Maybe::Record_nothing& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Maybe::cell_pack_nothing(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_nothing(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Maybe::pack(vm::CellBuilder& cb, const Maybe::Record_just& data) const { - return cb.store_long_bool(1, 1) - && X_.store_from(cb, data.value); -} - -bool Maybe::pack_just(vm::CellBuilder& cb, Ref value) const { - return cb.store_long_bool(1, 1) - && X_.store_from(cb, value); -} - -bool Maybe::cell_pack(Ref& cell_ref, const Maybe::Record_just& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Maybe::cell_pack_just(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_just(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool Maybe::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case nothing: - return cs.advance(1) - && pp.cons("nothing"); - case just: - return cs.advance(1) - && pp.open("just") - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for Maybe"); -} - - -// -// code for type `Either` -// - -int Either::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case left: - return cs.have(1) ? left : -1; - case right: - return cs.have(1) ? right : -1; - } - return -1; -} - -bool Either::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case left: - return cs.advance(1) - && X_.skip(cs); - case right: - return cs.advance(1) - && Y_.skip(cs); - } - return false; -} - -bool Either::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case left: - return cs.advance(1) - && X_.validate_skip(ops, cs, weak); - case right: - return cs.advance(1) - && Y_.validate_skip(ops, cs, weak); - } - return false; -} - -bool Either::unpack(vm::CellSlice& cs, Either::Record_left& data) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, data.value); -} - -bool Either::unpack_left(vm::CellSlice& cs, Ref& value) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, value); -} - -bool Either::cell_unpack(Ref cell_ref, Either::Record_left& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Either::cell_unpack_left(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_left(cs, value) && cs.empty_ext(); -} - -bool Either::unpack(vm::CellSlice& cs, Either::Record_right& data) const { - return cs.fetch_ulong(1) == 1 - && Y_.fetch_to(cs, data.value); -} - -bool Either::unpack_right(vm::CellSlice& cs, Ref& value) const { - return cs.fetch_ulong(1) == 1 - && Y_.fetch_to(cs, value); -} - -bool Either::cell_unpack(Ref cell_ref, Either::Record_right& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Either::cell_unpack_right(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_right(cs, value) && cs.empty_ext(); -} - -bool Either::pack(vm::CellBuilder& cb, const Either::Record_left& data) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, data.value); -} - -bool Either::pack_left(vm::CellBuilder& cb, Ref value) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, value); -} - -bool Either::cell_pack(Ref& cell_ref, const Either::Record_left& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Either::cell_pack_left(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_left(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool Either::pack(vm::CellBuilder& cb, const Either::Record_right& data) const { - return cb.store_long_bool(1, 1) - && Y_.store_from(cb, data.value); -} - -bool Either::pack_right(vm::CellBuilder& cb, Ref value) const { - return cb.store_long_bool(1, 1) - && Y_.store_from(cb, value); -} - -bool Either::cell_pack(Ref& cell_ref, const Either::Record_right& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Either::cell_pack_right(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_right(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool Either::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case left: - return cs.advance(1) - && pp.open("left") - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - case right: - return cs.advance(1) - && pp.open("right") - && pp.field("value") - && Y_.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for Either"); -} - - -// -// code for type `Both` -// - -int Both::check_tag(const vm::CellSlice& cs) const { - return pair; -} - -bool Both::skip(vm::CellSlice& cs) const { - return X_.skip(cs) - && Y_.skip(cs); -} - -bool Both::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return X_.validate_skip(ops, cs, weak) - && Y_.validate_skip(ops, cs, weak); -} - -bool Both::unpack(vm::CellSlice& cs, Both::Record& data) const { - return X_.fetch_to(cs, data.first) - && Y_.fetch_to(cs, data.second); -} - -bool Both::unpack_pair(vm::CellSlice& cs, Ref& first, Ref& second) const { - return X_.fetch_to(cs, first) - && Y_.fetch_to(cs, second); -} - -bool Both::cell_unpack(Ref cell_ref, Both::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Both::cell_unpack_pair(Ref cell_ref, Ref& first, Ref& second) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_pair(cs, first, second) && cs.empty_ext(); -} - -bool Both::pack(vm::CellBuilder& cb, const Both::Record& data) const { - return X_.store_from(cb, data.first) - && Y_.store_from(cb, data.second); -} - -bool Both::pack_pair(vm::CellBuilder& cb, Ref first, Ref second) const { - return X_.store_from(cb, first) - && Y_.store_from(cb, second); -} - -bool Both::cell_pack(Ref& cell_ref, const Both::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Both::cell_pack_pair(Ref& cell_ref, Ref first, Ref second) const { - vm::CellBuilder cb; - return pack_pair(cb, std::move(first), std::move(second)) && std::move(cb).finalize_to(cell_ref); -} - -bool Both::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("pair") - && pp.field("first") - && X_.print_skip(pp, cs) - && pp.field("second") - && Y_.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `Bit` -// - -int Bit::check_tag(const vm::CellSlice& cs) const { - return bit; -} - -bool Bit::unpack(vm::CellSlice& cs, Bit::Record& data) const { - return cs.fetch_bool_to(data.x); -} - -bool Bit::unpack_bit(vm::CellSlice& cs, bool& x) const { - return cs.fetch_bool_to(x); -} - -bool Bit::cell_unpack(Ref cell_ref, Bit::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Bit::cell_unpack_bit(Ref cell_ref, bool& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bit(cs, x) && cs.empty_ext(); -} - -bool Bit::pack(vm::CellBuilder& cb, const Bit::Record& data) const { - return cb.store_ulong_rchk_bool(data.x, 1); -} - -bool Bit::pack_bit(vm::CellBuilder& cb, bool x) const { - return cb.store_ulong_rchk_bool(x, 1); -} - -bool Bit::cell_pack(Ref& cell_ref, const Bit::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Bit::cell_pack_bit(Ref& cell_ref, bool x) const { - vm::CellBuilder cb; - return pack_bit(cb, x) && std::move(cb).finalize_to(cell_ref); -} - -bool Bit::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int t1; - return pp.open("bit") - && cs.fetch_bool_to(t1) - && pp.field_int(t1) - && pp.close(); -} - -const Bit t_Bit; - -// -// code for type `Hashmap` -// - -int Hashmap::check_tag(const vm::CellSlice& cs) const { - return hm_edge; -} - -bool Hashmap::skip(vm::CellSlice& cs) const { - int l, m; - return HmLabel{m_}.skip(cs, l) - && add_r1(m, l, m_) - && HashmapNode{m, X_}.skip(cs); -} - -bool Hashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l, m; - return HmLabel{m_}.validate_skip(ops, cs, weak, l) - && add_r1(m, l, m_) - && HashmapNode{m, X_}.validate_skip(ops, cs, weak); -} - -bool Hashmap::unpack(vm::CellSlice& cs, Hashmap::Record& data) const { - return (data.n = m_) >= 0 - && HmLabel{m_}.fetch_to(cs, data.label, data.l) - && add_r1(data.m, data.l, m_) - && HashmapNode{data.m, X_}.fetch_to(cs, data.node); -} - -bool Hashmap::cell_unpack(Ref cell_ref, Hashmap::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Hashmap::pack(vm::CellBuilder& cb, const Hashmap::Record& data) const { - int l, m; - return tlb::store_from(cb, HmLabel{m_}, data.label, l) - && add_r1(m, l, m_) - && HashmapNode{m, X_}.store_from(cb, data.node); -} - -bool Hashmap::cell_pack(Ref& cell_ref, const Hashmap::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Hashmap::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int l, m; - return pp.open("hm_edge") - && pp.field("label") - && HmLabel{m_}.print_skip(pp, cs, l) - && add_r1(m, l, m_) - && pp.field("node") - && HashmapNode{m, X_}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `HashmapNode` -// - -int HashmapNode::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 2 2 - return m_ ? hmn_fork : hmn_leaf; -} - -int HashmapNode::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hmn_leaf: - return hmn_leaf; - case hmn_fork: - return hmn_fork; - } - return -1; -} - -bool HashmapNode::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hmn_leaf: - return m_ == 0 - && X_.skip(cs); - case hmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(2); - } - } - return false; -} - -bool HashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case hmn_leaf: - return m_ == 0 - && X_.validate_skip(ops, cs, weak); - case hmn_fork: { - int n; - return add_r1(n, 1, m_) - && Hashmap{n, X_}.validate_skip_ref(ops, cs, weak) - && Hashmap{n, X_}.validate_skip_ref(ops, cs, weak); - } - } - return false; -} - -bool HashmapNode::unpack(vm::CellSlice& cs, HashmapNode::Record_hmn_leaf& data) const { - return m_ == 0 - && X_.fetch_to(cs, data.value); -} - -bool HashmapNode::unpack_hmn_leaf(vm::CellSlice& cs, Ref& value) const { - return m_ == 0 - && X_.fetch_to(cs, value); -} - -bool HashmapNode::cell_unpack(Ref cell_ref, HashmapNode::Record_hmn_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapNode::cell_unpack_hmn_leaf(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hmn_leaf(cs, value) && cs.empty_ext(); -} - -bool HashmapNode::unpack(vm::CellSlice& cs, HashmapNode::Record_hmn_fork& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right); -} - -bool HashmapNode::unpack_hmn_fork(vm::CellSlice& cs, int& n, Ref& left, Ref& right) const { - return add_r1(n, 1, m_) - && cs.fetch_ref_to(left) - && cs.fetch_ref_to(right); -} - -bool HashmapNode::cell_unpack(Ref cell_ref, HashmapNode::Record_hmn_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapNode::cell_unpack_hmn_fork(Ref cell_ref, int& n, Ref& left, Ref& right) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hmn_fork(cs, n, left, right) && cs.empty_ext(); -} - -bool HashmapNode::pack(vm::CellBuilder& cb, const HashmapNode::Record_hmn_leaf& data) const { - return m_ == 0 - && X_.store_from(cb, data.value); -} - -bool HashmapNode::pack_hmn_leaf(vm::CellBuilder& cb, Ref value) const { - return m_ == 0 - && X_.store_from(cb, value); -} - -bool HashmapNode::cell_pack(Ref& cell_ref, const HashmapNode::Record_hmn_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapNode::cell_pack_hmn_leaf(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_hmn_leaf(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapNode::pack(vm::CellBuilder& cb, const HashmapNode::Record_hmn_fork& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right); -} - -bool HashmapNode::pack_hmn_fork(vm::CellBuilder& cb, Ref left, Ref right) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(left) - && cb.store_ref_bool(right); -} - -bool HashmapNode::cell_pack(Ref& cell_ref, const HashmapNode::Record_hmn_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapNode::cell_pack_hmn_fork(Ref& cell_ref, Ref left, Ref right) const { - vm::CellBuilder cb; - return pack_hmn_fork(cb, std::move(left), std::move(right)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapNode::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hmn_leaf: - return pp.open("hmn_leaf") - && m_ == 0 - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - case hmn_fork: { - int n; - return pp.open("hmn_fork") - && add_r1(n, 1, m_) - && pp.field("left") - && Hashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && Hashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - } - return pp.fail("unknown constructor for HashmapNode"); -} - - -// -// code for type `HmLabel` -// -constexpr char HmLabel::cons_len[3]; -constexpr unsigned char HmLabel::cons_tag[3]; - -int HmLabel::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hml_short: - return cs.have(1) ? hml_short : -1; - case hml_long: - return cs.have(2) ? hml_long : -1; - case hml_same: - return cs.have(2) ? hml_same : -1; - } - return -1; -} - -bool HmLabel::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hml_short: { - int m_; - return cs.advance(1) - && t_Unary.skip(cs, m_) - && m_ <= n_ - && cs.advance(m_); - } - case hml_long: { - int m_; - return cs.advance(2) - && cs.fetch_uint_leq(n_, m_) - && cs.advance(m_); - } - case hml_same: { - int m_; - return cs.advance(3) - && cs.fetch_uint_leq(n_, m_); - } - } - return false; -} - -bool HmLabel::skip(vm::CellSlice& cs, int& m_) const { - switch (get_tag(cs)) { - case hml_short: - return cs.advance(1) - && t_Unary.skip(cs, m_) - && m_ <= n_ - && cs.advance(m_); - case hml_long: - return cs.advance(2) - && cs.fetch_uint_leq(n_, m_) - && cs.advance(m_); - case hml_same: - return cs.advance(3) - && cs.fetch_uint_leq(n_, m_); - } - return false; -} - -bool HmLabel::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case hml_short: { - int m_; - return cs.advance(1) - && t_Unary.validate_skip(ops, cs, weak, m_) - && m_ <= n_ - && cs.advance(m_); - } - case hml_long: { - int m_; - return cs.advance(2) - && cs.fetch_uint_leq(n_, m_) - && cs.advance(m_); - } - case hml_same: { - int m_; - return cs.advance(3) - && cs.fetch_uint_leq(n_, m_); - } - } - return false; -} - -bool HmLabel::validate_skip(int* ops, vm::CellSlice& cs, bool weak, int& m_) const { - switch (get_tag(cs)) { - case hml_short: - return cs.advance(1) - && t_Unary.validate_skip(ops, cs, weak, m_) - && m_ <= n_ - && cs.advance(m_); - case hml_long: - return cs.advance(2) - && cs.fetch_uint_leq(n_, m_) - && cs.advance(m_); - case hml_same: - return cs.advance(3) - && cs.fetch_uint_leq(n_, m_); - } - return false; -} - -bool HmLabel::fetch_to(vm::CellSlice& cs, Ref& res, int& m_) const { - res = Ref{true, cs}; - return skip(cs, m_) && res.unique_write().cut_tail(cs); -} - -bool HmLabel::unpack(vm::CellSlice& cs, HmLabel::Record_hml_short& data, int& m_) const { - return cs.fetch_ulong(1) == 0 - && (data.m = n_) >= 0 - && t_Unary.fetch_to(cs, data.len, data.n) - && data.n <= n_ - && cs.fetch_bitstring_to(data.n, data.s) - && (m_ = data.n) >= 0; -} - -bool HmLabel::cell_unpack(Ref cell_ref, HmLabel::Record_hml_short& data, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data, m_) && cs.empty_ext(); -} - -bool HmLabel::unpack(vm::CellSlice& cs, HmLabel::Record_hml_long& data, int& m_) const { - return cs.fetch_ulong(2) == 2 - && (data.m = n_) >= 0 - && cs.fetch_uint_leq(n_, data.n) - && cs.fetch_bitstring_to(data.n, data.s) - && (m_ = data.n) >= 0; -} - -bool HmLabel::unpack_hml_long(vm::CellSlice& cs, int& m, int& n, Ref& s, int& m_) const { - return cs.fetch_ulong(2) == 2 - && (m = n_) >= 0 - && cs.fetch_uint_leq(n_, n) - && cs.fetch_bitstring_to(n, s) - && (m_ = n) >= 0; -} - -bool HmLabel::cell_unpack(Ref cell_ref, HmLabel::Record_hml_long& data, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data, m_) && cs.empty_ext(); -} - -bool HmLabel::cell_unpack_hml_long(Ref cell_ref, int& m, int& n, Ref& s, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hml_long(cs, m, n, s, m_) && cs.empty_ext(); -} - -bool HmLabel::unpack(vm::CellSlice& cs, HmLabel::Record_hml_same& data, int& m_) const { - return cs.fetch_ulong(2) == 3 - && (data.m = n_) >= 0 - && cs.fetch_bool_to(data.v) - && cs.fetch_uint_leq(n_, data.n) - && (m_ = data.n) >= 0; -} - -bool HmLabel::unpack_hml_same(vm::CellSlice& cs, int& m, bool& v, int& n, int& m_) const { - return cs.fetch_ulong(2) == 3 - && (m = n_) >= 0 - && cs.fetch_bool_to(v) - && cs.fetch_uint_leq(n_, n) - && (m_ = n) >= 0; -} - -bool HmLabel::cell_unpack(Ref cell_ref, HmLabel::Record_hml_same& data, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data, m_) && cs.empty_ext(); -} - -bool HmLabel::cell_unpack_hml_same(Ref cell_ref, int& m, bool& v, int& n, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hml_same(cs, m, v, n, m_) && cs.empty_ext(); -} - -bool HmLabel::pack(vm::CellBuilder& cb, const HmLabel::Record_hml_short& data, int& m_) const { - return cb.store_long_bool(0, 1) - && tlb::store_from(cb, t_Unary, data.len, m_) - && m_ <= n_ - && cb.append_bitstring_chk(data.s, m_); -} - -bool HmLabel::cell_pack(Ref& cell_ref, const HmLabel::Record_hml_short& data, int& m_) const { - vm::CellBuilder cb; - return pack(cb, data, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool HmLabel::pack(vm::CellBuilder& cb, const HmLabel::Record_hml_long& data, int& m_) const { - return cb.store_long_bool(2, 2) - && cb.store_uint_leq(n_, data.n) - && cb.append_bitstring_chk(data.s, data.n) - && (m_ = data.n) >= 0; -} - -bool HmLabel::pack_hml_long(vm::CellBuilder& cb, int n, Ref s, int& m_) const { - return cb.store_long_bool(2, 2) - && cb.store_uint_leq(n_, n) - && cb.append_bitstring_chk(s, n) - && (m_ = n) >= 0; -} - -bool HmLabel::cell_pack(Ref& cell_ref, const HmLabel::Record_hml_long& data, int& m_) const { - vm::CellBuilder cb; - return pack(cb, data, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool HmLabel::cell_pack_hml_long(Ref& cell_ref, int n, Ref s, int& m_) const { - vm::CellBuilder cb; - return pack_hml_long(cb, n, std::move(s), m_) && std::move(cb).finalize_to(cell_ref); -} - -bool HmLabel::pack(vm::CellBuilder& cb, const HmLabel::Record_hml_same& data, int& m_) const { - return cb.store_long_bool(3, 2) - && cb.store_ulong_rchk_bool(data.v, 1) - && cb.store_uint_leq(n_, data.n) - && (m_ = data.n) >= 0; -} - -bool HmLabel::pack_hml_same(vm::CellBuilder& cb, bool v, int n, int& m_) const { - return cb.store_long_bool(3, 2) - && cb.store_ulong_rchk_bool(v, 1) - && cb.store_uint_leq(n_, n) - && (m_ = n) >= 0; -} - -bool HmLabel::cell_pack(Ref& cell_ref, const HmLabel::Record_hml_same& data, int& m_) const { - vm::CellBuilder cb; - return pack(cb, data, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool HmLabel::cell_pack_hml_same(Ref& cell_ref, bool v, int n, int& m_) const { - vm::CellBuilder cb; - return pack_hml_same(cb, v, n, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool HmLabel::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hml_short: { - int m_; - return cs.advance(1) - && pp.open("hml_short") - && pp.field("len") - && t_Unary.print_skip(pp, cs, m_) - && m_ <= n_ - && pp.fetch_bits_field(cs, m_, "s") - && pp.close(); - } - case hml_long: { - int m_; - return cs.advance(2) - && pp.open("hml_long") - && cs.fetch_uint_leq(n_, m_) - && pp.field_int(m_, "n") - && pp.fetch_bits_field(cs, m_, "s") - && pp.close(); - } - case hml_same: { - int m_; - return cs.advance(2) - && pp.open("hml_same") - && pp.fetch_uint_field(cs, 1, "v") - && cs.fetch_uint_leq(n_, m_) - && pp.field_int(m_, "n") - && pp.close(); - } - } - return pp.fail("unknown constructor for HmLabel"); -} - -bool HmLabel::print_skip(PrettyPrinter& pp, vm::CellSlice& cs, int& m_) const { - switch (get_tag(cs)) { - case hml_short: - return cs.advance(1) - && pp.open("hml_short") - && pp.field("len") - && t_Unary.print_skip(pp, cs, m_) - && m_ <= n_ - && pp.fetch_bits_field(cs, m_, "s") - && pp.close(); - case hml_long: - return cs.advance(2) - && pp.open("hml_long") - && cs.fetch_uint_leq(n_, m_) - && pp.field_int(m_, "n") - && pp.fetch_bits_field(cs, m_, "s") - && pp.close(); - case hml_same: - return cs.advance(2) - && pp.open("hml_same") - && pp.fetch_uint_field(cs, 1, "v") - && cs.fetch_uint_leq(n_, m_) - && pp.field_int(m_, "n") - && pp.close(); - } - return pp.fail("unknown constructor for HmLabel"); -} - - -// -// code for type `Unary` -// - -int Unary::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case unary_zero: - return cs.have(1) ? unary_zero : -1; - case unary_succ: - return cs.have(1) ? unary_succ : -1; - } - return -1; -} - -bool Unary::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case unary_zero: - return cs.advance(1); - case unary_succ: { - int n; - return cs.advance(1) - && skip(cs, n); - } - } - return false; -} - -bool Unary::skip(vm::CellSlice& cs, int& m_) const { - switch (get_tag(cs)) { - case unary_zero: - return (m_ = 0) >= 0 - && cs.advance(1); - case unary_succ: { - int n; - return cs.advance(1) - && skip(cs, n) - && (m_ = n + 1) >= 0; - } - } - return false; -} - -bool Unary::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case unary_zero: - return cs.advance(1); - case unary_succ: { - int n; - return cs.advance(1) - && validate_skip(ops, cs, weak, n); - } - } - return false; -} - -bool Unary::validate_skip(int* ops, vm::CellSlice& cs, bool weak, int& m_) const { - switch (get_tag(cs)) { - case unary_zero: - return (m_ = 0) >= 0 - && cs.advance(1); - case unary_succ: { - int n; - return cs.advance(1) - && validate_skip(ops, cs, weak, n) - && (m_ = n + 1) >= 0; - } - } - return false; -} - -bool Unary::fetch_to(vm::CellSlice& cs, Ref& res, int& m_) const { - res = Ref{true, cs}; - return skip(cs, m_) && res.unique_write().cut_tail(cs); -} - -bool Unary::unpack(vm::CellSlice& cs, Unary::Record_unary_zero& data, int& m_) const { - return cs.fetch_ulong(1) == 0 - && (m_ = 0) >= 0; -} - -bool Unary::unpack_unary_zero(vm::CellSlice& cs, int& m_) const { - return cs.fetch_ulong(1) == 0 - && (m_ = 0) >= 0; -} - -bool Unary::cell_unpack(Ref cell_ref, Unary::Record_unary_zero& data, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data, m_) && cs.empty_ext(); -} - -bool Unary::cell_unpack_unary_zero(Ref cell_ref, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_unary_zero(cs, m_) && cs.empty_ext(); -} - -bool Unary::unpack(vm::CellSlice& cs, Unary::Record_unary_succ& data, int& m_) const { - return cs.fetch_ulong(1) == 1 - && fetch_to(cs, data.x, data.n) - && (m_ = data.n + 1) >= 0; -} - -bool Unary::unpack_unary_succ(vm::CellSlice& cs, int& n, Ref& x, int& m_) const { - return cs.fetch_ulong(1) == 1 - && fetch_to(cs, x, n) - && (m_ = n + 1) >= 0; -} - -bool Unary::cell_unpack(Ref cell_ref, Unary::Record_unary_succ& data, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data, m_) && cs.empty_ext(); -} - -bool Unary::cell_unpack_unary_succ(Ref cell_ref, int& n, Ref& x, int& m_) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_unary_succ(cs, n, x, m_) && cs.empty_ext(); -} - -bool Unary::pack(vm::CellBuilder& cb, const Unary::Record_unary_zero& data, int& m_) const { - return cb.store_long_bool(0, 1) - && (m_ = 0) >= 0; -} - -bool Unary::pack_unary_zero(vm::CellBuilder& cb, int& m_) const { - return cb.store_long_bool(0, 1) - && (m_ = 0) >= 0; -} - -bool Unary::cell_pack(Ref& cell_ref, const Unary::Record_unary_zero& data, int& m_) const { - vm::CellBuilder cb; - return pack(cb, data, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool Unary::cell_pack_unary_zero(Ref& cell_ref, int& m_) const { - vm::CellBuilder cb; - return pack_unary_zero(cb, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool Unary::pack(vm::CellBuilder& cb, const Unary::Record_unary_succ& data, int& m_) const { - int n; - return cb.store_long_bool(1, 1) - && tlb::store_from(cb, *this, data.x, n) - && (m_ = n + 1) >= 0; -} - -bool Unary::pack_unary_succ(vm::CellBuilder& cb, Ref x, int& m_) const { - int n; - return cb.store_long_bool(1, 1) - && tlb::store_from(cb, *this, x, n) - && (m_ = n + 1) >= 0; -} - -bool Unary::cell_pack(Ref& cell_ref, const Unary::Record_unary_succ& data, int& m_) const { - vm::CellBuilder cb; - return pack(cb, data, m_) && std::move(cb).finalize_to(cell_ref); -} - -bool Unary::cell_pack_unary_succ(Ref& cell_ref, Ref x, int& m_) const { - vm::CellBuilder cb; - return pack_unary_succ(cb, std::move(x), m_) && std::move(cb).finalize_to(cell_ref); -} - -bool Unary::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case unary_zero: - return cs.advance(1) - && pp.cons("unary_zero"); - case unary_succ: { - int n; - return cs.advance(1) - && pp.open("unary_succ") - && pp.field("x") - && print_skip(pp, cs, n) - && pp.close(); - } - } - return pp.fail("unknown constructor for Unary"); -} - -bool Unary::print_skip(PrettyPrinter& pp, vm::CellSlice& cs, int& m_) const { - switch (get_tag(cs)) { - case unary_zero: - return cs.advance(1) - && pp.cons("unary_zero") - && (m_ = 0) >= 0; - case unary_succ: { - int n; - return cs.advance(1) - && pp.open("unary_succ") - && pp.field("x") - && print_skip(pp, cs, n) - && (m_ = n + 1) >= 0 - && pp.close(); - } - } - return pp.fail("unknown constructor for Unary"); -} - -const Unary t_Unary; - -// -// code for type `HashmapE` -// - -int HashmapE::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hme_empty: - return cs.have(1) ? hme_empty : -1; - case hme_root: - return cs.have(1) ? hme_root : -1; - } - return -1; -} - -bool HashmapE::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hme_empty: - return cs.advance(1); - case hme_root: - return cs.advance_ext(0x10001); - } - return false; -} - -bool HashmapE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case hme_empty: - return cs.advance(1); - case hme_root: - return cs.advance(1) - && Hashmap{m_, X_}.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool HashmapE::unpack(vm::CellSlice& cs, HashmapE::Record_hme_empty& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool HashmapE::unpack_hme_empty(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool HashmapE::cell_unpack(Ref cell_ref, HashmapE::Record_hme_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapE::cell_unpack_hme_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hme_empty(cs) && cs.empty_ext(); -} - -bool HashmapE::unpack(vm::CellSlice& cs, HashmapE::Record_hme_root& data) const { - return cs.fetch_ulong(1) == 1 - && (data.n = m_) >= 0 - && cs.fetch_ref_to(data.root); -} - -bool HashmapE::unpack_hme_root(vm::CellSlice& cs, int& n, Ref& root) const { - return cs.fetch_ulong(1) == 1 - && (n = m_) >= 0 - && cs.fetch_ref_to(root); -} - -bool HashmapE::cell_unpack(Ref cell_ref, HashmapE::Record_hme_root& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapE::cell_unpack_hme_root(Ref cell_ref, int& n, Ref& root) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_hme_root(cs, n, root) && cs.empty_ext(); -} - -bool HashmapE::pack(vm::CellBuilder& cb, const HashmapE::Record_hme_empty& data) const { - return cb.store_long_bool(0, 1); -} - -bool HashmapE::pack_hme_empty(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool HashmapE::cell_pack(Ref& cell_ref, const HashmapE::Record_hme_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapE::cell_pack_hme_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_hme_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapE::pack(vm::CellBuilder& cb, const HashmapE::Record_hme_root& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.root); -} - -bool HashmapE::pack_hme_root(vm::CellBuilder& cb, Ref root) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(root); -} - -bool HashmapE::cell_pack(Ref& cell_ref, const HashmapE::Record_hme_root& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapE::cell_pack_hme_root(Ref& cell_ref, Ref root) const { - vm::CellBuilder cb; - return pack_hme_root(cb, std::move(root)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case hme_empty: - return cs.advance(1) - && pp.cons("hme_empty"); - case hme_root: - return cs.advance(1) - && pp.open("hme_root") - && pp.field("root") - && Hashmap{m_, X_}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for HashmapE"); -} - - -// -// code for type `BitstringSet` -// - -int BitstringSet::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool BitstringSet::skip(vm::CellSlice& cs) const { - return Hashmap{m_, t_True}.skip(cs); -} - -bool BitstringSet::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return Hashmap{m_, t_True}.validate_skip(ops, cs, weak); -} - -bool BitstringSet::unpack(vm::CellSlice& cs, BitstringSet::Record& data) const { - return (data.n = m_) >= 0 - && Hashmap{m_, t_True}.fetch_to(cs, data.x); -} - -bool BitstringSet::unpack_cons1(vm::CellSlice& cs, int& n, Ref& x) const { - return (n = m_) >= 0 - && Hashmap{m_, t_True}.fetch_to(cs, x); -} - -bool BitstringSet::cell_unpack(Ref cell_ref, BitstringSet::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BitstringSet::cell_unpack_cons1(Ref cell_ref, int& n, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, n, x) && cs.empty_ext(); -} - -bool BitstringSet::pack(vm::CellBuilder& cb, const BitstringSet::Record& data) const { - return Hashmap{m_, t_True}.store_from(cb, data.x); -} - -bool BitstringSet::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return Hashmap{m_, t_True}.store_from(cb, x); -} - -bool BitstringSet::cell_pack(Ref& cell_ref, const BitstringSet::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BitstringSet::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool BitstringSet::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && Hashmap{m_, t_True}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `HashmapAug` -// - -int HashmapAug::check_tag(const vm::CellSlice& cs) const { - return ahm_edge; -} - -bool HashmapAug::skip(vm::CellSlice& cs) const { - int l, m; - return HmLabel{m_}.skip(cs, l) - && add_r1(m, l, m_) - && HashmapAugNode{m, X_, Y_}.skip(cs); -} - -bool HashmapAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l, m; - return HmLabel{m_}.validate_skip(ops, cs, weak, l) - && add_r1(m, l, m_) - && HashmapAugNode{m, X_, Y_}.validate_skip(ops, cs, weak); -} - -bool HashmapAug::unpack(vm::CellSlice& cs, HashmapAug::Record& data) const { - return (data.n = m_) >= 0 - && HmLabel{m_}.fetch_to(cs, data.label, data.l) - && add_r1(data.m, data.l, m_) - && HashmapAugNode{data.m, X_, Y_}.fetch_to(cs, data.node); -} - -bool HashmapAug::cell_unpack(Ref cell_ref, HashmapAug::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapAug::pack(vm::CellBuilder& cb, const HashmapAug::Record& data) const { - int l, m; - return tlb::store_from(cb, HmLabel{m_}, data.label, l) - && add_r1(m, l, m_) - && HashmapAugNode{m, X_, Y_}.store_from(cb, data.node); -} - -bool HashmapAug::cell_pack(Ref& cell_ref, const HashmapAug::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAug::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int l, m; - return pp.open("ahm_edge") - && pp.field("label") - && HmLabel{m_}.print_skip(pp, cs, l) - && add_r1(m, l, m_) - && pp.field("node") - && HashmapAugNode{m, X_, Y_}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `HashmapAugNode` -// - -int HashmapAugNode::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 2 2 - return m_ ? ahmn_fork : ahmn_leaf; -} - -int HashmapAugNode::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahmn_leaf: - return ahmn_leaf; - case ahmn_fork: - return ahmn_fork; - } - return -1; -} - -bool HashmapAugNode::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahmn_leaf: - return m_ == 0 - && Y_.skip(cs) - && X_.skip(cs); - case ahmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(2) - && Y_.skip(cs); - } - } - return false; -} - -bool HashmapAugNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case ahmn_leaf: - return m_ == 0 - && Y_.validate_skip(ops, cs, weak) - && X_.validate_skip(ops, cs, weak); - case ahmn_fork: { - int n; - return add_r1(n, 1, m_) - && HashmapAug{n, X_, Y_}.validate_skip_ref(ops, cs, weak) - && HashmapAug{n, X_, Y_}.validate_skip_ref(ops, cs, weak) - && Y_.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool HashmapAugNode::unpack(vm::CellSlice& cs, HashmapAugNode::Record_ahmn_leaf& data) const { - return m_ == 0 - && Y_.fetch_to(cs, data.extra) - && X_.fetch_to(cs, data.value); -} - -bool HashmapAugNode::unpack_ahmn_leaf(vm::CellSlice& cs, Ref& extra, Ref& value) const { - return m_ == 0 - && Y_.fetch_to(cs, extra) - && X_.fetch_to(cs, value); -} - -bool HashmapAugNode::cell_unpack(Ref cell_ref, HashmapAugNode::Record_ahmn_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapAugNode::cell_unpack_ahmn_leaf(Ref cell_ref, Ref& extra, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ahmn_leaf(cs, extra, value) && cs.empty_ext(); -} - -bool HashmapAugNode::unpack(vm::CellSlice& cs, HashmapAugNode::Record_ahmn_fork& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right) - && Y_.fetch_to(cs, data.extra); -} - -bool HashmapAugNode::cell_unpack(Ref cell_ref, HashmapAugNode::Record_ahmn_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapAugNode::pack(vm::CellBuilder& cb, const HashmapAugNode::Record_ahmn_leaf& data) const { - return m_ == 0 - && Y_.store_from(cb, data.extra) - && X_.store_from(cb, data.value); -} - -bool HashmapAugNode::pack_ahmn_leaf(vm::CellBuilder& cb, Ref extra, Ref value) const { - return m_ == 0 - && Y_.store_from(cb, extra) - && X_.store_from(cb, value); -} - -bool HashmapAugNode::cell_pack(Ref& cell_ref, const HashmapAugNode::Record_ahmn_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugNode::cell_pack_ahmn_leaf(Ref& cell_ref, Ref extra, Ref value) const { - vm::CellBuilder cb; - return pack_ahmn_leaf(cb, std::move(extra), std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugNode::pack(vm::CellBuilder& cb, const HashmapAugNode::Record_ahmn_fork& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right) - && Y_.store_from(cb, data.extra); -} - -bool HashmapAugNode::cell_pack(Ref& cell_ref, const HashmapAugNode::Record_ahmn_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugNode::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahmn_leaf: - return pp.open("ahmn_leaf") - && m_ == 0 - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - case ahmn_fork: { - int n; - return pp.open("ahmn_fork") - && add_r1(n, 1, m_) - && pp.field("left") - && HashmapAug{n, X_, Y_}.print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && HashmapAug{n, X_, Y_}.print_ref(pp, cs.fetch_ref()) - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for HashmapAugNode"); -} - - -// -// code for type `HashmapAugE` -// - -int HashmapAugE::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahme_empty: - return cs.have(1) ? ahme_empty : -1; - case ahme_root: - return cs.have(1) ? ahme_root : -1; - } - return -1; -} - -bool HashmapAugE::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahme_empty: - return cs.advance(1) - && Y_.skip(cs); - case ahme_root: - return cs.advance_ext(0x10001) - && Y_.skip(cs); - } - return false; -} - -bool HashmapAugE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case ahme_empty: - return cs.advance(1) - && Y_.validate_skip(ops, cs, weak); - case ahme_root: - return cs.advance(1) - && HashmapAug{m_, X_, Y_}.validate_skip_ref(ops, cs, weak) - && Y_.validate_skip(ops, cs, weak); - } - return false; -} - -bool HashmapAugE::unpack(vm::CellSlice& cs, HashmapAugE::Record_ahme_empty& data) const { - return cs.fetch_ulong(1) == 0 - && Y_.fetch_to(cs, data.extra); -} - -bool HashmapAugE::unpack_ahme_empty(vm::CellSlice& cs, Ref& extra) const { - return cs.fetch_ulong(1) == 0 - && Y_.fetch_to(cs, extra); -} - -bool HashmapAugE::cell_unpack(Ref cell_ref, HashmapAugE::Record_ahme_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapAugE::cell_unpack_ahme_empty(Ref cell_ref, Ref& extra) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ahme_empty(cs, extra) && cs.empty_ext(); -} - -bool HashmapAugE::unpack(vm::CellSlice& cs, HashmapAugE::Record_ahme_root& data) const { - return cs.fetch_ulong(1) == 1 - && (data.n = m_) >= 0 - && cs.fetch_ref_to(data.root) - && Y_.fetch_to(cs, data.extra); -} - -bool HashmapAugE::unpack_ahme_root(vm::CellSlice& cs, int& n, Ref& root, Ref& extra) const { - return cs.fetch_ulong(1) == 1 - && (n = m_) >= 0 - && cs.fetch_ref_to(root) - && Y_.fetch_to(cs, extra); -} - -bool HashmapAugE::cell_unpack(Ref cell_ref, HashmapAugE::Record_ahme_root& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HashmapAugE::cell_unpack_ahme_root(Ref cell_ref, int& n, Ref& root, Ref& extra) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ahme_root(cs, n, root, extra) && cs.empty_ext(); -} - -bool HashmapAugE::pack(vm::CellBuilder& cb, const HashmapAugE::Record_ahme_empty& data) const { - return cb.store_long_bool(0, 1) - && Y_.store_from(cb, data.extra); -} - -bool HashmapAugE::pack_ahme_empty(vm::CellBuilder& cb, Ref extra) const { - return cb.store_long_bool(0, 1) - && Y_.store_from(cb, extra); -} - -bool HashmapAugE::cell_pack(Ref& cell_ref, const HashmapAugE::Record_ahme_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugE::cell_pack_ahme_empty(Ref& cell_ref, Ref extra) const { - vm::CellBuilder cb; - return pack_ahme_empty(cb, std::move(extra)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugE::pack(vm::CellBuilder& cb, const HashmapAugE::Record_ahme_root& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.root) - && Y_.store_from(cb, data.extra); -} - -bool HashmapAugE::pack_ahme_root(vm::CellBuilder& cb, Ref root, Ref extra) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(root) - && Y_.store_from(cb, extra); -} - -bool HashmapAugE::cell_pack(Ref& cell_ref, const HashmapAugE::Record_ahme_root& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugE::cell_pack_ahme_root(Ref& cell_ref, Ref root, Ref extra) const { - vm::CellBuilder cb; - return pack_ahme_root(cb, std::move(root), std::move(extra)) && std::move(cb).finalize_to(cell_ref); -} - -bool HashmapAugE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case ahme_empty: - return cs.advance(1) - && pp.open("ahme_empty") - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.close(); - case ahme_root: - return cs.advance(1) - && pp.open("ahme_root") - && pp.field("root") - && HashmapAug{m_, X_, Y_}.print_ref(pp, cs.fetch_ref()) - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for HashmapAugE"); -} - - -// -// code for type `VarHashmap` -// - -int VarHashmap::check_tag(const vm::CellSlice& cs) const { - return vhm_edge; -} - -bool VarHashmap::skip(vm::CellSlice& cs) const { - int l, m; - return HmLabel{m_}.skip(cs, l) - && add_r1(m, l, m_) - && VarHashmapNode{m, X_}.skip(cs); -} - -bool VarHashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l, m; - return HmLabel{m_}.validate_skip(ops, cs, weak, l) - && add_r1(m, l, m_) - && VarHashmapNode{m, X_}.validate_skip(ops, cs, weak); -} - -bool VarHashmap::unpack(vm::CellSlice& cs, VarHashmap::Record& data) const { - return (data.n = m_) >= 0 - && HmLabel{m_}.fetch_to(cs, data.label, data.l) - && add_r1(data.m, data.l, m_) - && VarHashmapNode{data.m, X_}.fetch_to(cs, data.node); -} - -bool VarHashmap::cell_unpack(Ref cell_ref, VarHashmap::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmap::pack(vm::CellBuilder& cb, const VarHashmap::Record& data) const { - int l, m; - return tlb::store_from(cb, HmLabel{m_}, data.label, l) - && add_r1(m, l, m_) - && VarHashmapNode{m, X_}.store_from(cb, data.node); -} - -bool VarHashmap::cell_pack(Ref& cell_ref, const VarHashmap::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmap::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int l, m; - return pp.open("vhm_edge") - && pp.field("label") - && HmLabel{m_}.print_skip(pp, cs, l) - && add_r1(m, l, m_) - && pp.field("node") - && VarHashmapNode{m, X_}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `VarHashmapNode` -// -constexpr char VarHashmapNode::cons_len[3]; -constexpr unsigned char VarHashmapNode::cons_tag[3]; - -int VarHashmapNode::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhmn_leaf: - return cs.have(2) ? vhmn_leaf : -1; - case vhmn_fork: - return cs.have(2) ? vhmn_fork : -1; - case vhmn_cont: - return cs.have(1) ? vhmn_cont : -1; - } - return -1; -} - -bool VarHashmapNode::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhmn_leaf: - return cs.advance(2) - && X_.skip(cs); - case vhmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance_ext(0x20002) - && Maybe{X_}.skip(cs); - } - case vhmn_cont: { - int n; - return add_r1(n, 1, m_) - && cs.advance_ext(0x10002) - && X_.skip(cs); - } - } - return false; -} - -bool VarHashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vhmn_leaf: - return cs.advance(2) - && X_.validate_skip(ops, cs, weak); - case vhmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance(2) - && VarHashmap{n, X_}.validate_skip_ref(ops, cs, weak) - && VarHashmap{n, X_}.validate_skip_ref(ops, cs, weak) - && Maybe{X_}.validate_skip(ops, cs, weak); - } - case vhmn_cont: { - int n; - return add_r1(n, 1, m_) - && cs.advance(2) - && VarHashmap{n, X_}.validate_skip_ref(ops, cs, weak) - && X_.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool VarHashmapNode::unpack(vm::CellSlice& cs, VarHashmapNode::Record_vhmn_leaf& data) const { - return cs.fetch_ulong(2) == 0 - && X_.fetch_to(cs, data.value); -} - -bool VarHashmapNode::unpack_vhmn_leaf(vm::CellSlice& cs, Ref& value) const { - return cs.fetch_ulong(2) == 0 - && X_.fetch_to(cs, value); -} - -bool VarHashmapNode::cell_unpack(Ref cell_ref, VarHashmapNode::Record_vhmn_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmapNode::cell_unpack_vhmn_leaf(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vhmn_leaf(cs, value) && cs.empty_ext(); -} - -bool VarHashmapNode::unpack(vm::CellSlice& cs, VarHashmapNode::Record_vhmn_fork& data) const { - return cs.fetch_ulong(2) == 1 - && add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right) - && Maybe{X_}.fetch_to(cs, data.value); -} - -bool VarHashmapNode::cell_unpack(Ref cell_ref, VarHashmapNode::Record_vhmn_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmapNode::unpack(vm::CellSlice& cs, VarHashmapNode::Record_vhmn_cont& data) const { - return cs.fetch_ulong(1) == 1 - && add_r1(data.n, 1, m_) - && cs.fetch_bool_to(data.branch) - && cs.fetch_ref_to(data.child) - && X_.fetch_to(cs, data.value); -} - -bool VarHashmapNode::cell_unpack(Ref cell_ref, VarHashmapNode::Record_vhmn_cont& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmapNode::pack(vm::CellBuilder& cb, const VarHashmapNode::Record_vhmn_leaf& data) const { - return cb.store_long_bool(0, 2) - && X_.store_from(cb, data.value); -} - -bool VarHashmapNode::pack_vhmn_leaf(vm::CellBuilder& cb, Ref value) const { - return cb.store_long_bool(0, 2) - && X_.store_from(cb, value); -} - -bool VarHashmapNode::cell_pack(Ref& cell_ref, const VarHashmapNode::Record_vhmn_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapNode::cell_pack_vhmn_leaf(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_vhmn_leaf(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapNode::pack(vm::CellBuilder& cb, const VarHashmapNode::Record_vhmn_fork& data) const { - int n; - return cb.store_long_bool(1, 2) - && add_r1(n, 1, m_) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right) - && Maybe{X_}.store_from(cb, data.value); -} - -bool VarHashmapNode::cell_pack(Ref& cell_ref, const VarHashmapNode::Record_vhmn_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapNode::pack(vm::CellBuilder& cb, const VarHashmapNode::Record_vhmn_cont& data) const { - int n; - return cb.store_long_bool(1, 1) - && add_r1(n, 1, m_) - && cb.store_ulong_rchk_bool(data.branch, 1) - && cb.store_ref_bool(data.child) - && X_.store_from(cb, data.value); -} - -bool VarHashmapNode::cell_pack(Ref& cell_ref, const VarHashmapNode::Record_vhmn_cont& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapNode::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhmn_leaf: - return cs.advance(2) - && pp.open("vhmn_leaf") - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - case vhmn_fork: { - int n; - return cs.advance(2) - && pp.open("vhmn_fork") - && add_r1(n, 1, m_) - && pp.field("left") - && VarHashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && VarHashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.field("value") - && Maybe{X_}.print_skip(pp, cs) - && pp.close(); - } - case vhmn_cont: { - int n; - return cs.advance(1) - && pp.open("vhmn_cont") - && add_r1(n, 1, m_) - && pp.fetch_uint_field(cs, 1, "branch") - && pp.field("child") - && VarHashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for VarHashmapNode"); -} - - -// -// code for type `VarHashmapE` -// - -int VarHashmapE::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhme_empty: - return cs.have(1) ? vhme_empty : -1; - case vhme_root: - return cs.have(1) ? vhme_root : -1; - } - return -1; -} - -bool VarHashmapE::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhme_empty: - return cs.advance(1); - case vhme_root: - return cs.advance_ext(0x10001); - } - return false; -} - -bool VarHashmapE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vhme_empty: - return cs.advance(1); - case vhme_root: - return cs.advance(1) - && VarHashmap{m_, X_}.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool VarHashmapE::unpack(vm::CellSlice& cs, VarHashmapE::Record_vhme_empty& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool VarHashmapE::unpack_vhme_empty(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool VarHashmapE::cell_unpack(Ref cell_ref, VarHashmapE::Record_vhme_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmapE::cell_unpack_vhme_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vhme_empty(cs) && cs.empty_ext(); -} - -bool VarHashmapE::unpack(vm::CellSlice& cs, VarHashmapE::Record_vhme_root& data) const { - return cs.fetch_ulong(1) == 1 - && (data.n = m_) >= 0 - && cs.fetch_ref_to(data.root); -} - -bool VarHashmapE::unpack_vhme_root(vm::CellSlice& cs, int& n, Ref& root) const { - return cs.fetch_ulong(1) == 1 - && (n = m_) >= 0 - && cs.fetch_ref_to(root); -} - -bool VarHashmapE::cell_unpack(Ref cell_ref, VarHashmapE::Record_vhme_root& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarHashmapE::cell_unpack_vhme_root(Ref cell_ref, int& n, Ref& root) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vhme_root(cs, n, root) && cs.empty_ext(); -} - -bool VarHashmapE::pack(vm::CellBuilder& cb, const VarHashmapE::Record_vhme_empty& data) const { - return cb.store_long_bool(0, 1); -} - -bool VarHashmapE::pack_vhme_empty(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool VarHashmapE::cell_pack(Ref& cell_ref, const VarHashmapE::Record_vhme_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapE::cell_pack_vhme_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vhme_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapE::pack(vm::CellBuilder& cb, const VarHashmapE::Record_vhme_root& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.root); -} - -bool VarHashmapE::pack_vhme_root(vm::CellBuilder& cb, Ref root) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(root); -} - -bool VarHashmapE::cell_pack(Ref& cell_ref, const VarHashmapE::Record_vhme_root& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapE::cell_pack_vhme_root(Ref& cell_ref, Ref root) const { - vm::CellBuilder cb; - return pack_vhme_root(cb, std::move(root)) && std::move(cb).finalize_to(cell_ref); -} - -bool VarHashmapE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vhme_empty: - return cs.advance(1) - && pp.cons("vhme_empty"); - case vhme_root: - return cs.advance(1) - && pp.open("vhme_root") - && pp.field("root") - && VarHashmap{m_, X_}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for VarHashmapE"); -} - - -// -// code for type `PfxHashmap` -// - -int PfxHashmap::check_tag(const vm::CellSlice& cs) const { - return phm_edge; -} - -bool PfxHashmap::skip(vm::CellSlice& cs) const { - int l, m; - return HmLabel{m_}.skip(cs, l) - && add_r1(m, l, m_) - && PfxHashmapNode{m, X_}.skip(cs); -} - -bool PfxHashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l, m; - return HmLabel{m_}.validate_skip(ops, cs, weak, l) - && add_r1(m, l, m_) - && PfxHashmapNode{m, X_}.validate_skip(ops, cs, weak); -} - -bool PfxHashmap::unpack(vm::CellSlice& cs, PfxHashmap::Record& data) const { - return (data.n = m_) >= 0 - && HmLabel{m_}.fetch_to(cs, data.label, data.l) - && add_r1(data.m, data.l, m_) - && PfxHashmapNode{data.m, X_}.fetch_to(cs, data.node); -} - -bool PfxHashmap::cell_unpack(Ref cell_ref, PfxHashmap::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool PfxHashmap::pack(vm::CellBuilder& cb, const PfxHashmap::Record& data) const { - int l, m; - return tlb::store_from(cb, HmLabel{m_}, data.label, l) - && add_r1(m, l, m_) - && PfxHashmapNode{m, X_}.store_from(cb, data.node); -} - -bool PfxHashmap::cell_pack(Ref& cell_ref, const PfxHashmap::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmap::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int l, m; - return pp.open("phm_edge") - && pp.field("label") - && HmLabel{m_}.print_skip(pp, cs, l) - && add_r1(m, l, m_) - && pp.field("node") - && PfxHashmapNode{m, X_}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `PfxHashmapNode` -// - -int PfxHashmapNode::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phmn_leaf: - return cs.have(1) ? phmn_leaf : -1; - case phmn_fork: - return cs.have(1) ? phmn_fork : -1; - } - return -1; -} - -bool PfxHashmapNode::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phmn_leaf: - return cs.advance(1) - && X_.skip(cs); - case phmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance_ext(0x20001); - } - } - return false; -} - -bool PfxHashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case phmn_leaf: - return cs.advance(1) - && X_.validate_skip(ops, cs, weak); - case phmn_fork: { - int n; - return add_r1(n, 1, m_) - && cs.advance(1) - && PfxHashmap{n, X_}.validate_skip_ref(ops, cs, weak) - && PfxHashmap{n, X_}.validate_skip_ref(ops, cs, weak); - } - } - return false; -} - -bool PfxHashmapNode::unpack(vm::CellSlice& cs, PfxHashmapNode::Record_phmn_leaf& data) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, data.value); -} - -bool PfxHashmapNode::unpack_phmn_leaf(vm::CellSlice& cs, Ref& value) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, value); -} - -bool PfxHashmapNode::cell_unpack(Ref cell_ref, PfxHashmapNode::Record_phmn_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool PfxHashmapNode::cell_unpack_phmn_leaf(Ref cell_ref, Ref& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_phmn_leaf(cs, value) && cs.empty_ext(); -} - -bool PfxHashmapNode::unpack(vm::CellSlice& cs, PfxHashmapNode::Record_phmn_fork& data) const { - return cs.fetch_ulong(1) == 1 - && add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right); -} - -bool PfxHashmapNode::unpack_phmn_fork(vm::CellSlice& cs, int& n, Ref& left, Ref& right) const { - return cs.fetch_ulong(1) == 1 - && add_r1(n, 1, m_) - && cs.fetch_ref_to(left) - && cs.fetch_ref_to(right); -} - -bool PfxHashmapNode::cell_unpack(Ref cell_ref, PfxHashmapNode::Record_phmn_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool PfxHashmapNode::cell_unpack_phmn_fork(Ref cell_ref, int& n, Ref& left, Ref& right) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_phmn_fork(cs, n, left, right) && cs.empty_ext(); -} - -bool PfxHashmapNode::pack(vm::CellBuilder& cb, const PfxHashmapNode::Record_phmn_leaf& data) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, data.value); -} - -bool PfxHashmapNode::pack_phmn_leaf(vm::CellBuilder& cb, Ref value) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, value); -} - -bool PfxHashmapNode::cell_pack(Ref& cell_ref, const PfxHashmapNode::Record_phmn_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapNode::cell_pack_phmn_leaf(Ref& cell_ref, Ref value) const { - vm::CellBuilder cb; - return pack_phmn_leaf(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapNode::pack(vm::CellBuilder& cb, const PfxHashmapNode::Record_phmn_fork& data) const { - int n; - return cb.store_long_bool(1, 1) - && add_r1(n, 1, m_) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right); -} - -bool PfxHashmapNode::pack_phmn_fork(vm::CellBuilder& cb, Ref left, Ref right) const { - int n; - return cb.store_long_bool(1, 1) - && add_r1(n, 1, m_) - && cb.store_ref_bool(left) - && cb.store_ref_bool(right); -} - -bool PfxHashmapNode::cell_pack(Ref& cell_ref, const PfxHashmapNode::Record_phmn_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapNode::cell_pack_phmn_fork(Ref& cell_ref, Ref left, Ref right) const { - vm::CellBuilder cb; - return pack_phmn_fork(cb, std::move(left), std::move(right)) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapNode::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phmn_leaf: - return cs.advance(1) - && pp.open("phmn_leaf") - && pp.field("value") - && X_.print_skip(pp, cs) - && pp.close(); - case phmn_fork: { - int n; - return cs.advance(1) - && pp.open("phmn_fork") - && add_r1(n, 1, m_) - && pp.field("left") - && PfxHashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && PfxHashmap{n, X_}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - } - return pp.fail("unknown constructor for PfxHashmapNode"); -} - - -// -// code for type `PfxHashmapE` -// - -int PfxHashmapE::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phme_empty: - return cs.have(1) ? phme_empty : -1; - case phme_root: - return cs.have(1) ? phme_root : -1; - } - return -1; -} - -bool PfxHashmapE::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phme_empty: - return cs.advance(1); - case phme_root: - return cs.advance_ext(0x10001); - } - return false; -} - -bool PfxHashmapE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case phme_empty: - return cs.advance(1); - case phme_root: - return cs.advance(1) - && PfxHashmap{m_, X_}.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool PfxHashmapE::unpack(vm::CellSlice& cs, PfxHashmapE::Record_phme_empty& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool PfxHashmapE::unpack_phme_empty(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool PfxHashmapE::cell_unpack(Ref cell_ref, PfxHashmapE::Record_phme_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool PfxHashmapE::cell_unpack_phme_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_phme_empty(cs) && cs.empty_ext(); -} - -bool PfxHashmapE::unpack(vm::CellSlice& cs, PfxHashmapE::Record_phme_root& data) const { - return cs.fetch_ulong(1) == 1 - && (data.n = m_) >= 0 - && cs.fetch_ref_to(data.root); -} - -bool PfxHashmapE::unpack_phme_root(vm::CellSlice& cs, int& n, Ref& root) const { - return cs.fetch_ulong(1) == 1 - && (n = m_) >= 0 - && cs.fetch_ref_to(root); -} - -bool PfxHashmapE::cell_unpack(Ref cell_ref, PfxHashmapE::Record_phme_root& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool PfxHashmapE::cell_unpack_phme_root(Ref cell_ref, int& n, Ref& root) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_phme_root(cs, n, root) && cs.empty_ext(); -} - -bool PfxHashmapE::pack(vm::CellBuilder& cb, const PfxHashmapE::Record_phme_empty& data) const { - return cb.store_long_bool(0, 1); -} - -bool PfxHashmapE::pack_phme_empty(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool PfxHashmapE::cell_pack(Ref& cell_ref, const PfxHashmapE::Record_phme_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapE::cell_pack_phme_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_phme_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapE::pack(vm::CellBuilder& cb, const PfxHashmapE::Record_phme_root& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.root); -} - -bool PfxHashmapE::pack_phme_root(vm::CellBuilder& cb, Ref root) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(root); -} - -bool PfxHashmapE::cell_pack(Ref& cell_ref, const PfxHashmapE::Record_phme_root& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapE::cell_pack_phme_root(Ref& cell_ref, Ref root) const { - vm::CellBuilder cb; - return pack_phme_root(cb, std::move(root)) && std::move(cb).finalize_to(cell_ref); -} - -bool PfxHashmapE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case phme_empty: - return cs.advance(1) - && pp.cons("phme_empty"); - case phme_root: - return cs.advance(1) - && pp.open("phme_root") - && pp.field("root") - && PfxHashmap{m_, X_}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for PfxHashmapE"); -} - - -// -// code for type `MsgAddressExt` -// - -int MsgAddressExt::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_none: - return cs.have(2) ? addr_none : -1; - case addr_extern: - return cs.prefetch_ulong(2) == 1 ? addr_extern : -1; - } - return -1; -} - -bool MsgAddressExt::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_none: - return cs.advance(2); - case addr_extern: { - int len; - return cs.advance(2) - && cs.fetch_uint_to(9, len) - && cs.advance(len); - } - } - return false; -} - -bool MsgAddressExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case addr_none: - return cs.advance(2); - case addr_extern: { - int len; - return cs.fetch_ulong(2) == 1 - && cs.fetch_uint_to(9, len) - && cs.advance(len); - } - } - return false; -} - -bool MsgAddressExt::unpack(vm::CellSlice& cs, MsgAddressExt::Record_addr_none& data) const { - return cs.fetch_ulong(2) == 0; -} - -bool MsgAddressExt::unpack_addr_none(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0; -} - -bool MsgAddressExt::cell_unpack(Ref cell_ref, MsgAddressExt::Record_addr_none& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddressExt::cell_unpack_addr_none(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_addr_none(cs) && cs.empty_ext(); -} - -bool MsgAddressExt::unpack(vm::CellSlice& cs, MsgAddressExt::Record_addr_extern& data) const { - return cs.fetch_ulong(2) == 1 - && cs.fetch_uint_to(9, data.len) - && cs.fetch_bitstring_to(data.len, data.external_address); -} - -bool MsgAddressExt::unpack_addr_extern(vm::CellSlice& cs, int& len, Ref& external_address) const { - return cs.fetch_ulong(2) == 1 - && cs.fetch_uint_to(9, len) - && cs.fetch_bitstring_to(len, external_address); -} - -bool MsgAddressExt::cell_unpack(Ref cell_ref, MsgAddressExt::Record_addr_extern& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddressExt::cell_unpack_addr_extern(Ref cell_ref, int& len, Ref& external_address) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_addr_extern(cs, len, external_address) && cs.empty_ext(); -} - -bool MsgAddressExt::pack(vm::CellBuilder& cb, const MsgAddressExt::Record_addr_none& data) const { - return cb.store_long_bool(0, 2); -} - -bool MsgAddressExt::pack_addr_none(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 2); -} - -bool MsgAddressExt::cell_pack(Ref& cell_ref, const MsgAddressExt::Record_addr_none& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressExt::cell_pack_addr_none(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_addr_none(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressExt::pack(vm::CellBuilder& cb, const MsgAddressExt::Record_addr_extern& data) const { - return cb.store_long_bool(1, 2) - && cb.store_ulong_rchk_bool(data.len, 9) - && cb.append_bitstring_chk(data.external_address, data.len); -} - -bool MsgAddressExt::pack_addr_extern(vm::CellBuilder& cb, int len, Ref external_address) const { - return cb.store_long_bool(1, 2) - && cb.store_ulong_rchk_bool(len, 9) - && cb.append_bitstring_chk(external_address, len); -} - -bool MsgAddressExt::cell_pack(Ref& cell_ref, const MsgAddressExt::Record_addr_extern& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressExt::cell_pack_addr_extern(Ref& cell_ref, int len, Ref external_address) const { - vm::CellBuilder cb; - return pack_addr_extern(cb, len, std::move(external_address)) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressExt::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_none: - return cs.advance(2) - && pp.cons("addr_none"); - case addr_extern: { - int len; - return cs.fetch_ulong(2) == 1 - && pp.open("addr_extern") - && cs.fetch_uint_to(9, len) - && pp.field_int(len, "len") - && pp.fetch_bits_field(cs, len, "external_address") - && pp.close(); - } - } - return pp.fail("unknown constructor for MsgAddressExt"); -} - -const MsgAddressExt t_MsgAddressExt; - -// -// code for type `Anycast` -// - -int Anycast::check_tag(const vm::CellSlice& cs) const { - return anycast_info; -} - -bool Anycast::skip(vm::CellSlice& cs) const { - int depth; - return cs.fetch_uint_leq(30, depth) - && 1 <= depth - && cs.advance(depth); -} - -bool Anycast::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int depth; - return cs.fetch_uint_leq(30, depth) - && 1 <= depth - && cs.advance(depth); -} - -bool Anycast::unpack(vm::CellSlice& cs, Anycast::Record& data) const { - return cs.fetch_uint_leq(30, data.depth) - && 1 <= data.depth - && cs.fetch_bitstring_to(data.depth, data.rewrite_pfx); -} - -bool Anycast::unpack_anycast_info(vm::CellSlice& cs, int& depth, Ref& rewrite_pfx) const { - return cs.fetch_uint_leq(30, depth) - && 1 <= depth - && cs.fetch_bitstring_to(depth, rewrite_pfx); -} - -bool Anycast::cell_unpack(Ref cell_ref, Anycast::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Anycast::cell_unpack_anycast_info(Ref cell_ref, int& depth, Ref& rewrite_pfx) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_anycast_info(cs, depth, rewrite_pfx) && cs.empty_ext(); -} - -bool Anycast::pack(vm::CellBuilder& cb, const Anycast::Record& data) const { - return cb.store_uint_leq(30, data.depth) - && 1 <= data.depth - && cb.append_bitstring_chk(data.rewrite_pfx, data.depth); -} - -bool Anycast::pack_anycast_info(vm::CellBuilder& cb, int depth, Ref rewrite_pfx) const { - return cb.store_uint_leq(30, depth) - && 1 <= depth - && cb.append_bitstring_chk(rewrite_pfx, depth); -} - -bool Anycast::cell_pack(Ref& cell_ref, const Anycast::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Anycast::cell_pack_anycast_info(Ref& cell_ref, int depth, Ref rewrite_pfx) const { - vm::CellBuilder cb; - return pack_anycast_info(cb, depth, std::move(rewrite_pfx)) && std::move(cb).finalize_to(cell_ref); -} - -bool Anycast::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int depth; - return pp.open("anycast_info") - && cs.fetch_uint_leq(30, depth) - && pp.field_int(depth, "depth") - && 1 <= depth - && pp.fetch_bits_field(cs, depth, "rewrite_pfx") - && pp.close(); -} - -const Anycast t_Anycast; - -// -// code for type `MsgAddressInt` -// -constexpr unsigned char MsgAddressInt::cons_tag[2]; - -int MsgAddressInt::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_std: - return cs.have(2) ? addr_std : -1; - case addr_var: - return cs.have(2) ? addr_var : -1; - } - return -1; -} - -bool MsgAddressInt::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_std: - return cs.advance(2) - && t_Maybe_Anycast.skip(cs) - && cs.advance(264); - case addr_var: { - int addr_len; - return cs.advance(2) - && t_Maybe_Anycast.skip(cs) - && cs.fetch_uint_to(9, addr_len) - && cs.advance(32) - && cs.advance(addr_len); - } - } - return false; -} - -bool MsgAddressInt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case addr_std: - return cs.advance(2) - && t_Maybe_Anycast.validate_skip(ops, cs, weak) - && cs.advance(264); - case addr_var: { - int addr_len; - return cs.advance(2) - && t_Maybe_Anycast.validate_skip(ops, cs, weak) - && cs.fetch_uint_to(9, addr_len) - && cs.advance(32) - && cs.advance(addr_len); - } - } - return false; -} - -bool MsgAddressInt::unpack(vm::CellSlice& cs, MsgAddressInt::Record_addr_std& data) const { - return cs.fetch_ulong(2) == 2 - && t_Maybe_Anycast.fetch_to(cs, data.anycast) - && cs.fetch_int_to(8, data.workchain_id) - && cs.fetch_bits_to(data.address.bits(), 256); -} - -bool MsgAddressInt::unpack_addr_std(vm::CellSlice& cs, Ref& anycast, int& workchain_id, td::BitArray<256>& address) const { - return cs.fetch_ulong(2) == 2 - && t_Maybe_Anycast.fetch_to(cs, anycast) - && cs.fetch_int_to(8, workchain_id) - && cs.fetch_bits_to(address.bits(), 256); -} - -bool MsgAddressInt::cell_unpack(Ref cell_ref, MsgAddressInt::Record_addr_std& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddressInt::cell_unpack_addr_std(Ref cell_ref, Ref& anycast, int& workchain_id, td::BitArray<256>& address) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_addr_std(cs, anycast, workchain_id, address) && cs.empty_ext(); -} - -bool MsgAddressInt::unpack(vm::CellSlice& cs, MsgAddressInt::Record_addr_var& data) const { - return cs.fetch_ulong(2) == 3 - && t_Maybe_Anycast.fetch_to(cs, data.anycast) - && cs.fetch_uint_to(9, data.addr_len) - && cs.fetch_int_to(32, data.workchain_id) - && cs.fetch_bitstring_to(data.addr_len, data.address); -} - -bool MsgAddressInt::cell_unpack(Ref cell_ref, MsgAddressInt::Record_addr_var& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddressInt::pack(vm::CellBuilder& cb, const MsgAddressInt::Record_addr_std& data) const { - return cb.store_long_bool(2, 2) - && t_Maybe_Anycast.store_from(cb, data.anycast) - && cb.store_long_rchk_bool(data.workchain_id, 8) - && cb.store_bits_bool(data.address.cbits(), 256); -} - -bool MsgAddressInt::pack_addr_std(vm::CellBuilder& cb, Ref anycast, int workchain_id, td::BitArray<256> address) const { - return cb.store_long_bool(2, 2) - && t_Maybe_Anycast.store_from(cb, anycast) - && cb.store_long_rchk_bool(workchain_id, 8) - && cb.store_bits_bool(address.cbits(), 256); -} - -bool MsgAddressInt::cell_pack(Ref& cell_ref, const MsgAddressInt::Record_addr_std& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressInt::cell_pack_addr_std(Ref& cell_ref, Ref anycast, int workchain_id, td::BitArray<256> address) const { - vm::CellBuilder cb; - return pack_addr_std(cb, std::move(anycast), workchain_id, address) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressInt::pack(vm::CellBuilder& cb, const MsgAddressInt::Record_addr_var& data) const { - return cb.store_long_bool(3, 2) - && t_Maybe_Anycast.store_from(cb, data.anycast) - && cb.store_ulong_rchk_bool(data.addr_len, 9) - && cb.store_long_rchk_bool(data.workchain_id, 32) - && cb.append_bitstring_chk(data.address, data.addr_len); -} - -bool MsgAddressInt::cell_pack(Ref& cell_ref, const MsgAddressInt::Record_addr_var& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddressInt::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_std: - return cs.advance(2) - && pp.open("addr_std") - && pp.field("anycast") - && t_Maybe_Anycast.print_skip(pp, cs) - && pp.fetch_int_field(cs, 8, "workchain_id") - && pp.fetch_bits_field(cs, 256, "address") - && pp.close(); - case addr_var: { - int addr_len; - return cs.advance(2) - && pp.open("addr_var") - && pp.field("anycast") - && t_Maybe_Anycast.print_skip(pp, cs) - && cs.fetch_uint_to(9, addr_len) - && pp.field_int(addr_len, "addr_len") - && pp.fetch_int_field(cs, 32, "workchain_id") - && pp.fetch_bits_field(cs, addr_len, "address") - && pp.close(); - } - } - return pp.fail("unknown constructor for MsgAddressInt"); -} - -const MsgAddressInt t_MsgAddressInt; - -// -// code for type `MsgAddress` -// - -int MsgAddress::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return cons1; - case cons2: - return cons2; - } - return -1; -} - -bool MsgAddress::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return t_MsgAddressInt.skip(cs); - case cons2: - return t_MsgAddressExt.skip(cs); - } - return false; -} - -bool MsgAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cons1: - return t_MsgAddressInt.validate_skip(ops, cs, weak); - case cons2: - return t_MsgAddressExt.validate_skip(ops, cs, weak); - } - return false; -} - -bool MsgAddress::unpack(vm::CellSlice& cs, MsgAddress::Record_cons1& data) const { - return t_MsgAddressInt.fetch_to(cs, data.x); -} - -bool MsgAddress::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_MsgAddressInt.fetch_to(cs, x); -} - -bool MsgAddress::cell_unpack(Ref cell_ref, MsgAddress::Record_cons1& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddress::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool MsgAddress::unpack(vm::CellSlice& cs, MsgAddress::Record_cons2& data) const { - return t_MsgAddressExt.fetch_to(cs, data.x); -} - -bool MsgAddress::unpack_cons2(vm::CellSlice& cs, Ref& x) const { - return t_MsgAddressExt.fetch_to(cs, x); -} - -bool MsgAddress::cell_unpack(Ref cell_ref, MsgAddress::Record_cons2& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgAddress::cell_unpack_cons2(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons2(cs, x) && cs.empty_ext(); -} - -bool MsgAddress::pack(vm::CellBuilder& cb, const MsgAddress::Record_cons1& data) const { - return t_MsgAddressInt.store_from(cb, data.x); -} - -bool MsgAddress::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_MsgAddressInt.store_from(cb, x); -} - -bool MsgAddress::cell_pack(Ref& cell_ref, const MsgAddress::Record_cons1& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddress::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddress::pack(vm::CellBuilder& cb, const MsgAddress::Record_cons2& data) const { - return t_MsgAddressExt.store_from(cb, data.x); -} - -bool MsgAddress::pack_cons2(vm::CellBuilder& cb, Ref x) const { - return t_MsgAddressExt.store_from(cb, x); -} - -bool MsgAddress::cell_pack(Ref& cell_ref, const MsgAddress::Record_cons2& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddress::cell_pack_cons2(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons2(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgAddress::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return pp.open() - && pp.field() - && t_MsgAddressInt.print_skip(pp, cs) - && pp.close(); - case cons2: - return pp.open() - && pp.field() - && t_MsgAddressExt.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for MsgAddress"); -} - -const MsgAddress t_MsgAddress; - -// -// code for type `VarUInteger` -// - -int VarUInteger::check_tag(const vm::CellSlice& cs) const { - return var_uint; -} - -bool VarUInteger::skip(vm::CellSlice& cs) const { - int len; - return cs.fetch_uint_less(m_, len) - && cs.advance(8 * len); -} - -bool VarUInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len; - return cs.fetch_uint_less(m_, len) - && cs.advance(8 * len); -} - -bool VarUInteger::unpack(vm::CellSlice& cs, VarUInteger::Record& data) const { - return (data.n = m_) >= 0 - && cs.fetch_uint_less(m_, data.len) - && cs.fetch_uint256_to(8 * data.len, data.value); -} - -bool VarUInteger::unpack_var_uint(vm::CellSlice& cs, int& n, int& len, RefInt256& value) const { - return (n = m_) >= 0 - && cs.fetch_uint_less(m_, len) - && cs.fetch_uint256_to(8 * len, value); -} - -bool VarUInteger::cell_unpack(Ref cell_ref, VarUInteger::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarUInteger::cell_unpack_var_uint(Ref cell_ref, int& n, int& len, RefInt256& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_var_uint(cs, n, len, value) && cs.empty_ext(); -} - -bool VarUInteger::pack(vm::CellBuilder& cb, const VarUInteger::Record& data) const { - return cb.store_uint_less(m_, data.len) - && cb.store_int256_bool(data.value, 8 * data.len, false); -} - -bool VarUInteger::pack_var_uint(vm::CellBuilder& cb, int len, RefInt256 value) const { - return cb.store_uint_less(m_, len) - && cb.store_int256_bool(value, 8 * len, false); -} - -bool VarUInteger::cell_pack(Ref& cell_ref, const VarUInteger::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarUInteger::cell_pack_var_uint(Ref& cell_ref, int len, RefInt256 value) const { - vm::CellBuilder cb; - return pack_var_uint(cb, len, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool VarUInteger::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int len; - return pp.open("var_uint") - && cs.fetch_uint_less(m_, len) - && pp.field_int(len, "len") - && pp.fetch_uint256_field(cs, 8 * len, "value") - && pp.close(); -} - - -// -// code for type `VarInteger` -// - -int VarInteger::check_tag(const vm::CellSlice& cs) const { - return var_int; -} - -bool VarInteger::skip(vm::CellSlice& cs) const { - int len; - return cs.fetch_uint_less(m_, len) - && cs.advance(8 * len); -} - -bool VarInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len; - return cs.fetch_uint_less(m_, len) - && cs.advance(8 * len); -} - -bool VarInteger::unpack(vm::CellSlice& cs, VarInteger::Record& data) const { - return (data.n = m_) >= 0 - && cs.fetch_uint_less(m_, data.len) - && cs.fetch_int256_to(8 * data.len, data.value); -} - -bool VarInteger::unpack_var_int(vm::CellSlice& cs, int& n, int& len, RefInt256& value) const { - return (n = m_) >= 0 - && cs.fetch_uint_less(m_, len) - && cs.fetch_int256_to(8 * len, value); -} - -bool VarInteger::cell_unpack(Ref cell_ref, VarInteger::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VarInteger::cell_unpack_var_int(Ref cell_ref, int& n, int& len, RefInt256& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_var_int(cs, n, len, value) && cs.empty_ext(); -} - -bool VarInteger::pack(vm::CellBuilder& cb, const VarInteger::Record& data) const { - return cb.store_uint_less(m_, data.len) - && cb.store_int256_bool(data.value, 8 * data.len); -} - -bool VarInteger::pack_var_int(vm::CellBuilder& cb, int len, RefInt256 value) const { - return cb.store_uint_less(m_, len) - && cb.store_int256_bool(value, 8 * len); -} - -bool VarInteger::cell_pack(Ref& cell_ref, const VarInteger::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VarInteger::cell_pack_var_int(Ref& cell_ref, int len, RefInt256 value) const { - vm::CellBuilder cb; - return pack_var_int(cb, len, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool VarInteger::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int len; - return pp.open("var_int") - && cs.fetch_uint_less(m_, len) - && pp.field_int(len, "len") - && pp.fetch_int256_field(cs, 8 * len, "value") - && pp.close(); -} - - -// -// code for type `Grams` -// - -int Grams::check_tag(const vm::CellSlice& cs) const { - return nanograms; -} - -bool Grams::skip(vm::CellSlice& cs) const { - return t_VarUInteger_16.skip(cs); -} - -bool Grams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_16.validate_skip(ops, cs, weak); -} - -bool Grams::unpack(vm::CellSlice& cs, Grams::Record& data) const { - return t_VarUInteger_16.fetch_to(cs, data.amount); -} - -bool Grams::unpack_nanograms(vm::CellSlice& cs, Ref& amount) const { - return t_VarUInteger_16.fetch_to(cs, amount); -} - -bool Grams::cell_unpack(Ref cell_ref, Grams::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Grams::cell_unpack_nanograms(Ref cell_ref, Ref& amount) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_nanograms(cs, amount) && cs.empty_ext(); -} - -bool Grams::pack(vm::CellBuilder& cb, const Grams::Record& data) const { - return t_VarUInteger_16.store_from(cb, data.amount); -} - -bool Grams::pack_nanograms(vm::CellBuilder& cb, Ref amount) const { - return t_VarUInteger_16.store_from(cb, amount); -} - -bool Grams::cell_pack(Ref& cell_ref, const Grams::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Grams::cell_pack_nanograms(Ref& cell_ref, Ref amount) const { - vm::CellBuilder cb; - return pack_nanograms(cb, std::move(amount)) && std::move(cb).finalize_to(cell_ref); -} - -bool Grams::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("nanograms") - && pp.field("amount") - && t_VarUInteger_16.print_skip(pp, cs) - && pp.close(); -} - -const Grams t_Grams; - -// -// code for type `ExtraCurrencyCollection` -// - -int ExtraCurrencyCollection::check_tag(const vm::CellSlice& cs) const { - return extra_currencies; -} - -bool ExtraCurrencyCollection::skip(vm::CellSlice& cs) const { - return t_HashmapE_32_VarUInteger_32.skip(cs); -} - -bool ExtraCurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_32_VarUInteger_32.validate_skip(ops, cs, weak); -} - -bool ExtraCurrencyCollection::unpack(vm::CellSlice& cs, ExtraCurrencyCollection::Record& data) const { - return t_HashmapE_32_VarUInteger_32.fetch_to(cs, data.dict); -} - -bool ExtraCurrencyCollection::unpack_extra_currencies(vm::CellSlice& cs, Ref& dict) const { - return t_HashmapE_32_VarUInteger_32.fetch_to(cs, dict); -} - -bool ExtraCurrencyCollection::cell_unpack(Ref cell_ref, ExtraCurrencyCollection::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ExtraCurrencyCollection::cell_unpack_extra_currencies(Ref cell_ref, Ref& dict) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_extra_currencies(cs, dict) && cs.empty_ext(); -} - -bool ExtraCurrencyCollection::pack(vm::CellBuilder& cb, const ExtraCurrencyCollection::Record& data) const { - return t_HashmapE_32_VarUInteger_32.store_from(cb, data.dict); -} - -bool ExtraCurrencyCollection::pack_extra_currencies(vm::CellBuilder& cb, Ref dict) const { - return t_HashmapE_32_VarUInteger_32.store_from(cb, dict); -} - -bool ExtraCurrencyCollection::cell_pack(Ref& cell_ref, const ExtraCurrencyCollection::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ExtraCurrencyCollection::cell_pack_extra_currencies(Ref& cell_ref, Ref dict) const { - vm::CellBuilder cb; - return pack_extra_currencies(cb, std::move(dict)) && std::move(cb).finalize_to(cell_ref); -} - -bool ExtraCurrencyCollection::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("extra_currencies") - && pp.field("dict") - && t_HashmapE_32_VarUInteger_32.print_skip(pp, cs) - && pp.close(); -} - -const ExtraCurrencyCollection t_ExtraCurrencyCollection; - -// -// code for type `CurrencyCollection` -// - -int CurrencyCollection::check_tag(const vm::CellSlice& cs) const { - return currencies; -} - -bool CurrencyCollection::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) - && t_ExtraCurrencyCollection.skip(cs); -} - -bool CurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) - && t_ExtraCurrencyCollection.validate_skip(ops, cs, weak); -} - -bool CurrencyCollection::unpack(vm::CellSlice& cs, CurrencyCollection::Record& data) const { - return t_Grams.fetch_to(cs, data.grams) - && t_ExtraCurrencyCollection.fetch_to(cs, data.other); -} - -bool CurrencyCollection::unpack_currencies(vm::CellSlice& cs, Ref& grams, Ref& other) const { - return t_Grams.fetch_to(cs, grams) - && t_ExtraCurrencyCollection.fetch_to(cs, other); -} - -bool CurrencyCollection::cell_unpack(Ref cell_ref, CurrencyCollection::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CurrencyCollection::cell_unpack_currencies(Ref cell_ref, Ref& grams, Ref& other) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_currencies(cs, grams, other) && cs.empty_ext(); -} - -bool CurrencyCollection::pack(vm::CellBuilder& cb, const CurrencyCollection::Record& data) const { - return t_Grams.store_from(cb, data.grams) - && t_ExtraCurrencyCollection.store_from(cb, data.other); -} - -bool CurrencyCollection::pack_currencies(vm::CellBuilder& cb, Ref grams, Ref other) const { - return t_Grams.store_from(cb, grams) - && t_ExtraCurrencyCollection.store_from(cb, other); -} - -bool CurrencyCollection::cell_pack(Ref& cell_ref, const CurrencyCollection::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CurrencyCollection::cell_pack_currencies(Ref& cell_ref, Ref grams, Ref other) const { - vm::CellBuilder cb; - return pack_currencies(cb, std::move(grams), std::move(other)) && std::move(cb).finalize_to(cell_ref); -} - -bool CurrencyCollection::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("currencies") - && pp.field("grams") - && t_Grams.print_skip(pp, cs) - && pp.field("other") - && t_ExtraCurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const CurrencyCollection t_CurrencyCollection; - -// -// code for type `CommonMsgInfo` -// -constexpr char CommonMsgInfo::cons_len[3]; -constexpr unsigned char CommonMsgInfo::cons_tag[3]; - -int CommonMsgInfo::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.have(1) ? int_msg_info : -1; - case ext_in_msg_info: - return cs.have(2) ? ext_in_msg_info : -1; - case ext_out_msg_info: - return cs.have(2) ? ext_out_msg_info : -1; - } - return -1; -} - -bool CommonMsgInfo::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(4) - && t_MsgAddressInt.skip(cs) - && t_MsgAddressInt.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(96); - case ext_in_msg_info: - return cs.advance(2) - && t_MsgAddressExt.skip(cs) - && t_MsgAddressInt.skip(cs) - && t_Grams.skip(cs); - case ext_out_msg_info: - return cs.advance(2) - && t_MsgAddressInt.skip(cs) - && t_MsgAddressExt.skip(cs) - && cs.advance(96); - } - return false; -} - -bool CommonMsgInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(4) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(96); - case ext_in_msg_info: - return cs.advance(2) - && t_MsgAddressExt.validate_skip(ops, cs, weak) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case ext_out_msg_info: - return cs.advance(2) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_MsgAddressExt.validate_skip(ops, cs, weak) - && cs.advance(96); - } - return false; -} - -bool CommonMsgInfo::unpack(vm::CellSlice& cs, CommonMsgInfo::Record_int_msg_info& data) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_bool_to(data.ihr_disabled) - && cs.fetch_bool_to(data.bounce) - && cs.fetch_bool_to(data.bounced) - && t_MsgAddressInt.fetch_to(cs, data.src) - && t_MsgAddressInt.fetch_to(cs, data.dest) - && t_CurrencyCollection.fetch_to(cs, data.value) - && t_Grams.fetch_to(cs, data.ihr_fee) - && t_Grams.fetch_to(cs, data.fwd_fee) - && cs.fetch_uint_to(64, data.created_lt) - && cs.fetch_uint_to(32, data.created_at); -} - -bool CommonMsgInfo::cell_unpack(Ref cell_ref, CommonMsgInfo::Record_int_msg_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CommonMsgInfo::unpack(vm::CellSlice& cs, CommonMsgInfo::Record_ext_in_msg_info& data) const { - return cs.fetch_ulong(2) == 2 - && t_MsgAddressExt.fetch_to(cs, data.src) - && t_MsgAddressInt.fetch_to(cs, data.dest) - && t_Grams.fetch_to(cs, data.import_fee); -} - -bool CommonMsgInfo::unpack_ext_in_msg_info(vm::CellSlice& cs, Ref& src, Ref& dest, Ref& import_fee) const { - return cs.fetch_ulong(2) == 2 - && t_MsgAddressExt.fetch_to(cs, src) - && t_MsgAddressInt.fetch_to(cs, dest) - && t_Grams.fetch_to(cs, import_fee); -} - -bool CommonMsgInfo::cell_unpack(Ref cell_ref, CommonMsgInfo::Record_ext_in_msg_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CommonMsgInfo::cell_unpack_ext_in_msg_info(Ref cell_ref, Ref& src, Ref& dest, Ref& import_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ext_in_msg_info(cs, src, dest, import_fee) && cs.empty_ext(); -} - -bool CommonMsgInfo::unpack(vm::CellSlice& cs, CommonMsgInfo::Record_ext_out_msg_info& data) const { - return cs.fetch_ulong(2) == 3 - && t_MsgAddressInt.fetch_to(cs, data.src) - && t_MsgAddressExt.fetch_to(cs, data.dest) - && cs.fetch_uint_to(64, data.created_lt) - && cs.fetch_uint_to(32, data.created_at); -} - -bool CommonMsgInfo::cell_unpack(Ref cell_ref, CommonMsgInfo::Record_ext_out_msg_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CommonMsgInfo::pack(vm::CellBuilder& cb, const CommonMsgInfo::Record_int_msg_info& data) const { - return cb.store_long_bool(0, 1) - && cb.store_ulong_rchk_bool(data.ihr_disabled, 1) - && cb.store_ulong_rchk_bool(data.bounce, 1) - && cb.store_ulong_rchk_bool(data.bounced, 1) - && t_MsgAddressInt.store_from(cb, data.src) - && t_MsgAddressInt.store_from(cb, data.dest) - && t_CurrencyCollection.store_from(cb, data.value) - && t_Grams.store_from(cb, data.ihr_fee) - && t_Grams.store_from(cb, data.fwd_fee) - && cb.store_ulong_rchk_bool(data.created_lt, 64) - && cb.store_ulong_rchk_bool(data.created_at, 32); -} - -bool CommonMsgInfo::cell_pack(Ref& cell_ref, const CommonMsgInfo::Record_int_msg_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfo::pack(vm::CellBuilder& cb, const CommonMsgInfo::Record_ext_in_msg_info& data) const { - return cb.store_long_bool(2, 2) - && t_MsgAddressExt.store_from(cb, data.src) - && t_MsgAddressInt.store_from(cb, data.dest) - && t_Grams.store_from(cb, data.import_fee); -} - -bool CommonMsgInfo::pack_ext_in_msg_info(vm::CellBuilder& cb, Ref src, Ref dest, Ref import_fee) const { - return cb.store_long_bool(2, 2) - && t_MsgAddressExt.store_from(cb, src) - && t_MsgAddressInt.store_from(cb, dest) - && t_Grams.store_from(cb, import_fee); -} - -bool CommonMsgInfo::cell_pack(Ref& cell_ref, const CommonMsgInfo::Record_ext_in_msg_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfo::cell_pack_ext_in_msg_info(Ref& cell_ref, Ref src, Ref dest, Ref import_fee) const { - vm::CellBuilder cb; - return pack_ext_in_msg_info(cb, std::move(src), std::move(dest), std::move(import_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfo::pack(vm::CellBuilder& cb, const CommonMsgInfo::Record_ext_out_msg_info& data) const { - return cb.store_long_bool(3, 2) - && t_MsgAddressInt.store_from(cb, data.src) - && t_MsgAddressExt.store_from(cb, data.dest) - && cb.store_ulong_rchk_bool(data.created_lt, 64) - && cb.store_ulong_rchk_bool(data.created_at, 32); -} - -bool CommonMsgInfo::cell_pack(Ref& cell_ref, const CommonMsgInfo::Record_ext_out_msg_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(1) - && pp.open("int_msg_info") - && pp.fetch_uint_field(cs, 1, "ihr_disabled") - && pp.fetch_uint_field(cs, 1, "bounce") - && pp.fetch_uint_field(cs, 1, "bounced") - && pp.field("src") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("dest") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("value") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("ihr_fee") - && t_Grams.print_skip(pp, cs) - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "created_lt") - && pp.fetch_uint_field(cs, 32, "created_at") - && pp.close(); - case ext_in_msg_info: - return cs.advance(2) - && pp.open("ext_in_msg_info") - && pp.field("src") - && t_MsgAddressExt.print_skip(pp, cs) - && pp.field("dest") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("import_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case ext_out_msg_info: - return cs.advance(2) - && pp.open("ext_out_msg_info") - && pp.field("src") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("dest") - && t_MsgAddressExt.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "created_lt") - && pp.fetch_uint_field(cs, 32, "created_at") - && pp.close(); - } - return pp.fail("unknown constructor for CommonMsgInfo"); -} - -const CommonMsgInfo t_CommonMsgInfo; - -// -// code for type `CommonMsgInfoRelaxed` -// -constexpr char CommonMsgInfoRelaxed::cons_len[2]; -constexpr unsigned char CommonMsgInfoRelaxed::cons_tag[2]; - -int CommonMsgInfoRelaxed::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.have(1) ? int_msg_info : -1; - case ext_out_msg_info: - return cs.prefetch_ulong(2) == 3 ? ext_out_msg_info : -1; - } - return -1; -} - -bool CommonMsgInfoRelaxed::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(4) - && t_MsgAddress.skip(cs) - && t_MsgAddressInt.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(96); - case ext_out_msg_info: - return cs.advance(2) - && t_MsgAddress.skip(cs) - && t_MsgAddressExt.skip(cs) - && cs.advance(96); - } - return false; -} - -bool CommonMsgInfoRelaxed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(4) - && t_MsgAddress.validate_skip(ops, cs, weak) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(96); - case ext_out_msg_info: - return cs.fetch_ulong(2) == 3 - && t_MsgAddress.validate_skip(ops, cs, weak) - && t_MsgAddressExt.validate_skip(ops, cs, weak) - && cs.advance(96); - } - return false; -} - -bool CommonMsgInfoRelaxed::unpack(vm::CellSlice& cs, CommonMsgInfoRelaxed::Record_int_msg_info& data) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_bool_to(data.ihr_disabled) - && cs.fetch_bool_to(data.bounce) - && cs.fetch_bool_to(data.bounced) - && t_MsgAddress.fetch_to(cs, data.src) - && t_MsgAddressInt.fetch_to(cs, data.dest) - && t_CurrencyCollection.fetch_to(cs, data.value) - && t_Grams.fetch_to(cs, data.ihr_fee) - && t_Grams.fetch_to(cs, data.fwd_fee) - && cs.fetch_uint_to(64, data.created_lt) - && cs.fetch_uint_to(32, data.created_at); -} - -bool CommonMsgInfoRelaxed::cell_unpack(Ref cell_ref, CommonMsgInfoRelaxed::Record_int_msg_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CommonMsgInfoRelaxed::unpack(vm::CellSlice& cs, CommonMsgInfoRelaxed::Record_ext_out_msg_info& data) const { - return cs.fetch_ulong(2) == 3 - && t_MsgAddress.fetch_to(cs, data.src) - && t_MsgAddressExt.fetch_to(cs, data.dest) - && cs.fetch_uint_to(64, data.created_lt) - && cs.fetch_uint_to(32, data.created_at); -} - -bool CommonMsgInfoRelaxed::cell_unpack(Ref cell_ref, CommonMsgInfoRelaxed::Record_ext_out_msg_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CommonMsgInfoRelaxed::pack(vm::CellBuilder& cb, const CommonMsgInfoRelaxed::Record_int_msg_info& data) const { - return cb.store_long_bool(0, 1) - && cb.store_ulong_rchk_bool(data.ihr_disabled, 1) - && cb.store_ulong_rchk_bool(data.bounce, 1) - && cb.store_ulong_rchk_bool(data.bounced, 1) - && t_MsgAddress.store_from(cb, data.src) - && t_MsgAddressInt.store_from(cb, data.dest) - && t_CurrencyCollection.store_from(cb, data.value) - && t_Grams.store_from(cb, data.ihr_fee) - && t_Grams.store_from(cb, data.fwd_fee) - && cb.store_ulong_rchk_bool(data.created_lt, 64) - && cb.store_ulong_rchk_bool(data.created_at, 32); -} - -bool CommonMsgInfoRelaxed::cell_pack(Ref& cell_ref, const CommonMsgInfoRelaxed::Record_int_msg_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfoRelaxed::pack(vm::CellBuilder& cb, const CommonMsgInfoRelaxed::Record_ext_out_msg_info& data) const { - return cb.store_long_bool(3, 2) - && t_MsgAddress.store_from(cb, data.src) - && t_MsgAddressExt.store_from(cb, data.dest) - && cb.store_ulong_rchk_bool(data.created_lt, 64) - && cb.store_ulong_rchk_bool(data.created_at, 32); -} - -bool CommonMsgInfoRelaxed::cell_pack(Ref& cell_ref, const CommonMsgInfoRelaxed::Record_ext_out_msg_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CommonMsgInfoRelaxed::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(1) - && pp.open("int_msg_info") - && pp.fetch_uint_field(cs, 1, "ihr_disabled") - && pp.fetch_uint_field(cs, 1, "bounce") - && pp.fetch_uint_field(cs, 1, "bounced") - && pp.field("src") - && t_MsgAddress.print_skip(pp, cs) - && pp.field("dest") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("value") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("ihr_fee") - && t_Grams.print_skip(pp, cs) - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "created_lt") - && pp.fetch_uint_field(cs, 32, "created_at") - && pp.close(); - case ext_out_msg_info: - return cs.fetch_ulong(2) == 3 - && pp.open("ext_out_msg_info") - && pp.field("src") - && t_MsgAddress.print_skip(pp, cs) - && pp.field("dest") - && t_MsgAddressExt.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "created_lt") - && pp.fetch_uint_field(cs, 32, "created_at") - && pp.close(); - } - return pp.fail("unknown constructor for CommonMsgInfoRelaxed"); -} - -const CommonMsgInfoRelaxed t_CommonMsgInfoRelaxed; - -// -// code for type `TickTock` -// - -int TickTock::check_tag(const vm::CellSlice& cs) const { - return tick_tock; -} - -bool TickTock::unpack(vm::CellSlice& cs, TickTock::Record& data) const { - return cs.fetch_bool_to(data.tick) - && cs.fetch_bool_to(data.tock); -} - -bool TickTock::unpack_tick_tock(vm::CellSlice& cs, bool& tick, bool& tock) const { - return cs.fetch_bool_to(tick) - && cs.fetch_bool_to(tock); -} - -bool TickTock::cell_unpack(Ref cell_ref, TickTock::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TickTock::cell_unpack_tick_tock(Ref cell_ref, bool& tick, bool& tock) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tick_tock(cs, tick, tock) && cs.empty_ext(); -} - -bool TickTock::pack(vm::CellBuilder& cb, const TickTock::Record& data) const { - return cb.store_ulong_rchk_bool(data.tick, 1) - && cb.store_ulong_rchk_bool(data.tock, 1); -} - -bool TickTock::pack_tick_tock(vm::CellBuilder& cb, bool tick, bool tock) const { - return cb.store_ulong_rchk_bool(tick, 1) - && cb.store_ulong_rchk_bool(tock, 1); -} - -bool TickTock::cell_pack(Ref& cell_ref, const TickTock::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TickTock::cell_pack_tick_tock(Ref& cell_ref, bool tick, bool tock) const { - vm::CellBuilder cb; - return pack_tick_tock(cb, tick, tock) && std::move(cb).finalize_to(cell_ref); -} - -bool TickTock::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("tick_tock") - && pp.fetch_uint_field(cs, 1, "tick") - && pp.fetch_uint_field(cs, 1, "tock") - && pp.close(); -} - -const TickTock t_TickTock; - -// -// code for type `StateInit` -// - -int StateInit::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool StateInit::skip(vm::CellSlice& cs) const { - return t_Maybe_natwidth_5.skip(cs) - && t_Maybe_TickTock.skip(cs) - && t_Maybe_Ref_Cell.skip(cs) - && t_Maybe_Ref_Cell.skip(cs) - && t_HashmapE_256_SimpleLib.skip(cs); -} - -bool StateInit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_natwidth_5.validate_skip(ops, cs, weak) - && t_Maybe_TickTock.validate_skip(ops, cs, weak) - && t_Maybe_Ref_Cell.validate_skip(ops, cs, weak) - && t_Maybe_Ref_Cell.validate_skip(ops, cs, weak) - && t_HashmapE_256_SimpleLib.validate_skip(ops, cs, weak); -} - -bool StateInit::unpack(vm::CellSlice& cs, StateInit::Record& data) const { - return t_Maybe_natwidth_5.fetch_to(cs, data.split_depth) - && t_Maybe_TickTock.fetch_to(cs, data.special) - && t_Maybe_Ref_Cell.fetch_to(cs, data.code) - && t_Maybe_Ref_Cell.fetch_to(cs, data.data) - && t_HashmapE_256_SimpleLib.fetch_to(cs, data.library); -} - -bool StateInit::cell_unpack(Ref cell_ref, StateInit::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool StateInit::pack(vm::CellBuilder& cb, const StateInit::Record& data) const { - return t_Maybe_natwidth_5.store_from(cb, data.split_depth) - && t_Maybe_TickTock.store_from(cb, data.special) - && t_Maybe_Ref_Cell.store_from(cb, data.code) - && t_Maybe_Ref_Cell.store_from(cb, data.data) - && t_HashmapE_256_SimpleLib.store_from(cb, data.library); -} - -bool StateInit::cell_pack(Ref& cell_ref, const StateInit::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool StateInit::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("split_depth") - && t_Maybe_natwidth_5.print_skip(pp, cs) - && pp.field("special") - && t_Maybe_TickTock.print_skip(pp, cs) - && pp.field("code") - && t_Maybe_Ref_Cell.print_skip(pp, cs) - && pp.field("data") - && t_Maybe_Ref_Cell.print_skip(pp, cs) - && pp.field("library") - && t_HashmapE_256_SimpleLib.print_skip(pp, cs) - && pp.close(); -} - -const StateInit t_StateInit; - -// -// code for type `SimpleLib` -// - -int SimpleLib::check_tag(const vm::CellSlice& cs) const { - return simple_lib; -} - -bool SimpleLib::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance_ext(0x10001); -} - -bool SimpleLib::unpack(vm::CellSlice& cs, SimpleLib::Record& data) const { - return cs.fetch_bool_to(data.public1) - && cs.fetch_ref_to(data.root); -} - -bool SimpleLib::unpack_simple_lib(vm::CellSlice& cs, bool& public1, Ref& root) const { - return cs.fetch_bool_to(public1) - && cs.fetch_ref_to(root); -} - -bool SimpleLib::cell_unpack(Ref cell_ref, SimpleLib::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SimpleLib::cell_unpack_simple_lib(Ref cell_ref, bool& public1, Ref& root) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_simple_lib(cs, public1, root) && cs.empty_ext(); -} - -bool SimpleLib::pack(vm::CellBuilder& cb, const SimpleLib::Record& data) const { - return cb.store_ulong_rchk_bool(data.public1, 1) - && cb.store_ref_bool(data.root); -} - -bool SimpleLib::pack_simple_lib(vm::CellBuilder& cb, bool public1, Ref root) const { - return cb.store_ulong_rchk_bool(public1, 1) - && cb.store_ref_bool(root); -} - -bool SimpleLib::cell_pack(Ref& cell_ref, const SimpleLib::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SimpleLib::cell_pack_simple_lib(Ref& cell_ref, bool public1, Ref root) const { - vm::CellBuilder cb; - return pack_simple_lib(cb, public1, std::move(root)) && std::move(cb).finalize_to(cell_ref); -} - -bool SimpleLib::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("simple_lib") - && pp.fetch_uint_field(cs, 1, "public") - && pp.field("root") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const SimpleLib t_SimpleLib; - -// -// code for type `Message` -// - -int Message::check_tag(const vm::CellSlice& cs) const { - return message; -} - -bool Message::skip(vm::CellSlice& cs) const { - return t_CommonMsgInfo.skip(cs) - && t_Maybe_Either_StateInit_Ref_StateInit.skip(cs) - && Either{X_, RefT{X_}}.skip(cs); -} - -bool Message::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CommonMsgInfo.validate_skip(ops, cs, weak) - && t_Maybe_Either_StateInit_Ref_StateInit.validate_skip(ops, cs, weak) - && Either{X_, RefT{X_}}.validate_skip(ops, cs, weak); -} - -bool Message::unpack(vm::CellSlice& cs, Message::Record& data) const { - return t_CommonMsgInfo.fetch_to(cs, data.info) - && t_Maybe_Either_StateInit_Ref_StateInit.fetch_to(cs, data.init) - && Either{X_, RefT{X_}}.fetch_to(cs, data.body); -} - -bool Message::unpack_message(vm::CellSlice& cs, Ref& info, Ref& init, Ref& body) const { - return t_CommonMsgInfo.fetch_to(cs, info) - && t_Maybe_Either_StateInit_Ref_StateInit.fetch_to(cs, init) - && Either{X_, RefT{X_}}.fetch_to(cs, body); -} - -bool Message::cell_unpack(Ref cell_ref, Message::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Message::cell_unpack_message(Ref cell_ref, Ref& info, Ref& init, Ref& body) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_message(cs, info, init, body) && cs.empty_ext(); -} - -bool Message::pack(vm::CellBuilder& cb, const Message::Record& data) const { - return t_CommonMsgInfo.store_from(cb, data.info) - && t_Maybe_Either_StateInit_Ref_StateInit.store_from(cb, data.init) - && Either{X_, RefT{X_}}.store_from(cb, data.body); -} - -bool Message::pack_message(vm::CellBuilder& cb, Ref info, Ref init, Ref body) const { - return t_CommonMsgInfo.store_from(cb, info) - && t_Maybe_Either_StateInit_Ref_StateInit.store_from(cb, init) - && Either{X_, RefT{X_}}.store_from(cb, body); -} - -bool Message::cell_pack(Ref& cell_ref, const Message::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Message::cell_pack_message(Ref& cell_ref, Ref info, Ref init, Ref body) const { - vm::CellBuilder cb; - return pack_message(cb, std::move(info), std::move(init), std::move(body)) && std::move(cb).finalize_to(cell_ref); -} - -bool Message::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("message") - && pp.field("info") - && t_CommonMsgInfo.print_skip(pp, cs) - && pp.field("init") - && t_Maybe_Either_StateInit_Ref_StateInit.print_skip(pp, cs) - && pp.field("body") - && Either{X_, RefT{X_}}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `MessageRelaxed` -// - -int MessageRelaxed::check_tag(const vm::CellSlice& cs) const { - return message; -} - -bool MessageRelaxed::skip(vm::CellSlice& cs) const { - return t_CommonMsgInfoRelaxed.skip(cs) - && t_Maybe_Either_StateInit_Ref_StateInit.skip(cs) - && Either{X_, RefT{X_}}.skip(cs); -} - -bool MessageRelaxed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CommonMsgInfoRelaxed.validate_skip(ops, cs, weak) - && t_Maybe_Either_StateInit_Ref_StateInit.validate_skip(ops, cs, weak) - && Either{X_, RefT{X_}}.validate_skip(ops, cs, weak); -} - -bool MessageRelaxed::unpack(vm::CellSlice& cs, MessageRelaxed::Record& data) const { - return t_CommonMsgInfoRelaxed.fetch_to(cs, data.info) - && t_Maybe_Either_StateInit_Ref_StateInit.fetch_to(cs, data.init) - && Either{X_, RefT{X_}}.fetch_to(cs, data.body); -} - -bool MessageRelaxed::unpack_message(vm::CellSlice& cs, Ref& info, Ref& init, Ref& body) const { - return t_CommonMsgInfoRelaxed.fetch_to(cs, info) - && t_Maybe_Either_StateInit_Ref_StateInit.fetch_to(cs, init) - && Either{X_, RefT{X_}}.fetch_to(cs, body); -} - -bool MessageRelaxed::cell_unpack(Ref cell_ref, MessageRelaxed::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MessageRelaxed::cell_unpack_message(Ref cell_ref, Ref& info, Ref& init, Ref& body) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_message(cs, info, init, body) && cs.empty_ext(); -} - -bool MessageRelaxed::pack(vm::CellBuilder& cb, const MessageRelaxed::Record& data) const { - return t_CommonMsgInfoRelaxed.store_from(cb, data.info) - && t_Maybe_Either_StateInit_Ref_StateInit.store_from(cb, data.init) - && Either{X_, RefT{X_}}.store_from(cb, data.body); -} - -bool MessageRelaxed::pack_message(vm::CellBuilder& cb, Ref info, Ref init, Ref body) const { - return t_CommonMsgInfoRelaxed.store_from(cb, info) - && t_Maybe_Either_StateInit_Ref_StateInit.store_from(cb, init) - && Either{X_, RefT{X_}}.store_from(cb, body); -} - -bool MessageRelaxed::cell_pack(Ref& cell_ref, const MessageRelaxed::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MessageRelaxed::cell_pack_message(Ref& cell_ref, Ref info, Ref init, Ref body) const { - vm::CellBuilder cb; - return pack_message(cb, std::move(info), std::move(init), std::move(body)) && std::move(cb).finalize_to(cell_ref); -} - -bool MessageRelaxed::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("message") - && pp.field("info") - && t_CommonMsgInfoRelaxed.print_skip(pp, cs) - && pp.field("init") - && t_Maybe_Either_StateInit_Ref_StateInit.print_skip(pp, cs) - && pp.field("body") - && Either{X_, RefT{X_}}.print_skip(pp, cs) - && pp.close(); -} - - -// -// code for type `MessageAny` -// - -int MessageAny::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool MessageAny::skip(vm::CellSlice& cs) const { - return t_Message_Any.skip(cs); -} - -bool MessageAny::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Message_Any.validate_skip(ops, cs, weak); -} - -bool MessageAny::unpack(vm::CellSlice& cs, MessageAny::Record& data) const { - return t_Message_Any.fetch_to(cs, data.x); -} - -bool MessageAny::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_Message_Any.fetch_to(cs, x); -} - -bool MessageAny::cell_unpack(Ref cell_ref, MessageAny::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MessageAny::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool MessageAny::pack(vm::CellBuilder& cb, const MessageAny::Record& data) const { - return t_Message_Any.store_from(cb, data.x); -} - -bool MessageAny::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_Message_Any.store_from(cb, x); -} - -bool MessageAny::cell_pack(Ref& cell_ref, const MessageAny::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MessageAny::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool MessageAny::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_Message_Any.print_skip(pp, cs) - && pp.close(); -} - -const MessageAny t_MessageAny; - -// -// code for type `IntermediateAddress` -// -constexpr char IntermediateAddress::cons_len[3]; -constexpr unsigned char IntermediateAddress::cons_tag[3]; - -int IntermediateAddress::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case interm_addr_regular: - return cs.have(1) ? interm_addr_regular : -1; - case interm_addr_simple: - return cs.have(2) ? interm_addr_simple : -1; - case interm_addr_ext: - return cs.have(2) ? interm_addr_ext : -1; - } - return -1; -} - -bool IntermediateAddress::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case interm_addr_regular: - return cs.advance(8); - case interm_addr_simple: - return cs.advance(74); - case interm_addr_ext: - return cs.advance(98); - } - return false; -} - -bool IntermediateAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case interm_addr_regular: { - int use_dest_bits; - return cs.advance(1) - && cs.fetch_uint_leq(96, use_dest_bits); - } - case interm_addr_simple: - return cs.advance(74); - case interm_addr_ext: - return cs.advance(98); - } - return false; -} - -bool IntermediateAddress::unpack(vm::CellSlice& cs, IntermediateAddress::Record_interm_addr_regular& data) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_uint_leq(96, data.use_dest_bits); -} - -bool IntermediateAddress::unpack_interm_addr_regular(vm::CellSlice& cs, int& use_dest_bits) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_uint_leq(96, use_dest_bits); -} - -bool IntermediateAddress::cell_unpack(Ref cell_ref, IntermediateAddress::Record_interm_addr_regular& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool IntermediateAddress::cell_unpack_interm_addr_regular(Ref cell_ref, int& use_dest_bits) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_interm_addr_regular(cs, use_dest_bits) && cs.empty_ext(); -} - -bool IntermediateAddress::unpack(vm::CellSlice& cs, IntermediateAddress::Record_interm_addr_simple& data) const { - return cs.fetch_ulong(2) == 2 - && cs.fetch_int_to(8, data.workchain_id) - && cs.fetch_uint_to(64, data.addr_pfx); -} - -bool IntermediateAddress::unpack_interm_addr_simple(vm::CellSlice& cs, int& workchain_id, unsigned long long& addr_pfx) const { - return cs.fetch_ulong(2) == 2 - && cs.fetch_int_to(8, workchain_id) - && cs.fetch_uint_to(64, addr_pfx); -} - -bool IntermediateAddress::cell_unpack(Ref cell_ref, IntermediateAddress::Record_interm_addr_simple& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool IntermediateAddress::cell_unpack_interm_addr_simple(Ref cell_ref, int& workchain_id, unsigned long long& addr_pfx) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_interm_addr_simple(cs, workchain_id, addr_pfx) && cs.empty_ext(); -} - -bool IntermediateAddress::unpack(vm::CellSlice& cs, IntermediateAddress::Record_interm_addr_ext& data) const { - return cs.fetch_ulong(2) == 3 - && cs.fetch_int_to(32, data.workchain_id) - && cs.fetch_uint_to(64, data.addr_pfx); -} - -bool IntermediateAddress::unpack_interm_addr_ext(vm::CellSlice& cs, int& workchain_id, unsigned long long& addr_pfx) const { - return cs.fetch_ulong(2) == 3 - && cs.fetch_int_to(32, workchain_id) - && cs.fetch_uint_to(64, addr_pfx); -} - -bool IntermediateAddress::cell_unpack(Ref cell_ref, IntermediateAddress::Record_interm_addr_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool IntermediateAddress::cell_unpack_interm_addr_ext(Ref cell_ref, int& workchain_id, unsigned long long& addr_pfx) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_interm_addr_ext(cs, workchain_id, addr_pfx) && cs.empty_ext(); -} - -bool IntermediateAddress::pack(vm::CellBuilder& cb, const IntermediateAddress::Record_interm_addr_regular& data) const { - return cb.store_long_bool(0, 1) - && cb.store_uint_leq(96, data.use_dest_bits); -} - -bool IntermediateAddress::pack_interm_addr_regular(vm::CellBuilder& cb, int use_dest_bits) const { - return cb.store_long_bool(0, 1) - && cb.store_uint_leq(96, use_dest_bits); -} - -bool IntermediateAddress::cell_pack(Ref& cell_ref, const IntermediateAddress::Record_interm_addr_regular& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::cell_pack_interm_addr_regular(Ref& cell_ref, int use_dest_bits) const { - vm::CellBuilder cb; - return pack_interm_addr_regular(cb, use_dest_bits) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::pack(vm::CellBuilder& cb, const IntermediateAddress::Record_interm_addr_simple& data) const { - return cb.store_long_bool(2, 2) - && cb.store_long_rchk_bool(data.workchain_id, 8) - && cb.store_ulong_rchk_bool(data.addr_pfx, 64); -} - -bool IntermediateAddress::pack_interm_addr_simple(vm::CellBuilder& cb, int workchain_id, unsigned long long addr_pfx) const { - return cb.store_long_bool(2, 2) - && cb.store_long_rchk_bool(workchain_id, 8) - && cb.store_ulong_rchk_bool(addr_pfx, 64); -} - -bool IntermediateAddress::cell_pack(Ref& cell_ref, const IntermediateAddress::Record_interm_addr_simple& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::cell_pack_interm_addr_simple(Ref& cell_ref, int workchain_id, unsigned long long addr_pfx) const { - vm::CellBuilder cb; - return pack_interm_addr_simple(cb, workchain_id, addr_pfx) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::pack(vm::CellBuilder& cb, const IntermediateAddress::Record_interm_addr_ext& data) const { - return cb.store_long_bool(3, 2) - && cb.store_long_rchk_bool(data.workchain_id, 32) - && cb.store_ulong_rchk_bool(data.addr_pfx, 64); -} - -bool IntermediateAddress::pack_interm_addr_ext(vm::CellBuilder& cb, int workchain_id, unsigned long long addr_pfx) const { - return cb.store_long_bool(3, 2) - && cb.store_long_rchk_bool(workchain_id, 32) - && cb.store_ulong_rchk_bool(addr_pfx, 64); -} - -bool IntermediateAddress::cell_pack(Ref& cell_ref, const IntermediateAddress::Record_interm_addr_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::cell_pack_interm_addr_ext(Ref& cell_ref, int workchain_id, unsigned long long addr_pfx) const { - vm::CellBuilder cb; - return pack_interm_addr_ext(cb, workchain_id, addr_pfx) && std::move(cb).finalize_to(cell_ref); -} - -bool IntermediateAddress::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case interm_addr_regular: { - int use_dest_bits; - return cs.advance(1) - && pp.open("interm_addr_regular") - && cs.fetch_uint_leq(96, use_dest_bits) - && pp.field_int(use_dest_bits, "use_dest_bits") - && pp.close(); - } - case interm_addr_simple: - return cs.advance(2) - && pp.open("interm_addr_simple") - && pp.fetch_int_field(cs, 8, "workchain_id") - && pp.fetch_uint_field(cs, 64, "addr_pfx") - && pp.close(); - case interm_addr_ext: - return cs.advance(2) - && pp.open("interm_addr_ext") - && pp.fetch_int_field(cs, 32, "workchain_id") - && pp.fetch_uint_field(cs, 64, "addr_pfx") - && pp.close(); - } - return pp.fail("unknown constructor for IntermediateAddress"); -} - -const IntermediateAddress t_IntermediateAddress; - -// -// code for type `MsgEnvelope` -// -constexpr unsigned char MsgEnvelope::cons_tag[1]; - -int MsgEnvelope::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 4 ? msg_envelope : -1; -} - -bool MsgEnvelope::skip(vm::CellSlice& cs) const { - return cs.advance(4) - && t_IntermediateAddress.skip(cs) - && t_IntermediateAddress.skip(cs) - && t_Grams.skip(cs) - && cs.advance_refs(1); -} - -bool MsgEnvelope::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 4 - && t_IntermediateAddress.validate_skip(ops, cs, weak) - && t_IntermediateAddress.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Message_Any.validate_skip_ref(ops, cs, weak); -} - -bool MsgEnvelope::unpack(vm::CellSlice& cs, MsgEnvelope::Record& data) const { - return cs.fetch_ulong(4) == 4 - && t_IntermediateAddress.fetch_to(cs, data.cur_addr) - && t_IntermediateAddress.fetch_to(cs, data.next_addr) - && t_Grams.fetch_to(cs, data.fwd_fee_remaining) - && cs.fetch_ref_to(data.msg); -} - -bool MsgEnvelope::cell_unpack(Ref cell_ref, MsgEnvelope::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgEnvelope::pack(vm::CellBuilder& cb, const MsgEnvelope::Record& data) const { - return cb.store_long_bool(4, 4) - && t_IntermediateAddress.store_from(cb, data.cur_addr) - && t_IntermediateAddress.store_from(cb, data.next_addr) - && t_Grams.store_from(cb, data.fwd_fee_remaining) - && cb.store_ref_bool(data.msg); -} - -bool MsgEnvelope::cell_pack(Ref& cell_ref, const MsgEnvelope::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgEnvelope::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 4 - && pp.open("msg_envelope") - && pp.field("cur_addr") - && t_IntermediateAddress.print_skip(pp, cs) - && pp.field("next_addr") - && t_IntermediateAddress.print_skip(pp, cs) - && pp.field("fwd_fee_remaining") - && t_Grams.print_skip(pp, cs) - && pp.field("msg") - && t_Message_Any.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const MsgEnvelope t_MsgEnvelope; - -// -// code for type `InMsg` -// -constexpr unsigned char InMsg::cons_tag[7]; - -int InMsg::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.prefetch_ulong(3) == 0 ? msg_import_ext : -1; - case msg_import_ihr: - return cs.have(3) ? msg_import_ihr : -1; - case msg_import_imm: - return cs.have(3) ? msg_import_imm : -1; - case msg_import_fin: - return cs.have(3) ? msg_import_fin : -1; - case msg_import_tr: - return cs.have(3) ? msg_import_tr : -1; - case msg_discard_fin: - return cs.have(3) ? msg_discard_fin : -1; - case msg_discard_tr: - return cs.have(3) ? msg_discard_tr : -1; - } - return -1; -} - -bool InMsg::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.advance_ext(0x20003); - case msg_import_ihr: - return cs.advance_ext(0x20003) - && t_Grams.skip(cs) - && cs.advance_refs(1); - case msg_import_imm: - return cs.advance_ext(0x20003) - && t_Grams.skip(cs); - case msg_import_fin: - return cs.advance_ext(0x20003) - && t_Grams.skip(cs); - case msg_import_tr: - return cs.advance_ext(0x20003) - && t_Grams.skip(cs); - case msg_discard_fin: - return cs.advance_ext(0x10043) - && t_Grams.skip(cs); - case msg_discard_tr: - return cs.advance_ext(0x10043) - && t_Grams.skip(cs) - && cs.advance_refs(1); - } - return false; -} - -bool InMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.fetch_ulong(3) == 0 - && t_Message_Any.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak); - case msg_import_ihr: - return cs.advance(3) - && t_Message_Any.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance_refs(1); - case msg_import_imm: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case msg_import_fin: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case msg_import_tr: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case msg_discard_fin: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && cs.advance(64) - && t_Grams.validate_skip(ops, cs, weak); - case msg_discard_tr: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && cs.advance(64) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance_refs(1); - } - return false; -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_import_ext& data) const { - return cs.fetch_ulong(3) == 0 - && cs.fetch_ref_to(data.msg) - && cs.fetch_ref_to(data.transaction); -} - -bool InMsg::unpack_msg_import_ext(vm::CellSlice& cs, Ref& msg, Ref& transaction) const { - return cs.fetch_ulong(3) == 0 - && cs.fetch_ref_to(msg) - && cs.fetch_ref_to(transaction); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_import_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::cell_unpack_msg_import_ext(Ref cell_ref, Ref& msg, Ref& transaction) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_import_ext(cs, msg, transaction) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_import_ihr& data) const { - return cs.fetch_ulong(3) == 2 - && cs.fetch_ref_to(data.msg) - && cs.fetch_ref_to(data.transaction) - && t_Grams.fetch_to(cs, data.ihr_fee) - && cs.fetch_ref_to(data.proof_created); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_import_ihr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_import_imm& data) const { - return cs.fetch_ulong(3) == 3 - && cs.fetch_ref_to(data.in_msg) - && cs.fetch_ref_to(data.transaction) - && t_Grams.fetch_to(cs, data.fwd_fee); -} - -bool InMsg::unpack_msg_import_imm(vm::CellSlice& cs, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const { - return cs.fetch_ulong(3) == 3 - && cs.fetch_ref_to(in_msg) - && cs.fetch_ref_to(transaction) - && t_Grams.fetch_to(cs, fwd_fee); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_import_imm& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::cell_unpack_msg_import_imm(Ref cell_ref, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_import_imm(cs, in_msg, transaction, fwd_fee) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_import_fin& data) const { - return cs.fetch_ulong(3) == 4 - && cs.fetch_ref_to(data.in_msg) - && cs.fetch_ref_to(data.transaction) - && t_Grams.fetch_to(cs, data.fwd_fee); -} - -bool InMsg::unpack_msg_import_fin(vm::CellSlice& cs, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const { - return cs.fetch_ulong(3) == 4 - && cs.fetch_ref_to(in_msg) - && cs.fetch_ref_to(transaction) - && t_Grams.fetch_to(cs, fwd_fee); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_import_fin& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::cell_unpack_msg_import_fin(Ref cell_ref, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_import_fin(cs, in_msg, transaction, fwd_fee) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_import_tr& data) const { - return cs.fetch_ulong(3) == 5 - && cs.fetch_ref_to(data.in_msg) - && cs.fetch_ref_to(data.out_msg) - && t_Grams.fetch_to(cs, data.transit_fee); -} - -bool InMsg::unpack_msg_import_tr(vm::CellSlice& cs, Ref& in_msg, Ref& out_msg, Ref& transit_fee) const { - return cs.fetch_ulong(3) == 5 - && cs.fetch_ref_to(in_msg) - && cs.fetch_ref_to(out_msg) - && t_Grams.fetch_to(cs, transit_fee); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_import_tr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::cell_unpack_msg_import_tr(Ref cell_ref, Ref& in_msg, Ref& out_msg, Ref& transit_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_import_tr(cs, in_msg, out_msg, transit_fee) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_discard_fin& data) const { - return cs.fetch_ulong(3) == 6 - && cs.fetch_ref_to(data.in_msg) - && cs.fetch_uint_to(64, data.transaction_id) - && t_Grams.fetch_to(cs, data.fwd_fee); -} - -bool InMsg::unpack_msg_discard_fin(vm::CellSlice& cs, Ref& in_msg, unsigned long long& transaction_id, Ref& fwd_fee) const { - return cs.fetch_ulong(3) == 6 - && cs.fetch_ref_to(in_msg) - && cs.fetch_uint_to(64, transaction_id) - && t_Grams.fetch_to(cs, fwd_fee); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_discard_fin& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::cell_unpack_msg_discard_fin(Ref cell_ref, Ref& in_msg, unsigned long long& transaction_id, Ref& fwd_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_discard_fin(cs, in_msg, transaction_id, fwd_fee) && cs.empty_ext(); -} - -bool InMsg::unpack(vm::CellSlice& cs, InMsg::Record_msg_discard_tr& data) const { - return cs.fetch_ulong(3) == 7 - && cs.fetch_ref_to(data.in_msg) - && cs.fetch_uint_to(64, data.transaction_id) - && t_Grams.fetch_to(cs, data.fwd_fee) - && cs.fetch_ref_to(data.proof_delivered); -} - -bool InMsg::cell_unpack(Ref cell_ref, InMsg::Record_msg_discard_tr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_import_ext& data) const { - return cb.store_long_bool(0, 3) - && cb.store_ref_bool(data.msg) - && cb.store_ref_bool(data.transaction); -} - -bool InMsg::pack_msg_import_ext(vm::CellBuilder& cb, Ref msg, Ref transaction) const { - return cb.store_long_bool(0, 3) - && cb.store_ref_bool(msg) - && cb.store_ref_bool(transaction); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_import_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::cell_pack_msg_import_ext(Ref& cell_ref, Ref msg, Ref transaction) const { - vm::CellBuilder cb; - return pack_msg_import_ext(cb, std::move(msg), std::move(transaction)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_import_ihr& data) const { - return cb.store_long_bool(2, 3) - && cb.store_ref_bool(data.msg) - && cb.store_ref_bool(data.transaction) - && t_Grams.store_from(cb, data.ihr_fee) - && cb.store_ref_bool(data.proof_created); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_import_ihr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_import_imm& data) const { - return cb.store_long_bool(3, 3) - && cb.store_ref_bool(data.in_msg) - && cb.store_ref_bool(data.transaction) - && t_Grams.store_from(cb, data.fwd_fee); -} - -bool InMsg::pack_msg_import_imm(vm::CellBuilder& cb, Ref in_msg, Ref transaction, Ref fwd_fee) const { - return cb.store_long_bool(3, 3) - && cb.store_ref_bool(in_msg) - && cb.store_ref_bool(transaction) - && t_Grams.store_from(cb, fwd_fee); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_import_imm& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::cell_pack_msg_import_imm(Ref& cell_ref, Ref in_msg, Ref transaction, Ref fwd_fee) const { - vm::CellBuilder cb; - return pack_msg_import_imm(cb, std::move(in_msg), std::move(transaction), std::move(fwd_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_import_fin& data) const { - return cb.store_long_bool(4, 3) - && cb.store_ref_bool(data.in_msg) - && cb.store_ref_bool(data.transaction) - && t_Grams.store_from(cb, data.fwd_fee); -} - -bool InMsg::pack_msg_import_fin(vm::CellBuilder& cb, Ref in_msg, Ref transaction, Ref fwd_fee) const { - return cb.store_long_bool(4, 3) - && cb.store_ref_bool(in_msg) - && cb.store_ref_bool(transaction) - && t_Grams.store_from(cb, fwd_fee); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_import_fin& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::cell_pack_msg_import_fin(Ref& cell_ref, Ref in_msg, Ref transaction, Ref fwd_fee) const { - vm::CellBuilder cb; - return pack_msg_import_fin(cb, std::move(in_msg), std::move(transaction), std::move(fwd_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_import_tr& data) const { - return cb.store_long_bool(5, 3) - && cb.store_ref_bool(data.in_msg) - && cb.store_ref_bool(data.out_msg) - && t_Grams.store_from(cb, data.transit_fee); -} - -bool InMsg::pack_msg_import_tr(vm::CellBuilder& cb, Ref in_msg, Ref out_msg, Ref transit_fee) const { - return cb.store_long_bool(5, 3) - && cb.store_ref_bool(in_msg) - && cb.store_ref_bool(out_msg) - && t_Grams.store_from(cb, transit_fee); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_import_tr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::cell_pack_msg_import_tr(Ref& cell_ref, Ref in_msg, Ref out_msg, Ref transit_fee) const { - vm::CellBuilder cb; - return pack_msg_import_tr(cb, std::move(in_msg), std::move(out_msg), std::move(transit_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_discard_fin& data) const { - return cb.store_long_bool(6, 3) - && cb.store_ref_bool(data.in_msg) - && cb.store_ulong_rchk_bool(data.transaction_id, 64) - && t_Grams.store_from(cb, data.fwd_fee); -} - -bool InMsg::pack_msg_discard_fin(vm::CellBuilder& cb, Ref in_msg, unsigned long long transaction_id, Ref fwd_fee) const { - return cb.store_long_bool(6, 3) - && cb.store_ref_bool(in_msg) - && cb.store_ulong_rchk_bool(transaction_id, 64) - && t_Grams.store_from(cb, fwd_fee); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_discard_fin& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::cell_pack_msg_discard_fin(Ref& cell_ref, Ref in_msg, unsigned long long transaction_id, Ref fwd_fee) const { - vm::CellBuilder cb; - return pack_msg_discard_fin(cb, std::move(in_msg), transaction_id, std::move(fwd_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::pack(vm::CellBuilder& cb, const InMsg::Record_msg_discard_tr& data) const { - return cb.store_long_bool(7, 3) - && cb.store_ref_bool(data.in_msg) - && cb.store_ulong_rchk_bool(data.transaction_id, 64) - && t_Grams.store_from(cb, data.fwd_fee) - && cb.store_ref_bool(data.proof_delivered); -} - -bool InMsg::cell_pack(Ref& cell_ref, const InMsg::Record_msg_discard_tr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsg::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.fetch_ulong(3) == 0 - && pp.open("msg_import_ext") - && pp.field("msg") - && t_Message_Any.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_import_ihr: - return cs.advance(3) - && pp.open("msg_import_ihr") - && pp.field("msg") - && t_Message_Any.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.field("ihr_fee") - && t_Grams.print_skip(pp, cs) - && pp.field("proof_created") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_import_imm: - return cs.advance(3) - && pp.open("msg_import_imm") - && pp.field("in_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case msg_import_fin: - return cs.advance(3) - && pp.open("msg_import_fin") - && pp.field("in_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case msg_import_tr: - return cs.advance(3) - && pp.open("msg_import_tr") - && pp.field("in_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("transit_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case msg_discard_fin: - return cs.advance(3) - && pp.open("msg_discard_fin") - && pp.field("in_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 64, "transaction_id") - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case msg_discard_tr: - return cs.advance(3) - && pp.open("msg_discard_tr") - && pp.field("in_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 64, "transaction_id") - && pp.field("fwd_fee") - && t_Grams.print_skip(pp, cs) - && pp.field("proof_delivered") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for InMsg"); -} - -const InMsg t_InMsg; - -// -// code for type `ImportFees` -// - -int ImportFees::check_tag(const vm::CellSlice& cs) const { - return import_fees; -} - -bool ImportFees::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool ImportFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ImportFees::unpack(vm::CellSlice& cs, ImportFees::Record& data) const { - return t_Grams.fetch_to(cs, data.fees_collected) - && t_CurrencyCollection.fetch_to(cs, data.value_imported); -} - -bool ImportFees::unpack_import_fees(vm::CellSlice& cs, Ref& fees_collected, Ref& value_imported) const { - return t_Grams.fetch_to(cs, fees_collected) - && t_CurrencyCollection.fetch_to(cs, value_imported); -} - -bool ImportFees::cell_unpack(Ref cell_ref, ImportFees::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ImportFees::cell_unpack_import_fees(Ref cell_ref, Ref& fees_collected, Ref& value_imported) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_import_fees(cs, fees_collected, value_imported) && cs.empty_ext(); -} - -bool ImportFees::pack(vm::CellBuilder& cb, const ImportFees::Record& data) const { - return t_Grams.store_from(cb, data.fees_collected) - && t_CurrencyCollection.store_from(cb, data.value_imported); -} - -bool ImportFees::pack_import_fees(vm::CellBuilder& cb, Ref fees_collected, Ref value_imported) const { - return t_Grams.store_from(cb, fees_collected) - && t_CurrencyCollection.store_from(cb, value_imported); -} - -bool ImportFees::cell_pack(Ref& cell_ref, const ImportFees::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ImportFees::cell_pack_import_fees(Ref& cell_ref, Ref fees_collected, Ref value_imported) const { - vm::CellBuilder cb; - return pack_import_fees(cb, std::move(fees_collected), std::move(value_imported)) && std::move(cb).finalize_to(cell_ref); -} - -bool ImportFees::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("import_fees") - && pp.field("fees_collected") - && t_Grams.print_skip(pp, cs) - && pp.field("value_imported") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ImportFees t_ImportFees; - -// -// code for type `InMsgDescr` -// - -int InMsgDescr::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool InMsgDescr::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_256_InMsg_ImportFees.skip(cs); -} - -bool InMsgDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_256_InMsg_ImportFees.validate_skip(ops, cs, weak); -} - -bool InMsgDescr::unpack(vm::CellSlice& cs, InMsgDescr::Record& data) const { - return t_HashmapAugE_256_InMsg_ImportFees.fetch_to(cs, data.x); -} - -bool InMsgDescr::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_256_InMsg_ImportFees.fetch_to(cs, x); -} - -bool InMsgDescr::cell_unpack(Ref cell_ref, InMsgDescr::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool InMsgDescr::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool InMsgDescr::pack(vm::CellBuilder& cb, const InMsgDescr::Record& data) const { - return t_HashmapAugE_256_InMsg_ImportFees.store_from(cb, data.x); -} - -bool InMsgDescr::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_256_InMsg_ImportFees.store_from(cb, x); -} - -bool InMsgDescr::cell_pack(Ref& cell_ref, const InMsgDescr::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsgDescr::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool InMsgDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_256_InMsg_ImportFees.print_skip(pp, cs) - && pp.close(); -} - -const InMsgDescr t_InMsgDescr; - -// -// code for type `OutMsg` -// -constexpr char OutMsg::cons_len[8]; -constexpr unsigned char OutMsg::cons_tag[8]; - -int OutMsg::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.have(3) ? msg_export_ext : -1; - case msg_export_imm: - return cs.have(3) ? msg_export_imm : -1; - case msg_export_new: - return cs.have(3) ? msg_export_new : -1; - case msg_export_tr: - return cs.have(3) ? msg_export_tr : -1; - case msg_export_deq: - return cs.have(4) ? msg_export_deq : -1; - case msg_export_deq_short: - return cs.have(4) ? msg_export_deq_short : -1; - case msg_export_tr_req: - return cs.have(3) ? msg_export_tr_req : -1; - case msg_export_deq_imm: - return cs.prefetch_ulong(3) == 4 ? msg_export_deq_imm : -1; - } - return -1; -} - -bool OutMsg::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.advance_ext(0x20003); - case msg_export_imm: - return cs.advance_ext(0x30003); - case msg_export_new: - return cs.advance_ext(0x20003); - case msg_export_tr: - return cs.advance_ext(0x20003); - case msg_export_deq: - return cs.advance_ext(0x10043); - case msg_export_deq_short: - return cs.advance(420); - case msg_export_tr_req: - return cs.advance_ext(0x20003); - case msg_export_deq_imm: - return cs.advance_ext(0x20003); - } - return false; -} - -bool OutMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.advance(3) - && t_Message_Any.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak); - case msg_export_imm: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && t_InMsg.validate_skip_ref(ops, cs, weak); - case msg_export_new: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_Transaction.validate_skip_ref(ops, cs, weak); - case msg_export_tr: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_InMsg.validate_skip_ref(ops, cs, weak); - case msg_export_deq: - return cs.advance(4) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && cs.advance(63); - case msg_export_deq_short: - return cs.advance(420); - case msg_export_tr_req: - return cs.advance(3) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_InMsg.validate_skip_ref(ops, cs, weak); - case msg_export_deq_imm: - return cs.fetch_ulong(3) == 4 - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak) - && t_InMsg.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_ext& data) const { - return cs.fetch_ulong(3) == 0 - && cs.fetch_ref_to(data.msg) - && cs.fetch_ref_to(data.transaction); -} - -bool OutMsg::unpack_msg_export_ext(vm::CellSlice& cs, Ref& msg, Ref& transaction) const { - return cs.fetch_ulong(3) == 0 - && cs.fetch_ref_to(msg) - && cs.fetch_ref_to(transaction); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_ext(Ref cell_ref, Ref& msg, Ref& transaction) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_ext(cs, msg, transaction) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_imm& data) const { - return cs.fetch_ulong(3) == 2 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_ref_to(data.transaction) - && cs.fetch_ref_to(data.reimport); -} - -bool OutMsg::unpack_msg_export_imm(vm::CellSlice& cs, Ref& out_msg, Ref& transaction, Ref& reimport) const { - return cs.fetch_ulong(3) == 2 - && cs.fetch_ref_to(out_msg) - && cs.fetch_ref_to(transaction) - && cs.fetch_ref_to(reimport); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_imm& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_imm(Ref cell_ref, Ref& out_msg, Ref& transaction, Ref& reimport) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_imm(cs, out_msg, transaction, reimport) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_new& data) const { - return cs.fetch_ulong(3) == 1 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_ref_to(data.transaction); -} - -bool OutMsg::unpack_msg_export_new(vm::CellSlice& cs, Ref& out_msg, Ref& transaction) const { - return cs.fetch_ulong(3) == 1 - && cs.fetch_ref_to(out_msg) - && cs.fetch_ref_to(transaction); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_new& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_new(Ref cell_ref, Ref& out_msg, Ref& transaction) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_new(cs, out_msg, transaction) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_tr& data) const { - return cs.fetch_ulong(3) == 3 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_ref_to(data.imported); -} - -bool OutMsg::unpack_msg_export_tr(vm::CellSlice& cs, Ref& out_msg, Ref& imported) const { - return cs.fetch_ulong(3) == 3 - && cs.fetch_ref_to(out_msg) - && cs.fetch_ref_to(imported); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_tr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_tr(Ref cell_ref, Ref& out_msg, Ref& imported) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_tr(cs, out_msg, imported) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_deq& data) const { - return cs.fetch_ulong(4) == 12 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_uint_to(63, data.import_block_lt); -} - -bool OutMsg::unpack_msg_export_deq(vm::CellSlice& cs, Ref& out_msg, long long& import_block_lt) const { - return cs.fetch_ulong(4) == 12 - && cs.fetch_ref_to(out_msg) - && cs.fetch_uint_to(63, import_block_lt); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_deq& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_deq(Ref cell_ref, Ref& out_msg, long long& import_block_lt) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_deq(cs, out_msg, import_block_lt) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_deq_short& data) const { - return cs.fetch_ulong(4) == 13 - && cs.fetch_bits_to(data.msg_env_hash.bits(), 256) - && cs.fetch_int_to(32, data.next_workchain) - && cs.fetch_uint_to(64, data.next_addr_pfx) - && cs.fetch_uint_to(64, data.import_block_lt); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_deq_short& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_tr_req& data) const { - return cs.fetch_ulong(3) == 7 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_ref_to(data.imported); -} - -bool OutMsg::unpack_msg_export_tr_req(vm::CellSlice& cs, Ref& out_msg, Ref& imported) const { - return cs.fetch_ulong(3) == 7 - && cs.fetch_ref_to(out_msg) - && cs.fetch_ref_to(imported); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_tr_req& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_tr_req(Ref cell_ref, Ref& out_msg, Ref& imported) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_tr_req(cs, out_msg, imported) && cs.empty_ext(); -} - -bool OutMsg::unpack(vm::CellSlice& cs, OutMsg::Record_msg_export_deq_imm& data) const { - return cs.fetch_ulong(3) == 4 - && cs.fetch_ref_to(data.out_msg) - && cs.fetch_ref_to(data.reimport); -} - -bool OutMsg::unpack_msg_export_deq_imm(vm::CellSlice& cs, Ref& out_msg, Ref& reimport) const { - return cs.fetch_ulong(3) == 4 - && cs.fetch_ref_to(out_msg) - && cs.fetch_ref_to(reimport); -} - -bool OutMsg::cell_unpack(Ref cell_ref, OutMsg::Record_msg_export_deq_imm& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsg::cell_unpack_msg_export_deq_imm(Ref cell_ref, Ref& out_msg, Ref& reimport) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_msg_export_deq_imm(cs, out_msg, reimport) && cs.empty_ext(); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_ext& data) const { - return cb.store_long_bool(0, 3) - && cb.store_ref_bool(data.msg) - && cb.store_ref_bool(data.transaction); -} - -bool OutMsg::pack_msg_export_ext(vm::CellBuilder& cb, Ref msg, Ref transaction) const { - return cb.store_long_bool(0, 3) - && cb.store_ref_bool(msg) - && cb.store_ref_bool(transaction); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_ext(Ref& cell_ref, Ref msg, Ref transaction) const { - vm::CellBuilder cb; - return pack_msg_export_ext(cb, std::move(msg), std::move(transaction)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_imm& data) const { - return cb.store_long_bool(2, 3) - && cb.store_ref_bool(data.out_msg) - && cb.store_ref_bool(data.transaction) - && cb.store_ref_bool(data.reimport); -} - -bool OutMsg::pack_msg_export_imm(vm::CellBuilder& cb, Ref out_msg, Ref transaction, Ref reimport) const { - return cb.store_long_bool(2, 3) - && cb.store_ref_bool(out_msg) - && cb.store_ref_bool(transaction) - && cb.store_ref_bool(reimport); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_imm& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_imm(Ref& cell_ref, Ref out_msg, Ref transaction, Ref reimport) const { - vm::CellBuilder cb; - return pack_msg_export_imm(cb, std::move(out_msg), std::move(transaction), std::move(reimport)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_new& data) const { - return cb.store_long_bool(1, 3) - && cb.store_ref_bool(data.out_msg) - && cb.store_ref_bool(data.transaction); -} - -bool OutMsg::pack_msg_export_new(vm::CellBuilder& cb, Ref out_msg, Ref transaction) const { - return cb.store_long_bool(1, 3) - && cb.store_ref_bool(out_msg) - && cb.store_ref_bool(transaction); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_new& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_new(Ref& cell_ref, Ref out_msg, Ref transaction) const { - vm::CellBuilder cb; - return pack_msg_export_new(cb, std::move(out_msg), std::move(transaction)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_tr& data) const { - return cb.store_long_bool(3, 3) - && cb.store_ref_bool(data.out_msg) - && cb.store_ref_bool(data.imported); -} - -bool OutMsg::pack_msg_export_tr(vm::CellBuilder& cb, Ref out_msg, Ref imported) const { - return cb.store_long_bool(3, 3) - && cb.store_ref_bool(out_msg) - && cb.store_ref_bool(imported); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_tr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_tr(Ref& cell_ref, Ref out_msg, Ref imported) const { - vm::CellBuilder cb; - return pack_msg_export_tr(cb, std::move(out_msg), std::move(imported)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_deq& data) const { - return cb.store_long_bool(12, 4) - && cb.store_ref_bool(data.out_msg) - && cb.store_ulong_rchk_bool(data.import_block_lt, 63); -} - -bool OutMsg::pack_msg_export_deq(vm::CellBuilder& cb, Ref out_msg, long long import_block_lt) const { - return cb.store_long_bool(12, 4) - && cb.store_ref_bool(out_msg) - && cb.store_ulong_rchk_bool(import_block_lt, 63); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_deq& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_deq(Ref& cell_ref, Ref out_msg, long long import_block_lt) const { - vm::CellBuilder cb; - return pack_msg_export_deq(cb, std::move(out_msg), import_block_lt) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_deq_short& data) const { - return cb.store_long_bool(13, 4) - && cb.store_bits_bool(data.msg_env_hash.cbits(), 256) - && cb.store_long_rchk_bool(data.next_workchain, 32) - && cb.store_ulong_rchk_bool(data.next_addr_pfx, 64) - && cb.store_ulong_rchk_bool(data.import_block_lt, 64); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_deq_short& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_tr_req& data) const { - return cb.store_long_bool(7, 3) - && cb.store_ref_bool(data.out_msg) - && cb.store_ref_bool(data.imported); -} - -bool OutMsg::pack_msg_export_tr_req(vm::CellBuilder& cb, Ref out_msg, Ref imported) const { - return cb.store_long_bool(7, 3) - && cb.store_ref_bool(out_msg) - && cb.store_ref_bool(imported); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_tr_req& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_tr_req(Ref& cell_ref, Ref out_msg, Ref imported) const { - vm::CellBuilder cb; - return pack_msg_export_tr_req(cb, std::move(out_msg), std::move(imported)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::pack(vm::CellBuilder& cb, const OutMsg::Record_msg_export_deq_imm& data) const { - return cb.store_long_bool(4, 3) - && cb.store_ref_bool(data.out_msg) - && cb.store_ref_bool(data.reimport); -} - -bool OutMsg::pack_msg_export_deq_imm(vm::CellBuilder& cb, Ref out_msg, Ref reimport) const { - return cb.store_long_bool(4, 3) - && cb.store_ref_bool(out_msg) - && cb.store_ref_bool(reimport); -} - -bool OutMsg::cell_pack(Ref& cell_ref, const OutMsg::Record_msg_export_deq_imm& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::cell_pack_msg_export_deq_imm(Ref& cell_ref, Ref out_msg, Ref reimport) const { - vm::CellBuilder cb; - return pack_msg_export_deq_imm(cb, std::move(out_msg), std::move(reimport)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsg::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.advance(3) - && pp.open("msg_export_ext") - && pp.field("msg") - && t_Message_Any.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_export_imm: - return cs.advance(3) - && pp.open("msg_export_imm") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.field("reimport") - && t_InMsg.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_export_new: - return cs.advance(3) - && pp.open("msg_export_new") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_export_tr: - return cs.advance(3) - && pp.open("msg_export_tr") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("imported") - && t_InMsg.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_export_deq: - return cs.advance(4) - && pp.open("msg_export_deq") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 63, "import_block_lt") - && pp.close(); - case msg_export_deq_short: - return cs.advance(4) - && pp.open("msg_export_deq_short") - && pp.fetch_bits_field(cs, 256, "msg_env_hash") - && pp.fetch_int_field(cs, 32, "next_workchain") - && pp.fetch_uint_field(cs, 64, "next_addr_pfx") - && pp.fetch_uint_field(cs, 64, "import_block_lt") - && pp.close(); - case msg_export_tr_req: - return cs.advance(3) - && pp.open("msg_export_tr_req") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("imported") - && t_InMsg.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case msg_export_deq_imm: - return cs.fetch_ulong(3) == 4 - && pp.open("msg_export_deq_imm") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.field("reimport") - && t_InMsg.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for OutMsg"); -} - -const OutMsg t_OutMsg; - -// -// code for type `EnqueuedMsg` -// - -int EnqueuedMsg::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool EnqueuedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) - && t_MsgEnvelope.validate_skip_ref(ops, cs, weak); -} - -bool EnqueuedMsg::unpack(vm::CellSlice& cs, EnqueuedMsg::Record& data) const { - return cs.fetch_uint_to(64, data.enqueued_lt) - && cs.fetch_ref_to(data.out_msg); -} - -bool EnqueuedMsg::unpack_cons1(vm::CellSlice& cs, unsigned long long& enqueued_lt, Ref& out_msg) const { - return cs.fetch_uint_to(64, enqueued_lt) - && cs.fetch_ref_to(out_msg); -} - -bool EnqueuedMsg::cell_unpack(Ref cell_ref, EnqueuedMsg::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool EnqueuedMsg::cell_unpack_cons1(Ref cell_ref, unsigned long long& enqueued_lt, Ref& out_msg) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, enqueued_lt, out_msg) && cs.empty_ext(); -} - -bool EnqueuedMsg::pack(vm::CellBuilder& cb, const EnqueuedMsg::Record& data) const { - return cb.store_ulong_rchk_bool(data.enqueued_lt, 64) - && cb.store_ref_bool(data.out_msg); -} - -bool EnqueuedMsg::pack_cons1(vm::CellBuilder& cb, unsigned long long enqueued_lt, Ref out_msg) const { - return cb.store_ulong_rchk_bool(enqueued_lt, 64) - && cb.store_ref_bool(out_msg); -} - -bool EnqueuedMsg::cell_pack(Ref& cell_ref, const EnqueuedMsg::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool EnqueuedMsg::cell_pack_cons1(Ref& cell_ref, unsigned long long enqueued_lt, Ref out_msg) const { - vm::CellBuilder cb; - return pack_cons1(cb, enqueued_lt, std::move(out_msg)) && std::move(cb).finalize_to(cell_ref); -} - -bool EnqueuedMsg::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_uint_field(cs, 64, "enqueued_lt") - && pp.field("out_msg") - && t_MsgEnvelope.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const EnqueuedMsg t_EnqueuedMsg; - -// -// code for type `OutMsgDescr` -// - -int OutMsgDescr::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool OutMsgDescr::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.skip(cs); -} - -bool OutMsgDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool OutMsgDescr::unpack(vm::CellSlice& cs, OutMsgDescr::Record& data) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.fetch_to(cs, data.x); -} - -bool OutMsgDescr::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.fetch_to(cs, x); -} - -bool OutMsgDescr::cell_unpack(Ref cell_ref, OutMsgDescr::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsgDescr::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool OutMsgDescr::pack(vm::CellBuilder& cb, const OutMsgDescr::Record& data) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.store_from(cb, data.x); -} - -bool OutMsgDescr::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_256_OutMsg_CurrencyCollection.store_from(cb, x); -} - -bool OutMsgDescr::cell_pack(Ref& cell_ref, const OutMsgDescr::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgDescr::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_256_OutMsg_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const OutMsgDescr t_OutMsgDescr; - -// -// code for type `OutMsgQueue` -// - -int OutMsgQueue::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool OutMsgQueue::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.skip(cs); -} - -bool OutMsgQueue::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.validate_skip(ops, cs, weak); -} - -bool OutMsgQueue::unpack(vm::CellSlice& cs, OutMsgQueue::Record& data) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.fetch_to(cs, data.x); -} - -bool OutMsgQueue::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.fetch_to(cs, x); -} - -bool OutMsgQueue::cell_unpack(Ref cell_ref, OutMsgQueue::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsgQueue::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool OutMsgQueue::pack(vm::CellBuilder& cb, const OutMsgQueue::Record& data) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.store_from(cb, data.x); -} - -bool OutMsgQueue::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_352_EnqueuedMsg_uint64.store_from(cb, x); -} - -bool OutMsgQueue::cell_pack(Ref& cell_ref, const OutMsgQueue::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgQueue::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgQueue::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_352_EnqueuedMsg_uint64.print_skip(pp, cs) - && pp.close(); -} - -const OutMsgQueue t_OutMsgQueue; - -// -// code for type `ProcessedUpto` -// - -int ProcessedUpto::check_tag(const vm::CellSlice& cs) const { - return processed_upto; -} - -bool ProcessedUpto::unpack(vm::CellSlice& cs, ProcessedUpto::Record& data) const { - return cs.fetch_uint_to(64, data.last_msg_lt) - && cs.fetch_bits_to(data.last_msg_hash.bits(), 256); -} - -bool ProcessedUpto::unpack_processed_upto(vm::CellSlice& cs, unsigned long long& last_msg_lt, td::BitArray<256>& last_msg_hash) const { - return cs.fetch_uint_to(64, last_msg_lt) - && cs.fetch_bits_to(last_msg_hash.bits(), 256); -} - -bool ProcessedUpto::cell_unpack(Ref cell_ref, ProcessedUpto::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProcessedUpto::cell_unpack_processed_upto(Ref cell_ref, unsigned long long& last_msg_lt, td::BitArray<256>& last_msg_hash) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_processed_upto(cs, last_msg_lt, last_msg_hash) && cs.empty_ext(); -} - -bool ProcessedUpto::pack(vm::CellBuilder& cb, const ProcessedUpto::Record& data) const { - return cb.store_ulong_rchk_bool(data.last_msg_lt, 64) - && cb.store_bits_bool(data.last_msg_hash.cbits(), 256); -} - -bool ProcessedUpto::pack_processed_upto(vm::CellBuilder& cb, unsigned long long last_msg_lt, td::BitArray<256> last_msg_hash) const { - return cb.store_ulong_rchk_bool(last_msg_lt, 64) - && cb.store_bits_bool(last_msg_hash.cbits(), 256); -} - -bool ProcessedUpto::cell_pack(Ref& cell_ref, const ProcessedUpto::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProcessedUpto::cell_pack_processed_upto(Ref& cell_ref, unsigned long long last_msg_lt, td::BitArray<256> last_msg_hash) const { - vm::CellBuilder cb; - return pack_processed_upto(cb, last_msg_lt, last_msg_hash) && std::move(cb).finalize_to(cell_ref); -} - -bool ProcessedUpto::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("processed_upto") - && pp.fetch_uint_field(cs, 64, "last_msg_lt") - && pp.fetch_bits_field(cs, 256, "last_msg_hash") - && pp.close(); -} - -const ProcessedUpto t_ProcessedUpto; - -// -// code for type `ProcessedInfo` -// - -int ProcessedInfo::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ProcessedInfo::skip(vm::CellSlice& cs) const { - return t_HashmapE_96_ProcessedUpto.skip(cs); -} - -bool ProcessedInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_96_ProcessedUpto.validate_skip(ops, cs, weak); -} - -bool ProcessedInfo::unpack(vm::CellSlice& cs, ProcessedInfo::Record& data) const { - return t_HashmapE_96_ProcessedUpto.fetch_to(cs, data.x); -} - -bool ProcessedInfo::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapE_96_ProcessedUpto.fetch_to(cs, x); -} - -bool ProcessedInfo::cell_unpack(Ref cell_ref, ProcessedInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProcessedInfo::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ProcessedInfo::pack(vm::CellBuilder& cb, const ProcessedInfo::Record& data) const { - return t_HashmapE_96_ProcessedUpto.store_from(cb, data.x); -} - -bool ProcessedInfo::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapE_96_ProcessedUpto.store_from(cb, x); -} - -bool ProcessedInfo::cell_pack(Ref& cell_ref, const ProcessedInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProcessedInfo::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ProcessedInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapE_96_ProcessedUpto.print_skip(pp, cs) - && pp.close(); -} - -const ProcessedInfo t_ProcessedInfo; - -// -// code for type `IhrPendingSince` -// - -int IhrPendingSince::check_tag(const vm::CellSlice& cs) const { - return ihr_pending; -} - -bool IhrPendingSince::unpack(vm::CellSlice& cs, IhrPendingSince::Record& data) const { - return cs.fetch_uint_to(64, data.import_lt); -} - -bool IhrPendingSince::unpack_ihr_pending(vm::CellSlice& cs, unsigned long long& import_lt) const { - return cs.fetch_uint_to(64, import_lt); -} - -bool IhrPendingSince::cell_unpack(Ref cell_ref, IhrPendingSince::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool IhrPendingSince::cell_unpack_ihr_pending(Ref cell_ref, unsigned long long& import_lt) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ihr_pending(cs, import_lt) && cs.empty_ext(); -} - -bool IhrPendingSince::pack(vm::CellBuilder& cb, const IhrPendingSince::Record& data) const { - return cb.store_ulong_rchk_bool(data.import_lt, 64); -} - -bool IhrPendingSince::pack_ihr_pending(vm::CellBuilder& cb, unsigned long long import_lt) const { - return cb.store_ulong_rchk_bool(import_lt, 64); -} - -bool IhrPendingSince::cell_pack(Ref& cell_ref, const IhrPendingSince::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool IhrPendingSince::cell_pack_ihr_pending(Ref& cell_ref, unsigned long long import_lt) const { - vm::CellBuilder cb; - return pack_ihr_pending(cb, import_lt) && std::move(cb).finalize_to(cell_ref); -} - -bool IhrPendingSince::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("ihr_pending") - && pp.fetch_uint_field(cs, 64, "import_lt") - && pp.close(); -} - -const IhrPendingSince t_IhrPendingSince; - -// -// code for type `IhrPendingInfo` -// - -int IhrPendingInfo::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool IhrPendingInfo::skip(vm::CellSlice& cs) const { - return t_HashmapE_320_IhrPendingSince.skip(cs); -} - -bool IhrPendingInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_320_IhrPendingSince.validate_skip(ops, cs, weak); -} - -bool IhrPendingInfo::unpack(vm::CellSlice& cs, IhrPendingInfo::Record& data) const { - return t_HashmapE_320_IhrPendingSince.fetch_to(cs, data.x); -} - -bool IhrPendingInfo::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapE_320_IhrPendingSince.fetch_to(cs, x); -} - -bool IhrPendingInfo::cell_unpack(Ref cell_ref, IhrPendingInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool IhrPendingInfo::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool IhrPendingInfo::pack(vm::CellBuilder& cb, const IhrPendingInfo::Record& data) const { - return t_HashmapE_320_IhrPendingSince.store_from(cb, data.x); -} - -bool IhrPendingInfo::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapE_320_IhrPendingSince.store_from(cb, x); -} - -bool IhrPendingInfo::cell_pack(Ref& cell_ref, const IhrPendingInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool IhrPendingInfo::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool IhrPendingInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapE_320_IhrPendingSince.print_skip(pp, cs) - && pp.close(); -} - -const IhrPendingInfo t_IhrPendingInfo; - -// -// code for type `OutMsgQueueInfo` -// - -int OutMsgQueueInfo::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool OutMsgQueueInfo::skip(vm::CellSlice& cs) const { - return t_OutMsgQueue.skip(cs) - && t_ProcessedInfo.skip(cs) - && t_IhrPendingInfo.skip(cs); -} - -bool OutMsgQueueInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_OutMsgQueue.validate_skip(ops, cs, weak) - && t_ProcessedInfo.validate_skip(ops, cs, weak) - && t_IhrPendingInfo.validate_skip(ops, cs, weak); -} - -bool OutMsgQueueInfo::unpack(vm::CellSlice& cs, OutMsgQueueInfo::Record& data) const { - return t_OutMsgQueue.fetch_to(cs, data.out_queue) - && t_ProcessedInfo.fetch_to(cs, data.proc_info) - && t_IhrPendingInfo.fetch_to(cs, data.ihr_pending); -} - -bool OutMsgQueueInfo::unpack_cons1(vm::CellSlice& cs, Ref& out_queue, Ref& proc_info, Ref& ihr_pending) const { - return t_OutMsgQueue.fetch_to(cs, out_queue) - && t_ProcessedInfo.fetch_to(cs, proc_info) - && t_IhrPendingInfo.fetch_to(cs, ihr_pending); -} - -bool OutMsgQueueInfo::cell_unpack(Ref cell_ref, OutMsgQueueInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutMsgQueueInfo::cell_unpack_cons1(Ref cell_ref, Ref& out_queue, Ref& proc_info, Ref& ihr_pending) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, out_queue, proc_info, ihr_pending) && cs.empty_ext(); -} - -bool OutMsgQueueInfo::pack(vm::CellBuilder& cb, const OutMsgQueueInfo::Record& data) const { - return t_OutMsgQueue.store_from(cb, data.out_queue) - && t_ProcessedInfo.store_from(cb, data.proc_info) - && t_IhrPendingInfo.store_from(cb, data.ihr_pending); -} - -bool OutMsgQueueInfo::pack_cons1(vm::CellBuilder& cb, Ref out_queue, Ref proc_info, Ref ihr_pending) const { - return t_OutMsgQueue.store_from(cb, out_queue) - && t_ProcessedInfo.store_from(cb, proc_info) - && t_IhrPendingInfo.store_from(cb, ihr_pending); -} - -bool OutMsgQueueInfo::cell_pack(Ref& cell_ref, const OutMsgQueueInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgQueueInfo::cell_pack_cons1(Ref& cell_ref, Ref out_queue, Ref proc_info, Ref ihr_pending) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(out_queue), std::move(proc_info), std::move(ihr_pending)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutMsgQueueInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("out_queue") - && t_OutMsgQueue.print_skip(pp, cs) - && pp.field("proc_info") - && t_ProcessedInfo.print_skip(pp, cs) - && pp.field("ihr_pending") - && t_IhrPendingInfo.print_skip(pp, cs) - && pp.close(); -} - -const OutMsgQueueInfo t_OutMsgQueueInfo; - -// -// code for type `StorageUsed` -// - -int StorageUsed::check_tag(const vm::CellSlice& cs) const { - return storage_used; -} - -bool StorageUsed::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) - && t_VarUInteger_7.skip(cs) - && t_VarUInteger_7.skip(cs); -} - -bool StorageUsed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) - && t_VarUInteger_7.validate_skip(ops, cs, weak) - && t_VarUInteger_7.validate_skip(ops, cs, weak); -} - -bool StorageUsed::unpack(vm::CellSlice& cs, StorageUsed::Record& data) const { - return t_VarUInteger_7.fetch_to(cs, data.cells) - && t_VarUInteger_7.fetch_to(cs, data.bits) - && t_VarUInteger_7.fetch_to(cs, data.public_cells); -} - -bool StorageUsed::unpack_storage_used(vm::CellSlice& cs, Ref& cells, Ref& bits, Ref& public_cells) const { - return t_VarUInteger_7.fetch_to(cs, cells) - && t_VarUInteger_7.fetch_to(cs, bits) - && t_VarUInteger_7.fetch_to(cs, public_cells); -} - -bool StorageUsed::cell_unpack(Ref cell_ref, StorageUsed::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool StorageUsed::cell_unpack_storage_used(Ref cell_ref, Ref& cells, Ref& bits, Ref& public_cells) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_storage_used(cs, cells, bits, public_cells) && cs.empty_ext(); -} - -bool StorageUsed::pack(vm::CellBuilder& cb, const StorageUsed::Record& data) const { - return t_VarUInteger_7.store_from(cb, data.cells) - && t_VarUInteger_7.store_from(cb, data.bits) - && t_VarUInteger_7.store_from(cb, data.public_cells); -} - -bool StorageUsed::pack_storage_used(vm::CellBuilder& cb, Ref cells, Ref bits, Ref public_cells) const { - return t_VarUInteger_7.store_from(cb, cells) - && t_VarUInteger_7.store_from(cb, bits) - && t_VarUInteger_7.store_from(cb, public_cells); -} - -bool StorageUsed::cell_pack(Ref& cell_ref, const StorageUsed::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageUsed::cell_pack_storage_used(Ref& cell_ref, Ref cells, Ref bits, Ref public_cells) const { - vm::CellBuilder cb; - return pack_storage_used(cb, std::move(cells), std::move(bits), std::move(public_cells)) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageUsed::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("storage_used") - && pp.field("cells") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.field("bits") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.field("public_cells") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.close(); -} - -const StorageUsed t_StorageUsed; - -// -// code for type `StorageUsedShort` -// - -int StorageUsedShort::check_tag(const vm::CellSlice& cs) const { - return storage_used_short; -} - -bool StorageUsedShort::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) - && t_VarUInteger_7.skip(cs); -} - -bool StorageUsedShort::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) - && t_VarUInteger_7.validate_skip(ops, cs, weak); -} - -bool StorageUsedShort::unpack(vm::CellSlice& cs, StorageUsedShort::Record& data) const { - return t_VarUInteger_7.fetch_to(cs, data.cells) - && t_VarUInteger_7.fetch_to(cs, data.bits); -} - -bool StorageUsedShort::unpack_storage_used_short(vm::CellSlice& cs, Ref& cells, Ref& bits) const { - return t_VarUInteger_7.fetch_to(cs, cells) - && t_VarUInteger_7.fetch_to(cs, bits); -} - -bool StorageUsedShort::cell_unpack(Ref cell_ref, StorageUsedShort::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool StorageUsedShort::cell_unpack_storage_used_short(Ref cell_ref, Ref& cells, Ref& bits) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_storage_used_short(cs, cells, bits) && cs.empty_ext(); -} - -bool StorageUsedShort::pack(vm::CellBuilder& cb, const StorageUsedShort::Record& data) const { - return t_VarUInteger_7.store_from(cb, data.cells) - && t_VarUInteger_7.store_from(cb, data.bits); -} - -bool StorageUsedShort::pack_storage_used_short(vm::CellBuilder& cb, Ref cells, Ref bits) const { - return t_VarUInteger_7.store_from(cb, cells) - && t_VarUInteger_7.store_from(cb, bits); -} - -bool StorageUsedShort::cell_pack(Ref& cell_ref, const StorageUsedShort::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageUsedShort::cell_pack_storage_used_short(Ref& cell_ref, Ref cells, Ref bits) const { - vm::CellBuilder cb; - return pack_storage_used_short(cb, std::move(cells), std::move(bits)) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageUsedShort::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("storage_used_short") - && pp.field("cells") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.field("bits") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.close(); -} - -const StorageUsedShort t_StorageUsedShort; - -// -// code for type `StorageInfo` -// - -int StorageInfo::check_tag(const vm::CellSlice& cs) const { - return storage_info; -} - -bool StorageInfo::skip(vm::CellSlice& cs) const { - return t_StorageUsed.skip(cs) - && cs.advance(32) - && t_Maybe_Grams.skip(cs); -} - -bool StorageInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_StorageUsed.validate_skip(ops, cs, weak) - && cs.advance(32) - && t_Maybe_Grams.validate_skip(ops, cs, weak); -} - -bool StorageInfo::unpack(vm::CellSlice& cs, StorageInfo::Record& data) const { - return t_StorageUsed.fetch_to(cs, data.used) - && cs.fetch_uint_to(32, data.last_paid) - && t_Maybe_Grams.fetch_to(cs, data.due_payment); -} - -bool StorageInfo::unpack_storage_info(vm::CellSlice& cs, Ref& used, unsigned& last_paid, Ref& due_payment) const { - return t_StorageUsed.fetch_to(cs, used) - && cs.fetch_uint_to(32, last_paid) - && t_Maybe_Grams.fetch_to(cs, due_payment); -} - -bool StorageInfo::cell_unpack(Ref cell_ref, StorageInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool StorageInfo::cell_unpack_storage_info(Ref cell_ref, Ref& used, unsigned& last_paid, Ref& due_payment) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_storage_info(cs, used, last_paid, due_payment) && cs.empty_ext(); -} - -bool StorageInfo::pack(vm::CellBuilder& cb, const StorageInfo::Record& data) const { - return t_StorageUsed.store_from(cb, data.used) - && cb.store_ulong_rchk_bool(data.last_paid, 32) - && t_Maybe_Grams.store_from(cb, data.due_payment); -} - -bool StorageInfo::pack_storage_info(vm::CellBuilder& cb, Ref used, unsigned last_paid, Ref due_payment) const { - return t_StorageUsed.store_from(cb, used) - && cb.store_ulong_rchk_bool(last_paid, 32) - && t_Maybe_Grams.store_from(cb, due_payment); -} - -bool StorageInfo::cell_pack(Ref& cell_ref, const StorageInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageInfo::cell_pack_storage_info(Ref& cell_ref, Ref used, unsigned last_paid, Ref due_payment) const { - vm::CellBuilder cb; - return pack_storage_info(cb, std::move(used), last_paid, std::move(due_payment)) && std::move(cb).finalize_to(cell_ref); -} - -bool StorageInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("storage_info") - && pp.field("used") - && t_StorageUsed.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "last_paid") - && pp.field("due_payment") - && t_Maybe_Grams.print_skip(pp, cs) - && pp.close(); -} - -const StorageInfo t_StorageInfo; - -// -// code for type `Account` -// - -int Account::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_none: - return cs.have(1) ? account_none : -1; - case account: - return cs.have(1) ? account : -1; - } - return -1; -} - -bool Account::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_none: - return cs.advance(1); - case account: - return cs.advance(1) - && t_MsgAddressInt.skip(cs) - && t_StorageInfo.skip(cs) - && t_AccountStorage.skip(cs); - } - return false; -} - -bool Account::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case account_none: - return cs.advance(1); - case account: - return cs.advance(1) - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && t_StorageInfo.validate_skip(ops, cs, weak) - && t_AccountStorage.validate_skip(ops, cs, weak); - } - return false; -} - -bool Account::unpack(vm::CellSlice& cs, Account::Record_account_none& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool Account::unpack_account_none(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool Account::cell_unpack(Ref cell_ref, Account::Record_account_none& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Account::cell_unpack_account_none(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_none(cs) && cs.empty_ext(); -} - -bool Account::unpack(vm::CellSlice& cs, Account::Record_account& data) const { - return cs.fetch_ulong(1) == 1 - && t_MsgAddressInt.fetch_to(cs, data.addr) - && t_StorageInfo.fetch_to(cs, data.storage_stat) - && t_AccountStorage.fetch_to(cs, data.storage); -} - -bool Account::unpack_account(vm::CellSlice& cs, Ref& addr, Ref& storage_stat, Ref& storage) const { - return cs.fetch_ulong(1) == 1 - && t_MsgAddressInt.fetch_to(cs, addr) - && t_StorageInfo.fetch_to(cs, storage_stat) - && t_AccountStorage.fetch_to(cs, storage); -} - -bool Account::cell_unpack(Ref cell_ref, Account::Record_account& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Account::cell_unpack_account(Ref cell_ref, Ref& addr, Ref& storage_stat, Ref& storage) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account(cs, addr, storage_stat, storage) && cs.empty_ext(); -} - -bool Account::pack(vm::CellBuilder& cb, const Account::Record_account_none& data) const { - return cb.store_long_bool(0, 1); -} - -bool Account::pack_account_none(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool Account::cell_pack(Ref& cell_ref, const Account::Record_account_none& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Account::cell_pack_account_none(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_account_none(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Account::pack(vm::CellBuilder& cb, const Account::Record_account& data) const { - return cb.store_long_bool(1, 1) - && t_MsgAddressInt.store_from(cb, data.addr) - && t_StorageInfo.store_from(cb, data.storage_stat) - && t_AccountStorage.store_from(cb, data.storage); -} - -bool Account::pack_account(vm::CellBuilder& cb, Ref addr, Ref storage_stat, Ref storage) const { - return cb.store_long_bool(1, 1) - && t_MsgAddressInt.store_from(cb, addr) - && t_StorageInfo.store_from(cb, storage_stat) - && t_AccountStorage.store_from(cb, storage); -} - -bool Account::cell_pack(Ref& cell_ref, const Account::Record_account& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Account::cell_pack_account(Ref& cell_ref, Ref addr, Ref storage_stat, Ref storage) const { - vm::CellBuilder cb; - return pack_account(cb, std::move(addr), std::move(storage_stat), std::move(storage)) && std::move(cb).finalize_to(cell_ref); -} - -bool Account::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_none: - return cs.advance(1) - && pp.cons("account_none"); - case account: - return cs.advance(1) - && pp.open("account") - && pp.field("addr") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.field("storage_stat") - && t_StorageInfo.print_skip(pp, cs) - && pp.field("storage") - && t_AccountStorage.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for Account"); -} - -const Account t_Account; - -// -// code for type `AccountStorage` -// - -int AccountStorage::check_tag(const vm::CellSlice& cs) const { - return account_storage; -} - -bool AccountStorage::skip(vm::CellSlice& cs) const { - return cs.advance(64) - && t_CurrencyCollection.skip(cs) - && t_AccountState.skip(cs); -} - -bool AccountStorage::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_AccountState.validate_skip(ops, cs, weak); -} - -bool AccountStorage::unpack(vm::CellSlice& cs, AccountStorage::Record& data) const { - return cs.fetch_uint_to(64, data.last_trans_lt) - && t_CurrencyCollection.fetch_to(cs, data.balance) - && t_AccountState.fetch_to(cs, data.state); -} - -bool AccountStorage::unpack_account_storage(vm::CellSlice& cs, unsigned long long& last_trans_lt, Ref& balance, Ref& state) const { - return cs.fetch_uint_to(64, last_trans_lt) - && t_CurrencyCollection.fetch_to(cs, balance) - && t_AccountState.fetch_to(cs, state); -} - -bool AccountStorage::cell_unpack(Ref cell_ref, AccountStorage::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountStorage::cell_unpack_account_storage(Ref cell_ref, unsigned long long& last_trans_lt, Ref& balance, Ref& state) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_storage(cs, last_trans_lt, balance, state) && cs.empty_ext(); -} - -bool AccountStorage::pack(vm::CellBuilder& cb, const AccountStorage::Record& data) const { - return cb.store_ulong_rchk_bool(data.last_trans_lt, 64) - && t_CurrencyCollection.store_from(cb, data.balance) - && t_AccountState.store_from(cb, data.state); -} - -bool AccountStorage::pack_account_storage(vm::CellBuilder& cb, unsigned long long last_trans_lt, Ref balance, Ref state) const { - return cb.store_ulong_rchk_bool(last_trans_lt, 64) - && t_CurrencyCollection.store_from(cb, balance) - && t_AccountState.store_from(cb, state); -} - -bool AccountStorage::cell_pack(Ref& cell_ref, const AccountStorage::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStorage::cell_pack_account_storage(Ref& cell_ref, unsigned long long last_trans_lt, Ref balance, Ref state) const { - vm::CellBuilder cb; - return pack_account_storage(cb, last_trans_lt, std::move(balance), std::move(state)) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStorage::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("account_storage") - && pp.fetch_uint_field(cs, 64, "last_trans_lt") - && pp.field("balance") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("state") - && t_AccountState.print_skip(pp, cs) - && pp.close(); -} - -const AccountStorage t_AccountStorage; - -// -// code for type `AccountState` -// -constexpr char AccountState::cons_len[3]; -constexpr unsigned char AccountState::cons_tag[3]; - -int AccountState::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_uninit: - return cs.have(2) ? account_uninit : -1; - case account_active: - return cs.have(1) ? account_active : -1; - case account_frozen: - return cs.have(2) ? account_frozen : -1; - } - return -1; -} - -bool AccountState::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_uninit: - return cs.advance(2); - case account_active: - return cs.advance(1) - && t_StateInit.skip(cs); - case account_frozen: - return cs.advance(258); - } - return false; -} - -bool AccountState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case account_uninit: - return cs.advance(2); - case account_active: - return cs.advance(1) - && t_StateInit.validate_skip(ops, cs, weak); - case account_frozen: - return cs.advance(258); - } - return false; -} - -bool AccountState::unpack(vm::CellSlice& cs, AccountState::Record_account_uninit& data) const { - return cs.fetch_ulong(2) == 0; -} - -bool AccountState::unpack_account_uninit(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0; -} - -bool AccountState::cell_unpack(Ref cell_ref, AccountState::Record_account_uninit& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountState::cell_unpack_account_uninit(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_uninit(cs) && cs.empty_ext(); -} - -bool AccountState::unpack(vm::CellSlice& cs, AccountState::Record_account_active& data) const { - return cs.fetch_ulong(1) == 1 - && t_StateInit.fetch_to(cs, data.x); -} - -bool AccountState::unpack_account_active(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_ulong(1) == 1 - && t_StateInit.fetch_to(cs, x); -} - -bool AccountState::cell_unpack(Ref cell_ref, AccountState::Record_account_active& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountState::cell_unpack_account_active(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_active(cs, x) && cs.empty_ext(); -} - -bool AccountState::unpack(vm::CellSlice& cs, AccountState::Record_account_frozen& data) const { - return cs.fetch_ulong(2) == 1 - && cs.fetch_bits_to(data.state_hash.bits(), 256); -} - -bool AccountState::unpack_account_frozen(vm::CellSlice& cs, td::BitArray<256>& state_hash) const { - return cs.fetch_ulong(2) == 1 - && cs.fetch_bits_to(state_hash.bits(), 256); -} - -bool AccountState::cell_unpack(Ref cell_ref, AccountState::Record_account_frozen& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountState::cell_unpack_account_frozen(Ref cell_ref, td::BitArray<256>& state_hash) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_frozen(cs, state_hash) && cs.empty_ext(); -} - -bool AccountState::pack(vm::CellBuilder& cb, const AccountState::Record_account_uninit& data) const { - return cb.store_long_bool(0, 2); -} - -bool AccountState::pack_account_uninit(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 2); -} - -bool AccountState::cell_pack(Ref& cell_ref, const AccountState::Record_account_uninit& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::cell_pack_account_uninit(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_account_uninit(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::pack(vm::CellBuilder& cb, const AccountState::Record_account_active& data) const { - return cb.store_long_bool(1, 1) - && t_StateInit.store_from(cb, data.x); -} - -bool AccountState::pack_account_active(vm::CellBuilder& cb, Ref x) const { - return cb.store_long_bool(1, 1) - && t_StateInit.store_from(cb, x); -} - -bool AccountState::cell_pack(Ref& cell_ref, const AccountState::Record_account_active& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::cell_pack_account_active(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_account_active(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::pack(vm::CellBuilder& cb, const AccountState::Record_account_frozen& data) const { - return cb.store_long_bool(1, 2) - && cb.store_bits_bool(data.state_hash.cbits(), 256); -} - -bool AccountState::pack_account_frozen(vm::CellBuilder& cb, td::BitArray<256> state_hash) const { - return cb.store_long_bool(1, 2) - && cb.store_bits_bool(state_hash.cbits(), 256); -} - -bool AccountState::cell_pack(Ref& cell_ref, const AccountState::Record_account_frozen& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::cell_pack_account_frozen(Ref& cell_ref, td::BitArray<256> state_hash) const { - vm::CellBuilder cb; - return pack_account_frozen(cb, state_hash) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountState::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_uninit: - return cs.advance(2) - && pp.cons("account_uninit"); - case account_active: - return cs.advance(1) - && pp.open("account_active") - && pp.field() - && t_StateInit.print_skip(pp, cs) - && pp.close(); - case account_frozen: - return cs.advance(2) - && pp.open("account_frozen") - && pp.fetch_bits_field(cs, 256, "state_hash") - && pp.close(); - } - return pp.fail("unknown constructor for AccountState"); -} - -const AccountState t_AccountState; - -// -// code for type `AccountStatus` -// - -int AccountStatus::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case acc_state_uninit: - return cs.have(2) ? acc_state_uninit : -1; - case acc_state_frozen: - return cs.have(2) ? acc_state_frozen : -1; - case acc_state_active: - return cs.have(2) ? acc_state_active : -1; - case acc_state_nonexist: - return cs.have(2) ? acc_state_nonexist : -1; - } - return -1; -} - -bool AccountStatus::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = (char)cs.fetch_ulong(2); - return value >= 0; -} - -bool AccountStatus::store_enum_from(vm::CellBuilder& cb, int value) const { - return cb.store_long_rchk_bool(value, 2); -} - -bool AccountStatus::unpack(vm::CellSlice& cs, AccountStatus::Record_acc_state_uninit& data) const { - return cs.fetch_ulong(2) == 0; -} - -bool AccountStatus::unpack_acc_state_uninit(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0; -} - -bool AccountStatus::cell_unpack(Ref cell_ref, AccountStatus::Record_acc_state_uninit& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountStatus::cell_unpack_acc_state_uninit(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acc_state_uninit(cs) && cs.empty_ext(); -} - -bool AccountStatus::unpack(vm::CellSlice& cs, AccountStatus::Record_acc_state_frozen& data) const { - return cs.fetch_ulong(2) == 1; -} - -bool AccountStatus::unpack_acc_state_frozen(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 1; -} - -bool AccountStatus::cell_unpack(Ref cell_ref, AccountStatus::Record_acc_state_frozen& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountStatus::cell_unpack_acc_state_frozen(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acc_state_frozen(cs) && cs.empty_ext(); -} - -bool AccountStatus::unpack(vm::CellSlice& cs, AccountStatus::Record_acc_state_active& data) const { - return cs.fetch_ulong(2) == 2; -} - -bool AccountStatus::unpack_acc_state_active(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 2; -} - -bool AccountStatus::cell_unpack(Ref cell_ref, AccountStatus::Record_acc_state_active& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountStatus::cell_unpack_acc_state_active(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acc_state_active(cs) && cs.empty_ext(); -} - -bool AccountStatus::unpack(vm::CellSlice& cs, AccountStatus::Record_acc_state_nonexist& data) const { - return cs.fetch_ulong(2) == 3; -} - -bool AccountStatus::unpack_acc_state_nonexist(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 3; -} - -bool AccountStatus::cell_unpack(Ref cell_ref, AccountStatus::Record_acc_state_nonexist& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountStatus::cell_unpack_acc_state_nonexist(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acc_state_nonexist(cs) && cs.empty_ext(); -} - -bool AccountStatus::pack(vm::CellBuilder& cb, const AccountStatus::Record_acc_state_uninit& data) const { - return cb.store_long_bool(0, 2); -} - -bool AccountStatus::pack_acc_state_uninit(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 2); -} - -bool AccountStatus::cell_pack(Ref& cell_ref, const AccountStatus::Record_acc_state_uninit& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::cell_pack_acc_state_uninit(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acc_state_uninit(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::pack(vm::CellBuilder& cb, const AccountStatus::Record_acc_state_frozen& data) const { - return cb.store_long_bool(1, 2); -} - -bool AccountStatus::pack_acc_state_frozen(vm::CellBuilder& cb) const { - return cb.store_long_bool(1, 2); -} - -bool AccountStatus::cell_pack(Ref& cell_ref, const AccountStatus::Record_acc_state_frozen& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::cell_pack_acc_state_frozen(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acc_state_frozen(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::pack(vm::CellBuilder& cb, const AccountStatus::Record_acc_state_active& data) const { - return cb.store_long_bool(2, 2); -} - -bool AccountStatus::pack_acc_state_active(vm::CellBuilder& cb) const { - return cb.store_long_bool(2, 2); -} - -bool AccountStatus::cell_pack(Ref& cell_ref, const AccountStatus::Record_acc_state_active& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::cell_pack_acc_state_active(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acc_state_active(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::pack(vm::CellBuilder& cb, const AccountStatus::Record_acc_state_nonexist& data) const { - return cb.store_long_bool(3, 2); -} - -bool AccountStatus::pack_acc_state_nonexist(vm::CellBuilder& cb) const { - return cb.store_long_bool(3, 2); -} - -bool AccountStatus::cell_pack(Ref& cell_ref, const AccountStatus::Record_acc_state_nonexist& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::cell_pack_acc_state_nonexist(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acc_state_nonexist(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountStatus::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case acc_state_uninit: - return cs.advance(2) - && pp.cons("acc_state_uninit"); - case acc_state_frozen: - return cs.advance(2) - && pp.cons("acc_state_frozen"); - case acc_state_active: - return cs.advance(2) - && pp.cons("acc_state_active"); - case acc_state_nonexist: - return cs.advance(2) - && pp.cons("acc_state_nonexist"); - } - return pp.fail("unknown constructor for AccountStatus"); -} - -const AccountStatus t_AccountStatus; - -// -// code for type `ShardAccount` -// - -int ShardAccount::check_tag(const vm::CellSlice& cs) const { - return account_descr; -} - -bool ShardAccount::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Account.validate_skip_ref(ops, cs, weak) - && cs.advance(320); -} - -bool ShardAccount::unpack(vm::CellSlice& cs, ShardAccount::Record& data) const { - return cs.fetch_ref_to(data.account) - && cs.fetch_bits_to(data.last_trans_hash.bits(), 256) - && cs.fetch_uint_to(64, data.last_trans_lt); -} - -bool ShardAccount::unpack_account_descr(vm::CellSlice& cs, Ref& account, td::BitArray<256>& last_trans_hash, unsigned long long& last_trans_lt) const { - return cs.fetch_ref_to(account) - && cs.fetch_bits_to(last_trans_hash.bits(), 256) - && cs.fetch_uint_to(64, last_trans_lt); -} - -bool ShardAccount::cell_unpack(Ref cell_ref, ShardAccount::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardAccount::cell_unpack_account_descr(Ref cell_ref, Ref& account, td::BitArray<256>& last_trans_hash, unsigned long long& last_trans_lt) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_account_descr(cs, account, last_trans_hash, last_trans_lt) && cs.empty_ext(); -} - -bool ShardAccount::pack(vm::CellBuilder& cb, const ShardAccount::Record& data) const { - return cb.store_ref_bool(data.account) - && cb.store_bits_bool(data.last_trans_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.last_trans_lt, 64); -} - -bool ShardAccount::pack_account_descr(vm::CellBuilder& cb, Ref account, td::BitArray<256> last_trans_hash, unsigned long long last_trans_lt) const { - return cb.store_ref_bool(account) - && cb.store_bits_bool(last_trans_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(last_trans_lt, 64); -} - -bool ShardAccount::cell_pack(Ref& cell_ref, const ShardAccount::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccount::cell_pack_account_descr(Ref& cell_ref, Ref account, td::BitArray<256> last_trans_hash, unsigned long long last_trans_lt) const { - vm::CellBuilder cb; - return pack_account_descr(cb, std::move(account), last_trans_hash, last_trans_lt) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccount::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("account_descr") - && pp.field("account") - && t_Account.print_ref(pp, cs.fetch_ref()) - && pp.fetch_bits_field(cs, 256, "last_trans_hash") - && pp.fetch_uint_field(cs, 64, "last_trans_lt") - && pp.close(); -} - -const ShardAccount t_ShardAccount; - -// -// code for type `DepthBalanceInfo` -// - -int DepthBalanceInfo::check_tag(const vm::CellSlice& cs) const { - return depth_balance; -} - -bool DepthBalanceInfo::skip(vm::CellSlice& cs) const { - return cs.advance(5) - && t_CurrencyCollection.skip(cs); -} - -bool DepthBalanceInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int split_depth; - return cs.fetch_uint_leq(30, split_depth) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool DepthBalanceInfo::unpack(vm::CellSlice& cs, DepthBalanceInfo::Record& data) const { - return cs.fetch_uint_leq(30, data.split_depth) - && t_CurrencyCollection.fetch_to(cs, data.balance); -} - -bool DepthBalanceInfo::unpack_depth_balance(vm::CellSlice& cs, int& split_depth, Ref& balance) const { - return cs.fetch_uint_leq(30, split_depth) - && t_CurrencyCollection.fetch_to(cs, balance); -} - -bool DepthBalanceInfo::cell_unpack(Ref cell_ref, DepthBalanceInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DepthBalanceInfo::cell_unpack_depth_balance(Ref cell_ref, int& split_depth, Ref& balance) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_depth_balance(cs, split_depth, balance) && cs.empty_ext(); -} - -bool DepthBalanceInfo::pack(vm::CellBuilder& cb, const DepthBalanceInfo::Record& data) const { - return cb.store_uint_leq(30, data.split_depth) - && t_CurrencyCollection.store_from(cb, data.balance); -} - -bool DepthBalanceInfo::pack_depth_balance(vm::CellBuilder& cb, int split_depth, Ref balance) const { - return cb.store_uint_leq(30, split_depth) - && t_CurrencyCollection.store_from(cb, balance); -} - -bool DepthBalanceInfo::cell_pack(Ref& cell_ref, const DepthBalanceInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DepthBalanceInfo::cell_pack_depth_balance(Ref& cell_ref, int split_depth, Ref balance) const { - vm::CellBuilder cb; - return pack_depth_balance(cb, split_depth, std::move(balance)) && std::move(cb).finalize_to(cell_ref); -} - -bool DepthBalanceInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int split_depth; - return pp.open("depth_balance") - && cs.fetch_uint_leq(30, split_depth) - && pp.field_int(split_depth, "split_depth") - && pp.field("balance") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const DepthBalanceInfo t_DepthBalanceInfo; - -// -// code for type `ShardAccounts` -// - -int ShardAccounts::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardAccounts::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.skip(cs); -} - -bool ShardAccounts::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.validate_skip(ops, cs, weak); -} - -bool ShardAccounts::unpack(vm::CellSlice& cs, ShardAccounts::Record& data) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.fetch_to(cs, data.x); -} - -bool ShardAccounts::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.fetch_to(cs, x); -} - -bool ShardAccounts::cell_unpack(Ref cell_ref, ShardAccounts::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardAccounts::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ShardAccounts::pack(vm::CellBuilder& cb, const ShardAccounts::Record& data) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.store_from(cb, data.x); -} - -bool ShardAccounts::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.store_from(cb, x); -} - -bool ShardAccounts::cell_pack(Ref& cell_ref, const ShardAccounts::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccounts::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccounts::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_256_ShardAccount_DepthBalanceInfo.print_skip(pp, cs) - && pp.close(); -} - -const ShardAccounts t_ShardAccounts; - -// -// code for auxiliary type `Transaction_aux` -// - -int Transaction_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool Transaction_aux::skip(vm::CellSlice& cs) const { - return t_Maybe_Ref_Message_Any.skip(cs) - && t_HashmapE_15_Ref_Message_Any.skip(cs); -} - -bool Transaction_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_Ref_Message_Any.validate_skip(ops, cs, weak) - && t_HashmapE_15_Ref_Message_Any.validate_skip(ops, cs, weak); -} - -bool Transaction_aux::unpack(vm::CellSlice& cs, Transaction_aux::Record& data) const { - return t_Maybe_Ref_Message_Any.fetch_to(cs, data.in_msg) - && t_HashmapE_15_Ref_Message_Any.fetch_to(cs, data.out_msgs); -} - -bool Transaction_aux::unpack_cons1(vm::CellSlice& cs, Ref& in_msg, Ref& out_msgs) const { - return t_Maybe_Ref_Message_Any.fetch_to(cs, in_msg) - && t_HashmapE_15_Ref_Message_Any.fetch_to(cs, out_msgs); -} - -bool Transaction_aux::cell_unpack(Ref cell_ref, Transaction_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Transaction_aux::cell_unpack_cons1(Ref cell_ref, Ref& in_msg, Ref& out_msgs) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, in_msg, out_msgs) && cs.empty_ext(); -} - -bool Transaction_aux::pack(vm::CellBuilder& cb, const Transaction_aux::Record& data) const { - return t_Maybe_Ref_Message_Any.store_from(cb, data.in_msg) - && t_HashmapE_15_Ref_Message_Any.store_from(cb, data.out_msgs); -} - -bool Transaction_aux::pack_cons1(vm::CellBuilder& cb, Ref in_msg, Ref out_msgs) const { - return t_Maybe_Ref_Message_Any.store_from(cb, in_msg) - && t_HashmapE_15_Ref_Message_Any.store_from(cb, out_msgs); -} - -bool Transaction_aux::cell_pack(Ref& cell_ref, const Transaction_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Transaction_aux::cell_pack_cons1(Ref& cell_ref, Ref in_msg, Ref out_msgs) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(in_msg), std::move(out_msgs)) && std::move(cb).finalize_to(cell_ref); -} - -bool Transaction_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("in_msg") - && t_Maybe_Ref_Message_Any.print_skip(pp, cs) - && pp.field("out_msgs") - && t_HashmapE_15_Ref_Message_Any.print_skip(pp, cs) - && pp.close(); -} - -const Transaction_aux t_Transaction_aux; - -// -// code for type `Transaction` -// -constexpr unsigned char Transaction::cons_tag[1]; - -int Transaction::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 7 ? transaction : -1; -} - -bool Transaction::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x102b7) - && t_CurrencyCollection.skip(cs) - && cs.advance_refs(2); -} - -bool Transaction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 7 - && cs.advance(691) - && t_Transaction_aux.validate_skip_ref(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_HASH_UPDATE_Account.validate_skip_ref(ops, cs, weak) - && t_TransactionDescr.validate_skip_ref(ops, cs, weak); -} - -bool Transaction::unpack(vm::CellSlice& cs, Transaction::Record& data) const { - return cs.fetch_ulong(4) == 7 - && cs.fetch_bits_to(data.account_addr.bits(), 256) - && cs.fetch_uint_to(64, data.lt) - && cs.fetch_bits_to(data.prev_trans_hash.bits(), 256) - && cs.fetch_uint_to(64, data.prev_trans_lt) - && cs.fetch_uint_to(32, data.now) - && cs.fetch_uint_to(15, data.outmsg_cnt) - && t_AccountStatus.fetch_enum_to(cs, data.orig_status) - && t_AccountStatus.fetch_enum_to(cs, data.end_status) - && t_Transaction_aux.cell_unpack(cs.fetch_ref(), data.r1) - && t_CurrencyCollection.fetch_to(cs, data.total_fees) - && cs.fetch_ref_to(data.state_update) - && cs.fetch_ref_to(data.description); -} - -bool Transaction::cell_unpack(Ref cell_ref, Transaction::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Transaction::pack(vm::CellBuilder& cb, const Transaction::Record& data) const { - Ref tmp_cell; - return cb.store_long_bool(7, 4) - && cb.store_bits_bool(data.account_addr.cbits(), 256) - && cb.store_ulong_rchk_bool(data.lt, 64) - && cb.store_bits_bool(data.prev_trans_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.prev_trans_lt, 64) - && cb.store_ulong_rchk_bool(data.now, 32) - && cb.store_ulong_rchk_bool(data.outmsg_cnt, 15) - && t_AccountStatus.store_enum_from(cb, data.orig_status) - && t_AccountStatus.store_enum_from(cb, data.end_status) - && t_Transaction_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)) - && t_CurrencyCollection.store_from(cb, data.total_fees) - && cb.store_ref_bool(data.state_update) - && cb.store_ref_bool(data.description); -} - -bool Transaction::cell_pack(Ref& cell_ref, const Transaction::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Transaction::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 7 - && pp.open("transaction") - && pp.fetch_bits_field(cs, 256, "account_addr") - && pp.fetch_uint_field(cs, 64, "lt") - && pp.fetch_bits_field(cs, 256, "prev_trans_hash") - && pp.fetch_uint_field(cs, 64, "prev_trans_lt") - && pp.fetch_uint_field(cs, 32, "now") - && pp.fetch_uint_field(cs, 15, "outmsg_cnt") - && pp.field("orig_status") - && t_AccountStatus.print_skip(pp, cs) - && pp.field("end_status") - && t_AccountStatus.print_skip(pp, cs) - && pp.field() - && t_Transaction_aux.print_ref(pp, cs.fetch_ref()) - && pp.field("total_fees") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("state_update") - && t_HASH_UPDATE_Account.print_ref(pp, cs.fetch_ref()) - && pp.field("description") - && t_TransactionDescr.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const Transaction t_Transaction; - -// -// code for type `MERKLE_UPDATE` -// -constexpr unsigned char MERKLE_UPDATE::cons_tag[1]; - -int MERKLE_UPDATE::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 2 ? _merkle_update : -1; -} - -bool MERKLE_UPDATE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 2 - && cs.advance(512) - && X_.validate_skip_ref(ops, cs, weak) - && X_.validate_skip_ref(ops, cs, weak); -} - -bool MERKLE_UPDATE::unpack(vm::CellSlice& cs, MERKLE_UPDATE::Record& data) const { - return cs.fetch_ulong(8) == 2 - && cs.fetch_bits_to(data.old_hash.bits(), 256) - && cs.fetch_bits_to(data.new_hash.bits(), 256) - && cs.fetch_ref_to(data.old) - && cs.fetch_ref_to(data.new1); -} - -bool MERKLE_UPDATE::cell_unpack(Ref cell_ref, MERKLE_UPDATE::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MERKLE_UPDATE::pack(vm::CellBuilder& cb, const MERKLE_UPDATE::Record& data) const { - return cb.store_long_bool(2, 8) - && cb.store_bits_bool(data.old_hash.cbits(), 256) - && cb.store_bits_bool(data.new_hash.cbits(), 256) - && cb.store_ref_bool(data.old) - && cb.store_ref_bool(data.new1); -} - -bool MERKLE_UPDATE::cell_pack(Ref& cell_ref, const MERKLE_UPDATE::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MERKLE_UPDATE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 2 - && pp.open("!merkle_update") - && pp.fetch_bits_field(cs, 256, "old_hash") - && pp.fetch_bits_field(cs, 256, "new_hash") - && pp.field("old") - && X_.print_ref(pp, cs.fetch_ref()) - && pp.field("new") - && X_.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - - -// -// code for type `HASH_UPDATE` -// -constexpr unsigned char HASH_UPDATE::cons_tag[1]; - -int HASH_UPDATE::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x72 ? update_hashes : -1; -} - -bool HASH_UPDATE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x72 - && cs.advance(512); -} - -bool HASH_UPDATE::unpack(vm::CellSlice& cs, HASH_UPDATE::Record& data) const { - return cs.fetch_ulong(8) == 0x72 - && cs.fetch_bits_to(data.old_hash.bits(), 256) - && cs.fetch_bits_to(data.new_hash.bits(), 256); -} - -bool HASH_UPDATE::unpack_update_hashes(vm::CellSlice& cs, td::BitArray<256>& old_hash, td::BitArray<256>& new_hash) const { - return cs.fetch_ulong(8) == 0x72 - && cs.fetch_bits_to(old_hash.bits(), 256) - && cs.fetch_bits_to(new_hash.bits(), 256); -} - -bool HASH_UPDATE::cell_unpack(Ref cell_ref, HASH_UPDATE::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool HASH_UPDATE::cell_unpack_update_hashes(Ref cell_ref, td::BitArray<256>& old_hash, td::BitArray<256>& new_hash) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_update_hashes(cs, old_hash, new_hash) && cs.empty_ext(); -} - -bool HASH_UPDATE::pack(vm::CellBuilder& cb, const HASH_UPDATE::Record& data) const { - return cb.store_long_bool(0x72, 8) - && cb.store_bits_bool(data.old_hash.cbits(), 256) - && cb.store_bits_bool(data.new_hash.cbits(), 256); -} - -bool HASH_UPDATE::pack_update_hashes(vm::CellBuilder& cb, td::BitArray<256> old_hash, td::BitArray<256> new_hash) const { - return cb.store_long_bool(0x72, 8) - && cb.store_bits_bool(old_hash.cbits(), 256) - && cb.store_bits_bool(new_hash.cbits(), 256); -} - -bool HASH_UPDATE::cell_pack(Ref& cell_ref, const HASH_UPDATE::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool HASH_UPDATE::cell_pack_update_hashes(Ref& cell_ref, td::BitArray<256> old_hash, td::BitArray<256> new_hash) const { - vm::CellBuilder cb; - return pack_update_hashes(cb, old_hash, new_hash) && std::move(cb).finalize_to(cell_ref); -} - -bool HASH_UPDATE::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x72 - && pp.open("update_hashes") - && pp.fetch_bits_field(cs, 256, "old_hash") - && pp.fetch_bits_field(cs, 256, "new_hash") - && pp.close(); -} - - -// -// code for type `MERKLE_PROOF` -// -constexpr unsigned char MERKLE_PROOF::cons_tag[1]; - -int MERKLE_PROOF::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 3 ? _merkle_proof : -1; -} - -bool MERKLE_PROOF::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 3 - && cs.advance(272) - && X_.validate_skip_ref(ops, cs, weak); -} - -bool MERKLE_PROOF::unpack(vm::CellSlice& cs, MERKLE_PROOF::Record& data) const { - return cs.fetch_ulong(8) == 3 - && cs.fetch_bits_to(data.virtual_hash.bits(), 256) - && cs.fetch_uint_to(16, data.depth) - && cs.fetch_ref_to(data.virtual_root); -} - -bool MERKLE_PROOF::unpack__merkle_proof(vm::CellSlice& cs, td::BitArray<256>& virtual_hash, int& depth, Ref& virtual_root) const { - return cs.fetch_ulong(8) == 3 - && cs.fetch_bits_to(virtual_hash.bits(), 256) - && cs.fetch_uint_to(16, depth) - && cs.fetch_ref_to(virtual_root); -} - -bool MERKLE_PROOF::cell_unpack(Ref cell_ref, MERKLE_PROOF::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MERKLE_PROOF::cell_unpack__merkle_proof(Ref cell_ref, td::BitArray<256>& virtual_hash, int& depth, Ref& virtual_root) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack__merkle_proof(cs, virtual_hash, depth, virtual_root) && cs.empty_ext(); -} - -bool MERKLE_PROOF::pack(vm::CellBuilder& cb, const MERKLE_PROOF::Record& data) const { - return cb.store_long_bool(3, 8) - && cb.store_bits_bool(data.virtual_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.depth, 16) - && cb.store_ref_bool(data.virtual_root); -} - -bool MERKLE_PROOF::pack__merkle_proof(vm::CellBuilder& cb, td::BitArray<256> virtual_hash, int depth, Ref virtual_root) const { - return cb.store_long_bool(3, 8) - && cb.store_bits_bool(virtual_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(depth, 16) - && cb.store_ref_bool(virtual_root); -} - -bool MERKLE_PROOF::cell_pack(Ref& cell_ref, const MERKLE_PROOF::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MERKLE_PROOF::cell_pack__merkle_proof(Ref& cell_ref, td::BitArray<256> virtual_hash, int depth, Ref virtual_root) const { - vm::CellBuilder cb; - return pack__merkle_proof(cb, virtual_hash, depth, std::move(virtual_root)) && std::move(cb).finalize_to(cell_ref); -} - -bool MERKLE_PROOF::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 3 - && pp.open("!merkle_proof") - && pp.fetch_bits_field(cs, 256, "virtual_hash") - && pp.fetch_uint_field(cs, 16, "depth") - && pp.field("virtual_root") - && X_.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - - -// -// code for type `AccountBlock` -// -constexpr unsigned char AccountBlock::cons_tag[1]; - -int AccountBlock::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 5 ? acc_trans : -1; -} - -bool AccountBlock::skip(vm::CellSlice& cs) const { - return cs.advance(260) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.skip(cs) - && cs.advance_refs(1); -} - -bool AccountBlock::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 5 - && cs.advance(256) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.validate_skip(ops, cs, weak) - && t_HASH_UPDATE_Account.validate_skip_ref(ops, cs, weak); -} - -bool AccountBlock::unpack(vm::CellSlice& cs, AccountBlock::Record& data) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_bits_to(data.account_addr.bits(), 256) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.fetch_to(cs, data.transactions) - && cs.fetch_ref_to(data.state_update); -} - -bool AccountBlock::unpack_acc_trans(vm::CellSlice& cs, td::BitArray<256>& account_addr, Ref& transactions, Ref& state_update) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_bits_to(account_addr.bits(), 256) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.fetch_to(cs, transactions) - && cs.fetch_ref_to(state_update); -} - -bool AccountBlock::cell_unpack(Ref cell_ref, AccountBlock::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccountBlock::cell_unpack_acc_trans(Ref cell_ref, td::BitArray<256>& account_addr, Ref& transactions, Ref& state_update) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acc_trans(cs, account_addr, transactions, state_update) && cs.empty_ext(); -} - -bool AccountBlock::pack(vm::CellBuilder& cb, const AccountBlock::Record& data) const { - return cb.store_long_bool(5, 4) - && cb.store_bits_bool(data.account_addr.cbits(), 256) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.store_from(cb, data.transactions) - && cb.store_ref_bool(data.state_update); -} - -bool AccountBlock::pack_acc_trans(vm::CellBuilder& cb, td::BitArray<256> account_addr, Ref transactions, Ref state_update) const { - return cb.store_long_bool(5, 4) - && cb.store_bits_bool(account_addr.cbits(), 256) - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.store_from(cb, transactions) - && cb.store_ref_bool(state_update); -} - -bool AccountBlock::cell_pack(Ref& cell_ref, const AccountBlock::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountBlock::cell_pack_acc_trans(Ref& cell_ref, td::BitArray<256> account_addr, Ref transactions, Ref state_update) const { - vm::CellBuilder cb; - return pack_acc_trans(cb, account_addr, std::move(transactions), std::move(state_update)) && std::move(cb).finalize_to(cell_ref); -} - -bool AccountBlock::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 5 - && pp.open("acc_trans") - && pp.fetch_bits_field(cs, 256, "account_addr") - && pp.field("transactions") - && t_HashmapAug_64_Ref_Transaction_CurrencyCollection.print_skip(pp, cs) - && pp.field("state_update") - && t_HASH_UPDATE_Account.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const AccountBlock t_AccountBlock; - -// -// code for type `ShardAccountBlocks` -// - -int ShardAccountBlocks::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardAccountBlocks::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.skip(cs); -} - -bool ShardAccountBlocks::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ShardAccountBlocks::unpack(vm::CellSlice& cs, ShardAccountBlocks::Record& data) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.fetch_to(cs, data.x); -} - -bool ShardAccountBlocks::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.fetch_to(cs, x); -} - -bool ShardAccountBlocks::cell_unpack(Ref cell_ref, ShardAccountBlocks::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardAccountBlocks::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ShardAccountBlocks::pack(vm::CellBuilder& cb, const ShardAccountBlocks::Record& data) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.store_from(cb, data.x); -} - -bool ShardAccountBlocks::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_256_AccountBlock_CurrencyCollection.store_from(cb, x); -} - -bool ShardAccountBlocks::cell_pack(Ref& cell_ref, const ShardAccountBlocks::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccountBlocks::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardAccountBlocks::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_256_AccountBlock_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ShardAccountBlocks t_ShardAccountBlocks; - -// -// code for type `TrStoragePhase` -// - -int TrStoragePhase::check_tag(const vm::CellSlice& cs) const { - return tr_phase_storage; -} - -bool TrStoragePhase::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) - && t_Maybe_Grams.skip(cs) - && t_AccStatusChange.skip(cs); -} - -bool TrStoragePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) - && t_Maybe_Grams.validate_skip(ops, cs, weak) - && t_AccStatusChange.validate_skip(ops, cs, weak); -} - -bool TrStoragePhase::unpack(vm::CellSlice& cs, TrStoragePhase::Record& data) const { - return t_Grams.fetch_to(cs, data.storage_fees_collected) - && t_Maybe_Grams.fetch_to(cs, data.storage_fees_due) - && t_AccStatusChange.fetch_enum_to(cs, data.status_change); -} - -bool TrStoragePhase::unpack_tr_phase_storage(vm::CellSlice& cs, Ref& storage_fees_collected, Ref& storage_fees_due, char& status_change) const { - return t_Grams.fetch_to(cs, storage_fees_collected) - && t_Maybe_Grams.fetch_to(cs, storage_fees_due) - && t_AccStatusChange.fetch_enum_to(cs, status_change); -} - -bool TrStoragePhase::cell_unpack(Ref cell_ref, TrStoragePhase::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrStoragePhase::cell_unpack_tr_phase_storage(Ref cell_ref, Ref& storage_fees_collected, Ref& storage_fees_due, char& status_change) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_storage(cs, storage_fees_collected, storage_fees_due, status_change) && cs.empty_ext(); -} - -bool TrStoragePhase::pack(vm::CellBuilder& cb, const TrStoragePhase::Record& data) const { - return t_Grams.store_from(cb, data.storage_fees_collected) - && t_Maybe_Grams.store_from(cb, data.storage_fees_due) - && t_AccStatusChange.store_enum_from(cb, data.status_change); -} - -bool TrStoragePhase::pack_tr_phase_storage(vm::CellBuilder& cb, Ref storage_fees_collected, Ref storage_fees_due, char status_change) const { - return t_Grams.store_from(cb, storage_fees_collected) - && t_Maybe_Grams.store_from(cb, storage_fees_due) - && t_AccStatusChange.store_enum_from(cb, status_change); -} - -bool TrStoragePhase::cell_pack(Ref& cell_ref, const TrStoragePhase::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrStoragePhase::cell_pack_tr_phase_storage(Ref& cell_ref, Ref storage_fees_collected, Ref storage_fees_due, char status_change) const { - vm::CellBuilder cb; - return pack_tr_phase_storage(cb, std::move(storage_fees_collected), std::move(storage_fees_due), status_change) && std::move(cb).finalize_to(cell_ref); -} - -bool TrStoragePhase::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("tr_phase_storage") - && pp.field("storage_fees_collected") - && t_Grams.print_skip(pp, cs) - && pp.field("storage_fees_due") - && t_Maybe_Grams.print_skip(pp, cs) - && pp.field("status_change") - && t_AccStatusChange.print_skip(pp, cs) - && pp.close(); -} - -const TrStoragePhase t_TrStoragePhase; - -// -// code for type `AccStatusChange` -// -constexpr char AccStatusChange::cons_len[3]; -constexpr unsigned char AccStatusChange::cons_tag[3]; - -int AccStatusChange::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case acst_unchanged: - return cs.have(1) ? acst_unchanged : -1; - case acst_frozen: - return cs.have(2) ? acst_frozen : -1; - case acst_deleted: - return cs.have(2) ? acst_deleted : -1; - } - return -1; -} - -bool AccStatusChange::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case acst_unchanged: - return cs.advance(1); - case acst_frozen: - return cs.advance(2); - case acst_deleted: - return cs.advance(2); - } - return false; -} - -bool AccStatusChange::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case acst_unchanged: - return cs.advance(1); - case acst_frozen: - return cs.advance(2); - case acst_deleted: - return cs.advance(2); - } - return false; -} - -bool AccStatusChange::fetch_enum_to(vm::CellSlice& cs, char& value) const { - int t = get_tag(cs); - value = (char)t; - return t >= 0 && cs.advance(cons_len[t]); -} - -bool AccStatusChange::store_enum_from(vm::CellBuilder& cb, int value) const { - return (unsigned)value < 3 && cb.store_long_bool(cons_tag[value], cons_len[value]); -} - -bool AccStatusChange::unpack(vm::CellSlice& cs, AccStatusChange::Record_acst_unchanged& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool AccStatusChange::unpack_acst_unchanged(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool AccStatusChange::cell_unpack(Ref cell_ref, AccStatusChange::Record_acst_unchanged& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccStatusChange::cell_unpack_acst_unchanged(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acst_unchanged(cs) && cs.empty_ext(); -} - -bool AccStatusChange::unpack(vm::CellSlice& cs, AccStatusChange::Record_acst_frozen& data) const { - return cs.fetch_ulong(2) == 2; -} - -bool AccStatusChange::unpack_acst_frozen(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 2; -} - -bool AccStatusChange::cell_unpack(Ref cell_ref, AccStatusChange::Record_acst_frozen& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccStatusChange::cell_unpack_acst_frozen(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acst_frozen(cs) && cs.empty_ext(); -} - -bool AccStatusChange::unpack(vm::CellSlice& cs, AccStatusChange::Record_acst_deleted& data) const { - return cs.fetch_ulong(2) == 3; -} - -bool AccStatusChange::unpack_acst_deleted(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 3; -} - -bool AccStatusChange::cell_unpack(Ref cell_ref, AccStatusChange::Record_acst_deleted& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool AccStatusChange::cell_unpack_acst_deleted(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_acst_deleted(cs) && cs.empty_ext(); -} - -bool AccStatusChange::pack(vm::CellBuilder& cb, const AccStatusChange::Record_acst_unchanged& data) const { - return cb.store_long_bool(0, 1); -} - -bool AccStatusChange::pack_acst_unchanged(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool AccStatusChange::cell_pack(Ref& cell_ref, const AccStatusChange::Record_acst_unchanged& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::cell_pack_acst_unchanged(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acst_unchanged(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::pack(vm::CellBuilder& cb, const AccStatusChange::Record_acst_frozen& data) const { - return cb.store_long_bool(2, 2); -} - -bool AccStatusChange::pack_acst_frozen(vm::CellBuilder& cb) const { - return cb.store_long_bool(2, 2); -} - -bool AccStatusChange::cell_pack(Ref& cell_ref, const AccStatusChange::Record_acst_frozen& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::cell_pack_acst_frozen(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acst_frozen(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::pack(vm::CellBuilder& cb, const AccStatusChange::Record_acst_deleted& data) const { - return cb.store_long_bool(3, 2); -} - -bool AccStatusChange::pack_acst_deleted(vm::CellBuilder& cb) const { - return cb.store_long_bool(3, 2); -} - -bool AccStatusChange::cell_pack(Ref& cell_ref, const AccStatusChange::Record_acst_deleted& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::cell_pack_acst_deleted(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_acst_deleted(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool AccStatusChange::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case acst_unchanged: - return cs.advance(1) - && pp.cons("acst_unchanged"); - case acst_frozen: - return cs.advance(2) - && pp.cons("acst_frozen"); - case acst_deleted: - return cs.advance(2) - && pp.cons("acst_deleted"); - } - return pp.fail("unknown constructor for AccStatusChange"); -} - -const AccStatusChange t_AccStatusChange; - -// -// code for type `TrCreditPhase` -// - -int TrCreditPhase::check_tag(const vm::CellSlice& cs) const { - return tr_phase_credit; -} - -bool TrCreditPhase::skip(vm::CellSlice& cs) const { - return t_Maybe_Grams.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool TrCreditPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_Grams.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool TrCreditPhase::unpack(vm::CellSlice& cs, TrCreditPhase::Record& data) const { - return t_Maybe_Grams.fetch_to(cs, data.due_fees_collected) - && t_CurrencyCollection.fetch_to(cs, data.credit); -} - -bool TrCreditPhase::unpack_tr_phase_credit(vm::CellSlice& cs, Ref& due_fees_collected, Ref& credit) const { - return t_Maybe_Grams.fetch_to(cs, due_fees_collected) - && t_CurrencyCollection.fetch_to(cs, credit); -} - -bool TrCreditPhase::cell_unpack(Ref cell_ref, TrCreditPhase::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrCreditPhase::cell_unpack_tr_phase_credit(Ref cell_ref, Ref& due_fees_collected, Ref& credit) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_credit(cs, due_fees_collected, credit) && cs.empty_ext(); -} - -bool TrCreditPhase::pack(vm::CellBuilder& cb, const TrCreditPhase::Record& data) const { - return t_Maybe_Grams.store_from(cb, data.due_fees_collected) - && t_CurrencyCollection.store_from(cb, data.credit); -} - -bool TrCreditPhase::pack_tr_phase_credit(vm::CellBuilder& cb, Ref due_fees_collected, Ref credit) const { - return t_Maybe_Grams.store_from(cb, due_fees_collected) - && t_CurrencyCollection.store_from(cb, credit); -} - -bool TrCreditPhase::cell_pack(Ref& cell_ref, const TrCreditPhase::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrCreditPhase::cell_pack_tr_phase_credit(Ref& cell_ref, Ref due_fees_collected, Ref credit) const { - vm::CellBuilder cb; - return pack_tr_phase_credit(cb, std::move(due_fees_collected), std::move(credit)) && std::move(cb).finalize_to(cell_ref); -} - -bool TrCreditPhase::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("tr_phase_credit") - && pp.field("due_fees_collected") - && t_Maybe_Grams.print_skip(pp, cs) - && pp.field("credit") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const TrCreditPhase t_TrCreditPhase; - -// -// code for auxiliary type `TrComputePhase_aux` -// - -int TrComputePhase_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool TrComputePhase_aux::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) - && t_VarUInteger_7.skip(cs) - && t_Maybe_VarUInteger_3.skip(cs) - && cs.advance(40) - && t_Maybe_int32.skip(cs) - && cs.advance(544); -} - -bool TrComputePhase_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) - && t_VarUInteger_7.validate_skip(ops, cs, weak) - && t_Maybe_VarUInteger_3.validate_skip(ops, cs, weak) - && cs.advance(40) - && t_Maybe_int32.validate_skip(ops, cs, weak) - && cs.advance(544); -} - -bool TrComputePhase_aux::unpack(vm::CellSlice& cs, TrComputePhase_aux::Record& data) const { - return t_VarUInteger_7.fetch_to(cs, data.gas_used) - && t_VarUInteger_7.fetch_to(cs, data.gas_limit) - && t_Maybe_VarUInteger_3.fetch_to(cs, data.gas_credit) - && cs.fetch_int_to(8, data.mode) - && cs.fetch_int_to(32, data.exit_code) - && t_Maybe_int32.fetch_to(cs, data.exit_arg) - && cs.fetch_uint_to(32, data.vm_steps) - && cs.fetch_bits_to(data.vm_init_state_hash.bits(), 256) - && cs.fetch_bits_to(data.vm_final_state_hash.bits(), 256); -} - -bool TrComputePhase_aux::cell_unpack(Ref cell_ref, TrComputePhase_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrComputePhase_aux::pack(vm::CellBuilder& cb, const TrComputePhase_aux::Record& data) const { - return t_VarUInteger_7.store_from(cb, data.gas_used) - && t_VarUInteger_7.store_from(cb, data.gas_limit) - && t_Maybe_VarUInteger_3.store_from(cb, data.gas_credit) - && cb.store_long_rchk_bool(data.mode, 8) - && cb.store_long_rchk_bool(data.exit_code, 32) - && t_Maybe_int32.store_from(cb, data.exit_arg) - && cb.store_ulong_rchk_bool(data.vm_steps, 32) - && cb.store_bits_bool(data.vm_init_state_hash.cbits(), 256) - && cb.store_bits_bool(data.vm_final_state_hash.cbits(), 256); -} - -bool TrComputePhase_aux::cell_pack(Ref& cell_ref, const TrComputePhase_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrComputePhase_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("gas_used") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.field("gas_limit") - && t_VarUInteger_7.print_skip(pp, cs) - && pp.field("gas_credit") - && t_Maybe_VarUInteger_3.print_skip(pp, cs) - && pp.fetch_int_field(cs, 8, "mode") - && pp.fetch_int_field(cs, 32, "exit_code") - && pp.field("exit_arg") - && t_Maybe_int32.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "vm_steps") - && pp.fetch_bits_field(cs, 256, "vm_init_state_hash") - && pp.fetch_bits_field(cs, 256, "vm_final_state_hash") - && pp.close(); -} - -const TrComputePhase_aux t_TrComputePhase_aux; - -// -// code for type `TrComputePhase` -// - -int TrComputePhase::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.have(1) ? tr_phase_compute_skipped : -1; - case tr_phase_compute_vm: - return cs.have(1) ? tr_phase_compute_vm : -1; - } - return -1; -} - -bool TrComputePhase::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.advance(3); - case tr_phase_compute_vm: - return cs.advance(4) - && t_Grams.skip(cs) - && cs.advance_refs(1); - } - return false; -} - -bool TrComputePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.advance(1) - && t_ComputeSkipReason.validate_skip(ops, cs, weak); - case tr_phase_compute_vm: - return cs.advance(4) - && t_Grams.validate_skip(ops, cs, weak) - && t_TrComputePhase_aux.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool TrComputePhase::unpack(vm::CellSlice& cs, TrComputePhase::Record_tr_phase_compute_skipped& data) const { - return cs.fetch_ulong(1) == 0 - && t_ComputeSkipReason.fetch_enum_to(cs, data.reason); -} - -bool TrComputePhase::unpack_tr_phase_compute_skipped(vm::CellSlice& cs, char& reason) const { - return cs.fetch_ulong(1) == 0 - && t_ComputeSkipReason.fetch_enum_to(cs, reason); -} - -bool TrComputePhase::cell_unpack(Ref cell_ref, TrComputePhase::Record_tr_phase_compute_skipped& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrComputePhase::cell_unpack_tr_phase_compute_skipped(Ref cell_ref, char& reason) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_compute_skipped(cs, reason) && cs.empty_ext(); -} - -bool TrComputePhase::unpack(vm::CellSlice& cs, TrComputePhase::Record_tr_phase_compute_vm& data) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_bool_to(data.success) - && cs.fetch_bool_to(data.msg_state_used) - && cs.fetch_bool_to(data.account_activated) - && t_Grams.fetch_to(cs, data.gas_fees) - && t_TrComputePhase_aux.cell_unpack(cs.fetch_ref(), data.r1); -} - -bool TrComputePhase::cell_unpack(Ref cell_ref, TrComputePhase::Record_tr_phase_compute_vm& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrComputePhase::pack(vm::CellBuilder& cb, const TrComputePhase::Record_tr_phase_compute_skipped& data) const { - return cb.store_long_bool(0, 1) - && t_ComputeSkipReason.store_enum_from(cb, data.reason); -} - -bool TrComputePhase::pack_tr_phase_compute_skipped(vm::CellBuilder& cb, char reason) const { - return cb.store_long_bool(0, 1) - && t_ComputeSkipReason.store_enum_from(cb, reason); -} - -bool TrComputePhase::cell_pack(Ref& cell_ref, const TrComputePhase::Record_tr_phase_compute_skipped& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrComputePhase::cell_pack_tr_phase_compute_skipped(Ref& cell_ref, char reason) const { - vm::CellBuilder cb; - return pack_tr_phase_compute_skipped(cb, reason) && std::move(cb).finalize_to(cell_ref); -} - -bool TrComputePhase::pack(vm::CellBuilder& cb, const TrComputePhase::Record_tr_phase_compute_vm& data) const { - Ref tmp_cell; - return cb.store_long_bool(1, 1) - && cb.store_ulong_rchk_bool(data.success, 1) - && cb.store_ulong_rchk_bool(data.msg_state_used, 1) - && cb.store_ulong_rchk_bool(data.account_activated, 1) - && t_Grams.store_from(cb, data.gas_fees) - && t_TrComputePhase_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)); -} - -bool TrComputePhase::cell_pack(Ref& cell_ref, const TrComputePhase::Record_tr_phase_compute_vm& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrComputePhase::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.advance(1) - && pp.open("tr_phase_compute_skipped") - && pp.field("reason") - && t_ComputeSkipReason.print_skip(pp, cs) - && pp.close(); - case tr_phase_compute_vm: - return cs.advance(1) - && pp.open("tr_phase_compute_vm") - && pp.fetch_uint_field(cs, 1, "success") - && pp.fetch_uint_field(cs, 1, "msg_state_used") - && pp.fetch_uint_field(cs, 1, "account_activated") - && pp.field("gas_fees") - && t_Grams.print_skip(pp, cs) - && pp.field() - && t_TrComputePhase_aux.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for TrComputePhase"); -} - -const TrComputePhase t_TrComputePhase; - -// -// code for type `ComputeSkipReason` -// - -int ComputeSkipReason::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cskip_no_state: - return cs.have(2) ? cskip_no_state : -1; - case cskip_bad_state: - return cs.have(2) ? cskip_bad_state : -1; - case cskip_no_gas: - return cs.prefetch_ulong(2) == 2 ? cskip_no_gas : -1; - } - return -1; -} - -bool ComputeSkipReason::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cskip_no_state: - return cs.advance(2); - case cskip_bad_state: - return cs.advance(2); - case cskip_no_gas: - return cs.fetch_ulong(2) == 2; - } - return false; -} - -bool ComputeSkipReason::fetch_enum_to(vm::CellSlice& cs, char& value) const { - int t = get_tag(cs); - value = (char)t; - return t >= 0 && cs.fetch_ulong(2) == (unsigned)t; -} - -bool ComputeSkipReason::store_enum_from(vm::CellBuilder& cb, int value) const { - return cb.store_uint_less(3, value); -} - -bool ComputeSkipReason::unpack(vm::CellSlice& cs, ComputeSkipReason::Record_cskip_no_state& data) const { - return cs.fetch_ulong(2) == 0; -} - -bool ComputeSkipReason::unpack_cskip_no_state(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0; -} - -bool ComputeSkipReason::cell_unpack(Ref cell_ref, ComputeSkipReason::Record_cskip_no_state& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComputeSkipReason::cell_unpack_cskip_no_state(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cskip_no_state(cs) && cs.empty_ext(); -} - -bool ComputeSkipReason::unpack(vm::CellSlice& cs, ComputeSkipReason::Record_cskip_bad_state& data) const { - return cs.fetch_ulong(2) == 1; -} - -bool ComputeSkipReason::unpack_cskip_bad_state(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 1; -} - -bool ComputeSkipReason::cell_unpack(Ref cell_ref, ComputeSkipReason::Record_cskip_bad_state& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComputeSkipReason::cell_unpack_cskip_bad_state(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cskip_bad_state(cs) && cs.empty_ext(); -} - -bool ComputeSkipReason::unpack(vm::CellSlice& cs, ComputeSkipReason::Record_cskip_no_gas& data) const { - return cs.fetch_ulong(2) == 2; -} - -bool ComputeSkipReason::unpack_cskip_no_gas(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 2; -} - -bool ComputeSkipReason::cell_unpack(Ref cell_ref, ComputeSkipReason::Record_cskip_no_gas& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComputeSkipReason::cell_unpack_cskip_no_gas(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cskip_no_gas(cs) && cs.empty_ext(); -} - -bool ComputeSkipReason::pack(vm::CellBuilder& cb, const ComputeSkipReason::Record_cskip_no_state& data) const { - return cb.store_long_bool(0, 2); -} - -bool ComputeSkipReason::pack_cskip_no_state(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 2); -} - -bool ComputeSkipReason::cell_pack(Ref& cell_ref, const ComputeSkipReason::Record_cskip_no_state& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::cell_pack_cskip_no_state(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cskip_no_state(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::pack(vm::CellBuilder& cb, const ComputeSkipReason::Record_cskip_bad_state& data) const { - return cb.store_long_bool(1, 2); -} - -bool ComputeSkipReason::pack_cskip_bad_state(vm::CellBuilder& cb) const { - return cb.store_long_bool(1, 2); -} - -bool ComputeSkipReason::cell_pack(Ref& cell_ref, const ComputeSkipReason::Record_cskip_bad_state& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::cell_pack_cskip_bad_state(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cskip_bad_state(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::pack(vm::CellBuilder& cb, const ComputeSkipReason::Record_cskip_no_gas& data) const { - return cb.store_long_bool(2, 2); -} - -bool ComputeSkipReason::pack_cskip_no_gas(vm::CellBuilder& cb) const { - return cb.store_long_bool(2, 2); -} - -bool ComputeSkipReason::cell_pack(Ref& cell_ref, const ComputeSkipReason::Record_cskip_no_gas& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::cell_pack_cskip_no_gas(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cskip_no_gas(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ComputeSkipReason::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cskip_no_state: - return cs.advance(2) - && pp.cons("cskip_no_state"); - case cskip_bad_state: - return cs.advance(2) - && pp.cons("cskip_bad_state"); - case cskip_no_gas: - return cs.fetch_ulong(2) == 2 - && pp.cons("cskip_no_gas"); - } - return pp.fail("unknown constructor for ComputeSkipReason"); -} - -const ComputeSkipReason t_ComputeSkipReason; - -// -// code for type `TrActionPhase` -// - -int TrActionPhase::check_tag(const vm::CellSlice& cs) const { - return tr_phase_action; -} - -bool TrActionPhase::skip(vm::CellSlice& cs) const { - return cs.advance(3) - && t_AccStatusChange.skip(cs) - && t_Maybe_Grams.skip(cs) - && t_Maybe_Grams.skip(cs) - && cs.advance(32) - && t_Maybe_int32.skip(cs) - && cs.advance(320) - && t_StorageUsedShort.skip(cs); -} - -bool TrActionPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(3) - && t_AccStatusChange.validate_skip(ops, cs, weak) - && t_Maybe_Grams.validate_skip(ops, cs, weak) - && t_Maybe_Grams.validate_skip(ops, cs, weak) - && cs.advance(32) - && t_Maybe_int32.validate_skip(ops, cs, weak) - && cs.advance(320) - && t_StorageUsedShort.validate_skip(ops, cs, weak); -} - -bool TrActionPhase::unpack(vm::CellSlice& cs, TrActionPhase::Record& data) const { - return cs.fetch_bool_to(data.success) - && cs.fetch_bool_to(data.valid) - && cs.fetch_bool_to(data.no_funds) - && t_AccStatusChange.fetch_enum_to(cs, data.status_change) - && t_Maybe_Grams.fetch_to(cs, data.total_fwd_fees) - && t_Maybe_Grams.fetch_to(cs, data.total_action_fees) - && cs.fetch_int_to(32, data.result_code) - && t_Maybe_int32.fetch_to(cs, data.result_arg) - && cs.fetch_uint_to(16, data.tot_actions) - && cs.fetch_uint_to(16, data.spec_actions) - && cs.fetch_uint_to(16, data.skipped_actions) - && cs.fetch_uint_to(16, data.msgs_created) - && cs.fetch_bits_to(data.action_list_hash.bits(), 256) - && t_StorageUsedShort.fetch_to(cs, data.tot_msg_size); -} - -bool TrActionPhase::cell_unpack(Ref cell_ref, TrActionPhase::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrActionPhase::pack(vm::CellBuilder& cb, const TrActionPhase::Record& data) const { - return cb.store_ulong_rchk_bool(data.success, 1) - && cb.store_ulong_rchk_bool(data.valid, 1) - && cb.store_ulong_rchk_bool(data.no_funds, 1) - && t_AccStatusChange.store_enum_from(cb, data.status_change) - && t_Maybe_Grams.store_from(cb, data.total_fwd_fees) - && t_Maybe_Grams.store_from(cb, data.total_action_fees) - && cb.store_long_rchk_bool(data.result_code, 32) - && t_Maybe_int32.store_from(cb, data.result_arg) - && cb.store_ulong_rchk_bool(data.tot_actions, 16) - && cb.store_ulong_rchk_bool(data.spec_actions, 16) - && cb.store_ulong_rchk_bool(data.skipped_actions, 16) - && cb.store_ulong_rchk_bool(data.msgs_created, 16) - && cb.store_bits_bool(data.action_list_hash.cbits(), 256) - && t_StorageUsedShort.store_from(cb, data.tot_msg_size); -} - -bool TrActionPhase::cell_pack(Ref& cell_ref, const TrActionPhase::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrActionPhase::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("tr_phase_action") - && pp.fetch_uint_field(cs, 1, "success") - && pp.fetch_uint_field(cs, 1, "valid") - && pp.fetch_uint_field(cs, 1, "no_funds") - && pp.field("status_change") - && t_AccStatusChange.print_skip(pp, cs) - && pp.field("total_fwd_fees") - && t_Maybe_Grams.print_skip(pp, cs) - && pp.field("total_action_fees") - && t_Maybe_Grams.print_skip(pp, cs) - && pp.fetch_int_field(cs, 32, "result_code") - && pp.field("result_arg") - && t_Maybe_int32.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 16, "tot_actions") - && pp.fetch_uint_field(cs, 16, "spec_actions") - && pp.fetch_uint_field(cs, 16, "skipped_actions") - && pp.fetch_uint_field(cs, 16, "msgs_created") - && pp.fetch_bits_field(cs, 256, "action_list_hash") - && pp.field("tot_msg_size") - && t_StorageUsedShort.print_skip(pp, cs) - && pp.close(); -} - -const TrActionPhase t_TrActionPhase; - -// -// code for type `TrBouncePhase` -// -constexpr char TrBouncePhase::cons_len[3]; -constexpr unsigned char TrBouncePhase::cons_tag[3]; - -int TrBouncePhase::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.have(2) ? tr_phase_bounce_negfunds : -1; - case tr_phase_bounce_nofunds: - return cs.have(2) ? tr_phase_bounce_nofunds : -1; - case tr_phase_bounce_ok: - return cs.have(1) ? tr_phase_bounce_ok : -1; - } - return -1; -} - -bool TrBouncePhase::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.advance(2); - case tr_phase_bounce_nofunds: - return cs.advance(2) - && t_StorageUsedShort.skip(cs) - && t_Grams.skip(cs); - case tr_phase_bounce_ok: - return cs.advance(1) - && t_StorageUsedShort.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs); - } - return false; -} - -bool TrBouncePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.advance(2); - case tr_phase_bounce_nofunds: - return cs.advance(2) - && t_StorageUsedShort.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case tr_phase_bounce_ok: - return cs.advance(1) - && t_StorageUsedShort.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - } - return false; -} - -bool TrBouncePhase::unpack(vm::CellSlice& cs, TrBouncePhase::Record_tr_phase_bounce_negfunds& data) const { - return cs.fetch_ulong(2) == 0; -} - -bool TrBouncePhase::unpack_tr_phase_bounce_negfunds(vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0; -} - -bool TrBouncePhase::cell_unpack(Ref cell_ref, TrBouncePhase::Record_tr_phase_bounce_negfunds& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrBouncePhase::cell_unpack_tr_phase_bounce_negfunds(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_bounce_negfunds(cs) && cs.empty_ext(); -} - -bool TrBouncePhase::unpack(vm::CellSlice& cs, TrBouncePhase::Record_tr_phase_bounce_nofunds& data) const { - return cs.fetch_ulong(2) == 1 - && t_StorageUsedShort.fetch_to(cs, data.msg_size) - && t_Grams.fetch_to(cs, data.req_fwd_fees); -} - -bool TrBouncePhase::unpack_tr_phase_bounce_nofunds(vm::CellSlice& cs, Ref& msg_size, Ref& req_fwd_fees) const { - return cs.fetch_ulong(2) == 1 - && t_StorageUsedShort.fetch_to(cs, msg_size) - && t_Grams.fetch_to(cs, req_fwd_fees); -} - -bool TrBouncePhase::cell_unpack(Ref cell_ref, TrBouncePhase::Record_tr_phase_bounce_nofunds& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrBouncePhase::cell_unpack_tr_phase_bounce_nofunds(Ref cell_ref, Ref& msg_size, Ref& req_fwd_fees) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_bounce_nofunds(cs, msg_size, req_fwd_fees) && cs.empty_ext(); -} - -bool TrBouncePhase::unpack(vm::CellSlice& cs, TrBouncePhase::Record_tr_phase_bounce_ok& data) const { - return cs.fetch_ulong(1) == 1 - && t_StorageUsedShort.fetch_to(cs, data.msg_size) - && t_Grams.fetch_to(cs, data.msg_fees) - && t_Grams.fetch_to(cs, data.fwd_fees); -} - -bool TrBouncePhase::unpack_tr_phase_bounce_ok(vm::CellSlice& cs, Ref& msg_size, Ref& msg_fees, Ref& fwd_fees) const { - return cs.fetch_ulong(1) == 1 - && t_StorageUsedShort.fetch_to(cs, msg_size) - && t_Grams.fetch_to(cs, msg_fees) - && t_Grams.fetch_to(cs, fwd_fees); -} - -bool TrBouncePhase::cell_unpack(Ref cell_ref, TrBouncePhase::Record_tr_phase_bounce_ok& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TrBouncePhase::cell_unpack_tr_phase_bounce_ok(Ref cell_ref, Ref& msg_size, Ref& msg_fees, Ref& fwd_fees) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_tr_phase_bounce_ok(cs, msg_size, msg_fees, fwd_fees) && cs.empty_ext(); -} - -bool TrBouncePhase::pack(vm::CellBuilder& cb, const TrBouncePhase::Record_tr_phase_bounce_negfunds& data) const { - return cb.store_long_bool(0, 2); -} - -bool TrBouncePhase::pack_tr_phase_bounce_negfunds(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 2); -} - -bool TrBouncePhase::cell_pack(Ref& cell_ref, const TrBouncePhase::Record_tr_phase_bounce_negfunds& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::cell_pack_tr_phase_bounce_negfunds(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_tr_phase_bounce_negfunds(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::pack(vm::CellBuilder& cb, const TrBouncePhase::Record_tr_phase_bounce_nofunds& data) const { - return cb.store_long_bool(1, 2) - && t_StorageUsedShort.store_from(cb, data.msg_size) - && t_Grams.store_from(cb, data.req_fwd_fees); -} - -bool TrBouncePhase::pack_tr_phase_bounce_nofunds(vm::CellBuilder& cb, Ref msg_size, Ref req_fwd_fees) const { - return cb.store_long_bool(1, 2) - && t_StorageUsedShort.store_from(cb, msg_size) - && t_Grams.store_from(cb, req_fwd_fees); -} - -bool TrBouncePhase::cell_pack(Ref& cell_ref, const TrBouncePhase::Record_tr_phase_bounce_nofunds& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::cell_pack_tr_phase_bounce_nofunds(Ref& cell_ref, Ref msg_size, Ref req_fwd_fees) const { - vm::CellBuilder cb; - return pack_tr_phase_bounce_nofunds(cb, std::move(msg_size), std::move(req_fwd_fees)) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::pack(vm::CellBuilder& cb, const TrBouncePhase::Record_tr_phase_bounce_ok& data) const { - return cb.store_long_bool(1, 1) - && t_StorageUsedShort.store_from(cb, data.msg_size) - && t_Grams.store_from(cb, data.msg_fees) - && t_Grams.store_from(cb, data.fwd_fees); -} - -bool TrBouncePhase::pack_tr_phase_bounce_ok(vm::CellBuilder& cb, Ref msg_size, Ref msg_fees, Ref fwd_fees) const { - return cb.store_long_bool(1, 1) - && t_StorageUsedShort.store_from(cb, msg_size) - && t_Grams.store_from(cb, msg_fees) - && t_Grams.store_from(cb, fwd_fees); -} - -bool TrBouncePhase::cell_pack(Ref& cell_ref, const TrBouncePhase::Record_tr_phase_bounce_ok& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::cell_pack_tr_phase_bounce_ok(Ref& cell_ref, Ref msg_size, Ref msg_fees, Ref fwd_fees) const { - vm::CellBuilder cb; - return pack_tr_phase_bounce_ok(cb, std::move(msg_size), std::move(msg_fees), std::move(fwd_fees)) && std::move(cb).finalize_to(cell_ref); -} - -bool TrBouncePhase::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.advance(2) - && pp.cons("tr_phase_bounce_negfunds"); - case tr_phase_bounce_nofunds: - return cs.advance(2) - && pp.open("tr_phase_bounce_nofunds") - && pp.field("msg_size") - && t_StorageUsedShort.print_skip(pp, cs) - && pp.field("req_fwd_fees") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case tr_phase_bounce_ok: - return cs.advance(1) - && pp.open("tr_phase_bounce_ok") - && pp.field("msg_size") - && t_StorageUsedShort.print_skip(pp, cs) - && pp.field("msg_fees") - && t_Grams.print_skip(pp, cs) - && pp.field("fwd_fees") - && t_Grams.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for TrBouncePhase"); -} - -const TrBouncePhase t_TrBouncePhase; - -// -// code for type `SplitMergeInfo` -// - -int SplitMergeInfo::check_tag(const vm::CellSlice& cs) const { - return split_merge_info; -} - -bool SplitMergeInfo::unpack(vm::CellSlice& cs, SplitMergeInfo::Record& data) const { - return cs.fetch_uint_to(6, data.cur_shard_pfx_len) - && cs.fetch_uint_to(6, data.acc_split_depth) - && cs.fetch_bits_to(data.this_addr.bits(), 256) - && cs.fetch_bits_to(data.sibling_addr.bits(), 256); -} - -bool SplitMergeInfo::cell_unpack(Ref cell_ref, SplitMergeInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SplitMergeInfo::pack(vm::CellBuilder& cb, const SplitMergeInfo::Record& data) const { - return cb.store_ulong_rchk_bool(data.cur_shard_pfx_len, 6) - && cb.store_ulong_rchk_bool(data.acc_split_depth, 6) - && cb.store_bits_bool(data.this_addr.cbits(), 256) - && cb.store_bits_bool(data.sibling_addr.cbits(), 256); -} - -bool SplitMergeInfo::cell_pack(Ref& cell_ref, const SplitMergeInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SplitMergeInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int cur_shard_pfx_len, acc_split_depth; - return pp.open("split_merge_info") - && cs.fetch_uint_to(6, cur_shard_pfx_len) - && pp.field_int(cur_shard_pfx_len, "cur_shard_pfx_len") - && cs.fetch_uint_to(6, acc_split_depth) - && pp.field_int(acc_split_depth, "acc_split_depth") - && pp.fetch_bits_field(cs, 256, "this_addr") - && pp.fetch_bits_field(cs, 256, "sibling_addr") - && pp.close(); -} - -const SplitMergeInfo t_SplitMergeInfo; - -// -// code for type `TransactionDescr` -// -constexpr char TransactionDescr::cons_len[7]; -constexpr unsigned char TransactionDescr::cons_tag[7]; - -int TransactionDescr::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.have(4) ? trans_ord : -1; - case trans_storage: - return cs.have(4) ? trans_storage : -1; - case trans_tick_tock: - return cs.have(3) ? trans_tick_tock : -1; - case trans_split_prepare: - return cs.have(4) ? trans_split_prepare : -1; - case trans_split_install: - return cs.have(4) ? trans_split_install : -1; - case trans_merge_prepare: - return cs.have(4) ? trans_merge_prepare : -1; - case trans_merge_install: - return cs.prefetch_ulong(4) == 7 ? trans_merge_install : -1; - } - return -1; -} - -bool TransactionDescr::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(5) - && t_Maybe_TrStoragePhase.skip(cs) - && t_Maybe_TrCreditPhase.skip(cs) - && t_TrComputePhase.skip(cs) - && t_Maybe_Ref_TrActionPhase.skip(cs) - && cs.advance(1) - && t_Maybe_TrBouncePhase.skip(cs) - && cs.advance(1); - case trans_storage: - return cs.advance(4) - && t_TrStoragePhase.skip(cs); - case trans_tick_tock: - return cs.advance(4) - && t_TrStoragePhase.skip(cs) - && t_TrComputePhase.skip(cs) - && t_Maybe_Ref_TrActionPhase.skip(cs) - && cs.advance(2); - case trans_split_prepare: - return cs.advance(528) - && t_Maybe_TrStoragePhase.skip(cs) - && t_TrComputePhase.skip(cs) - && t_Maybe_Ref_TrActionPhase.skip(cs) - && cs.advance(2); - case trans_split_install: - return cs.advance_ext(0x10211); - case trans_merge_prepare: - return cs.advance(528) - && t_TrStoragePhase.skip(cs) - && cs.advance(1); - case trans_merge_install: - return cs.advance_ext(0x10210) - && t_Maybe_TrStoragePhase.skip(cs) - && t_Maybe_TrCreditPhase.skip(cs) - && t_TrComputePhase.skip(cs) - && t_Maybe_Ref_TrActionPhase.skip(cs) - && cs.advance(2); - } - return false; -} - -bool TransactionDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(5) - && t_Maybe_TrStoragePhase.validate_skip(ops, cs, weak) - && t_Maybe_TrCreditPhase.validate_skip(ops, cs, weak) - && t_TrComputePhase.validate_skip(ops, cs, weak) - && t_Maybe_Ref_TrActionPhase.validate_skip(ops, cs, weak) - && cs.advance(1) - && t_Maybe_TrBouncePhase.validate_skip(ops, cs, weak) - && cs.advance(1); - case trans_storage: - return cs.advance(4) - && t_TrStoragePhase.validate_skip(ops, cs, weak); - case trans_tick_tock: - return cs.advance(4) - && t_TrStoragePhase.validate_skip(ops, cs, weak) - && t_TrComputePhase.validate_skip(ops, cs, weak) - && t_Maybe_Ref_TrActionPhase.validate_skip(ops, cs, weak) - && cs.advance(2); - case trans_split_prepare: - return cs.advance(528) - && t_Maybe_TrStoragePhase.validate_skip(ops, cs, weak) - && t_TrComputePhase.validate_skip(ops, cs, weak) - && t_Maybe_Ref_TrActionPhase.validate_skip(ops, cs, weak) - && cs.advance(2); - case trans_split_install: - return cs.advance(528) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && cs.advance(1); - case trans_merge_prepare: - return cs.advance(528) - && t_TrStoragePhase.validate_skip(ops, cs, weak) - && cs.advance(1); - case trans_merge_install: - return cs.fetch_ulong(4) == 7 - && cs.advance(524) - && t_Transaction.validate_skip_ref(ops, cs, weak) - && t_Maybe_TrStoragePhase.validate_skip(ops, cs, weak) - && t_Maybe_TrCreditPhase.validate_skip(ops, cs, weak) - && t_TrComputePhase.validate_skip(ops, cs, weak) - && t_Maybe_Ref_TrActionPhase.validate_skip(ops, cs, weak) - && cs.advance(2); - } - return false; -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_ord& data) const { - return cs.fetch_ulong(4) == 0 - && cs.fetch_bool_to(data.credit_first) - && t_Maybe_TrStoragePhase.fetch_to(cs, data.storage_ph) - && t_Maybe_TrCreditPhase.fetch_to(cs, data.credit_ph) - && t_TrComputePhase.fetch_to(cs, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.fetch_to(cs, data.action) - && cs.fetch_bool_to(data.aborted) - && t_Maybe_TrBouncePhase.fetch_to(cs, data.bounce) - && cs.fetch_bool_to(data.destroyed); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_ord& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_storage& data) const { - return cs.fetch_ulong(4) == 1 - && t_TrStoragePhase.fetch_to(cs, data.storage_ph); -} - -bool TransactionDescr::unpack_trans_storage(vm::CellSlice& cs, Ref& storage_ph) const { - return cs.fetch_ulong(4) == 1 - && t_TrStoragePhase.fetch_to(cs, storage_ph); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_storage& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::cell_unpack_trans_storage(Ref cell_ref, Ref& storage_ph) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_trans_storage(cs, storage_ph) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_tick_tock& data) const { - return cs.fetch_ulong(3) == 1 - && cs.fetch_bool_to(data.is_tock) - && t_TrStoragePhase.fetch_to(cs, data.storage_ph) - && t_TrComputePhase.fetch_to(cs, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.fetch_to(cs, data.action) - && cs.fetch_bool_to(data.aborted) - && cs.fetch_bool_to(data.destroyed); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_tick_tock& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_split_prepare& data) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_subslice_to(524, data.split_info) - && t_Maybe_TrStoragePhase.fetch_to(cs, data.storage_ph) - && t_TrComputePhase.fetch_to(cs, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.fetch_to(cs, data.action) - && cs.fetch_bool_to(data.aborted) - && cs.fetch_bool_to(data.destroyed); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_split_prepare& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_split_install& data) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_subslice_to(524, data.split_info) - && cs.fetch_ref_to(data.prepare_transaction) - && cs.fetch_bool_to(data.installed); -} - -bool TransactionDescr::unpack_trans_split_install(vm::CellSlice& cs, Ref& split_info, Ref& prepare_transaction, bool& installed) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_subslice_to(524, split_info) - && cs.fetch_ref_to(prepare_transaction) - && cs.fetch_bool_to(installed); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_split_install& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::cell_unpack_trans_split_install(Ref cell_ref, Ref& split_info, Ref& prepare_transaction, bool& installed) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_trans_split_install(cs, split_info, prepare_transaction, installed) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_merge_prepare& data) const { - return cs.fetch_ulong(4) == 6 - && cs.fetch_subslice_to(524, data.split_info) - && t_TrStoragePhase.fetch_to(cs, data.storage_ph) - && cs.fetch_bool_to(data.aborted); -} - -bool TransactionDescr::unpack_trans_merge_prepare(vm::CellSlice& cs, Ref& split_info, Ref& storage_ph, bool& aborted) const { - return cs.fetch_ulong(4) == 6 - && cs.fetch_subslice_to(524, split_info) - && t_TrStoragePhase.fetch_to(cs, storage_ph) - && cs.fetch_bool_to(aborted); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_merge_prepare& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::cell_unpack_trans_merge_prepare(Ref cell_ref, Ref& split_info, Ref& storage_ph, bool& aborted) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_trans_merge_prepare(cs, split_info, storage_ph, aborted) && cs.empty_ext(); -} - -bool TransactionDescr::unpack(vm::CellSlice& cs, TransactionDescr::Record_trans_merge_install& data) const { - return cs.fetch_ulong(4) == 7 - && cs.fetch_subslice_to(524, data.split_info) - && cs.fetch_ref_to(data.prepare_transaction) - && t_Maybe_TrStoragePhase.fetch_to(cs, data.storage_ph) - && t_Maybe_TrCreditPhase.fetch_to(cs, data.credit_ph) - && t_TrComputePhase.fetch_to(cs, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.fetch_to(cs, data.action) - && cs.fetch_bool_to(data.aborted) - && cs.fetch_bool_to(data.destroyed); -} - -bool TransactionDescr::cell_unpack(Ref cell_ref, TransactionDescr::Record_trans_merge_install& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_ord& data) const { - return cb.store_long_bool(0, 4) - && cb.store_ulong_rchk_bool(data.credit_first, 1) - && t_Maybe_TrStoragePhase.store_from(cb, data.storage_ph) - && t_Maybe_TrCreditPhase.store_from(cb, data.credit_ph) - && t_TrComputePhase.store_from(cb, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.store_from(cb, data.action) - && cb.store_ulong_rchk_bool(data.aborted, 1) - && t_Maybe_TrBouncePhase.store_from(cb, data.bounce) - && cb.store_ulong_rchk_bool(data.destroyed, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_ord& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_storage& data) const { - return cb.store_long_bool(1, 4) - && t_TrStoragePhase.store_from(cb, data.storage_ph); -} - -bool TransactionDescr::pack_trans_storage(vm::CellBuilder& cb, Ref storage_ph) const { - return cb.store_long_bool(1, 4) - && t_TrStoragePhase.store_from(cb, storage_ph); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_storage& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::cell_pack_trans_storage(Ref& cell_ref, Ref storage_ph) const { - vm::CellBuilder cb; - return pack_trans_storage(cb, std::move(storage_ph)) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_tick_tock& data) const { - return cb.store_long_bool(1, 3) - && cb.store_ulong_rchk_bool(data.is_tock, 1) - && t_TrStoragePhase.store_from(cb, data.storage_ph) - && t_TrComputePhase.store_from(cb, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.store_from(cb, data.action) - && cb.store_ulong_rchk_bool(data.aborted, 1) - && cb.store_ulong_rchk_bool(data.destroyed, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_tick_tock& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_split_prepare& data) const { - return cb.store_long_bool(4, 4) - && cb.append_cellslice_chk(data.split_info, 524) - && t_Maybe_TrStoragePhase.store_from(cb, data.storage_ph) - && t_TrComputePhase.store_from(cb, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.store_from(cb, data.action) - && cb.store_ulong_rchk_bool(data.aborted, 1) - && cb.store_ulong_rchk_bool(data.destroyed, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_split_prepare& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_split_install& data) const { - return cb.store_long_bool(5, 4) - && cb.append_cellslice_chk(data.split_info, 524) - && cb.store_ref_bool(data.prepare_transaction) - && cb.store_ulong_rchk_bool(data.installed, 1); -} - -bool TransactionDescr::pack_trans_split_install(vm::CellBuilder& cb, Ref split_info, Ref prepare_transaction, bool installed) const { - return cb.store_long_bool(5, 4) - && cb.append_cellslice_chk(split_info, 524) - && cb.store_ref_bool(prepare_transaction) - && cb.store_ulong_rchk_bool(installed, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_split_install& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::cell_pack_trans_split_install(Ref& cell_ref, Ref split_info, Ref prepare_transaction, bool installed) const { - vm::CellBuilder cb; - return pack_trans_split_install(cb, std::move(split_info), std::move(prepare_transaction), installed) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_merge_prepare& data) const { - return cb.store_long_bool(6, 4) - && cb.append_cellslice_chk(data.split_info, 524) - && t_TrStoragePhase.store_from(cb, data.storage_ph) - && cb.store_ulong_rchk_bool(data.aborted, 1); -} - -bool TransactionDescr::pack_trans_merge_prepare(vm::CellBuilder& cb, Ref split_info, Ref storage_ph, bool aborted) const { - return cb.store_long_bool(6, 4) - && cb.append_cellslice_chk(split_info, 524) - && t_TrStoragePhase.store_from(cb, storage_ph) - && cb.store_ulong_rchk_bool(aborted, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_merge_prepare& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::cell_pack_trans_merge_prepare(Ref& cell_ref, Ref split_info, Ref storage_ph, bool aborted) const { - vm::CellBuilder cb; - return pack_trans_merge_prepare(cb, std::move(split_info), std::move(storage_ph), aborted) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::pack(vm::CellBuilder& cb, const TransactionDescr::Record_trans_merge_install& data) const { - return cb.store_long_bool(7, 4) - && cb.append_cellslice_chk(data.split_info, 524) - && cb.store_ref_bool(data.prepare_transaction) - && t_Maybe_TrStoragePhase.store_from(cb, data.storage_ph) - && t_Maybe_TrCreditPhase.store_from(cb, data.credit_ph) - && t_TrComputePhase.store_from(cb, data.compute_ph) - && t_Maybe_Ref_TrActionPhase.store_from(cb, data.action) - && cb.store_ulong_rchk_bool(data.aborted, 1) - && cb.store_ulong_rchk_bool(data.destroyed, 1); -} - -bool TransactionDescr::cell_pack(Ref& cell_ref, const TransactionDescr::Record_trans_merge_install& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TransactionDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(4) - && pp.open("trans_ord") - && pp.fetch_uint_field(cs, 1, "credit_first") - && pp.field("storage_ph") - && t_Maybe_TrStoragePhase.print_skip(pp, cs) - && pp.field("credit_ph") - && t_Maybe_TrCreditPhase.print_skip(pp, cs) - && pp.field("compute_ph") - && t_TrComputePhase.print_skip(pp, cs) - && pp.field("action") - && t_Maybe_Ref_TrActionPhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "aborted") - && pp.field("bounce") - && t_Maybe_TrBouncePhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "destroyed") - && pp.close(); - case trans_storage: - return cs.advance(4) - && pp.open("trans_storage") - && pp.field("storage_ph") - && t_TrStoragePhase.print_skip(pp, cs) - && pp.close(); - case trans_tick_tock: - return cs.advance(3) - && pp.open("trans_tick_tock") - && pp.fetch_uint_field(cs, 1, "is_tock") - && pp.field("storage_ph") - && t_TrStoragePhase.print_skip(pp, cs) - && pp.field("compute_ph") - && t_TrComputePhase.print_skip(pp, cs) - && pp.field("action") - && t_Maybe_Ref_TrActionPhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "aborted") - && pp.fetch_uint_field(cs, 1, "destroyed") - && pp.close(); - case trans_split_prepare: - return cs.advance(4) - && pp.open("trans_split_prepare") - && pp.field("split_info") - && t_SplitMergeInfo.print_skip(pp, cs) - && pp.field("storage_ph") - && t_Maybe_TrStoragePhase.print_skip(pp, cs) - && pp.field("compute_ph") - && t_TrComputePhase.print_skip(pp, cs) - && pp.field("action") - && t_Maybe_Ref_TrActionPhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "aborted") - && pp.fetch_uint_field(cs, 1, "destroyed") - && pp.close(); - case trans_split_install: - return cs.advance(4) - && pp.open("trans_split_install") - && pp.field("split_info") - && t_SplitMergeInfo.print_skip(pp, cs) - && pp.field("prepare_transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 1, "installed") - && pp.close(); - case trans_merge_prepare: - return cs.advance(4) - && pp.open("trans_merge_prepare") - && pp.field("split_info") - && t_SplitMergeInfo.print_skip(pp, cs) - && pp.field("storage_ph") - && t_TrStoragePhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "aborted") - && pp.close(); - case trans_merge_install: - return cs.fetch_ulong(4) == 7 - && pp.open("trans_merge_install") - && pp.field("split_info") - && t_SplitMergeInfo.print_skip(pp, cs) - && pp.field("prepare_transaction") - && t_Transaction.print_ref(pp, cs.fetch_ref()) - && pp.field("storage_ph") - && t_Maybe_TrStoragePhase.print_skip(pp, cs) - && pp.field("credit_ph") - && t_Maybe_TrCreditPhase.print_skip(pp, cs) - && pp.field("compute_ph") - && t_TrComputePhase.print_skip(pp, cs) - && pp.field("action") - && t_Maybe_Ref_TrActionPhase.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "aborted") - && pp.fetch_uint_field(cs, 1, "destroyed") - && pp.close(); - } - return pp.fail("unknown constructor for TransactionDescr"); -} - -const TransactionDescr t_TransactionDescr; - -// -// code for type `SmartContractInfo` -// -constexpr unsigned SmartContractInfo::cons_tag[1]; - -int SmartContractInfo::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x76ef1ea ? smc_info : -1; -} - -bool SmartContractInfo::skip(vm::CellSlice& cs) const { - return cs.advance(480) - && t_CurrencyCollection.skip(cs) - && t_MsgAddressInt.skip(cs); -} - -bool SmartContractInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x76ef1ea - && cs.advance(448) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_MsgAddressInt.validate_skip(ops, cs, weak); -} - -bool SmartContractInfo::unpack(vm::CellSlice& cs, SmartContractInfo::Record& data) const { - return cs.fetch_ulong(32) == 0x76ef1ea - && cs.fetch_uint_to(16, data.actions) - && cs.fetch_uint_to(16, data.msgs_sent) - && cs.fetch_uint_to(32, data.unixtime) - && cs.fetch_uint_to(64, data.block_lt) - && cs.fetch_uint_to(64, data.trans_lt) - && cs.fetch_bits_to(data.rand_seed.bits(), 256) - && t_CurrencyCollection.fetch_to(cs, data.balance_remaining) - && t_MsgAddressInt.fetch_to(cs, data.myself); -} - -bool SmartContractInfo::cell_unpack(Ref cell_ref, SmartContractInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmartContractInfo::pack(vm::CellBuilder& cb, const SmartContractInfo::Record& data) const { - return cb.store_long_bool(0x76ef1ea, 32) - && cb.store_ulong_rchk_bool(data.actions, 16) - && cb.store_ulong_rchk_bool(data.msgs_sent, 16) - && cb.store_ulong_rchk_bool(data.unixtime, 32) - && cb.store_ulong_rchk_bool(data.block_lt, 64) - && cb.store_ulong_rchk_bool(data.trans_lt, 64) - && cb.store_bits_bool(data.rand_seed.cbits(), 256) - && t_CurrencyCollection.store_from(cb, data.balance_remaining) - && t_MsgAddressInt.store_from(cb, data.myself); -} - -bool SmartContractInfo::cell_pack(Ref& cell_ref, const SmartContractInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmartContractInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x76ef1ea - && pp.open("smc_info") - && pp.fetch_uint_field(cs, 16, "actions") - && pp.fetch_uint_field(cs, 16, "msgs_sent") - && pp.fetch_uint_field(cs, 32, "unixtime") - && pp.fetch_uint_field(cs, 64, "block_lt") - && pp.fetch_uint_field(cs, 64, "trans_lt") - && pp.fetch_bits_field(cs, 256, "rand_seed") - && pp.field("balance_remaining") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("myself") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.close(); -} - -const SmartContractInfo t_SmartContractInfo; - -// -// code for type `OutList` -// - -int OutList::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 2 2 - return m_ ? out_list : out_list_empty; -} - -int OutList::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case out_list_empty: - return out_list_empty; - case out_list: - return out_list; - } - return -1; -} - -bool OutList::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case out_list_empty: - return m_ == 0; - case out_list: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(1) - && t_OutAction.skip(cs); - } - } - return false; -} - -bool OutList::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case out_list_empty: - return m_ == 0; - case out_list: { - int n; - return add_r1(n, 1, m_) - && OutList{n}.validate_skip_ref(ops, cs, weak) - && t_OutAction.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool OutList::unpack(vm::CellSlice& cs, OutList::Record_out_list_empty& data) const { - return m_ == 0; -} - -bool OutList::unpack_out_list_empty(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool OutList::cell_unpack(Ref cell_ref, OutList::Record_out_list_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutList::cell_unpack_out_list_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_out_list_empty(cs) && cs.empty_ext(); -} - -bool OutList::unpack(vm::CellSlice& cs, OutList::Record_out_list& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.prev) - && t_OutAction.fetch_to(cs, data.action); -} - -bool OutList::unpack_out_list(vm::CellSlice& cs, int& n, Ref& prev, Ref& action) const { - return add_r1(n, 1, m_) - && cs.fetch_ref_to(prev) - && t_OutAction.fetch_to(cs, action); -} - -bool OutList::cell_unpack(Ref cell_ref, OutList::Record_out_list& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutList::cell_unpack_out_list(Ref cell_ref, int& n, Ref& prev, Ref& action) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_out_list(cs, n, prev, action) && cs.empty_ext(); -} - -bool OutList::pack(vm::CellBuilder& cb, const OutList::Record_out_list_empty& data) const { - return m_ == 0; -} - -bool OutList::pack_out_list_empty(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool OutList::cell_pack(Ref& cell_ref, const OutList::Record_out_list_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutList::cell_pack_out_list_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_out_list_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool OutList::pack(vm::CellBuilder& cb, const OutList::Record_out_list& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.prev) - && t_OutAction.store_from(cb, data.action); -} - -bool OutList::pack_out_list(vm::CellBuilder& cb, Ref prev, Ref action) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(prev) - && t_OutAction.store_from(cb, action); -} - -bool OutList::cell_pack(Ref& cell_ref, const OutList::Record_out_list& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutList::cell_pack_out_list(Ref& cell_ref, Ref prev, Ref action) const { - vm::CellBuilder cb; - return pack_out_list(cb, std::move(prev), std::move(action)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutList::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case out_list_empty: - return pp.cons("out_list_empty") - && m_ == 0; - case out_list: { - int n; - return pp.open("out_list") - && add_r1(n, 1, m_) - && pp.field("prev") - && OutList{n}.print_ref(pp, cs.fetch_ref()) - && pp.field("action") - && t_OutAction.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for OutList"); -} - - -// -// code for type `LibRef` -// - -int LibRef::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case libref_hash: - return cs.have(1) ? libref_hash : -1; - case libref_ref: - return cs.have(1) ? libref_ref : -1; - } - return -1; -} - -bool LibRef::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case libref_hash: - return cs.advance(257); - case libref_ref: - return cs.advance_ext(0x10001); - } - return false; -} - -bool LibRef::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case libref_hash: - return cs.advance(257); - case libref_ref: - return cs.advance_ext(0x10001); - } - return false; -} - -bool LibRef::unpack(vm::CellSlice& cs, LibRef::Record_libref_hash& data) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_bits_to(data.lib_hash.bits(), 256); -} - -bool LibRef::unpack_libref_hash(vm::CellSlice& cs, td::BitArray<256>& lib_hash) const { - return cs.fetch_ulong(1) == 0 - && cs.fetch_bits_to(lib_hash.bits(), 256); -} - -bool LibRef::cell_unpack(Ref cell_ref, LibRef::Record_libref_hash& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool LibRef::cell_unpack_libref_hash(Ref cell_ref, td::BitArray<256>& lib_hash) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_libref_hash(cs, lib_hash) && cs.empty_ext(); -} - -bool LibRef::unpack(vm::CellSlice& cs, LibRef::Record_libref_ref& data) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(data.library); -} - -bool LibRef::unpack_libref_ref(vm::CellSlice& cs, Ref& library) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(library); -} - -bool LibRef::cell_unpack(Ref cell_ref, LibRef::Record_libref_ref& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool LibRef::cell_unpack_libref_ref(Ref cell_ref, Ref& library) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_libref_ref(cs, library) && cs.empty_ext(); -} - -bool LibRef::pack(vm::CellBuilder& cb, const LibRef::Record_libref_hash& data) const { - return cb.store_long_bool(0, 1) - && cb.store_bits_bool(data.lib_hash.cbits(), 256); -} - -bool LibRef::pack_libref_hash(vm::CellBuilder& cb, td::BitArray<256> lib_hash) const { - return cb.store_long_bool(0, 1) - && cb.store_bits_bool(lib_hash.cbits(), 256); -} - -bool LibRef::cell_pack(Ref& cell_ref, const LibRef::Record_libref_hash& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool LibRef::cell_pack_libref_hash(Ref& cell_ref, td::BitArray<256> lib_hash) const { - vm::CellBuilder cb; - return pack_libref_hash(cb, lib_hash) && std::move(cb).finalize_to(cell_ref); -} - -bool LibRef::pack(vm::CellBuilder& cb, const LibRef::Record_libref_ref& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.library); -} - -bool LibRef::pack_libref_ref(vm::CellBuilder& cb, Ref library) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(library); -} - -bool LibRef::cell_pack(Ref& cell_ref, const LibRef::Record_libref_ref& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool LibRef::cell_pack_libref_ref(Ref& cell_ref, Ref library) const { - vm::CellBuilder cb; - return pack_libref_ref(cb, std::move(library)) && std::move(cb).finalize_to(cell_ref); -} - -bool LibRef::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case libref_hash: - return cs.advance(1) - && pp.open("libref_hash") - && pp.fetch_bits_field(cs, 256, "lib_hash") - && pp.close(); - case libref_ref: - return cs.advance(1) - && pp.open("libref_ref") - && pp.field("library") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for LibRef"); -} - -const LibRef t_LibRef; - -// -// code for type `OutAction` -// -constexpr unsigned OutAction::cons_tag[4]; - -int OutAction::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case action_send_msg: - return cs.prefetch_ulong(32) == 0xec3c86d ? action_send_msg : -1; - case action_set_code: - return cs.prefetch_ulong(32) == 0xad4de08eU ? action_set_code : -1; - case action_reserve_currency: - return cs.prefetch_ulong(32) == 0x36e6b809 ? action_reserve_currency : -1; - case action_change_library: - return cs.prefetch_ulong(32) == 0x26fa1dd4 ? action_change_library : -1; - } - return -1; -} - -bool OutAction::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case action_send_msg: - return cs.advance_ext(0x10028); - case action_set_code: - return cs.advance_ext(0x10020); - case action_reserve_currency: - return cs.advance(40) - && t_CurrencyCollection.skip(cs); - case action_change_library: { - int mode; - return cs.advance(32) - && cs.fetch_uint_to(7, mode) - && mode <= 2 - && t_LibRef.skip(cs); - } - } - return false; -} - -bool OutAction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case action_send_msg: - return cs.fetch_ulong(32) == 0xec3c86d - && cs.advance(8) - && t_MessageRelaxed_Any.validate_skip_ref(ops, cs, weak); - case action_set_code: - return cs.fetch_ulong(32) == 0xad4de08eU - && cs.advance_refs(1); - case action_reserve_currency: - return cs.fetch_ulong(32) == 0x36e6b809 - && cs.advance(8) - && t_CurrencyCollection.validate_skip(ops, cs, weak); - case action_change_library: { - int mode; - return cs.fetch_ulong(32) == 0x26fa1dd4 - && cs.fetch_uint_to(7, mode) - && mode <= 2 - && t_LibRef.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool OutAction::unpack(vm::CellSlice& cs, OutAction::Record_action_send_msg& data) const { - return cs.fetch_ulong(32) == 0xec3c86d - && cs.fetch_uint_to(8, data.mode) - && cs.fetch_ref_to(data.out_msg); -} - -bool OutAction::unpack_action_send_msg(vm::CellSlice& cs, int& mode, Ref& out_msg) const { - return cs.fetch_ulong(32) == 0xec3c86d - && cs.fetch_uint_to(8, mode) - && cs.fetch_ref_to(out_msg); -} - -bool OutAction::cell_unpack(Ref cell_ref, OutAction::Record_action_send_msg& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutAction::cell_unpack_action_send_msg(Ref cell_ref, int& mode, Ref& out_msg) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_action_send_msg(cs, mode, out_msg) && cs.empty_ext(); -} - -bool OutAction::unpack(vm::CellSlice& cs, OutAction::Record_action_set_code& data) const { - return cs.fetch_ulong(32) == 0xad4de08eU - && cs.fetch_ref_to(data.new_code); -} - -bool OutAction::unpack_action_set_code(vm::CellSlice& cs, Ref& new_code) const { - return cs.fetch_ulong(32) == 0xad4de08eU - && cs.fetch_ref_to(new_code); -} - -bool OutAction::cell_unpack(Ref cell_ref, OutAction::Record_action_set_code& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutAction::cell_unpack_action_set_code(Ref cell_ref, Ref& new_code) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_action_set_code(cs, new_code) && cs.empty_ext(); -} - -bool OutAction::unpack(vm::CellSlice& cs, OutAction::Record_action_reserve_currency& data) const { - return cs.fetch_ulong(32) == 0x36e6b809 - && cs.fetch_uint_to(8, data.mode) - && t_CurrencyCollection.fetch_to(cs, data.currency); -} - -bool OutAction::unpack_action_reserve_currency(vm::CellSlice& cs, int& mode, Ref& currency) const { - return cs.fetch_ulong(32) == 0x36e6b809 - && cs.fetch_uint_to(8, mode) - && t_CurrencyCollection.fetch_to(cs, currency); -} - -bool OutAction::cell_unpack(Ref cell_ref, OutAction::Record_action_reserve_currency& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutAction::cell_unpack_action_reserve_currency(Ref cell_ref, int& mode, Ref& currency) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_action_reserve_currency(cs, mode, currency) && cs.empty_ext(); -} - -bool OutAction::unpack(vm::CellSlice& cs, OutAction::Record_action_change_library& data) const { - return cs.fetch_ulong(32) == 0x26fa1dd4 - && cs.fetch_uint_to(7, data.mode) - && data.mode <= 2 - && t_LibRef.fetch_to(cs, data.libref); -} - -bool OutAction::unpack_action_change_library(vm::CellSlice& cs, int& mode, Ref& libref) const { - return cs.fetch_ulong(32) == 0x26fa1dd4 - && cs.fetch_uint_to(7, mode) - && mode <= 2 - && t_LibRef.fetch_to(cs, libref); -} - -bool OutAction::cell_unpack(Ref cell_ref, OutAction::Record_action_change_library& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutAction::cell_unpack_action_change_library(Ref cell_ref, int& mode, Ref& libref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_action_change_library(cs, mode, libref) && cs.empty_ext(); -} - -bool OutAction::pack(vm::CellBuilder& cb, const OutAction::Record_action_send_msg& data) const { - return cb.store_long_bool(0xec3c86d, 32) - && cb.store_ulong_rchk_bool(data.mode, 8) - && cb.store_ref_bool(data.out_msg); -} - -bool OutAction::pack_action_send_msg(vm::CellBuilder& cb, int mode, Ref out_msg) const { - return cb.store_long_bool(0xec3c86d, 32) - && cb.store_ulong_rchk_bool(mode, 8) - && cb.store_ref_bool(out_msg); -} - -bool OutAction::cell_pack(Ref& cell_ref, const OutAction::Record_action_send_msg& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::cell_pack_action_send_msg(Ref& cell_ref, int mode, Ref out_msg) const { - vm::CellBuilder cb; - return pack_action_send_msg(cb, mode, std::move(out_msg)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::pack(vm::CellBuilder& cb, const OutAction::Record_action_set_code& data) const { - return cb.store_long_bool(0xad4de08eU, 32) - && cb.store_ref_bool(data.new_code); -} - -bool OutAction::pack_action_set_code(vm::CellBuilder& cb, Ref new_code) const { - return cb.store_long_bool(0xad4de08eU, 32) - && cb.store_ref_bool(new_code); -} - -bool OutAction::cell_pack(Ref& cell_ref, const OutAction::Record_action_set_code& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::cell_pack_action_set_code(Ref& cell_ref, Ref new_code) const { - vm::CellBuilder cb; - return pack_action_set_code(cb, std::move(new_code)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::pack(vm::CellBuilder& cb, const OutAction::Record_action_reserve_currency& data) const { - return cb.store_long_bool(0x36e6b809, 32) - && cb.store_ulong_rchk_bool(data.mode, 8) - && t_CurrencyCollection.store_from(cb, data.currency); -} - -bool OutAction::pack_action_reserve_currency(vm::CellBuilder& cb, int mode, Ref currency) const { - return cb.store_long_bool(0x36e6b809, 32) - && cb.store_ulong_rchk_bool(mode, 8) - && t_CurrencyCollection.store_from(cb, currency); -} - -bool OutAction::cell_pack(Ref& cell_ref, const OutAction::Record_action_reserve_currency& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::cell_pack_action_reserve_currency(Ref& cell_ref, int mode, Ref currency) const { - vm::CellBuilder cb; - return pack_action_reserve_currency(cb, mode, std::move(currency)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::pack(vm::CellBuilder& cb, const OutAction::Record_action_change_library& data) const { - return cb.store_long_bool(0x26fa1dd4, 32) - && cb.store_ulong_rchk_bool(data.mode, 7) - && data.mode <= 2 - && t_LibRef.store_from(cb, data.libref); -} - -bool OutAction::pack_action_change_library(vm::CellBuilder& cb, int mode, Ref libref) const { - return cb.store_long_bool(0x26fa1dd4, 32) - && cb.store_ulong_rchk_bool(mode, 7) - && mode <= 2 - && t_LibRef.store_from(cb, libref); -} - -bool OutAction::cell_pack(Ref& cell_ref, const OutAction::Record_action_change_library& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::cell_pack_action_change_library(Ref& cell_ref, int mode, Ref libref) const { - vm::CellBuilder cb; - return pack_action_change_library(cb, mode, std::move(libref)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutAction::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case action_send_msg: { - int mode; - return cs.fetch_ulong(32) == 0xec3c86d - && pp.open("action_send_msg") - && cs.fetch_uint_to(8, mode) - && pp.field_int(mode, "mode") - && pp.field("out_msg") - && t_MessageRelaxed_Any.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - case action_set_code: - return cs.fetch_ulong(32) == 0xad4de08eU - && pp.open("action_set_code") - && pp.field("new_code") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case action_reserve_currency: { - int mode; - return cs.fetch_ulong(32) == 0x36e6b809 - && pp.open("action_reserve_currency") - && cs.fetch_uint_to(8, mode) - && pp.field_int(mode, "mode") - && pp.field("currency") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); - } - case action_change_library: { - int mode; - return cs.fetch_ulong(32) == 0x26fa1dd4 - && pp.open("action_change_library") - && cs.fetch_uint_to(7, mode) - && pp.field_int(mode, "mode") - && mode <= 2 - && pp.field("libref") - && t_LibRef.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for OutAction"); -} - -const OutAction t_OutAction; - -// -// code for type `OutListNode` -// - -int OutListNode::check_tag(const vm::CellSlice& cs) const { - return out_list_node; -} - -bool OutListNode::skip(vm::CellSlice& cs) const { - return cs.advance_refs(1) - && t_OutAction.skip(cs); -} - -bool OutListNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance_refs(1) - && t_OutAction.validate_skip(ops, cs, weak); -} - -bool OutListNode::unpack(vm::CellSlice& cs, OutListNode::Record& data) const { - return cs.fetch_ref_to(data.prev) - && t_OutAction.fetch_to(cs, data.action); -} - -bool OutListNode::unpack_out_list_node(vm::CellSlice& cs, Ref& prev, Ref& action) const { - return cs.fetch_ref_to(prev) - && t_OutAction.fetch_to(cs, action); -} - -bool OutListNode::cell_unpack(Ref cell_ref, OutListNode::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OutListNode::cell_unpack_out_list_node(Ref cell_ref, Ref& prev, Ref& action) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_out_list_node(cs, prev, action) && cs.empty_ext(); -} - -bool OutListNode::pack(vm::CellBuilder& cb, const OutListNode::Record& data) const { - return cb.store_ref_bool(data.prev) - && t_OutAction.store_from(cb, data.action); -} - -bool OutListNode::pack_out_list_node(vm::CellBuilder& cb, Ref prev, Ref action) const { - return cb.store_ref_bool(prev) - && t_OutAction.store_from(cb, action); -} - -bool OutListNode::cell_pack(Ref& cell_ref, const OutListNode::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OutListNode::cell_pack_out_list_node(Ref& cell_ref, Ref prev, Ref action) const { - vm::CellBuilder cb; - return pack_out_list_node(cb, std::move(prev), std::move(action)) && std::move(cb).finalize_to(cell_ref); -} - -bool OutListNode::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("out_list_node") - && pp.field("prev") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.field("action") - && t_OutAction.print_skip(pp, cs) - && pp.close(); -} - -const OutListNode t_OutListNode; - -// -// code for type `ShardIdent` -// - -int ShardIdent::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(2) == 0 ? shard_ident : -1; -} - -bool ShardIdent::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int shard_pfx_bits; - return cs.fetch_ulong(2) == 0 - && cs.fetch_uint_leq(60, shard_pfx_bits) - && cs.advance(96); -} - -bool ShardIdent::unpack(vm::CellSlice& cs, ShardIdent::Record& data) const { - return cs.fetch_ulong(2) == 0 - && cs.fetch_uint_leq(60, data.shard_pfx_bits) - && cs.fetch_int_to(32, data.workchain_id) - && cs.fetch_uint_to(64, data.shard_prefix); -} - -bool ShardIdent::unpack_shard_ident(vm::CellSlice& cs, int& shard_pfx_bits, int& workchain_id, unsigned long long& shard_prefix) const { - return cs.fetch_ulong(2) == 0 - && cs.fetch_uint_leq(60, shard_pfx_bits) - && cs.fetch_int_to(32, workchain_id) - && cs.fetch_uint_to(64, shard_prefix); -} - -bool ShardIdent::cell_unpack(Ref cell_ref, ShardIdent::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardIdent::cell_unpack_shard_ident(Ref cell_ref, int& shard_pfx_bits, int& workchain_id, unsigned long long& shard_prefix) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_shard_ident(cs, shard_pfx_bits, workchain_id, shard_prefix) && cs.empty_ext(); -} - -bool ShardIdent::pack(vm::CellBuilder& cb, const ShardIdent::Record& data) const { - return cb.store_long_bool(0, 2) - && cb.store_uint_leq(60, data.shard_pfx_bits) - && cb.store_long_rchk_bool(data.workchain_id, 32) - && cb.store_ulong_rchk_bool(data.shard_prefix, 64); -} - -bool ShardIdent::pack_shard_ident(vm::CellBuilder& cb, int shard_pfx_bits, int workchain_id, unsigned long long shard_prefix) const { - return cb.store_long_bool(0, 2) - && cb.store_uint_leq(60, shard_pfx_bits) - && cb.store_long_rchk_bool(workchain_id, 32) - && cb.store_ulong_rchk_bool(shard_prefix, 64); -} - -bool ShardIdent::cell_pack(Ref& cell_ref, const ShardIdent::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardIdent::cell_pack_shard_ident(Ref& cell_ref, int shard_pfx_bits, int workchain_id, unsigned long long shard_prefix) const { - vm::CellBuilder cb; - return pack_shard_ident(cb, shard_pfx_bits, workchain_id, shard_prefix) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardIdent::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int shard_pfx_bits; - return cs.fetch_ulong(2) == 0 - && pp.open("shard_ident") - && cs.fetch_uint_leq(60, shard_pfx_bits) - && pp.field_int(shard_pfx_bits, "shard_pfx_bits") - && pp.fetch_int_field(cs, 32, "workchain_id") - && pp.fetch_uint_field(cs, 64, "shard_prefix") - && pp.close(); -} - -const ShardIdent t_ShardIdent; - -// -// code for type `ExtBlkRef` -// - -int ExtBlkRef::check_tag(const vm::CellSlice& cs) const { - return ext_blk_ref; -} - -bool ExtBlkRef::unpack(vm::CellSlice& cs, ExtBlkRef::Record& data) const { - return cs.fetch_uint_to(64, data.end_lt) - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_bits_to(data.root_hash.bits(), 256) - && cs.fetch_bits_to(data.file_hash.bits(), 256); -} - -bool ExtBlkRef::cell_unpack(Ref cell_ref, ExtBlkRef::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ExtBlkRef::pack(vm::CellBuilder& cb, const ExtBlkRef::Record& data) const { - return cb.store_ulong_rchk_bool(data.end_lt, 64) - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_bits_bool(data.root_hash.cbits(), 256) - && cb.store_bits_bool(data.file_hash.cbits(), 256); -} - -bool ExtBlkRef::cell_pack(Ref& cell_ref, const ExtBlkRef::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ExtBlkRef::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("ext_blk_ref") - && pp.fetch_uint_field(cs, 64, "end_lt") - && pp.fetch_uint_field(cs, 32, "seq_no") - && pp.fetch_bits_field(cs, 256, "root_hash") - && pp.fetch_bits_field(cs, 256, "file_hash") - && pp.close(); -} - -const ExtBlkRef t_ExtBlkRef; - -// -// code for type `BlockIdExt` -// - -int BlockIdExt::check_tag(const vm::CellSlice& cs) const { - return block_id_ext; -} - -bool BlockIdExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_ShardIdent.validate_skip(ops, cs, weak) - && cs.advance(544); -} - -bool BlockIdExt::unpack(vm::CellSlice& cs, BlockIdExt::Record& data) const { - return cs.fetch_subslice_to(104, data.shard_id) - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_bits_to(data.root_hash.bits(), 256) - && cs.fetch_bits_to(data.file_hash.bits(), 256); -} - -bool BlockIdExt::cell_unpack(Ref cell_ref, BlockIdExt::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockIdExt::pack(vm::CellBuilder& cb, const BlockIdExt::Record& data) const { - return cb.append_cellslice_chk(data.shard_id, 104) - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_bits_bool(data.root_hash.cbits(), 256) - && cb.store_bits_bool(data.file_hash.cbits(), 256); -} - -bool BlockIdExt::cell_pack(Ref& cell_ref, const BlockIdExt::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockIdExt::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("block_id_ext") - && pp.field("shard_id") - && t_ShardIdent.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "seq_no") - && pp.fetch_bits_field(cs, 256, "root_hash") - && pp.fetch_bits_field(cs, 256, "file_hash") - && pp.close(); -} - -const BlockIdExt t_BlockIdExt; - -// -// code for type `BlkMasterInfo` -// - -int BlkMasterInfo::check_tag(const vm::CellSlice& cs) const { - return master_info; -} - -bool BlkMasterInfo::unpack(vm::CellSlice& cs, BlkMasterInfo::Record& data) const { - return cs.fetch_subslice_to(608, data.master); -} - -bool BlkMasterInfo::unpack_master_info(vm::CellSlice& cs, Ref& master) const { - return cs.fetch_subslice_to(608, master); -} - -bool BlkMasterInfo::cell_unpack(Ref cell_ref, BlkMasterInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlkMasterInfo::cell_unpack_master_info(Ref cell_ref, Ref& master) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_master_info(cs, master) && cs.empty_ext(); -} - -bool BlkMasterInfo::pack(vm::CellBuilder& cb, const BlkMasterInfo::Record& data) const { - return cb.append_cellslice_chk(data.master, 608); -} - -bool BlkMasterInfo::pack_master_info(vm::CellBuilder& cb, Ref master) const { - return cb.append_cellslice_chk(master, 608); -} - -bool BlkMasterInfo::cell_pack(Ref& cell_ref, const BlkMasterInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkMasterInfo::cell_pack_master_info(Ref& cell_ref, Ref master) const { - vm::CellBuilder cb; - return pack_master_info(cb, std::move(master)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkMasterInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("master_info") - && pp.field("master") - && t_ExtBlkRef.print_skip(pp, cs) - && pp.close(); -} - -const BlkMasterInfo t_BlkMasterInfo; - -// -// code for auxiliary type `ShardStateUnsplit_aux` -// - -int ShardStateUnsplit_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardStateUnsplit_aux::skip(vm::CellSlice& cs) const { - return cs.advance(128) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_HashmapE_256_LibDescr.skip(cs) - && t_Maybe_BlkMasterInfo.skip(cs); -} - -bool ShardStateUnsplit_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(128) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_HashmapE_256_LibDescr.validate_skip(ops, cs, weak) - && t_Maybe_BlkMasterInfo.validate_skip(ops, cs, weak); -} - -bool ShardStateUnsplit_aux::unpack(vm::CellSlice& cs, ShardStateUnsplit_aux::Record& data) const { - return cs.fetch_uint_to(64, data.overload_history) - && cs.fetch_uint_to(64, data.underload_history) - && t_CurrencyCollection.fetch_to(cs, data.total_balance) - && t_CurrencyCollection.fetch_to(cs, data.total_validator_fees) - && t_HashmapE_256_LibDescr.fetch_to(cs, data.libraries) - && t_Maybe_BlkMasterInfo.fetch_to(cs, data.master_ref); -} - -bool ShardStateUnsplit_aux::cell_unpack(Ref cell_ref, ShardStateUnsplit_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardStateUnsplit_aux::pack(vm::CellBuilder& cb, const ShardStateUnsplit_aux::Record& data) const { - return cb.store_ulong_rchk_bool(data.overload_history, 64) - && cb.store_ulong_rchk_bool(data.underload_history, 64) - && t_CurrencyCollection.store_from(cb, data.total_balance) - && t_CurrencyCollection.store_from(cb, data.total_validator_fees) - && t_HashmapE_256_LibDescr.store_from(cb, data.libraries) - && t_Maybe_BlkMasterInfo.store_from(cb, data.master_ref); -} - -bool ShardStateUnsplit_aux::cell_pack(Ref& cell_ref, const ShardStateUnsplit_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardStateUnsplit_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_uint_field(cs, 64, "overload_history") - && pp.fetch_uint_field(cs, 64, "underload_history") - && pp.field("total_balance") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("total_validator_fees") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("libraries") - && t_HashmapE_256_LibDescr.print_skip(pp, cs) - && pp.field("master_ref") - && t_Maybe_BlkMasterInfo.print_skip(pp, cs) - && pp.close(); -} - -const ShardStateUnsplit_aux t_ShardStateUnsplit_aux; - -// -// code for type `ShardStateUnsplit` -// -constexpr unsigned ShardStateUnsplit::cons_tag[1]; - -int ShardStateUnsplit::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x9023afe2U ? shard_state : -1; -} - -bool ShardStateUnsplit::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x30169) - && t_Maybe_Ref_McStateExtra.skip(cs); -} - -bool ShardStateUnsplit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x9023afe2U - && cs.advance(32) - && t_ShardIdent.validate_skip(ops, cs, weak) - && cs.advance(192) - && t_OutMsgQueueInfo.validate_skip_ref(ops, cs, weak) - && cs.advance(1) - && t_ShardAccounts.validate_skip_ref(ops, cs, weak) - && t_ShardStateUnsplit_aux.validate_skip_ref(ops, cs, weak) - && t_Maybe_Ref_McStateExtra.validate_skip(ops, cs, weak); -} - -bool ShardStateUnsplit::unpack(vm::CellSlice& cs, ShardStateUnsplit::Record& data) const { - return cs.fetch_ulong(32) == 0x9023afe2U - && cs.fetch_int_to(32, data.global_id) - && cs.fetch_subslice_to(104, data.shard_id) - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_uint_to(32, data.vert_seq_no) - && cs.fetch_uint_to(32, data.gen_utime) - && cs.fetch_uint_to(64, data.gen_lt) - && cs.fetch_uint_to(32, data.min_ref_mc_seqno) - && cs.fetch_ref_to(data.out_msg_queue_info) - && cs.fetch_bool_to(data.before_split) - && cs.fetch_ref_to(data.accounts) - && t_ShardStateUnsplit_aux.cell_unpack(cs.fetch_ref(), data.r1) - && t_Maybe_Ref_McStateExtra.fetch_to(cs, data.custom); -} - -bool ShardStateUnsplit::cell_unpack(Ref cell_ref, ShardStateUnsplit::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardStateUnsplit::pack(vm::CellBuilder& cb, const ShardStateUnsplit::Record& data) const { - Ref tmp_cell; - return cb.store_long_bool(0x9023afe2U, 32) - && cb.store_long_rchk_bool(data.global_id, 32) - && cb.append_cellslice_chk(data.shard_id, 104) - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_ulong_rchk_bool(data.vert_seq_no, 32) - && cb.store_ulong_rchk_bool(data.gen_utime, 32) - && cb.store_ulong_rchk_bool(data.gen_lt, 64) - && cb.store_ulong_rchk_bool(data.min_ref_mc_seqno, 32) - && cb.store_ref_bool(data.out_msg_queue_info) - && cb.store_ulong_rchk_bool(data.before_split, 1) - && cb.store_ref_bool(data.accounts) - && t_ShardStateUnsplit_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)) - && t_Maybe_Ref_McStateExtra.store_from(cb, data.custom); -} - -bool ShardStateUnsplit::cell_pack(Ref& cell_ref, const ShardStateUnsplit::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardStateUnsplit::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int vert_seq_no, before_split; - return cs.fetch_ulong(32) == 0x9023afe2U - && pp.open("shard_state") - && pp.fetch_int_field(cs, 32, "global_id") - && pp.field("shard_id") - && t_ShardIdent.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "seq_no") - && cs.fetch_uint_to(32, vert_seq_no) - && pp.field_int(vert_seq_no, "vert_seq_no") - && pp.fetch_uint_field(cs, 32, "gen_utime") - && pp.fetch_uint_field(cs, 64, "gen_lt") - && pp.fetch_uint_field(cs, 32, "min_ref_mc_seqno") - && pp.field("out_msg_queue_info") - && t_OutMsgQueueInfo.print_ref(pp, cs.fetch_ref()) - && cs.fetch_bool_to(before_split) - && pp.field_int(before_split, "before_split") - && pp.field("accounts") - && t_ShardAccounts.print_ref(pp, cs.fetch_ref()) - && pp.field() - && t_ShardStateUnsplit_aux.print_ref(pp, cs.fetch_ref()) - && pp.field("custom") - && t_Maybe_Ref_McStateExtra.print_skip(pp, cs) - && pp.close(); -} - -const ShardStateUnsplit t_ShardStateUnsplit; - -// -// code for type `ShardState` -// -constexpr char ShardState::cons_len[2]; -constexpr unsigned ShardState::cons_tag[2]; - -int ShardState::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return cons1; - case split_state: - return cs.prefetch_ulong(32) == 0x5f327da5 ? split_state : -1; - } - return -1; -} - -bool ShardState::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return t_ShardStateUnsplit.skip(cs); - case split_state: - return cs.advance_ext(0x20020); - } - return false; -} - -bool ShardState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cons1: - return t_ShardStateUnsplit.validate_skip(ops, cs, weak); - case split_state: - return cs.fetch_ulong(32) == 0x5f327da5 - && t_ShardStateUnsplit.validate_skip_ref(ops, cs, weak) - && t_ShardStateUnsplit.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool ShardState::unpack(vm::CellSlice& cs, ShardState::Record_cons1& data) const { - return t_ShardStateUnsplit.fetch_to(cs, data.x); -} - -bool ShardState::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_ShardStateUnsplit.fetch_to(cs, x); -} - -bool ShardState::cell_unpack(Ref cell_ref, ShardState::Record_cons1& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardState::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ShardState::unpack(vm::CellSlice& cs, ShardState::Record_split_state& data) const { - return cs.fetch_ulong(32) == 0x5f327da5 - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right); -} - -bool ShardState::unpack_split_state(vm::CellSlice& cs, Ref& left, Ref& right) const { - return cs.fetch_ulong(32) == 0x5f327da5 - && cs.fetch_ref_to(left) - && cs.fetch_ref_to(right); -} - -bool ShardState::cell_unpack(Ref cell_ref, ShardState::Record_split_state& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardState::cell_unpack_split_state(Ref cell_ref, Ref& left, Ref& right) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_split_state(cs, left, right) && cs.empty_ext(); -} - -bool ShardState::pack(vm::CellBuilder& cb, const ShardState::Record_cons1& data) const { - return t_ShardStateUnsplit.store_from(cb, data.x); -} - -bool ShardState::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_ShardStateUnsplit.store_from(cb, x); -} - -bool ShardState::cell_pack(Ref& cell_ref, const ShardState::Record_cons1& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardState::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardState::pack(vm::CellBuilder& cb, const ShardState::Record_split_state& data) const { - return cb.store_long_bool(0x5f327da5, 32) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right); -} - -bool ShardState::pack_split_state(vm::CellBuilder& cb, Ref left, Ref right) const { - return cb.store_long_bool(0x5f327da5, 32) - && cb.store_ref_bool(left) - && cb.store_ref_bool(right); -} - -bool ShardState::cell_pack(Ref& cell_ref, const ShardState::Record_split_state& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardState::cell_pack_split_state(Ref& cell_ref, Ref left, Ref right) const { - vm::CellBuilder cb; - return pack_split_state(cb, std::move(left), std::move(right)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardState::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return pp.open() - && pp.field() - && t_ShardStateUnsplit.print_skip(pp, cs) - && pp.close(); - case split_state: - return cs.fetch_ulong(32) == 0x5f327da5 - && pp.open("split_state") - && pp.field("left") - && t_ShardStateUnsplit.print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && t_ShardStateUnsplit.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for ShardState"); -} - -const ShardState t_ShardState; - -// -// code for type `LibDescr` -// - -int LibDescr::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(2) == 0 ? shared_lib_descr : -1; -} - -bool LibDescr::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10002) - && t_Hashmap_256_True.skip(cs); -} - -bool LibDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(2) == 0 - && cs.advance_refs(1) - && t_Hashmap_256_True.validate_skip(ops, cs, weak); -} - -bool LibDescr::unpack(vm::CellSlice& cs, LibDescr::Record& data) const { - return cs.fetch_ulong(2) == 0 - && cs.fetch_ref_to(data.lib) - && t_Hashmap_256_True.fetch_to(cs, data.publishers); -} - -bool LibDescr::unpack_shared_lib_descr(vm::CellSlice& cs, Ref& lib, Ref& publishers) const { - return cs.fetch_ulong(2) == 0 - && cs.fetch_ref_to(lib) - && t_Hashmap_256_True.fetch_to(cs, publishers); -} - -bool LibDescr::cell_unpack(Ref cell_ref, LibDescr::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool LibDescr::cell_unpack_shared_lib_descr(Ref cell_ref, Ref& lib, Ref& publishers) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_shared_lib_descr(cs, lib, publishers) && cs.empty_ext(); -} - -bool LibDescr::pack(vm::CellBuilder& cb, const LibDescr::Record& data) const { - return cb.store_long_bool(0, 2) - && cb.store_ref_bool(data.lib) - && t_Hashmap_256_True.store_from(cb, data.publishers); -} - -bool LibDescr::pack_shared_lib_descr(vm::CellBuilder& cb, Ref lib, Ref publishers) const { - return cb.store_long_bool(0, 2) - && cb.store_ref_bool(lib) - && t_Hashmap_256_True.store_from(cb, publishers); -} - -bool LibDescr::cell_pack(Ref& cell_ref, const LibDescr::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool LibDescr::cell_pack_shared_lib_descr(Ref& cell_ref, Ref lib, Ref publishers) const { - vm::CellBuilder cb; - return pack_shared_lib_descr(cb, std::move(lib), std::move(publishers)) && std::move(cb).finalize_to(cell_ref); -} - -bool LibDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(2) == 0 - && pp.open("shared_lib_descr") - && pp.field("lib") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.field("publishers") - && t_Hashmap_256_True.print_skip(pp, cs) - && pp.close(); -} - -const LibDescr t_LibDescr; - -// -// code for type `BlockInfo` -// -constexpr unsigned BlockInfo::cons_tag[1]; - -int BlockInfo::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x9bc7a987U ? block_info : -1; -} - -bool BlockInfo::skip(vm::CellSlice& cs) const { - int not_master, after_merge, vert_seqno_incr, flags, seq_no, vert_seq_no, prev_seq_no; - return cs.advance(64) - && cs.fetch_bool_to(not_master) - && cs.fetch_bool_to(after_merge) - && cs.advance(5) - && cs.fetch_bool_to(vert_seqno_incr) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && cs.fetch_uint_to(32, seq_no) - && cs.fetch_uint_to(32, vert_seq_no) - && vert_seqno_incr <= vert_seq_no - && add_r1(prev_seq_no, 1, seq_no) - && cs.advance(392) - && (!(flags & 1) || cs.advance(104)) - && (!not_master || cs.advance_refs(1)) - && cs.advance_refs(1) - && (!vert_seqno_incr || cs.advance_refs(1)); -} - -bool BlockInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int not_master, after_merge, vert_seqno_incr, flags, seq_no, vert_seq_no, prev_seq_no; - return cs.fetch_ulong(32) == 0x9bc7a987U - && cs.advance(32) - && cs.fetch_bool_to(not_master) - && cs.fetch_bool_to(after_merge) - && cs.advance(5) - && cs.fetch_bool_to(vert_seqno_incr) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && cs.fetch_uint_to(32, seq_no) - && cs.fetch_uint_to(32, vert_seq_no) - && vert_seqno_incr <= vert_seq_no - && add_r1(prev_seq_no, 1, seq_no) - && t_ShardIdent.validate_skip(ops, cs, weak) - && cs.advance(288) - && (!(flags & 1) || t_GlobalVersion.validate_skip(ops, cs, weak)) - && (!not_master || t_BlkMasterInfo.validate_skip_ref(ops, cs, weak)) - && BlkPrevInfo{after_merge}.validate_skip_ref(ops, cs, weak) - && (!vert_seqno_incr || t_BlkPrevInfo_0.validate_skip_ref(ops, cs, weak)); -} - -bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const { - int prev_seq_no; - return cs.fetch_ulong(32) == 0x9bc7a987U - && cs.fetch_uint_to(32, data.version) - && cs.fetch_bool_to(data.not_master) - && cs.fetch_bool_to(data.after_merge) - && cs.fetch_bool_to(data.before_split) - && cs.fetch_bool_to(data.after_split) - && cs.fetch_bool_to(data.want_split) - && cs.fetch_bool_to(data.want_merge) - && cs.fetch_bool_to(data.key_block) - && cs.fetch_bool_to(data.vert_seqno_incr) - && cs.fetch_uint_to(8, data.flags) - && data.flags <= 1 - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_uint_to(32, data.vert_seq_no) - && data.vert_seqno_incr <= data.vert_seq_no - && add_r1(prev_seq_no, 1, data.seq_no) - && cs.fetch_subslice_to(104, data.shard) - && cs.fetch_uint_to(32, data.gen_utime) - && cs.fetch_uint_to(64, data.start_lt) - && cs.fetch_uint_to(64, data.end_lt) - && cs.fetch_uint_to(32, data.gen_validator_list_hash_short) - && cs.fetch_uint_to(32, data.gen_catchain_seqno) - && cs.fetch_uint_to(32, data.min_ref_mc_seqno) - && cs.fetch_uint_to(32, data.prev_key_block_seqno) - && (!(data.flags & 1) || cs.fetch_subslice_to(104, data.gen_software)) - && (!data.not_master || cs.fetch_ref_to(data.master_ref)) - && cs.fetch_ref_to(data.prev_ref) - && (!data.vert_seqno_incr || cs.fetch_ref_to(data.prev_vert_ref)); -} - -bool BlockInfo::cell_unpack(Ref cell_ref, BlockInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockInfo::pack(vm::CellBuilder& cb, const BlockInfo::Record& data) const { - int prev_seq_no; - return cb.store_long_bool(0x9bc7a987U, 32) - && cb.store_ulong_rchk_bool(data.version, 32) - && cb.store_ulong_rchk_bool(data.not_master, 1) - && cb.store_ulong_rchk_bool(data.after_merge, 1) - && cb.store_ulong_rchk_bool(data.before_split, 1) - && cb.store_ulong_rchk_bool(data.after_split, 1) - && cb.store_ulong_rchk_bool(data.want_split, 1) - && cb.store_ulong_rchk_bool(data.want_merge, 1) - && cb.store_ulong_rchk_bool(data.key_block, 1) - && cb.store_ulong_rchk_bool(data.vert_seqno_incr, 1) - && cb.store_ulong_rchk_bool(data.flags, 8) - && data.flags <= 1 - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_ulong_rchk_bool(data.vert_seq_no, 32) - && data.vert_seqno_incr <= data.vert_seq_no - && add_r1(prev_seq_no, 1, data.seq_no) - && cb.append_cellslice_chk(data.shard, 104) - && cb.store_ulong_rchk_bool(data.gen_utime, 32) - && cb.store_ulong_rchk_bool(data.start_lt, 64) - && cb.store_ulong_rchk_bool(data.end_lt, 64) - && cb.store_ulong_rchk_bool(data.gen_validator_list_hash_short, 32) - && cb.store_ulong_rchk_bool(data.gen_catchain_seqno, 32) - && cb.store_ulong_rchk_bool(data.min_ref_mc_seqno, 32) - && cb.store_ulong_rchk_bool(data.prev_key_block_seqno, 32) - && (!(data.flags & 1) || cb.append_cellslice_chk(data.gen_software, 104)) - && (!data.not_master || cb.store_ref_bool(data.master_ref)) - && cb.store_ref_bool(data.prev_ref) - && (!data.vert_seqno_incr || cb.store_ref_bool(data.prev_vert_ref)); -} - -bool BlockInfo::cell_pack(Ref& cell_ref, const BlockInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int not_master, after_merge, before_split, after_split, vert_seqno_incr, flags, seq_no, vert_seq_no, prev_seq_no; - return cs.fetch_ulong(32) == 0x9bc7a987U - && pp.open("block_info") - && pp.fetch_uint_field(cs, 32, "version") - && cs.fetch_bool_to(not_master) - && pp.field_int(not_master, "not_master") - && cs.fetch_bool_to(after_merge) - && pp.field_int(after_merge, "after_merge") - && cs.fetch_bool_to(before_split) - && pp.field_int(before_split, "before_split") - && cs.fetch_bool_to(after_split) - && pp.field_int(after_split, "after_split") - && pp.fetch_uint_field(cs, 1, "want_split") - && pp.fetch_uint_field(cs, 1, "want_merge") - && pp.fetch_uint_field(cs, 1, "key_block") - && cs.fetch_bool_to(vert_seqno_incr) - && pp.field_int(vert_seqno_incr, "vert_seqno_incr") - && cs.fetch_uint_to(8, flags) - && pp.field_int(flags, "flags") - && flags <= 1 - && cs.fetch_uint_to(32, seq_no) - && pp.field_int(seq_no, "seq_no") - && cs.fetch_uint_to(32, vert_seq_no) - && pp.field_int(vert_seq_no, "vert_seq_no") - && vert_seqno_incr <= vert_seq_no - && add_r1(prev_seq_no, 1, seq_no) - && pp.field("shard") - && t_ShardIdent.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "gen_utime") - && pp.fetch_uint_field(cs, 64, "start_lt") - && pp.fetch_uint_field(cs, 64, "end_lt") - && pp.fetch_uint_field(cs, 32, "gen_validator_list_hash_short") - && pp.fetch_uint_field(cs, 32, "gen_catchain_seqno") - && pp.fetch_uint_field(cs, 32, "min_ref_mc_seqno") - && pp.fetch_uint_field(cs, 32, "prev_key_block_seqno") - && (!(flags & 1) || (pp.field("gen_software") && t_GlobalVersion.print_skip(pp, cs))) - && (!not_master || (pp.field("master_ref") && t_BlkMasterInfo.print_ref(pp, cs.fetch_ref()))) - && pp.field("prev_ref") - && BlkPrevInfo{after_merge}.print_ref(pp, cs.fetch_ref()) - && (!vert_seqno_incr || (pp.field("prev_vert_ref") && t_BlkPrevInfo_0.print_ref(pp, cs.fetch_ref()))) - && pp.close(); -} - -const BlockInfo t_BlockInfo; - -// -// code for type `BlkPrevInfo` -// - -int BlkPrevInfo::get_tag(const vm::CellSlice& cs) const { - switch (m_) { - case 0: - return prev_blk_info; - case 1: - return prev_blks_info; - default: - return -1; - } -} - -int BlkPrevInfo::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case prev_blk_info: - return prev_blk_info; - case prev_blks_info: - return prev_blks_info; - } - return -1; -} - -bool BlkPrevInfo::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case prev_blk_info: - return cs.advance(608) - && m_ == 0; - case prev_blks_info: - return cs.advance_refs(2) - && m_ == 1; - } - return false; -} - -bool BlkPrevInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case prev_blk_info: - return cs.advance(608) - && m_ == 0; - case prev_blks_info: - return t_ExtBlkRef.validate_skip_ref(ops, cs, weak) - && t_ExtBlkRef.validate_skip_ref(ops, cs, weak) - && m_ == 1; - } - return false; -} - -bool BlkPrevInfo::unpack(vm::CellSlice& cs, BlkPrevInfo::Record_prev_blk_info& data) const { - return cs.fetch_subslice_to(608, data.prev) - && m_ == 0; -} - -bool BlkPrevInfo::unpack_prev_blk_info(vm::CellSlice& cs, Ref& prev) const { - return cs.fetch_subslice_to(608, prev) - && m_ == 0; -} - -bool BlkPrevInfo::cell_unpack(Ref cell_ref, BlkPrevInfo::Record_prev_blk_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlkPrevInfo::cell_unpack_prev_blk_info(Ref cell_ref, Ref& prev) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_prev_blk_info(cs, prev) && cs.empty_ext(); -} - -bool BlkPrevInfo::unpack(vm::CellSlice& cs, BlkPrevInfo::Record_prev_blks_info& data) const { - return cs.fetch_ref_to(data.prev1) - && cs.fetch_ref_to(data.prev2) - && m_ == 1; -} - -bool BlkPrevInfo::unpack_prev_blks_info(vm::CellSlice& cs, Ref& prev1, Ref& prev2) const { - return cs.fetch_ref_to(prev1) - && cs.fetch_ref_to(prev2) - && m_ == 1; -} - -bool BlkPrevInfo::cell_unpack(Ref cell_ref, BlkPrevInfo::Record_prev_blks_info& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlkPrevInfo::cell_unpack_prev_blks_info(Ref cell_ref, Ref& prev1, Ref& prev2) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_prev_blks_info(cs, prev1, prev2) && cs.empty_ext(); -} - -bool BlkPrevInfo::pack(vm::CellBuilder& cb, const BlkPrevInfo::Record_prev_blk_info& data) const { - return cb.append_cellslice_chk(data.prev, 608) - && m_ == 0; -} - -bool BlkPrevInfo::pack_prev_blk_info(vm::CellBuilder& cb, Ref prev) const { - return cb.append_cellslice_chk(prev, 608) - && m_ == 0; -} - -bool BlkPrevInfo::cell_pack(Ref& cell_ref, const BlkPrevInfo::Record_prev_blk_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkPrevInfo::cell_pack_prev_blk_info(Ref& cell_ref, Ref prev) const { - vm::CellBuilder cb; - return pack_prev_blk_info(cb, std::move(prev)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkPrevInfo::pack(vm::CellBuilder& cb, const BlkPrevInfo::Record_prev_blks_info& data) const { - return cb.store_ref_bool(data.prev1) - && cb.store_ref_bool(data.prev2) - && m_ == 1; -} - -bool BlkPrevInfo::pack_prev_blks_info(vm::CellBuilder& cb, Ref prev1, Ref prev2) const { - return cb.store_ref_bool(prev1) - && cb.store_ref_bool(prev2) - && m_ == 1; -} - -bool BlkPrevInfo::cell_pack(Ref& cell_ref, const BlkPrevInfo::Record_prev_blks_info& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkPrevInfo::cell_pack_prev_blks_info(Ref& cell_ref, Ref prev1, Ref prev2) const { - vm::CellBuilder cb; - return pack_prev_blks_info(cb, std::move(prev1), std::move(prev2)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlkPrevInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case prev_blk_info: - return pp.open("prev_blk_info") - && pp.field("prev") - && t_ExtBlkRef.print_skip(pp, cs) - && m_ == 0 - && pp.close(); - case prev_blks_info: - return pp.open("prev_blks_info") - && pp.field("prev1") - && t_ExtBlkRef.print_ref(pp, cs.fetch_ref()) - && pp.field("prev2") - && t_ExtBlkRef.print_ref(pp, cs.fetch_ref()) - && m_ == 1 - && pp.close(); - } - return pp.fail("unknown constructor for BlkPrevInfo"); -} - - -// -// code for type `Block` -// -constexpr unsigned Block::cons_tag[1]; - -int Block::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x11ef55aa ? block : -1; -} - -bool Block::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x11ef55aa - && cs.advance(32) - && t_BlockInfo.validate_skip_ref(ops, cs, weak) - && t_ValueFlow.validate_skip_ref(ops, cs, weak) - && t_MERKLE_UPDATE_ShardState.validate_skip_ref(ops, cs, weak) - && t_BlockExtra.validate_skip_ref(ops, cs, weak); -} - -bool Block::unpack(vm::CellSlice& cs, Block::Record& data) const { - return cs.fetch_ulong(32) == 0x11ef55aa - && cs.fetch_int_to(32, data.global_id) - && cs.fetch_ref_to(data.info) - && cs.fetch_ref_to(data.value_flow) - && cs.fetch_ref_to(data.state_update) - && cs.fetch_ref_to(data.extra); -} - -bool Block::cell_unpack(Ref cell_ref, Block::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Block::pack(vm::CellBuilder& cb, const Block::Record& data) const { - return cb.store_long_bool(0x11ef55aa, 32) - && cb.store_long_rchk_bool(data.global_id, 32) - && cb.store_ref_bool(data.info) - && cb.store_ref_bool(data.value_flow) - && cb.store_ref_bool(data.state_update) - && cb.store_ref_bool(data.extra); -} - -bool Block::cell_pack(Ref& cell_ref, const Block::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Block::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x11ef55aa - && pp.open("block") - && pp.fetch_int_field(cs, 32, "global_id") - && pp.field("info") - && t_BlockInfo.print_ref(pp, cs.fetch_ref()) - && pp.field("value_flow") - && t_ValueFlow.print_ref(pp, cs.fetch_ref()) - && pp.field("state_update") - && t_MERKLE_UPDATE_ShardState.print_ref(pp, cs.fetch_ref()) - && pp.field("extra") - && t_BlockExtra.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const Block t_Block; - -// -// code for type `BlockExtra` -// -constexpr unsigned BlockExtra::cons_tag[1]; - -int BlockExtra::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x4a33f6fd ? block_extra : -1; -} - -bool BlockExtra::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x30220) - && t_Maybe_Ref_McBlockExtra.skip(cs); -} - -bool BlockExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x4a33f6fd - && t_InMsgDescr.validate_skip_ref(ops, cs, weak) - && t_OutMsgDescr.validate_skip_ref(ops, cs, weak) - && t_ShardAccountBlocks.validate_skip_ref(ops, cs, weak) - && cs.advance(512) - && t_Maybe_Ref_McBlockExtra.validate_skip(ops, cs, weak); -} - -bool BlockExtra::unpack(vm::CellSlice& cs, BlockExtra::Record& data) const { - return cs.fetch_ulong(32) == 0x4a33f6fd - && cs.fetch_ref_to(data.in_msg_descr) - && cs.fetch_ref_to(data.out_msg_descr) - && cs.fetch_ref_to(data.account_blocks) - && cs.fetch_bits_to(data.rand_seed.bits(), 256) - && cs.fetch_bits_to(data.created_by.bits(), 256) - && t_Maybe_Ref_McBlockExtra.fetch_to(cs, data.custom); -} - -bool BlockExtra::cell_unpack(Ref cell_ref, BlockExtra::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockExtra::pack(vm::CellBuilder& cb, const BlockExtra::Record& data) const { - return cb.store_long_bool(0x4a33f6fd, 32) - && cb.store_ref_bool(data.in_msg_descr) - && cb.store_ref_bool(data.out_msg_descr) - && cb.store_ref_bool(data.account_blocks) - && cb.store_bits_bool(data.rand_seed.cbits(), 256) - && cb.store_bits_bool(data.created_by.cbits(), 256) - && t_Maybe_Ref_McBlockExtra.store_from(cb, data.custom); -} - -bool BlockExtra::cell_pack(Ref& cell_ref, const BlockExtra::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockExtra::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x4a33f6fd - && pp.open("block_extra") - && pp.field("in_msg_descr") - && t_InMsgDescr.print_ref(pp, cs.fetch_ref()) - && pp.field("out_msg_descr") - && t_OutMsgDescr.print_ref(pp, cs.fetch_ref()) - && pp.field("account_blocks") - && t_ShardAccountBlocks.print_ref(pp, cs.fetch_ref()) - && pp.fetch_bits_field(cs, 256, "rand_seed") - && pp.fetch_bits_field(cs, 256, "created_by") - && pp.field("custom") - && t_Maybe_Ref_McBlockExtra.print_skip(pp, cs) - && pp.close(); -} - -const BlockExtra t_BlockExtra; - -// -// code for auxiliary type `ValueFlow_aux` -// - -int ValueFlow_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ValueFlow_aux::skip(vm::CellSlice& cs) const { - return t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool ValueFlow_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ValueFlow_aux::unpack(vm::CellSlice& cs, ValueFlow_aux::Record& data) const { - return t_CurrencyCollection.fetch_to(cs, data.from_prev_blk) - && t_CurrencyCollection.fetch_to(cs, data.to_next_blk) - && t_CurrencyCollection.fetch_to(cs, data.imported) - && t_CurrencyCollection.fetch_to(cs, data.exported); -} - -bool ValueFlow_aux::cell_unpack(Ref cell_ref, ValueFlow_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValueFlow_aux::pack(vm::CellBuilder& cb, const ValueFlow_aux::Record& data) const { - return t_CurrencyCollection.store_from(cb, data.from_prev_blk) - && t_CurrencyCollection.store_from(cb, data.to_next_blk) - && t_CurrencyCollection.store_from(cb, data.imported) - && t_CurrencyCollection.store_from(cb, data.exported); -} - -bool ValueFlow_aux::cell_pack(Ref& cell_ref, const ValueFlow_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValueFlow_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("from_prev_blk") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("to_next_blk") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("imported") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("exported") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ValueFlow_aux t_ValueFlow_aux; - -// -// code for auxiliary type `ValueFlow_aux1` -// - -int ValueFlow_aux1::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ValueFlow_aux1::skip(vm::CellSlice& cs) const { - return t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool ValueFlow_aux1::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ValueFlow_aux1::unpack(vm::CellSlice& cs, ValueFlow_aux1::Record& data) const { - return t_CurrencyCollection.fetch_to(cs, data.fees_imported) - && t_CurrencyCollection.fetch_to(cs, data.recovered) - && t_CurrencyCollection.fetch_to(cs, data.created) - && t_CurrencyCollection.fetch_to(cs, data.minted); -} - -bool ValueFlow_aux1::cell_unpack(Ref cell_ref, ValueFlow_aux1::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValueFlow_aux1::pack(vm::CellBuilder& cb, const ValueFlow_aux1::Record& data) const { - return t_CurrencyCollection.store_from(cb, data.fees_imported) - && t_CurrencyCollection.store_from(cb, data.recovered) - && t_CurrencyCollection.store_from(cb, data.created) - && t_CurrencyCollection.store_from(cb, data.minted); -} - -bool ValueFlow_aux1::cell_pack(Ref& cell_ref, const ValueFlow_aux1::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValueFlow_aux1::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("fees_imported") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("recovered") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("created") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("minted") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ValueFlow_aux1 t_ValueFlow_aux1; - -// -// code for type `ValueFlow` -// -constexpr unsigned ValueFlow::cons_tag[1]; - -int ValueFlow::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0xb8e48dfbU ? value_flow : -1; -} - -bool ValueFlow::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10020) - && t_CurrencyCollection.skip(cs) - && cs.advance_refs(1); -} - -bool ValueFlow::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0xb8e48dfbU - && t_ValueFlow_aux.validate_skip_ref(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_ValueFlow_aux1.validate_skip_ref(ops, cs, weak); -} - -bool ValueFlow::unpack(vm::CellSlice& cs, ValueFlow::Record& data) const { - return cs.fetch_ulong(32) == 0xb8e48dfbU - && t_ValueFlow_aux.cell_unpack(cs.fetch_ref(), data.r1) - && t_CurrencyCollection.fetch_to(cs, data.fees_collected) - && t_ValueFlow_aux1.cell_unpack(cs.fetch_ref(), data.r2); -} - -bool ValueFlow::cell_unpack(Ref cell_ref, ValueFlow::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValueFlow::pack(vm::CellBuilder& cb, const ValueFlow::Record& data) const { - Ref tmp_cell; - return cb.store_long_bool(0xb8e48dfbU, 32) - && t_ValueFlow_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)) - && t_CurrencyCollection.store_from(cb, data.fees_collected) - && t_ValueFlow_aux1.cell_pack(tmp_cell, data.r2) - && cb.store_ref_bool(std::move(tmp_cell)); -} - -bool ValueFlow::cell_pack(Ref& cell_ref, const ValueFlow::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValueFlow::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0xb8e48dfbU - && pp.open("value_flow") - && pp.field() - && t_ValueFlow_aux.print_ref(pp, cs.fetch_ref()) - && pp.field("fees_collected") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field() - && t_ValueFlow_aux1.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const ValueFlow t_ValueFlow; - -// -// code for type `BinTree` -// - -int BinTree::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bt_leaf: - return cs.have(1) ? bt_leaf : -1; - case bt_fork: - return cs.have(1) ? bt_fork : -1; - } - return -1; -} - -bool BinTree::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bt_leaf: - return cs.advance(1) - && X_.skip(cs); - case bt_fork: - return cs.advance_ext(0x20001); - } - return false; -} - -bool BinTree::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case bt_leaf: - return cs.advance(1) - && X_.validate_skip(ops, cs, weak); - case bt_fork: - return cs.advance(1) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool BinTree::unpack(vm::CellSlice& cs, BinTree::Record_bt_leaf& data) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, data.leaf); -} - -bool BinTree::unpack_bt_leaf(vm::CellSlice& cs, Ref& leaf) const { - return cs.fetch_ulong(1) == 0 - && X_.fetch_to(cs, leaf); -} - -bool BinTree::cell_unpack(Ref cell_ref, BinTree::Record_bt_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BinTree::cell_unpack_bt_leaf(Ref cell_ref, Ref& leaf) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bt_leaf(cs, leaf) && cs.empty_ext(); -} - -bool BinTree::unpack(vm::CellSlice& cs, BinTree::Record_bt_fork& data) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right); -} - -bool BinTree::unpack_bt_fork(vm::CellSlice& cs, Ref& left, Ref& right) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(left) - && cs.fetch_ref_to(right); -} - -bool BinTree::cell_unpack(Ref cell_ref, BinTree::Record_bt_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BinTree::cell_unpack_bt_fork(Ref cell_ref, Ref& left, Ref& right) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bt_fork(cs, left, right) && cs.empty_ext(); -} - -bool BinTree::pack(vm::CellBuilder& cb, const BinTree::Record_bt_leaf& data) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, data.leaf); -} - -bool BinTree::pack_bt_leaf(vm::CellBuilder& cb, Ref leaf) const { - return cb.store_long_bool(0, 1) - && X_.store_from(cb, leaf); -} - -bool BinTree::cell_pack(Ref& cell_ref, const BinTree::Record_bt_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTree::cell_pack_bt_leaf(Ref& cell_ref, Ref leaf) const { - vm::CellBuilder cb; - return pack_bt_leaf(cb, std::move(leaf)) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTree::pack(vm::CellBuilder& cb, const BinTree::Record_bt_fork& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right); -} - -bool BinTree::pack_bt_fork(vm::CellBuilder& cb, Ref left, Ref right) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(left) - && cb.store_ref_bool(right); -} - -bool BinTree::cell_pack(Ref& cell_ref, const BinTree::Record_bt_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTree::cell_pack_bt_fork(Ref& cell_ref, Ref left, Ref right) const { - vm::CellBuilder cb; - return pack_bt_fork(cb, std::move(left), std::move(right)) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTree::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bt_leaf: - return cs.advance(1) - && pp.open("bt_leaf") - && pp.field("leaf") - && X_.print_skip(pp, cs) - && pp.close(); - case bt_fork: - return cs.advance(1) - && pp.open("bt_fork") - && pp.field("left") - && print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for BinTree"); -} - - -// -// code for type `FutureSplitMerge` -// -constexpr char FutureSplitMerge::cons_len[3]; -constexpr unsigned char FutureSplitMerge::cons_tag[3]; - -int FutureSplitMerge::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case fsm_none: - return cs.have(1) ? fsm_none : -1; - case fsm_split: - return cs.have(2) ? fsm_split : -1; - case fsm_merge: - return cs.have(2) ? fsm_merge : -1; - } - return -1; -} - -bool FutureSplitMerge::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case fsm_none: - return cs.advance(1); - case fsm_split: - return cs.advance(66); - case fsm_merge: - return cs.advance(66); - } - return false; -} - -bool FutureSplitMerge::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case fsm_none: - return cs.advance(1); - case fsm_split: - return cs.advance(66); - case fsm_merge: - return cs.advance(66); - } - return false; -} - -bool FutureSplitMerge::unpack(vm::CellSlice& cs, FutureSplitMerge::Record_fsm_none& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool FutureSplitMerge::unpack_fsm_none(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool FutureSplitMerge::cell_unpack(Ref cell_ref, FutureSplitMerge::Record_fsm_none& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool FutureSplitMerge::cell_unpack_fsm_none(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_fsm_none(cs) && cs.empty_ext(); -} - -bool FutureSplitMerge::unpack(vm::CellSlice& cs, FutureSplitMerge::Record_fsm_split& data) const { - return cs.fetch_ulong(2) == 2 - && cs.fetch_uint_to(32, data.split_utime) - && cs.fetch_uint_to(32, data.interval); -} - -bool FutureSplitMerge::unpack_fsm_split(vm::CellSlice& cs, unsigned& split_utime, unsigned& interval) const { - return cs.fetch_ulong(2) == 2 - && cs.fetch_uint_to(32, split_utime) - && cs.fetch_uint_to(32, interval); -} - -bool FutureSplitMerge::cell_unpack(Ref cell_ref, FutureSplitMerge::Record_fsm_split& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool FutureSplitMerge::cell_unpack_fsm_split(Ref cell_ref, unsigned& split_utime, unsigned& interval) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_fsm_split(cs, split_utime, interval) && cs.empty_ext(); -} - -bool FutureSplitMerge::unpack(vm::CellSlice& cs, FutureSplitMerge::Record_fsm_merge& data) const { - return cs.fetch_ulong(2) == 3 - && cs.fetch_uint_to(32, data.merge_utime) - && cs.fetch_uint_to(32, data.interval); -} - -bool FutureSplitMerge::unpack_fsm_merge(vm::CellSlice& cs, unsigned& merge_utime, unsigned& interval) const { - return cs.fetch_ulong(2) == 3 - && cs.fetch_uint_to(32, merge_utime) - && cs.fetch_uint_to(32, interval); -} - -bool FutureSplitMerge::cell_unpack(Ref cell_ref, FutureSplitMerge::Record_fsm_merge& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool FutureSplitMerge::cell_unpack_fsm_merge(Ref cell_ref, unsigned& merge_utime, unsigned& interval) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_fsm_merge(cs, merge_utime, interval) && cs.empty_ext(); -} - -bool FutureSplitMerge::pack(vm::CellBuilder& cb, const FutureSplitMerge::Record_fsm_none& data) const { - return cb.store_long_bool(0, 1); -} - -bool FutureSplitMerge::pack_fsm_none(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool FutureSplitMerge::cell_pack(Ref& cell_ref, const FutureSplitMerge::Record_fsm_none& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::cell_pack_fsm_none(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_fsm_none(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::pack(vm::CellBuilder& cb, const FutureSplitMerge::Record_fsm_split& data) const { - return cb.store_long_bool(2, 2) - && cb.store_ulong_rchk_bool(data.split_utime, 32) - && cb.store_ulong_rchk_bool(data.interval, 32); -} - -bool FutureSplitMerge::pack_fsm_split(vm::CellBuilder& cb, unsigned split_utime, unsigned interval) const { - return cb.store_long_bool(2, 2) - && cb.store_ulong_rchk_bool(split_utime, 32) - && cb.store_ulong_rchk_bool(interval, 32); -} - -bool FutureSplitMerge::cell_pack(Ref& cell_ref, const FutureSplitMerge::Record_fsm_split& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::cell_pack_fsm_split(Ref& cell_ref, unsigned split_utime, unsigned interval) const { - vm::CellBuilder cb; - return pack_fsm_split(cb, split_utime, interval) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::pack(vm::CellBuilder& cb, const FutureSplitMerge::Record_fsm_merge& data) const { - return cb.store_long_bool(3, 2) - && cb.store_ulong_rchk_bool(data.merge_utime, 32) - && cb.store_ulong_rchk_bool(data.interval, 32); -} - -bool FutureSplitMerge::pack_fsm_merge(vm::CellBuilder& cb, unsigned merge_utime, unsigned interval) const { - return cb.store_long_bool(3, 2) - && cb.store_ulong_rchk_bool(merge_utime, 32) - && cb.store_ulong_rchk_bool(interval, 32); -} - -bool FutureSplitMerge::cell_pack(Ref& cell_ref, const FutureSplitMerge::Record_fsm_merge& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::cell_pack_fsm_merge(Ref& cell_ref, unsigned merge_utime, unsigned interval) const { - vm::CellBuilder cb; - return pack_fsm_merge(cb, merge_utime, interval) && std::move(cb).finalize_to(cell_ref); -} - -bool FutureSplitMerge::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case fsm_none: - return cs.advance(1) - && pp.cons("fsm_none"); - case fsm_split: - return cs.advance(2) - && pp.open("fsm_split") - && pp.fetch_uint_field(cs, 32, "split_utime") - && pp.fetch_uint_field(cs, 32, "interval") - && pp.close(); - case fsm_merge: - return cs.advance(2) - && pp.open("fsm_merge") - && pp.fetch_uint_field(cs, 32, "merge_utime") - && pp.fetch_uint_field(cs, 32, "interval") - && pp.close(); - } - return pp.fail("unknown constructor for FutureSplitMerge"); -} - -const FutureSplitMerge t_FutureSplitMerge; - -// -// code for auxiliary type `ShardDescr_aux` -// - -int ShardDescr_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardDescr_aux::skip(vm::CellSlice& cs) const { - return t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool ShardDescr_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ShardDescr_aux::unpack(vm::CellSlice& cs, ShardDescr_aux::Record& data) const { - return t_CurrencyCollection.fetch_to(cs, data.fees_collected) - && t_CurrencyCollection.fetch_to(cs, data.funds_created); -} - -bool ShardDescr_aux::unpack_cons1(vm::CellSlice& cs, Ref& fees_collected, Ref& funds_created) const { - return t_CurrencyCollection.fetch_to(cs, fees_collected) - && t_CurrencyCollection.fetch_to(cs, funds_created); -} - -bool ShardDescr_aux::cell_unpack(Ref cell_ref, ShardDescr_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardDescr_aux::cell_unpack_cons1(Ref cell_ref, Ref& fees_collected, Ref& funds_created) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, fees_collected, funds_created) && cs.empty_ext(); -} - -bool ShardDescr_aux::pack(vm::CellBuilder& cb, const ShardDescr_aux::Record& data) const { - return t_CurrencyCollection.store_from(cb, data.fees_collected) - && t_CurrencyCollection.store_from(cb, data.funds_created); -} - -bool ShardDescr_aux::pack_cons1(vm::CellBuilder& cb, Ref fees_collected, Ref funds_created) const { - return t_CurrencyCollection.store_from(cb, fees_collected) - && t_CurrencyCollection.store_from(cb, funds_created); -} - -bool ShardDescr_aux::cell_pack(Ref& cell_ref, const ShardDescr_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardDescr_aux::cell_pack_cons1(Ref& cell_ref, Ref fees_collected, Ref funds_created) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(fees_collected), std::move(funds_created)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardDescr_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("fees_collected") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("funds_created") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ShardDescr_aux t_ShardDescr_aux; - -// -// code for type `ShardDescr` -// -constexpr unsigned char ShardDescr::cons_tag[2]; - -int ShardDescr::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case shard_descr: - return cs.prefetch_ulong(4) == 11 ? shard_descr : -1; - case shard_descr_new: - return cs.have(4) ? shard_descr_new : -1; - } - return -1; -} - -bool ShardDescr::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case shard_descr: { - int flags; - return cs.advance(713) - && cs.fetch_uint_to(3, flags) - && flags == 0 - && cs.advance(160) - && t_FutureSplitMerge.skip(cs) - && t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs); - } - case shard_descr_new: { - int flags; - return cs.advance(713) - && cs.fetch_uint_to(3, flags) - && flags == 0 - && cs.advance(160) - && t_FutureSplitMerge.skip(cs) - && cs.advance_refs(1); - } - } - return false; -} - -bool ShardDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case shard_descr: { - int flags; - return cs.fetch_ulong(4) == 11 - && cs.advance(709) - && cs.fetch_uint_to(3, flags) - && flags == 0 - && cs.advance(160) - && t_FutureSplitMerge.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); - } - case shard_descr_new: { - int flags; - return cs.advance(713) - && cs.fetch_uint_to(3, flags) - && flags == 0 - && cs.advance(160) - && t_FutureSplitMerge.validate_skip(ops, cs, weak) - && t_ShardDescr_aux.validate_skip_ref(ops, cs, weak); - } - } - return false; -} - -bool ShardDescr::unpack(vm::CellSlice& cs, ShardDescr::Record_shard_descr& data) const { - return cs.fetch_ulong(4) == 11 - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_uint_to(32, data.reg_mc_seqno) - && cs.fetch_uint_to(64, data.start_lt) - && cs.fetch_uint_to(64, data.end_lt) - && cs.fetch_bits_to(data.root_hash.bits(), 256) - && cs.fetch_bits_to(data.file_hash.bits(), 256) - && cs.fetch_bool_to(data.before_split) - && cs.fetch_bool_to(data.before_merge) - && cs.fetch_bool_to(data.want_split) - && cs.fetch_bool_to(data.want_merge) - && cs.fetch_bool_to(data.nx_cc_updated) - && cs.fetch_uint_to(3, data.flags) - && data.flags == 0 - && cs.fetch_uint_to(32, data.next_catchain_seqno) - && cs.fetch_uint_to(64, data.next_validator_shard) - && cs.fetch_uint_to(32, data.min_ref_mc_seqno) - && cs.fetch_uint_to(32, data.gen_utime) - && t_FutureSplitMerge.fetch_to(cs, data.split_merge_at) - && t_CurrencyCollection.fetch_to(cs, data.fees_collected) - && t_CurrencyCollection.fetch_to(cs, data.funds_created); -} - -bool ShardDescr::cell_unpack(Ref cell_ref, ShardDescr::Record_shard_descr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardDescr::unpack(vm::CellSlice& cs, ShardDescr::Record_shard_descr_new& data) const { - return cs.fetch_ulong(4) == 10 - && cs.fetch_uint_to(32, data.seq_no) - && cs.fetch_uint_to(32, data.reg_mc_seqno) - && cs.fetch_uint_to(64, data.start_lt) - && cs.fetch_uint_to(64, data.end_lt) - && cs.fetch_bits_to(data.root_hash.bits(), 256) - && cs.fetch_bits_to(data.file_hash.bits(), 256) - && cs.fetch_bool_to(data.before_split) - && cs.fetch_bool_to(data.before_merge) - && cs.fetch_bool_to(data.want_split) - && cs.fetch_bool_to(data.want_merge) - && cs.fetch_bool_to(data.nx_cc_updated) - && cs.fetch_uint_to(3, data.flags) - && data.flags == 0 - && cs.fetch_uint_to(32, data.next_catchain_seqno) - && cs.fetch_uint_to(64, data.next_validator_shard) - && cs.fetch_uint_to(32, data.min_ref_mc_seqno) - && cs.fetch_uint_to(32, data.gen_utime) - && t_FutureSplitMerge.fetch_to(cs, data.split_merge_at) - && t_ShardDescr_aux.cell_unpack(cs.fetch_ref(), data.r1); -} - -bool ShardDescr::cell_unpack(Ref cell_ref, ShardDescr::Record_shard_descr_new& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardDescr::pack(vm::CellBuilder& cb, const ShardDescr::Record_shard_descr& data) const { - return cb.store_long_bool(11, 4) - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_ulong_rchk_bool(data.reg_mc_seqno, 32) - && cb.store_ulong_rchk_bool(data.start_lt, 64) - && cb.store_ulong_rchk_bool(data.end_lt, 64) - && cb.store_bits_bool(data.root_hash.cbits(), 256) - && cb.store_bits_bool(data.file_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.before_split, 1) - && cb.store_ulong_rchk_bool(data.before_merge, 1) - && cb.store_ulong_rchk_bool(data.want_split, 1) - && cb.store_ulong_rchk_bool(data.want_merge, 1) - && cb.store_ulong_rchk_bool(data.nx_cc_updated, 1) - && cb.store_ulong_rchk_bool(data.flags, 3) - && data.flags == 0 - && cb.store_ulong_rchk_bool(data.next_catchain_seqno, 32) - && cb.store_ulong_rchk_bool(data.next_validator_shard, 64) - && cb.store_ulong_rchk_bool(data.min_ref_mc_seqno, 32) - && cb.store_ulong_rchk_bool(data.gen_utime, 32) - && t_FutureSplitMerge.store_from(cb, data.split_merge_at) - && t_CurrencyCollection.store_from(cb, data.fees_collected) - && t_CurrencyCollection.store_from(cb, data.funds_created); -} - -bool ShardDescr::cell_pack(Ref& cell_ref, const ShardDescr::Record_shard_descr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardDescr::pack(vm::CellBuilder& cb, const ShardDescr::Record_shard_descr_new& data) const { - Ref tmp_cell; - return cb.store_long_bool(10, 4) - && cb.store_ulong_rchk_bool(data.seq_no, 32) - && cb.store_ulong_rchk_bool(data.reg_mc_seqno, 32) - && cb.store_ulong_rchk_bool(data.start_lt, 64) - && cb.store_ulong_rchk_bool(data.end_lt, 64) - && cb.store_bits_bool(data.root_hash.cbits(), 256) - && cb.store_bits_bool(data.file_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.before_split, 1) - && cb.store_ulong_rchk_bool(data.before_merge, 1) - && cb.store_ulong_rchk_bool(data.want_split, 1) - && cb.store_ulong_rchk_bool(data.want_merge, 1) - && cb.store_ulong_rchk_bool(data.nx_cc_updated, 1) - && cb.store_ulong_rchk_bool(data.flags, 3) - && data.flags == 0 - && cb.store_ulong_rchk_bool(data.next_catchain_seqno, 32) - && cb.store_ulong_rchk_bool(data.next_validator_shard, 64) - && cb.store_ulong_rchk_bool(data.min_ref_mc_seqno, 32) - && cb.store_ulong_rchk_bool(data.gen_utime, 32) - && t_FutureSplitMerge.store_from(cb, data.split_merge_at) - && t_ShardDescr_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)); -} - -bool ShardDescr::cell_pack(Ref& cell_ref, const ShardDescr::Record_shard_descr_new& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case shard_descr: { - int flags; - return cs.fetch_ulong(4) == 11 - && pp.open("shard_descr") - && pp.fetch_uint_field(cs, 32, "seq_no") - && pp.fetch_uint_field(cs, 32, "reg_mc_seqno") - && pp.fetch_uint_field(cs, 64, "start_lt") - && pp.fetch_uint_field(cs, 64, "end_lt") - && pp.fetch_bits_field(cs, 256, "root_hash") - && pp.fetch_bits_field(cs, 256, "file_hash") - && pp.fetch_uint_field(cs, 1, "before_split") - && pp.fetch_uint_field(cs, 1, "before_merge") - && pp.fetch_uint_field(cs, 1, "want_split") - && pp.fetch_uint_field(cs, 1, "want_merge") - && pp.fetch_uint_field(cs, 1, "nx_cc_updated") - && cs.fetch_uint_to(3, flags) - && pp.field_int(flags, "flags") - && flags == 0 - && pp.fetch_uint_field(cs, 32, "next_catchain_seqno") - && pp.fetch_uint_field(cs, 64, "next_validator_shard") - && pp.fetch_uint_field(cs, 32, "min_ref_mc_seqno") - && pp.fetch_uint_field(cs, 32, "gen_utime") - && pp.field("split_merge_at") - && t_FutureSplitMerge.print_skip(pp, cs) - && pp.field("fees_collected") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("funds_created") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); - } - case shard_descr_new: { - int flags; - return cs.advance(4) - && pp.open("shard_descr_new") - && pp.fetch_uint_field(cs, 32, "seq_no") - && pp.fetch_uint_field(cs, 32, "reg_mc_seqno") - && pp.fetch_uint_field(cs, 64, "start_lt") - && pp.fetch_uint_field(cs, 64, "end_lt") - && pp.fetch_bits_field(cs, 256, "root_hash") - && pp.fetch_bits_field(cs, 256, "file_hash") - && pp.fetch_uint_field(cs, 1, "before_split") - && pp.fetch_uint_field(cs, 1, "before_merge") - && pp.fetch_uint_field(cs, 1, "want_split") - && pp.fetch_uint_field(cs, 1, "want_merge") - && pp.fetch_uint_field(cs, 1, "nx_cc_updated") - && cs.fetch_uint_to(3, flags) - && pp.field_int(flags, "flags") - && flags == 0 - && pp.fetch_uint_field(cs, 32, "next_catchain_seqno") - && pp.fetch_uint_field(cs, 64, "next_validator_shard") - && pp.fetch_uint_field(cs, 32, "min_ref_mc_seqno") - && pp.fetch_uint_field(cs, 32, "gen_utime") - && pp.field("split_merge_at") - && t_FutureSplitMerge.print_skip(pp, cs) - && pp.field() - && t_ShardDescr_aux.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - } - return pp.fail("unknown constructor for ShardDescr"); -} - -const ShardDescr t_ShardDescr; - -// -// code for type `ShardHashes` -// - -int ShardHashes::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardHashes::skip(vm::CellSlice& cs) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.skip(cs); -} - -bool ShardHashes::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.validate_skip(ops, cs, weak); -} - -bool ShardHashes::unpack(vm::CellSlice& cs, ShardHashes::Record& data) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.fetch_to(cs, data.x); -} - -bool ShardHashes::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.fetch_to(cs, x); -} - -bool ShardHashes::cell_unpack(Ref cell_ref, ShardHashes::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardHashes::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ShardHashes::pack(vm::CellBuilder& cb, const ShardHashes::Record& data) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.store_from(cb, data.x); -} - -bool ShardHashes::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapE_32_Ref_BinTree_ShardDescr.store_from(cb, x); -} - -bool ShardHashes::cell_pack(Ref& cell_ref, const ShardHashes::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardHashes::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardHashes::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapE_32_Ref_BinTree_ShardDescr.print_skip(pp, cs) - && pp.close(); -} - -const ShardHashes t_ShardHashes; - -// -// code for type `BinTreeAug` -// - -int BinTreeAug::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bta_leaf: - return cs.have(1) ? bta_leaf : -1; - case bta_fork: - return cs.have(1) ? bta_fork : -1; - } - return -1; -} - -bool BinTreeAug::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bta_leaf: - return cs.advance(1) - && Y_.skip(cs) - && X_.skip(cs); - case bta_fork: - return cs.advance_ext(0x20001) - && Y_.skip(cs); - } - return false; -} - -bool BinTreeAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case bta_leaf: - return cs.advance(1) - && Y_.validate_skip(ops, cs, weak) - && X_.validate_skip(ops, cs, weak); - case bta_fork: - return cs.advance(1) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak) - && Y_.validate_skip(ops, cs, weak); - } - return false; -} - -bool BinTreeAug::unpack(vm::CellSlice& cs, BinTreeAug::Record_bta_leaf& data) const { - return cs.fetch_ulong(1) == 0 - && Y_.fetch_to(cs, data.extra) - && X_.fetch_to(cs, data.leaf); -} - -bool BinTreeAug::unpack_bta_leaf(vm::CellSlice& cs, Ref& extra, Ref& leaf) const { - return cs.fetch_ulong(1) == 0 - && Y_.fetch_to(cs, extra) - && X_.fetch_to(cs, leaf); -} - -bool BinTreeAug::cell_unpack(Ref cell_ref, BinTreeAug::Record_bta_leaf& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BinTreeAug::cell_unpack_bta_leaf(Ref cell_ref, Ref& extra, Ref& leaf) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bta_leaf(cs, extra, leaf) && cs.empty_ext(); -} - -bool BinTreeAug::unpack(vm::CellSlice& cs, BinTreeAug::Record_bta_fork& data) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(data.left) - && cs.fetch_ref_to(data.right) - && Y_.fetch_to(cs, data.extra); -} - -bool BinTreeAug::unpack_bta_fork(vm::CellSlice& cs, Ref& left, Ref& right, Ref& extra) const { - return cs.fetch_ulong(1) == 1 - && cs.fetch_ref_to(left) - && cs.fetch_ref_to(right) - && Y_.fetch_to(cs, extra); -} - -bool BinTreeAug::cell_unpack(Ref cell_ref, BinTreeAug::Record_bta_fork& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BinTreeAug::cell_unpack_bta_fork(Ref cell_ref, Ref& left, Ref& right, Ref& extra) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_bta_fork(cs, left, right, extra) && cs.empty_ext(); -} - -bool BinTreeAug::pack(vm::CellBuilder& cb, const BinTreeAug::Record_bta_leaf& data) const { - return cb.store_long_bool(0, 1) - && Y_.store_from(cb, data.extra) - && X_.store_from(cb, data.leaf); -} - -bool BinTreeAug::pack_bta_leaf(vm::CellBuilder& cb, Ref extra, Ref leaf) const { - return cb.store_long_bool(0, 1) - && Y_.store_from(cb, extra) - && X_.store_from(cb, leaf); -} - -bool BinTreeAug::cell_pack(Ref& cell_ref, const BinTreeAug::Record_bta_leaf& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTreeAug::cell_pack_bta_leaf(Ref& cell_ref, Ref extra, Ref leaf) const { - vm::CellBuilder cb; - return pack_bta_leaf(cb, std::move(extra), std::move(leaf)) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTreeAug::pack(vm::CellBuilder& cb, const BinTreeAug::Record_bta_fork& data) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(data.left) - && cb.store_ref_bool(data.right) - && Y_.store_from(cb, data.extra); -} - -bool BinTreeAug::pack_bta_fork(vm::CellBuilder& cb, Ref left, Ref right, Ref extra) const { - return cb.store_long_bool(1, 1) - && cb.store_ref_bool(left) - && cb.store_ref_bool(right) - && Y_.store_from(cb, extra); -} - -bool BinTreeAug::cell_pack(Ref& cell_ref, const BinTreeAug::Record_bta_fork& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTreeAug::cell_pack_bta_fork(Ref& cell_ref, Ref left, Ref right, Ref extra) const { - vm::CellBuilder cb; - return pack_bta_fork(cb, std::move(left), std::move(right), std::move(extra)) && std::move(cb).finalize_to(cell_ref); -} - -bool BinTreeAug::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case bta_leaf: - return cs.advance(1) - && pp.open("bta_leaf") - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.field("leaf") - && X_.print_skip(pp, cs) - && pp.close(); - case bta_fork: - return cs.advance(1) - && pp.open("bta_fork") - && pp.field("left") - && print_ref(pp, cs.fetch_ref()) - && pp.field("right") - && print_ref(pp, cs.fetch_ref()) - && pp.field("extra") - && Y_.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for BinTreeAug"); -} - - -// -// code for type `ShardFeeCreated` -// - -int ShardFeeCreated::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardFeeCreated::skip(vm::CellSlice& cs) const { - return t_CurrencyCollection.skip(cs) - && t_CurrencyCollection.skip(cs); -} - -bool ShardFeeCreated::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CurrencyCollection.validate_skip(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ShardFeeCreated::unpack(vm::CellSlice& cs, ShardFeeCreated::Record& data) const { - return t_CurrencyCollection.fetch_to(cs, data.fees) - && t_CurrencyCollection.fetch_to(cs, data.create); -} - -bool ShardFeeCreated::unpack_cons1(vm::CellSlice& cs, Ref& fees, Ref& create) const { - return t_CurrencyCollection.fetch_to(cs, fees) - && t_CurrencyCollection.fetch_to(cs, create); -} - -bool ShardFeeCreated::cell_unpack(Ref cell_ref, ShardFeeCreated::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardFeeCreated::cell_unpack_cons1(Ref cell_ref, Ref& fees, Ref& create) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, fees, create) && cs.empty_ext(); -} - -bool ShardFeeCreated::pack(vm::CellBuilder& cb, const ShardFeeCreated::Record& data) const { - return t_CurrencyCollection.store_from(cb, data.fees) - && t_CurrencyCollection.store_from(cb, data.create); -} - -bool ShardFeeCreated::pack_cons1(vm::CellBuilder& cb, Ref fees, Ref create) const { - return t_CurrencyCollection.store_from(cb, fees) - && t_CurrencyCollection.store_from(cb, create); -} - -bool ShardFeeCreated::cell_pack(Ref& cell_ref, const ShardFeeCreated::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardFeeCreated::cell_pack_cons1(Ref& cell_ref, Ref fees, Ref create) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(fees), std::move(create)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardFeeCreated::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("fees") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.field("create") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const ShardFeeCreated t_ShardFeeCreated; - -// -// code for type `ShardFees` -// - -int ShardFees::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ShardFees::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.skip(cs); -} - -bool ShardFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.validate_skip(ops, cs, weak); -} - -bool ShardFees::unpack(vm::CellSlice& cs, ShardFees::Record& data) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.fetch_to(cs, data.x); -} - -bool ShardFees::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.fetch_to(cs, x); -} - -bool ShardFees::cell_unpack(Ref cell_ref, ShardFees::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ShardFees::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool ShardFees::pack(vm::CellBuilder& cb, const ShardFees::Record& data) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.store_from(cb, data.x); -} - -bool ShardFees::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.store_from(cb, x); -} - -bool ShardFees::cell_pack(Ref& cell_ref, const ShardFees::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardFees::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ShardFees::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated.print_skip(pp, cs) - && pp.close(); -} - -const ShardFees t_ShardFees; - -// -// code for type `ConfigParams` -// - -int ConfigParams::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool ConfigParams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(256) - && t_Hashmap_32_Ref_Cell.validate_skip_ref(ops, cs, weak); -} - -bool ConfigParams::unpack(vm::CellSlice& cs, ConfigParams::Record& data) const { - return cs.fetch_bits_to(data.config_addr.bits(), 256) - && cs.fetch_ref_to(data.config); -} - -bool ConfigParams::unpack_cons1(vm::CellSlice& cs, td::BitArray<256>& config_addr, Ref& config) const { - return cs.fetch_bits_to(config_addr.bits(), 256) - && cs.fetch_ref_to(config); -} - -bool ConfigParams::cell_unpack(Ref cell_ref, ConfigParams::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParams::cell_unpack_cons1(Ref cell_ref, td::BitArray<256>& config_addr, Ref& config) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, config_addr, config) && cs.empty_ext(); -} - -bool ConfigParams::pack(vm::CellBuilder& cb, const ConfigParams::Record& data) const { - return cb.store_bits_bool(data.config_addr.cbits(), 256) - && cb.store_ref_bool(data.config); -} - -bool ConfigParams::pack_cons1(vm::CellBuilder& cb, td::BitArray<256> config_addr, Ref config) const { - return cb.store_bits_bool(config_addr.cbits(), 256) - && cb.store_ref_bool(config); -} - -bool ConfigParams::cell_pack(Ref& cell_ref, const ConfigParams::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParams::cell_pack_cons1(Ref& cell_ref, td::BitArray<256> config_addr, Ref config) const { - vm::CellBuilder cb; - return pack_cons1(cb, config_addr, std::move(config)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParams::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_bits_field(cs, 256, "config_addr") - && pp.field("config") - && t_Hashmap_32_Ref_Cell.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const ConfigParams t_ConfigParams; - -// -// code for type `ValidatorInfo` -// - -int ValidatorInfo::check_tag(const vm::CellSlice& cs) const { - return validator_info; -} - -bool ValidatorInfo::unpack(vm::CellSlice& cs, ValidatorInfo::Record& data) const { - return cs.fetch_uint_to(32, data.validator_list_hash_short) - && cs.fetch_uint_to(32, data.catchain_seqno) - && cs.fetch_bool_to(data.nx_cc_updated); -} - -bool ValidatorInfo::unpack_validator_info(vm::CellSlice& cs, unsigned& validator_list_hash_short, unsigned& catchain_seqno, bool& nx_cc_updated) const { - return cs.fetch_uint_to(32, validator_list_hash_short) - && cs.fetch_uint_to(32, catchain_seqno) - && cs.fetch_bool_to(nx_cc_updated); -} - -bool ValidatorInfo::cell_unpack(Ref cell_ref, ValidatorInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorInfo::cell_unpack_validator_info(Ref cell_ref, unsigned& validator_list_hash_short, unsigned& catchain_seqno, bool& nx_cc_updated) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_validator_info(cs, validator_list_hash_short, catchain_seqno, nx_cc_updated) && cs.empty_ext(); -} - -bool ValidatorInfo::pack(vm::CellBuilder& cb, const ValidatorInfo::Record& data) const { - return cb.store_ulong_rchk_bool(data.validator_list_hash_short, 32) - && cb.store_ulong_rchk_bool(data.catchain_seqno, 32) - && cb.store_ulong_rchk_bool(data.nx_cc_updated, 1); -} - -bool ValidatorInfo::pack_validator_info(vm::CellBuilder& cb, unsigned validator_list_hash_short, unsigned catchain_seqno, bool nx_cc_updated) const { - return cb.store_ulong_rchk_bool(validator_list_hash_short, 32) - && cb.store_ulong_rchk_bool(catchain_seqno, 32) - && cb.store_ulong_rchk_bool(nx_cc_updated, 1); -} - -bool ValidatorInfo::cell_pack(Ref& cell_ref, const ValidatorInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorInfo::cell_pack_validator_info(Ref& cell_ref, unsigned validator_list_hash_short, unsigned catchain_seqno, bool nx_cc_updated) const { - vm::CellBuilder cb; - return pack_validator_info(cb, validator_list_hash_short, catchain_seqno, nx_cc_updated) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("validator_info") - && pp.fetch_uint_field(cs, 32, "validator_list_hash_short") - && pp.fetch_uint_field(cs, 32, "catchain_seqno") - && pp.fetch_uint_field(cs, 1, "nx_cc_updated") - && pp.close(); -} - -const ValidatorInfo t_ValidatorInfo; - -// -// code for type `ValidatorBaseInfo` -// - -int ValidatorBaseInfo::check_tag(const vm::CellSlice& cs) const { - return validator_base_info; -} - -bool ValidatorBaseInfo::unpack(vm::CellSlice& cs, ValidatorBaseInfo::Record& data) const { - return cs.fetch_uint_to(32, data.validator_list_hash_short) - && cs.fetch_uint_to(32, data.catchain_seqno); -} - -bool ValidatorBaseInfo::unpack_validator_base_info(vm::CellSlice& cs, unsigned& validator_list_hash_short, unsigned& catchain_seqno) const { - return cs.fetch_uint_to(32, validator_list_hash_short) - && cs.fetch_uint_to(32, catchain_seqno); -} - -bool ValidatorBaseInfo::cell_unpack(Ref cell_ref, ValidatorBaseInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorBaseInfo::cell_unpack_validator_base_info(Ref cell_ref, unsigned& validator_list_hash_short, unsigned& catchain_seqno) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_validator_base_info(cs, validator_list_hash_short, catchain_seqno) && cs.empty_ext(); -} - -bool ValidatorBaseInfo::pack(vm::CellBuilder& cb, const ValidatorBaseInfo::Record& data) const { - return cb.store_ulong_rchk_bool(data.validator_list_hash_short, 32) - && cb.store_ulong_rchk_bool(data.catchain_seqno, 32); -} - -bool ValidatorBaseInfo::pack_validator_base_info(vm::CellBuilder& cb, unsigned validator_list_hash_short, unsigned catchain_seqno) const { - return cb.store_ulong_rchk_bool(validator_list_hash_short, 32) - && cb.store_ulong_rchk_bool(catchain_seqno, 32); -} - -bool ValidatorBaseInfo::cell_pack(Ref& cell_ref, const ValidatorBaseInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorBaseInfo::cell_pack_validator_base_info(Ref& cell_ref, unsigned validator_list_hash_short, unsigned catchain_seqno) const { - vm::CellBuilder cb; - return pack_validator_base_info(cb, validator_list_hash_short, catchain_seqno) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorBaseInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("validator_base_info") - && pp.fetch_uint_field(cs, 32, "validator_list_hash_short") - && pp.fetch_uint_field(cs, 32, "catchain_seqno") - && pp.close(); -} - -const ValidatorBaseInfo t_ValidatorBaseInfo; - -// -// code for type `KeyMaxLt` -// - -int KeyMaxLt::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool KeyMaxLt::unpack(vm::CellSlice& cs, KeyMaxLt::Record& data) const { - return cs.fetch_bool_to(data.key) - && cs.fetch_uint_to(64, data.max_end_lt); -} - -bool KeyMaxLt::unpack_cons1(vm::CellSlice& cs, bool& key, unsigned long long& max_end_lt) const { - return cs.fetch_bool_to(key) - && cs.fetch_uint_to(64, max_end_lt); -} - -bool KeyMaxLt::cell_unpack(Ref cell_ref, KeyMaxLt::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool KeyMaxLt::cell_unpack_cons1(Ref cell_ref, bool& key, unsigned long long& max_end_lt) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, key, max_end_lt) && cs.empty_ext(); -} - -bool KeyMaxLt::pack(vm::CellBuilder& cb, const KeyMaxLt::Record& data) const { - return cb.store_ulong_rchk_bool(data.key, 1) - && cb.store_ulong_rchk_bool(data.max_end_lt, 64); -} - -bool KeyMaxLt::pack_cons1(vm::CellBuilder& cb, bool key, unsigned long long max_end_lt) const { - return cb.store_ulong_rchk_bool(key, 1) - && cb.store_ulong_rchk_bool(max_end_lt, 64); -} - -bool KeyMaxLt::cell_pack(Ref& cell_ref, const KeyMaxLt::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool KeyMaxLt::cell_pack_cons1(Ref& cell_ref, bool key, unsigned long long max_end_lt) const { - vm::CellBuilder cb; - return pack_cons1(cb, key, max_end_lt) && std::move(cb).finalize_to(cell_ref); -} - -bool KeyMaxLt::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_uint_field(cs, 1, "key") - && pp.fetch_uint_field(cs, 64, "max_end_lt") - && pp.close(); -} - -const KeyMaxLt t_KeyMaxLt; - -// -// code for type `KeyExtBlkRef` -// - -int KeyExtBlkRef::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool KeyExtBlkRef::unpack(vm::CellSlice& cs, KeyExtBlkRef::Record& data) const { - return cs.fetch_bool_to(data.key) - && cs.fetch_subslice_to(608, data.blk_ref); -} - -bool KeyExtBlkRef::unpack_cons1(vm::CellSlice& cs, bool& key, Ref& blk_ref) const { - return cs.fetch_bool_to(key) - && cs.fetch_subslice_to(608, blk_ref); -} - -bool KeyExtBlkRef::cell_unpack(Ref cell_ref, KeyExtBlkRef::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool KeyExtBlkRef::cell_unpack_cons1(Ref cell_ref, bool& key, Ref& blk_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, key, blk_ref) && cs.empty_ext(); -} - -bool KeyExtBlkRef::pack(vm::CellBuilder& cb, const KeyExtBlkRef::Record& data) const { - return cb.store_ulong_rchk_bool(data.key, 1) - && cb.append_cellslice_chk(data.blk_ref, 608); -} - -bool KeyExtBlkRef::pack_cons1(vm::CellBuilder& cb, bool key, Ref blk_ref) const { - return cb.store_ulong_rchk_bool(key, 1) - && cb.append_cellslice_chk(blk_ref, 608); -} - -bool KeyExtBlkRef::cell_pack(Ref& cell_ref, const KeyExtBlkRef::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool KeyExtBlkRef::cell_pack_cons1(Ref& cell_ref, bool key, Ref blk_ref) const { - vm::CellBuilder cb; - return pack_cons1(cb, key, std::move(blk_ref)) && std::move(cb).finalize_to(cell_ref); -} - -bool KeyExtBlkRef::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_uint_field(cs, 1, "key") - && pp.field("blk_ref") - && t_ExtBlkRef.print_skip(pp, cs) - && pp.close(); -} - -const KeyExtBlkRef t_KeyExtBlkRef; - -// -// code for type `OldMcBlocksInfo` -// - -int OldMcBlocksInfo::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool OldMcBlocksInfo::skip(vm::CellSlice& cs) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.skip(cs); -} - -bool OldMcBlocksInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.validate_skip(ops, cs, weak); -} - -bool OldMcBlocksInfo::unpack(vm::CellSlice& cs, OldMcBlocksInfo::Record& data) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.fetch_to(cs, data.x); -} - -bool OldMcBlocksInfo::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.fetch_to(cs, x); -} - -bool OldMcBlocksInfo::cell_unpack(Ref cell_ref, OldMcBlocksInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool OldMcBlocksInfo::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool OldMcBlocksInfo::pack(vm::CellBuilder& cb, const OldMcBlocksInfo::Record& data) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.store_from(cb, data.x); -} - -bool OldMcBlocksInfo::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.store_from(cb, x); -} - -bool OldMcBlocksInfo::cell_pack(Ref& cell_ref, const OldMcBlocksInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool OldMcBlocksInfo::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool OldMcBlocksInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt.print_skip(pp, cs) - && pp.close(); -} - -const OldMcBlocksInfo t_OldMcBlocksInfo; - -// -// code for type `Counters` -// - -int Counters::check_tag(const vm::CellSlice& cs) const { - return counters; -} - -bool Counters::unpack(vm::CellSlice& cs, Counters::Record& data) const { - return cs.fetch_uint_to(32, data.last_updated) - && cs.fetch_uint_to(64, data.total) - && cs.fetch_uint_to(64, data.cnt2048) - && cs.fetch_uint_to(64, data.cnt65536); -} - -bool Counters::cell_unpack(Ref cell_ref, Counters::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Counters::pack(vm::CellBuilder& cb, const Counters::Record& data) const { - return cb.store_ulong_rchk_bool(data.last_updated, 32) - && cb.store_ulong_rchk_bool(data.total, 64) - && cb.store_ulong_rchk_bool(data.cnt2048, 64) - && cb.store_ulong_rchk_bool(data.cnt65536, 64); -} - -bool Counters::cell_pack(Ref& cell_ref, const Counters::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Counters::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("counters") - && pp.fetch_uint_field(cs, 32, "last_updated") - && pp.fetch_uint_field(cs, 64, "total") - && pp.fetch_uint_field(cs, 64, "cnt2048") - && pp.fetch_uint_field(cs, 64, "cnt65536") - && pp.close(); -} - -const Counters t_Counters; - -// -// code for type `CreatorStats` -// -constexpr unsigned char CreatorStats::cons_tag[1]; - -int CreatorStats::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 4 ? creator_info : -1; -} - -bool CreatorStats::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 4 - && cs.advance(448); -} - -bool CreatorStats::unpack(vm::CellSlice& cs, CreatorStats::Record& data) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_subslice_to(224, data.mc_blocks) - && cs.fetch_subslice_to(224, data.shard_blocks); -} - -bool CreatorStats::unpack_creator_info(vm::CellSlice& cs, Ref& mc_blocks, Ref& shard_blocks) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_subslice_to(224, mc_blocks) - && cs.fetch_subslice_to(224, shard_blocks); -} - -bool CreatorStats::cell_unpack(Ref cell_ref, CreatorStats::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CreatorStats::cell_unpack_creator_info(Ref cell_ref, Ref& mc_blocks, Ref& shard_blocks) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_creator_info(cs, mc_blocks, shard_blocks) && cs.empty_ext(); -} - -bool CreatorStats::pack(vm::CellBuilder& cb, const CreatorStats::Record& data) const { - return cb.store_long_bool(4, 4) - && cb.append_cellslice_chk(data.mc_blocks, 224) - && cb.append_cellslice_chk(data.shard_blocks, 224); -} - -bool CreatorStats::pack_creator_info(vm::CellBuilder& cb, Ref mc_blocks, Ref shard_blocks) const { - return cb.store_long_bool(4, 4) - && cb.append_cellslice_chk(mc_blocks, 224) - && cb.append_cellslice_chk(shard_blocks, 224); -} - -bool CreatorStats::cell_pack(Ref& cell_ref, const CreatorStats::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CreatorStats::cell_pack_creator_info(Ref& cell_ref, Ref mc_blocks, Ref shard_blocks) const { - vm::CellBuilder cb; - return pack_creator_info(cb, std::move(mc_blocks), std::move(shard_blocks)) && std::move(cb).finalize_to(cell_ref); -} - -bool CreatorStats::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 4 - && pp.open("creator_info") - && pp.field("mc_blocks") - && t_Counters.print_skip(pp, cs) - && pp.field("shard_blocks") - && t_Counters.print_skip(pp, cs) - && pp.close(); -} - -const CreatorStats t_CreatorStats; - -// -// code for type `BlockCreateStats` -// -constexpr unsigned char BlockCreateStats::cons_tag[2]; - -int BlockCreateStats::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case block_create_stats: - return cs.prefetch_ulong(8) == 23 ? block_create_stats : -1; - case block_create_stats_ext: - return cs.prefetch_ulong(8) == 0x34 ? block_create_stats_ext : -1; - } - return -1; -} - -bool BlockCreateStats::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case block_create_stats: - return cs.advance(8) - && t_HashmapE_256_CreatorStats.skip(cs); - case block_create_stats_ext: - return cs.advance(8) - && t_HashmapAugE_256_CreatorStats_uint32.skip(cs); - } - return false; -} - -bool BlockCreateStats::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case block_create_stats: - return cs.fetch_ulong(8) == 23 - && t_HashmapE_256_CreatorStats.validate_skip(ops, cs, weak); - case block_create_stats_ext: - return cs.fetch_ulong(8) == 0x34 - && t_HashmapAugE_256_CreatorStats_uint32.validate_skip(ops, cs, weak); - } - return false; -} - -bool BlockCreateStats::unpack(vm::CellSlice& cs, BlockCreateStats::Record_block_create_stats& data) const { - return cs.fetch_ulong(8) == 23 - && t_HashmapE_256_CreatorStats.fetch_to(cs, data.counters); -} - -bool BlockCreateStats::unpack_block_create_stats(vm::CellSlice& cs, Ref& counters) const { - return cs.fetch_ulong(8) == 23 - && t_HashmapE_256_CreatorStats.fetch_to(cs, counters); -} - -bool BlockCreateStats::cell_unpack(Ref cell_ref, BlockCreateStats::Record_block_create_stats& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockCreateStats::cell_unpack_block_create_stats(Ref cell_ref, Ref& counters) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_create_stats(cs, counters) && cs.empty_ext(); -} - -bool BlockCreateStats::unpack(vm::CellSlice& cs, BlockCreateStats::Record_block_create_stats_ext& data) const { - return cs.fetch_ulong(8) == 0x34 - && t_HashmapAugE_256_CreatorStats_uint32.fetch_to(cs, data.counters); -} - -bool BlockCreateStats::unpack_block_create_stats_ext(vm::CellSlice& cs, Ref& counters) const { - return cs.fetch_ulong(8) == 0x34 - && t_HashmapAugE_256_CreatorStats_uint32.fetch_to(cs, counters); -} - -bool BlockCreateStats::cell_unpack(Ref cell_ref, BlockCreateStats::Record_block_create_stats_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockCreateStats::cell_unpack_block_create_stats_ext(Ref cell_ref, Ref& counters) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_create_stats_ext(cs, counters) && cs.empty_ext(); -} - -bool BlockCreateStats::pack(vm::CellBuilder& cb, const BlockCreateStats::Record_block_create_stats& data) const { - return cb.store_long_bool(23, 8) - && t_HashmapE_256_CreatorStats.store_from(cb, data.counters); -} - -bool BlockCreateStats::pack_block_create_stats(vm::CellBuilder& cb, Ref counters) const { - return cb.store_long_bool(23, 8) - && t_HashmapE_256_CreatorStats.store_from(cb, counters); -} - -bool BlockCreateStats::cell_pack(Ref& cell_ref, const BlockCreateStats::Record_block_create_stats& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateStats::cell_pack_block_create_stats(Ref& cell_ref, Ref counters) const { - vm::CellBuilder cb; - return pack_block_create_stats(cb, std::move(counters)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateStats::pack(vm::CellBuilder& cb, const BlockCreateStats::Record_block_create_stats_ext& data) const { - return cb.store_long_bool(0x34, 8) - && t_HashmapAugE_256_CreatorStats_uint32.store_from(cb, data.counters); -} - -bool BlockCreateStats::pack_block_create_stats_ext(vm::CellBuilder& cb, Ref counters) const { - return cb.store_long_bool(0x34, 8) - && t_HashmapAugE_256_CreatorStats_uint32.store_from(cb, counters); -} - -bool BlockCreateStats::cell_pack(Ref& cell_ref, const BlockCreateStats::Record_block_create_stats_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateStats::cell_pack_block_create_stats_ext(Ref& cell_ref, Ref counters) const { - vm::CellBuilder cb; - return pack_block_create_stats_ext(cb, std::move(counters)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateStats::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case block_create_stats: - return cs.fetch_ulong(8) == 23 - && pp.open("block_create_stats") - && pp.field("counters") - && t_HashmapE_256_CreatorStats.print_skip(pp, cs) - && pp.close(); - case block_create_stats_ext: - return cs.fetch_ulong(8) == 0x34 - && pp.open("block_create_stats_ext") - && pp.field("counters") - && t_HashmapAugE_256_CreatorStats_uint32.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for BlockCreateStats"); -} - -const BlockCreateStats t_BlockCreateStats; - -// -// code for auxiliary type `McStateExtra_aux` -// - -int McStateExtra_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool McStateExtra_aux::skip(vm::CellSlice& cs) const { - int flags; - return cs.fetch_uint_to(16, flags) - && flags <= 1 - && cs.advance(65) - && t_OldMcBlocksInfo.skip(cs) - && cs.advance(1) - && t_Maybe_ExtBlkRef.skip(cs) - && (!(flags & 1) || t_BlockCreateStats.skip(cs)); -} - -bool McStateExtra_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int flags; - return cs.fetch_uint_to(16, flags) - && flags <= 1 - && cs.advance(65) - && t_OldMcBlocksInfo.validate_skip(ops, cs, weak) - && cs.advance(1) - && t_Maybe_ExtBlkRef.validate_skip(ops, cs, weak) - && (!(flags & 1) || t_BlockCreateStats.validate_skip(ops, cs, weak)); -} - -bool McStateExtra_aux::unpack(vm::CellSlice& cs, McStateExtra_aux::Record& data) const { - return cs.fetch_uint_to(16, data.flags) - && data.flags <= 1 - && cs.fetch_subslice_to(65, data.validator_info) - && t_OldMcBlocksInfo.fetch_to(cs, data.prev_blocks) - && cs.fetch_bool_to(data.after_key_block) - && t_Maybe_ExtBlkRef.fetch_to(cs, data.last_key_block) - && (!(data.flags & 1) || t_BlockCreateStats.fetch_to(cs, data.block_create_stats)); -} - -bool McStateExtra_aux::cell_unpack(Ref cell_ref, McStateExtra_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool McStateExtra_aux::pack(vm::CellBuilder& cb, const McStateExtra_aux::Record& data) const { - return cb.store_ulong_rchk_bool(data.flags, 16) - && data.flags <= 1 - && cb.append_cellslice_chk(data.validator_info, 65) - && t_OldMcBlocksInfo.store_from(cb, data.prev_blocks) - && cb.store_ulong_rchk_bool(data.after_key_block, 1) - && t_Maybe_ExtBlkRef.store_from(cb, data.last_key_block) - && (!(data.flags & 1) || t_BlockCreateStats.store_from(cb, data.block_create_stats)); -} - -bool McStateExtra_aux::cell_pack(Ref& cell_ref, const McStateExtra_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool McStateExtra_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int flags; - return pp.open() - && cs.fetch_uint_to(16, flags) - && pp.field_int(flags, "flags") - && flags <= 1 - && pp.field("validator_info") - && t_ValidatorInfo.print_skip(pp, cs) - && pp.field("prev_blocks") - && t_OldMcBlocksInfo.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 1, "after_key_block") - && pp.field("last_key_block") - && t_Maybe_ExtBlkRef.print_skip(pp, cs) - && (!(flags & 1) || (pp.field("block_create_stats") && t_BlockCreateStats.print_skip(pp, cs))) - && pp.close(); -} - -const McStateExtra_aux t_McStateExtra_aux; - -// -// code for type `McStateExtra` -// -constexpr unsigned short McStateExtra::cons_tag[1]; - -int McStateExtra::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(16) == 0xcc26 ? masterchain_state_extra : -1; -} - -bool McStateExtra::skip(vm::CellSlice& cs) const { - return cs.advance(16) - && t_ShardHashes.skip(cs) - && cs.advance_ext(0x20100) - && t_CurrencyCollection.skip(cs); -} - -bool McStateExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(16) == 0xcc26 - && t_ShardHashes.validate_skip(ops, cs, weak) - && t_ConfigParams.validate_skip(ops, cs, weak) - && t_McStateExtra_aux.validate_skip_ref(ops, cs, weak) - && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool McStateExtra::unpack(vm::CellSlice& cs, McStateExtra::Record& data) const { - return cs.fetch_ulong(16) == 0xcc26 - && t_ShardHashes.fetch_to(cs, data.shard_hashes) - && cs.fetch_subslice_ext_to(0x10100, data.config) - && t_McStateExtra_aux.cell_unpack(cs.fetch_ref(), data.r1) - && t_CurrencyCollection.fetch_to(cs, data.global_balance); -} - -bool McStateExtra::cell_unpack(Ref cell_ref, McStateExtra::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool McStateExtra::pack(vm::CellBuilder& cb, const McStateExtra::Record& data) const { - Ref tmp_cell; - return cb.store_long_bool(0xcc26, 16) - && t_ShardHashes.store_from(cb, data.shard_hashes) - && cb.append_cellslice_chk(data.config, 0x10100) - && t_McStateExtra_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)) - && t_CurrencyCollection.store_from(cb, data.global_balance); -} - -bool McStateExtra::cell_pack(Ref& cell_ref, const McStateExtra::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool McStateExtra::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0xcc26 - && pp.open("masterchain_state_extra") - && pp.field("shard_hashes") - && t_ShardHashes.print_skip(pp, cs) - && pp.field("config") - && t_ConfigParams.print_skip(pp, cs) - && pp.field() - && t_McStateExtra_aux.print_ref(pp, cs.fetch_ref()) - && pp.field("global_balance") - && t_CurrencyCollection.print_skip(pp, cs) - && pp.close(); -} - -const McStateExtra t_McStateExtra; - -// -// code for type `SigPubKey` -// -constexpr unsigned SigPubKey::cons_tag[1]; - -int SigPubKey::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x8e81278aU ? ed25519_pubkey : -1; -} - -bool SigPubKey::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x8e81278aU - && cs.advance(256); -} - -bool SigPubKey::unpack(vm::CellSlice& cs, SigPubKey::Record& data) const { - return cs.fetch_ulong(32) == 0x8e81278aU - && cs.fetch_bits_to(data.pubkey.bits(), 256); -} - -bool SigPubKey::unpack_ed25519_pubkey(vm::CellSlice& cs, td::BitArray<256>& pubkey) const { - return cs.fetch_ulong(32) == 0x8e81278aU - && cs.fetch_bits_to(pubkey.bits(), 256); -} - -bool SigPubKey::cell_unpack(Ref cell_ref, SigPubKey::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SigPubKey::cell_unpack_ed25519_pubkey(Ref cell_ref, td::BitArray<256>& pubkey) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ed25519_pubkey(cs, pubkey) && cs.empty_ext(); -} - -bool SigPubKey::pack(vm::CellBuilder& cb, const SigPubKey::Record& data) const { - return cb.store_long_bool(0x8e81278aU, 32) - && cb.store_bits_bool(data.pubkey.cbits(), 256); -} - -bool SigPubKey::pack_ed25519_pubkey(vm::CellBuilder& cb, td::BitArray<256> pubkey) const { - return cb.store_long_bool(0x8e81278aU, 32) - && cb.store_bits_bool(pubkey.cbits(), 256); -} - -bool SigPubKey::cell_pack(Ref& cell_ref, const SigPubKey::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SigPubKey::cell_pack_ed25519_pubkey(Ref& cell_ref, td::BitArray<256> pubkey) const { - vm::CellBuilder cb; - return pack_ed25519_pubkey(cb, pubkey) && std::move(cb).finalize_to(cell_ref); -} - -bool SigPubKey::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x8e81278aU - && pp.open("ed25519_pubkey") - && pp.fetch_bits_field(cs, 256, "pubkey") - && pp.close(); -} - -const SigPubKey t_SigPubKey; - -// -// code for type `CryptoSignatureSimple` -// -constexpr unsigned char CryptoSignatureSimple::cons_tag[1]; - -int CryptoSignatureSimple::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 5 ? ed25519_signature : -1; -} - -bool CryptoSignatureSimple::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 5 - && cs.advance(512); -} - -bool CryptoSignatureSimple::unpack(vm::CellSlice& cs, CryptoSignatureSimple::Record& data) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_bits_to(data.R.bits(), 256) - && cs.fetch_bits_to(data.s.bits(), 256); -} - -bool CryptoSignatureSimple::unpack_ed25519_signature(vm::CellSlice& cs, td::BitArray<256>& R, td::BitArray<256>& s) const { - return cs.fetch_ulong(4) == 5 - && cs.fetch_bits_to(R.bits(), 256) - && cs.fetch_bits_to(s.bits(), 256); -} - -bool CryptoSignatureSimple::cell_unpack(Ref cell_ref, CryptoSignatureSimple::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CryptoSignatureSimple::cell_unpack_ed25519_signature(Ref cell_ref, td::BitArray<256>& R, td::BitArray<256>& s) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_ed25519_signature(cs, R, s) && cs.empty_ext(); -} - -bool CryptoSignatureSimple::pack(vm::CellBuilder& cb, const CryptoSignatureSimple::Record& data) const { - return cb.store_long_bool(5, 4) - && cb.store_bits_bool(data.R.cbits(), 256) - && cb.store_bits_bool(data.s.cbits(), 256); -} - -bool CryptoSignatureSimple::pack_ed25519_signature(vm::CellBuilder& cb, td::BitArray<256> R, td::BitArray<256> s) const { - return cb.store_long_bool(5, 4) - && cb.store_bits_bool(R.cbits(), 256) - && cb.store_bits_bool(s.cbits(), 256); -} - -bool CryptoSignatureSimple::cell_pack(Ref& cell_ref, const CryptoSignatureSimple::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignatureSimple::cell_pack_ed25519_signature(Ref& cell_ref, td::BitArray<256> R, td::BitArray<256> s) const { - vm::CellBuilder cb; - return pack_ed25519_signature(cb, R, s) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignatureSimple::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 5 - && pp.open("ed25519_signature") - && pp.fetch_bits_field(cs, 256, "R") - && pp.fetch_bits_field(cs, 256, "s") - && pp.close(); -} - -const CryptoSignatureSimple t_CryptoSignatureSimple; - -// -// code for type `CryptoSignaturePair` -// - -int CryptoSignaturePair::check_tag(const vm::CellSlice& cs) const { - return sig_pair; -} - -bool CryptoSignaturePair::skip(vm::CellSlice& cs) const { - return cs.advance(256) - && t_CryptoSignature.skip(cs); -} - -bool CryptoSignaturePair::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(256) - && t_CryptoSignature.validate_skip(ops, cs, weak); -} - -bool CryptoSignaturePair::unpack(vm::CellSlice& cs, CryptoSignaturePair::Record& data) const { - return cs.fetch_bits_to(data.node_id_short.bits(), 256) - && t_CryptoSignature.fetch_to(cs, data.sign); -} - -bool CryptoSignaturePair::unpack_sig_pair(vm::CellSlice& cs, td::BitArray<256>& node_id_short, Ref& sign) const { - return cs.fetch_bits_to(node_id_short.bits(), 256) - && t_CryptoSignature.fetch_to(cs, sign); -} - -bool CryptoSignaturePair::cell_unpack(Ref cell_ref, CryptoSignaturePair::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CryptoSignaturePair::cell_unpack_sig_pair(Ref cell_ref, td::BitArray<256>& node_id_short, Ref& sign) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_sig_pair(cs, node_id_short, sign) && cs.empty_ext(); -} - -bool CryptoSignaturePair::pack(vm::CellBuilder& cb, const CryptoSignaturePair::Record& data) const { - return cb.store_bits_bool(data.node_id_short.cbits(), 256) - && t_CryptoSignature.store_from(cb, data.sign); -} - -bool CryptoSignaturePair::pack_sig_pair(vm::CellBuilder& cb, td::BitArray<256> node_id_short, Ref sign) const { - return cb.store_bits_bool(node_id_short.cbits(), 256) - && t_CryptoSignature.store_from(cb, sign); -} - -bool CryptoSignaturePair::cell_pack(Ref& cell_ref, const CryptoSignaturePair::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignaturePair::cell_pack_sig_pair(Ref& cell_ref, td::BitArray<256> node_id_short, Ref sign) const { - vm::CellBuilder cb; - return pack_sig_pair(cb, node_id_short, std::move(sign)) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignaturePair::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("sig_pair") - && pp.fetch_bits_field(cs, 256, "node_id_short") - && pp.field("sign") - && t_CryptoSignature.print_skip(pp, cs) - && pp.close(); -} - -const CryptoSignaturePair t_CryptoSignaturePair; - -// -// code for type `Certificate` -// -constexpr unsigned char Certificate::cons_tag[1]; - -int Certificate::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 4 ? certificate : -1; -} - -bool Certificate::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 4 - && t_SigPubKey.validate_skip(ops, cs, weak) - && cs.advance(64); -} - -bool Certificate::unpack(vm::CellSlice& cs, Certificate::Record& data) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_subslice_to(288, data.temp_key) - && cs.fetch_uint_to(32, data.valid_since) - && cs.fetch_uint_to(32, data.valid_until); -} - -bool Certificate::unpack_certificate(vm::CellSlice& cs, Ref& temp_key, unsigned& valid_since, unsigned& valid_until) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_subslice_to(288, temp_key) - && cs.fetch_uint_to(32, valid_since) - && cs.fetch_uint_to(32, valid_until); -} - -bool Certificate::cell_unpack(Ref cell_ref, Certificate::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Certificate::cell_unpack_certificate(Ref cell_ref, Ref& temp_key, unsigned& valid_since, unsigned& valid_until) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_certificate(cs, temp_key, valid_since, valid_until) && cs.empty_ext(); -} - -bool Certificate::pack(vm::CellBuilder& cb, const Certificate::Record& data) const { - return cb.store_long_bool(4, 4) - && cb.append_cellslice_chk(data.temp_key, 288) - && cb.store_ulong_rchk_bool(data.valid_since, 32) - && cb.store_ulong_rchk_bool(data.valid_until, 32); -} - -bool Certificate::pack_certificate(vm::CellBuilder& cb, Ref temp_key, unsigned valid_since, unsigned valid_until) const { - return cb.store_long_bool(4, 4) - && cb.append_cellslice_chk(temp_key, 288) - && cb.store_ulong_rchk_bool(valid_since, 32) - && cb.store_ulong_rchk_bool(valid_until, 32); -} - -bool Certificate::cell_pack(Ref& cell_ref, const Certificate::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Certificate::cell_pack_certificate(Ref& cell_ref, Ref temp_key, unsigned valid_since, unsigned valid_until) const { - vm::CellBuilder cb; - return pack_certificate(cb, std::move(temp_key), valid_since, valid_until) && std::move(cb).finalize_to(cell_ref); -} - -bool Certificate::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 4 - && pp.open("certificate") - && pp.field("temp_key") - && t_SigPubKey.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "valid_since") - && pp.fetch_uint_field(cs, 32, "valid_until") - && pp.close(); -} - -const Certificate t_Certificate; - -// -// code for type `CertificateEnv` -// -constexpr unsigned CertificateEnv::cons_tag[1]; - -int CertificateEnv::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(28) == 0xa419b7d ? certificate_env : -1; -} - -bool CertificateEnv::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(28) == 0xa419b7d - && t_Certificate.validate_skip(ops, cs, weak); -} - -bool CertificateEnv::unpack(vm::CellSlice& cs, CertificateEnv::Record& data) const { - return cs.fetch_ulong(28) == 0xa419b7d - && cs.fetch_subslice_to(356, data.certificate); -} - -bool CertificateEnv::unpack_certificate_env(vm::CellSlice& cs, Ref& certificate) const { - return cs.fetch_ulong(28) == 0xa419b7d - && cs.fetch_subslice_to(356, certificate); -} - -bool CertificateEnv::cell_unpack(Ref cell_ref, CertificateEnv::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CertificateEnv::cell_unpack_certificate_env(Ref cell_ref, Ref& certificate) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_certificate_env(cs, certificate) && cs.empty_ext(); -} - -bool CertificateEnv::pack(vm::CellBuilder& cb, const CertificateEnv::Record& data) const { - return cb.store_long_bool(0xa419b7d, 28) - && cb.append_cellslice_chk(data.certificate, 356); -} - -bool CertificateEnv::pack_certificate_env(vm::CellBuilder& cb, Ref certificate) const { - return cb.store_long_bool(0xa419b7d, 28) - && cb.append_cellslice_chk(certificate, 356); -} - -bool CertificateEnv::cell_pack(Ref& cell_ref, const CertificateEnv::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CertificateEnv::cell_pack_certificate_env(Ref& cell_ref, Ref certificate) const { - vm::CellBuilder cb; - return pack_certificate_env(cb, std::move(certificate)) && std::move(cb).finalize_to(cell_ref); -} - -bool CertificateEnv::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(28) == 0xa419b7d - && pp.open("certificate_env") - && pp.field("certificate") - && t_Certificate.print_skip(pp, cs) - && pp.close(); -} - -const CertificateEnv t_CertificateEnv; - -// -// code for type `SignedCertificate` -// - -int SignedCertificate::check_tag(const vm::CellSlice& cs) const { - return signed_certificate; -} - -bool SignedCertificate::skip(vm::CellSlice& cs) const { - return cs.advance(356) - && t_CryptoSignature.skip(cs); -} - -bool SignedCertificate::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Certificate.validate_skip(ops, cs, weak) - && t_CryptoSignature.validate_skip(ops, cs, weak); -} - -bool SignedCertificate::unpack(vm::CellSlice& cs, SignedCertificate::Record& data) const { - return cs.fetch_subslice_to(356, data.certificate) - && t_CryptoSignature.fetch_to(cs, data.certificate_signature); -} - -bool SignedCertificate::unpack_signed_certificate(vm::CellSlice& cs, Ref& certificate, Ref& certificate_signature) const { - return cs.fetch_subslice_to(356, certificate) - && t_CryptoSignature.fetch_to(cs, certificate_signature); -} - -bool SignedCertificate::cell_unpack(Ref cell_ref, SignedCertificate::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SignedCertificate::cell_unpack_signed_certificate(Ref cell_ref, Ref& certificate, Ref& certificate_signature) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_signed_certificate(cs, certificate, certificate_signature) && cs.empty_ext(); -} - -bool SignedCertificate::pack(vm::CellBuilder& cb, const SignedCertificate::Record& data) const { - return cb.append_cellslice_chk(data.certificate, 356) - && t_CryptoSignature.store_from(cb, data.certificate_signature); -} - -bool SignedCertificate::pack_signed_certificate(vm::CellBuilder& cb, Ref certificate, Ref certificate_signature) const { - return cb.append_cellslice_chk(certificate, 356) - && t_CryptoSignature.store_from(cb, certificate_signature); -} - -bool SignedCertificate::cell_pack(Ref& cell_ref, const SignedCertificate::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SignedCertificate::cell_pack_signed_certificate(Ref& cell_ref, Ref certificate, Ref certificate_signature) const { - vm::CellBuilder cb; - return pack_signed_certificate(cb, std::move(certificate), std::move(certificate_signature)) && std::move(cb).finalize_to(cell_ref); -} - -bool SignedCertificate::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("signed_certificate") - && pp.field("certificate") - && t_Certificate.print_skip(pp, cs) - && pp.field("certificate_signature") - && t_CryptoSignature.print_skip(pp, cs) - && pp.close(); -} - -const SignedCertificate t_SignedCertificate; - -// -// code for type `CryptoSignature` -// -constexpr char CryptoSignature::cons_len[2]; -constexpr unsigned char CryptoSignature::cons_tag[2]; - -int CryptoSignature::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return cons1; - case chained_signature: - return cs.prefetch_ulong(4) == 15 ? chained_signature : -1; - } - return -1; -} - -bool CryptoSignature::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return cs.advance(516); - case chained_signature: - return cs.advance_ext(0x10208); - } - return false; -} - -bool CryptoSignature::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cons1: - return t_CryptoSignatureSimple.validate_skip(ops, cs, weak); - case chained_signature: - return cs.fetch_ulong(4) == 15 - && t_SignedCertificate.validate_skip_ref(ops, cs, weak) - && t_CryptoSignatureSimple.validate_skip(ops, cs, weak); - } - return false; -} - -bool CryptoSignature::unpack(vm::CellSlice& cs, CryptoSignature::Record_cons1& data) const { - return cs.fetch_subslice_to(516, data.x); -} - -bool CryptoSignature::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(516, x); -} - -bool CryptoSignature::cell_unpack(Ref cell_ref, CryptoSignature::Record_cons1& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CryptoSignature::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool CryptoSignature::unpack(vm::CellSlice& cs, CryptoSignature::Record_chained_signature& data) const { - return cs.fetch_ulong(4) == 15 - && cs.fetch_ref_to(data.signed_cert) - && cs.fetch_subslice_to(516, data.temp_key_signature); -} - -bool CryptoSignature::unpack_chained_signature(vm::CellSlice& cs, Ref& signed_cert, Ref& temp_key_signature) const { - return cs.fetch_ulong(4) == 15 - && cs.fetch_ref_to(signed_cert) - && cs.fetch_subslice_to(516, temp_key_signature); -} - -bool CryptoSignature::cell_unpack(Ref cell_ref, CryptoSignature::Record_chained_signature& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CryptoSignature::cell_unpack_chained_signature(Ref cell_ref, Ref& signed_cert, Ref& temp_key_signature) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chained_signature(cs, signed_cert, temp_key_signature) && cs.empty_ext(); -} - -bool CryptoSignature::pack(vm::CellBuilder& cb, const CryptoSignature::Record_cons1& data) const { - return cb.append_cellslice_chk(data.x, 516); -} - -bool CryptoSignature::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 516); -} - -bool CryptoSignature::cell_pack(Ref& cell_ref, const CryptoSignature::Record_cons1& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignature::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignature::pack(vm::CellBuilder& cb, const CryptoSignature::Record_chained_signature& data) const { - return cb.store_long_bool(15, 4) - && cb.store_ref_bool(data.signed_cert) - && cb.append_cellslice_chk(data.temp_key_signature, 516); -} - -bool CryptoSignature::pack_chained_signature(vm::CellBuilder& cb, Ref signed_cert, Ref temp_key_signature) const { - return cb.store_long_bool(15, 4) - && cb.store_ref_bool(signed_cert) - && cb.append_cellslice_chk(temp_key_signature, 516); -} - -bool CryptoSignature::cell_pack(Ref& cell_ref, const CryptoSignature::Record_chained_signature& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignature::cell_pack_chained_signature(Ref& cell_ref, Ref signed_cert, Ref temp_key_signature) const { - vm::CellBuilder cb; - return pack_chained_signature(cb, std::move(signed_cert), std::move(temp_key_signature)) && std::move(cb).finalize_to(cell_ref); -} - -bool CryptoSignature::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons1: - return pp.open() - && pp.field() - && t_CryptoSignatureSimple.print_skip(pp, cs) - && pp.close(); - case chained_signature: - return cs.fetch_ulong(4) == 15 - && pp.open("chained_signature") - && pp.field("signed_cert") - && t_SignedCertificate.print_ref(pp, cs.fetch_ref()) - && pp.field("temp_key_signature") - && t_CryptoSignatureSimple.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for CryptoSignature"); -} - -const CryptoSignature t_CryptoSignature; - -// -// code for auxiliary type `McBlockExtra_aux` -// - -int McBlockExtra_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool McBlockExtra_aux::skip(vm::CellSlice& cs) const { - return t_HashmapE_16_CryptoSignaturePair.skip(cs) - && t_Maybe_Ref_InMsg.skip(cs) - && t_Maybe_Ref_InMsg.skip(cs); -} - -bool McBlockExtra_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_16_CryptoSignaturePair.validate_skip(ops, cs, weak) - && t_Maybe_Ref_InMsg.validate_skip(ops, cs, weak) - && t_Maybe_Ref_InMsg.validate_skip(ops, cs, weak); -} - -bool McBlockExtra_aux::unpack(vm::CellSlice& cs, McBlockExtra_aux::Record& data) const { - return t_HashmapE_16_CryptoSignaturePair.fetch_to(cs, data.prev_blk_signatures) - && t_Maybe_Ref_InMsg.fetch_to(cs, data.recover_create_msg) - && t_Maybe_Ref_InMsg.fetch_to(cs, data.mint_msg); -} - -bool McBlockExtra_aux::unpack_cons1(vm::CellSlice& cs, Ref& prev_blk_signatures, Ref& recover_create_msg, Ref& mint_msg) const { - return t_HashmapE_16_CryptoSignaturePair.fetch_to(cs, prev_blk_signatures) - && t_Maybe_Ref_InMsg.fetch_to(cs, recover_create_msg) - && t_Maybe_Ref_InMsg.fetch_to(cs, mint_msg); -} - -bool McBlockExtra_aux::cell_unpack(Ref cell_ref, McBlockExtra_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool McBlockExtra_aux::cell_unpack_cons1(Ref cell_ref, Ref& prev_blk_signatures, Ref& recover_create_msg, Ref& mint_msg) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, prev_blk_signatures, recover_create_msg, mint_msg) && cs.empty_ext(); -} - -bool McBlockExtra_aux::pack(vm::CellBuilder& cb, const McBlockExtra_aux::Record& data) const { - return t_HashmapE_16_CryptoSignaturePair.store_from(cb, data.prev_blk_signatures) - && t_Maybe_Ref_InMsg.store_from(cb, data.recover_create_msg) - && t_Maybe_Ref_InMsg.store_from(cb, data.mint_msg); -} - -bool McBlockExtra_aux::pack_cons1(vm::CellBuilder& cb, Ref prev_blk_signatures, Ref recover_create_msg, Ref mint_msg) const { - return t_HashmapE_16_CryptoSignaturePair.store_from(cb, prev_blk_signatures) - && t_Maybe_Ref_InMsg.store_from(cb, recover_create_msg) - && t_Maybe_Ref_InMsg.store_from(cb, mint_msg); -} - -bool McBlockExtra_aux::cell_pack(Ref& cell_ref, const McBlockExtra_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool McBlockExtra_aux::cell_pack_cons1(Ref& cell_ref, Ref prev_blk_signatures, Ref recover_create_msg, Ref mint_msg) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(prev_blk_signatures), std::move(recover_create_msg), std::move(mint_msg)) && std::move(cb).finalize_to(cell_ref); -} - -bool McBlockExtra_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("prev_blk_signatures") - && t_HashmapE_16_CryptoSignaturePair.print_skip(pp, cs) - && pp.field("recover_create_msg") - && t_Maybe_Ref_InMsg.print_skip(pp, cs) - && pp.field("mint_msg") - && t_Maybe_Ref_InMsg.print_skip(pp, cs) - && pp.close(); -} - -const McBlockExtra_aux t_McBlockExtra_aux; - -// -// code for type `McBlockExtra` -// -constexpr unsigned short McBlockExtra::cons_tag[1]; - -int McBlockExtra::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(16) == 0xcca5 ? masterchain_block_extra : -1; -} - -bool McBlockExtra::skip(vm::CellSlice& cs) const { - int key_block; - return cs.advance(16) - && cs.fetch_bool_to(key_block) - && t_ShardHashes.skip(cs) - && t_ShardFees.skip(cs) - && cs.advance_refs(1) - && (!key_block || t_ConfigParams.skip(cs)); -} - -bool McBlockExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int key_block; - return cs.fetch_ulong(16) == 0xcca5 - && cs.fetch_bool_to(key_block) - && t_ShardHashes.validate_skip(ops, cs, weak) - && t_ShardFees.validate_skip(ops, cs, weak) - && t_McBlockExtra_aux.validate_skip_ref(ops, cs, weak) - && (!key_block || t_ConfigParams.validate_skip(ops, cs, weak)); -} - -bool McBlockExtra::unpack(vm::CellSlice& cs, McBlockExtra::Record& data) const { - return cs.fetch_ulong(16) == 0xcca5 - && cs.fetch_bool_to(data.key_block) - && t_ShardHashes.fetch_to(cs, data.shard_hashes) - && t_ShardFees.fetch_to(cs, data.shard_fees) - && t_McBlockExtra_aux.cell_unpack(cs.fetch_ref(), data.r1) - && (!data.key_block || t_ConfigParams.fetch_to(cs, data.config)); -} - -bool McBlockExtra::cell_unpack(Ref cell_ref, McBlockExtra::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool McBlockExtra::pack(vm::CellBuilder& cb, const McBlockExtra::Record& data) const { - Ref tmp_cell; - return cb.store_long_bool(0xcca5, 16) - && cb.store_ulong_rchk_bool(data.key_block, 1) - && t_ShardHashes.store_from(cb, data.shard_hashes) - && t_ShardFees.store_from(cb, data.shard_fees) - && t_McBlockExtra_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)) - && (!data.key_block || t_ConfigParams.store_from(cb, data.config)); -} - -bool McBlockExtra::cell_pack(Ref& cell_ref, const McBlockExtra::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool McBlockExtra::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int key_block; - return cs.fetch_ulong(16) == 0xcca5 - && pp.open("masterchain_block_extra") - && cs.fetch_bool_to(key_block) - && pp.field_int(key_block, "key_block") - && pp.field("shard_hashes") - && t_ShardHashes.print_skip(pp, cs) - && pp.field("shard_fees") - && t_ShardFees.print_skip(pp, cs) - && pp.field() - && t_McBlockExtra_aux.print_ref(pp, cs.fetch_ref()) - && (!key_block || (pp.field("config") && t_ConfigParams.print_skip(pp, cs))) - && pp.close(); -} - -const McBlockExtra t_McBlockExtra; - -// -// code for type `ValidatorDescr` -// -constexpr unsigned char ValidatorDescr::cons_tag[2]; - -int ValidatorDescr::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validator: - return cs.prefetch_ulong(8) == 0x53 ? validator : -1; - case validator_addr: - return cs.prefetch_ulong(8) == 0x73 ? validator_addr : -1; - } - return -1; -} - -bool ValidatorDescr::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validator: - return cs.advance(360); - case validator_addr: - return cs.advance(616); - } - return false; -} - -bool ValidatorDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case validator: - return cs.fetch_ulong(8) == 0x53 - && t_SigPubKey.validate_skip(ops, cs, weak) - && cs.advance(64); - case validator_addr: - return cs.fetch_ulong(8) == 0x73 - && t_SigPubKey.validate_skip(ops, cs, weak) - && cs.advance(320); - } - return false; -} - -bool ValidatorDescr::unpack(vm::CellSlice& cs, ValidatorDescr::Record_validator& data) const { - return cs.fetch_ulong(8) == 0x53 - && cs.fetch_subslice_to(288, data.public_key) - && cs.fetch_uint_to(64, data.weight); -} - -bool ValidatorDescr::unpack_validator(vm::CellSlice& cs, Ref& public_key, unsigned long long& weight) const { - return cs.fetch_ulong(8) == 0x53 - && cs.fetch_subslice_to(288, public_key) - && cs.fetch_uint_to(64, weight); -} - -bool ValidatorDescr::cell_unpack(Ref cell_ref, ValidatorDescr::Record_validator& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorDescr::cell_unpack_validator(Ref cell_ref, Ref& public_key, unsigned long long& weight) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_validator(cs, public_key, weight) && cs.empty_ext(); -} - -bool ValidatorDescr::unpack(vm::CellSlice& cs, ValidatorDescr::Record_validator_addr& data) const { - return cs.fetch_ulong(8) == 0x73 - && cs.fetch_subslice_to(288, data.public_key) - && cs.fetch_uint_to(64, data.weight) - && cs.fetch_bits_to(data.adnl_addr.bits(), 256); -} - -bool ValidatorDescr::unpack_validator_addr(vm::CellSlice& cs, Ref& public_key, unsigned long long& weight, td::BitArray<256>& adnl_addr) const { - return cs.fetch_ulong(8) == 0x73 - && cs.fetch_subslice_to(288, public_key) - && cs.fetch_uint_to(64, weight) - && cs.fetch_bits_to(adnl_addr.bits(), 256); -} - -bool ValidatorDescr::cell_unpack(Ref cell_ref, ValidatorDescr::Record_validator_addr& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorDescr::cell_unpack_validator_addr(Ref cell_ref, Ref& public_key, unsigned long long& weight, td::BitArray<256>& adnl_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_validator_addr(cs, public_key, weight, adnl_addr) && cs.empty_ext(); -} - -bool ValidatorDescr::pack(vm::CellBuilder& cb, const ValidatorDescr::Record_validator& data) const { - return cb.store_long_bool(0x53, 8) - && cb.append_cellslice_chk(data.public_key, 288) - && cb.store_ulong_rchk_bool(data.weight, 64); -} - -bool ValidatorDescr::pack_validator(vm::CellBuilder& cb, Ref public_key, unsigned long long weight) const { - return cb.store_long_bool(0x53, 8) - && cb.append_cellslice_chk(public_key, 288) - && cb.store_ulong_rchk_bool(weight, 64); -} - -bool ValidatorDescr::cell_pack(Ref& cell_ref, const ValidatorDescr::Record_validator& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorDescr::cell_pack_validator(Ref& cell_ref, Ref public_key, unsigned long long weight) const { - vm::CellBuilder cb; - return pack_validator(cb, std::move(public_key), weight) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorDescr::pack(vm::CellBuilder& cb, const ValidatorDescr::Record_validator_addr& data) const { - return cb.store_long_bool(0x73, 8) - && cb.append_cellslice_chk(data.public_key, 288) - && cb.store_ulong_rchk_bool(data.weight, 64) - && cb.store_bits_bool(data.adnl_addr.cbits(), 256); -} - -bool ValidatorDescr::pack_validator_addr(vm::CellBuilder& cb, Ref public_key, unsigned long long weight, td::BitArray<256> adnl_addr) const { - return cb.store_long_bool(0x73, 8) - && cb.append_cellslice_chk(public_key, 288) - && cb.store_ulong_rchk_bool(weight, 64) - && cb.store_bits_bool(adnl_addr.cbits(), 256); -} - -bool ValidatorDescr::cell_pack(Ref& cell_ref, const ValidatorDescr::Record_validator_addr& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorDescr::cell_pack_validator_addr(Ref& cell_ref, Ref public_key, unsigned long long weight, td::BitArray<256> adnl_addr) const { - vm::CellBuilder cb; - return pack_validator_addr(cb, std::move(public_key), weight, adnl_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validator: - return cs.fetch_ulong(8) == 0x53 - && pp.open("validator") - && pp.field("public_key") - && t_SigPubKey.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "weight") - && pp.close(); - case validator_addr: - return cs.fetch_ulong(8) == 0x73 - && pp.open("validator_addr") - && pp.field("public_key") - && t_SigPubKey.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "weight") - && pp.fetch_bits_field(cs, 256, "adnl_addr") - && pp.close(); - } - return pp.fail("unknown constructor for ValidatorDescr"); -} - -const ValidatorDescr t_ValidatorDescr; - -// -// code for type `ValidatorSet` -// -constexpr unsigned char ValidatorSet::cons_tag[2]; - -int ValidatorSet::get_tag(const vm::CellSlice& cs) const { - switch (cs.bselect(6, 0x30)) { - case 0: - return cs.bit_at(6) ? validators_ext : validators; - default: - return -1; - } -} - -int ValidatorSet::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validators: - return cs.prefetch_ulong(8) == 17 ? validators : -1; - case validators_ext: - return cs.prefetch_ulong(8) == 18 ? validators_ext : -1; - } - return -1; -} - -bool ValidatorSet::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validators: { - int total, main; - return cs.advance(72) - && cs.fetch_uint_to(16, total) - && cs.fetch_uint_to(16, main) - && main <= total - && 1 <= main - && t_Hashmap_16_ValidatorDescr.skip(cs); - } - case validators_ext: { - int total, main; - return cs.advance(72) - && cs.fetch_uint_to(16, total) - && cs.fetch_uint_to(16, main) - && main <= total - && 1 <= main - && cs.advance(64) - && t_HashmapE_16_ValidatorDescr.skip(cs); - } - } - return false; -} - -bool ValidatorSet::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case validators: { - int total, main; - return cs.fetch_ulong(8) == 17 - && cs.advance(64) - && cs.fetch_uint_to(16, total) - && cs.fetch_uint_to(16, main) - && main <= total - && 1 <= main - && t_Hashmap_16_ValidatorDescr.validate_skip(ops, cs, weak); - } - case validators_ext: { - int total, main; - return cs.fetch_ulong(8) == 18 - && cs.advance(64) - && cs.fetch_uint_to(16, total) - && cs.fetch_uint_to(16, main) - && main <= total - && 1 <= main - && cs.advance(64) - && t_HashmapE_16_ValidatorDescr.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record_validators& data) const { - return cs.fetch_ulong(8) == 17 - && cs.fetch_uint_to(32, data.utime_since) - && cs.fetch_uint_to(32, data.utime_until) - && cs.fetch_uint_to(16, data.total) - && cs.fetch_uint_to(16, data.main) - && data.main <= data.total - && 1 <= data.main - && t_Hashmap_16_ValidatorDescr.fetch_to(cs, data.list); -} - -bool ValidatorSet::cell_unpack(Ref cell_ref, ValidatorSet::Record_validators& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record_validators_ext& data) const { - return cs.fetch_ulong(8) == 18 - && cs.fetch_uint_to(32, data.utime_since) - && cs.fetch_uint_to(32, data.utime_until) - && cs.fetch_uint_to(16, data.total) - && cs.fetch_uint_to(16, data.main) - && data.main <= data.total - && 1 <= data.main - && cs.fetch_uint_to(64, data.total_weight) - && t_HashmapE_16_ValidatorDescr.fetch_to(cs, data.list); -} - -bool ValidatorSet::cell_unpack(Ref cell_ref, ValidatorSet::Record_validators_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record_validators& data) const { - return cb.store_long_bool(17, 8) - && cb.store_ulong_rchk_bool(data.utime_since, 32) - && cb.store_ulong_rchk_bool(data.utime_until, 32) - && cb.store_ulong_rchk_bool(data.total, 16) - && cb.store_ulong_rchk_bool(data.main, 16) - && data.main <= data.total - && 1 <= data.main - && t_Hashmap_16_ValidatorDescr.store_from(cb, data.list); -} - -bool ValidatorSet::cell_pack(Ref& cell_ref, const ValidatorSet::Record_validators& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record_validators_ext& data) const { - return cb.store_long_bool(18, 8) - && cb.store_ulong_rchk_bool(data.utime_since, 32) - && cb.store_ulong_rchk_bool(data.utime_until, 32) - && cb.store_ulong_rchk_bool(data.total, 16) - && cb.store_ulong_rchk_bool(data.main, 16) - && data.main <= data.total - && 1 <= data.main - && cb.store_ulong_rchk_bool(data.total_weight, 64) - && t_HashmapE_16_ValidatorDescr.store_from(cb, data.list); -} - -bool ValidatorSet::cell_pack(Ref& cell_ref, const ValidatorSet::Record_validators_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorSet::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case validators: { - int total, main; - return cs.fetch_ulong(8) == 17 - && pp.open("validators") - && pp.fetch_uint_field(cs, 32, "utime_since") - && pp.fetch_uint_field(cs, 32, "utime_until") - && cs.fetch_uint_to(16, total) - && pp.field_int(total, "total") - && cs.fetch_uint_to(16, main) - && pp.field_int(main, "main") - && main <= total - && 1 <= main - && pp.field("list") - && t_Hashmap_16_ValidatorDescr.print_skip(pp, cs) - && pp.close(); - } - case validators_ext: { - int total, main; - return cs.fetch_ulong(8) == 18 - && pp.open("validators_ext") - && pp.fetch_uint_field(cs, 32, "utime_since") - && pp.fetch_uint_field(cs, 32, "utime_until") - && cs.fetch_uint_to(16, total) - && pp.field_int(total, "total") - && cs.fetch_uint_to(16, main) - && pp.field_int(main, "main") - && main <= total - && 1 <= main - && pp.fetch_uint_field(cs, 64, "total_weight") - && pp.field("list") - && t_HashmapE_16_ValidatorDescr.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for ValidatorSet"); -} - -const ValidatorSet t_ValidatorSet; - -// -// code for type `GlobalVersion` -// -constexpr unsigned char GlobalVersion::cons_tag[1]; - -int GlobalVersion::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xc4 ? capabilities : -1; -} - -bool GlobalVersion::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xc4 - && cs.advance(96); -} - -bool GlobalVersion::unpack(vm::CellSlice& cs, GlobalVersion::Record& data) const { - return cs.fetch_ulong(8) == 0xc4 - && cs.fetch_uint_to(32, data.version) - && cs.fetch_uint_to(64, data.capabilities); -} - -bool GlobalVersion::unpack_capabilities(vm::CellSlice& cs, unsigned& version, unsigned long long& capabilities) const { - return cs.fetch_ulong(8) == 0xc4 - && cs.fetch_uint_to(32, version) - && cs.fetch_uint_to(64, capabilities); -} - -bool GlobalVersion::cell_unpack(Ref cell_ref, GlobalVersion::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool GlobalVersion::cell_unpack_capabilities(Ref cell_ref, unsigned& version, unsigned long long& capabilities) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_capabilities(cs, version, capabilities) && cs.empty_ext(); -} - -bool GlobalVersion::pack(vm::CellBuilder& cb, const GlobalVersion::Record& data) const { - return cb.store_long_bool(0xc4, 8) - && cb.store_ulong_rchk_bool(data.version, 32) - && cb.store_ulong_rchk_bool(data.capabilities, 64); -} - -bool GlobalVersion::pack_capabilities(vm::CellBuilder& cb, unsigned version, unsigned long long capabilities) const { - return cb.store_long_bool(0xc4, 8) - && cb.store_ulong_rchk_bool(version, 32) - && cb.store_ulong_rchk_bool(capabilities, 64); -} - -bool GlobalVersion::cell_pack(Ref& cell_ref, const GlobalVersion::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool GlobalVersion::cell_pack_capabilities(Ref& cell_ref, unsigned version, unsigned long long capabilities) const { - vm::CellBuilder cb; - return pack_capabilities(cb, version, capabilities) && std::move(cb).finalize_to(cell_ref); -} - -bool GlobalVersion::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xc4 - && pp.open("capabilities") - && pp.fetch_uint_field(cs, 32, "version") - && pp.fetch_uint_field(cs, 64, "capabilities") - && pp.close(); -} - -const GlobalVersion t_GlobalVersion; - -// -// code for type `ConfigProposalSetup` -// -constexpr unsigned char ConfigProposalSetup::cons_tag[1]; - -int ConfigProposalSetup::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x36 ? cfg_vote_cfg : -1; -} - -bool ConfigProposalSetup::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x36 - && cs.advance(160); -} - -bool ConfigProposalSetup::unpack(vm::CellSlice& cs, ConfigProposalSetup::Record& data) const { - return cs.fetch_ulong(8) == 0x36 - && cs.fetch_uint_to(8, data.min_tot_rounds) - && cs.fetch_uint_to(8, data.max_tot_rounds) - && cs.fetch_uint_to(8, data.min_wins) - && cs.fetch_uint_to(8, data.max_losses) - && cs.fetch_uint_to(32, data.min_store_sec) - && cs.fetch_uint_to(32, data.max_store_sec) - && cs.fetch_uint_to(32, data.bit_price) - && cs.fetch_uint_to(32, data.cell_price); -} - -bool ConfigProposalSetup::cell_unpack(Ref cell_ref, ConfigProposalSetup::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigProposalSetup::pack(vm::CellBuilder& cb, const ConfigProposalSetup::Record& data) const { - return cb.store_long_bool(0x36, 8) - && cb.store_ulong_rchk_bool(data.min_tot_rounds, 8) - && cb.store_ulong_rchk_bool(data.max_tot_rounds, 8) - && cb.store_ulong_rchk_bool(data.min_wins, 8) - && cb.store_ulong_rchk_bool(data.max_losses, 8) - && cb.store_ulong_rchk_bool(data.min_store_sec, 32) - && cb.store_ulong_rchk_bool(data.max_store_sec, 32) - && cb.store_ulong_rchk_bool(data.bit_price, 32) - && cb.store_ulong_rchk_bool(data.cell_price, 32); -} - -bool ConfigProposalSetup::cell_pack(Ref& cell_ref, const ConfigProposalSetup::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigProposalSetup::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x36 - && pp.open("cfg_vote_cfg") - && pp.fetch_uint_field(cs, 8, "min_tot_rounds") - && pp.fetch_uint_field(cs, 8, "max_tot_rounds") - && pp.fetch_uint_field(cs, 8, "min_wins") - && pp.fetch_uint_field(cs, 8, "max_losses") - && pp.fetch_uint_field(cs, 32, "min_store_sec") - && pp.fetch_uint_field(cs, 32, "max_store_sec") - && pp.fetch_uint_field(cs, 32, "bit_price") - && pp.fetch_uint_field(cs, 32, "cell_price") - && pp.close(); -} - -const ConfigProposalSetup t_ConfigProposalSetup; - -// -// code for type `ConfigVotingSetup` -// -constexpr unsigned char ConfigVotingSetup::cons_tag[1]; - -int ConfigVotingSetup::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x91 ? cfg_vote_setup : -1; -} - -bool ConfigVotingSetup::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x91 - && t_ConfigProposalSetup.validate_skip_ref(ops, cs, weak) - && t_ConfigProposalSetup.validate_skip_ref(ops, cs, weak); -} - -bool ConfigVotingSetup::unpack(vm::CellSlice& cs, ConfigVotingSetup::Record& data) const { - return cs.fetch_ulong(8) == 0x91 - && cs.fetch_ref_to(data.normal_params) - && cs.fetch_ref_to(data.critical_params); -} - -bool ConfigVotingSetup::unpack_cfg_vote_setup(vm::CellSlice& cs, Ref& normal_params, Ref& critical_params) const { - return cs.fetch_ulong(8) == 0x91 - && cs.fetch_ref_to(normal_params) - && cs.fetch_ref_to(critical_params); -} - -bool ConfigVotingSetup::cell_unpack(Ref cell_ref, ConfigVotingSetup::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigVotingSetup::cell_unpack_cfg_vote_setup(Ref cell_ref, Ref& normal_params, Ref& critical_params) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cfg_vote_setup(cs, normal_params, critical_params) && cs.empty_ext(); -} - -bool ConfigVotingSetup::pack(vm::CellBuilder& cb, const ConfigVotingSetup::Record& data) const { - return cb.store_long_bool(0x91, 8) - && cb.store_ref_bool(data.normal_params) - && cb.store_ref_bool(data.critical_params); -} - -bool ConfigVotingSetup::pack_cfg_vote_setup(vm::CellBuilder& cb, Ref normal_params, Ref critical_params) const { - return cb.store_long_bool(0x91, 8) - && cb.store_ref_bool(normal_params) - && cb.store_ref_bool(critical_params); -} - -bool ConfigVotingSetup::cell_pack(Ref& cell_ref, const ConfigVotingSetup::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigVotingSetup::cell_pack_cfg_vote_setup(Ref& cell_ref, Ref normal_params, Ref critical_params) const { - vm::CellBuilder cb; - return pack_cfg_vote_setup(cb, std::move(normal_params), std::move(critical_params)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigVotingSetup::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x91 - && pp.open("cfg_vote_setup") - && pp.field("normal_params") - && t_ConfigProposalSetup.print_ref(pp, cs.fetch_ref()) - && pp.field("critical_params") - && t_ConfigProposalSetup.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const ConfigVotingSetup t_ConfigVotingSetup; - -// -// code for type `ConfigProposal` -// -constexpr unsigned char ConfigProposal::cons_tag[1]; - -int ConfigProposal::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xf3 ? cfg_proposal : -1; -} - -bool ConfigProposal::skip(vm::CellSlice& cs) const { - return cs.advance(40) - && t_Maybe_Ref_Cell.skip(cs) - && t_Maybe_uint256.skip(cs); -} - -bool ConfigProposal::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xf3 - && cs.advance(32) - && t_Maybe_Ref_Cell.validate_skip(ops, cs, weak) - && t_Maybe_uint256.validate_skip(ops, cs, weak); -} - -bool ConfigProposal::unpack(vm::CellSlice& cs, ConfigProposal::Record& data) const { - return cs.fetch_ulong(8) == 0xf3 - && cs.fetch_int_to(32, data.param_id) - && t_Maybe_Ref_Cell.fetch_to(cs, data.param_value) - && t_Maybe_uint256.fetch_to(cs, data.if_hash_equal); -} - -bool ConfigProposal::unpack_cfg_proposal(vm::CellSlice& cs, int& param_id, Ref& param_value, Ref& if_hash_equal) const { - return cs.fetch_ulong(8) == 0xf3 - && cs.fetch_int_to(32, param_id) - && t_Maybe_Ref_Cell.fetch_to(cs, param_value) - && t_Maybe_uint256.fetch_to(cs, if_hash_equal); -} - -bool ConfigProposal::cell_unpack(Ref cell_ref, ConfigProposal::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigProposal::cell_unpack_cfg_proposal(Ref cell_ref, int& param_id, Ref& param_value, Ref& if_hash_equal) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cfg_proposal(cs, param_id, param_value, if_hash_equal) && cs.empty_ext(); -} - -bool ConfigProposal::pack(vm::CellBuilder& cb, const ConfigProposal::Record& data) const { - return cb.store_long_bool(0xf3, 8) - && cb.store_long_rchk_bool(data.param_id, 32) - && t_Maybe_Ref_Cell.store_from(cb, data.param_value) - && t_Maybe_uint256.store_from(cb, data.if_hash_equal); -} - -bool ConfigProposal::pack_cfg_proposal(vm::CellBuilder& cb, int param_id, Ref param_value, Ref if_hash_equal) const { - return cb.store_long_bool(0xf3, 8) - && cb.store_long_rchk_bool(param_id, 32) - && t_Maybe_Ref_Cell.store_from(cb, param_value) - && t_Maybe_uint256.store_from(cb, if_hash_equal); -} - -bool ConfigProposal::cell_pack(Ref& cell_ref, const ConfigProposal::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigProposal::cell_pack_cfg_proposal(Ref& cell_ref, int param_id, Ref param_value, Ref if_hash_equal) const { - vm::CellBuilder cb; - return pack_cfg_proposal(cb, param_id, std::move(param_value), std::move(if_hash_equal)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigProposal::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xf3 - && pp.open("cfg_proposal") - && pp.fetch_int_field(cs, 32, "param_id") - && pp.field("param_value") - && t_Maybe_Ref_Cell.print_skip(pp, cs) - && pp.field("if_hash_equal") - && t_Maybe_uint256.print_skip(pp, cs) - && pp.close(); -} - -const ConfigProposal t_ConfigProposal; - -// -// code for type `ConfigProposalStatus` -// -constexpr unsigned char ConfigProposalStatus::cons_tag[1]; - -int ConfigProposalStatus::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xce ? cfg_proposal_status : -1; -} - -bool ConfigProposalStatus::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10029) - && t_HashmapE_16_True.skip(cs) - && cs.advance(344); -} - -bool ConfigProposalStatus::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xce - && cs.advance(32) - && t_ConfigProposal.validate_skip_ref(ops, cs, weak) - && cs.advance(1) - && t_HashmapE_16_True.validate_skip(ops, cs, weak) - && cs.advance(344); -} - -bool ConfigProposalStatus::unpack(vm::CellSlice& cs, ConfigProposalStatus::Record& data) const { - return cs.fetch_ulong(8) == 0xce - && cs.fetch_uint_to(32, data.expires) - && cs.fetch_ref_to(data.proposal) - && cs.fetch_bool_to(data.is_critical) - && t_HashmapE_16_True.fetch_to(cs, data.voters) - && cs.fetch_int_to(64, data.remaining_weight) - && cs.fetch_uint256_to(256, data.validator_set_id) - && cs.fetch_uint_to(8, data.rounds_remaining) - && cs.fetch_uint_to(8, data.wins) - && cs.fetch_uint_to(8, data.losses); -} - -bool ConfigProposalStatus::cell_unpack(Ref cell_ref, ConfigProposalStatus::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigProposalStatus::pack(vm::CellBuilder& cb, const ConfigProposalStatus::Record& data) const { - return cb.store_long_bool(0xce, 8) - && cb.store_ulong_rchk_bool(data.expires, 32) - && cb.store_ref_bool(data.proposal) - && cb.store_ulong_rchk_bool(data.is_critical, 1) - && t_HashmapE_16_True.store_from(cb, data.voters) - && cb.store_long_rchk_bool(data.remaining_weight, 64) - && cb.store_int256_bool(data.validator_set_id, 256, false) - && cb.store_ulong_rchk_bool(data.rounds_remaining, 8) - && cb.store_ulong_rchk_bool(data.wins, 8) - && cb.store_ulong_rchk_bool(data.losses, 8); -} - -bool ConfigProposalStatus::cell_pack(Ref& cell_ref, const ConfigProposalStatus::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigProposalStatus::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xce - && pp.open("cfg_proposal_status") - && pp.fetch_uint_field(cs, 32, "expires") - && pp.field("proposal") - && t_ConfigProposal.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 1, "is_critical") - && pp.field("voters") - && t_HashmapE_16_True.print_skip(pp, cs) - && pp.fetch_int_field(cs, 64, "remaining_weight") - && pp.fetch_uint256_field(cs, 256, "validator_set_id") - && pp.fetch_uint_field(cs, 8, "rounds_remaining") - && pp.fetch_uint_field(cs, 8, "wins") - && pp.fetch_uint_field(cs, 8, "losses") - && pp.close(); -} - -const ConfigProposalStatus t_ConfigProposalStatus; - -// -// code for type `WorkchainFormat` -// - -int WorkchainFormat::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case wfmt_basic: - return cs.prefetch_ulong(4) == 1 ? wfmt_basic : -1; - case wfmt_ext: - return cs.have(4) ? wfmt_ext : -1; - } - return -1; -} - -bool WorkchainFormat::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case wfmt_basic: - return cs.advance(100) - && m_ == 1; - case wfmt_ext: { - int min_addr_len, max_addr_len, addr_len_step, workchain_type_id; - return cs.advance(4) - && cs.fetch_uint_to(12, min_addr_len) - && cs.fetch_uint_to(12, max_addr_len) - && cs.fetch_uint_to(12, addr_len_step) - && 64 <= min_addr_len - && min_addr_len <= max_addr_len - && max_addr_len <= 1023 - && addr_len_step <= 1023 - && cs.fetch_uint_to(32, workchain_type_id) - && 1 <= workchain_type_id - && m_ == 0; - } - } - return false; -} - -bool WorkchainFormat::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case wfmt_basic: - return cs.fetch_ulong(4) == 1 - && cs.advance(96) - && m_ == 1; - case wfmt_ext: { - int min_addr_len, max_addr_len, addr_len_step, workchain_type_id; - return cs.advance(4) - && cs.fetch_uint_to(12, min_addr_len) - && cs.fetch_uint_to(12, max_addr_len) - && cs.fetch_uint_to(12, addr_len_step) - && 64 <= min_addr_len - && min_addr_len <= max_addr_len - && max_addr_len <= 1023 - && addr_len_step <= 1023 - && cs.fetch_uint_to(32, workchain_type_id) - && 1 <= workchain_type_id - && m_ == 0; - } - } - return false; -} - -bool WorkchainFormat::unpack(vm::CellSlice& cs, WorkchainFormat::Record_wfmt_basic& data) const { - return cs.fetch_ulong(4) == 1 - && cs.fetch_int_to(32, data.vm_version) - && cs.fetch_uint_to(64, data.vm_mode) - && m_ == 1; -} - -bool WorkchainFormat::unpack_wfmt_basic(vm::CellSlice& cs, int& vm_version, unsigned long long& vm_mode) const { - return cs.fetch_ulong(4) == 1 - && cs.fetch_int_to(32, vm_version) - && cs.fetch_uint_to(64, vm_mode) - && m_ == 1; -} - -bool WorkchainFormat::cell_unpack(Ref cell_ref, WorkchainFormat::Record_wfmt_basic& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool WorkchainFormat::cell_unpack_wfmt_basic(Ref cell_ref, int& vm_version, unsigned long long& vm_mode) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_wfmt_basic(cs, vm_version, vm_mode) && cs.empty_ext(); -} - -bool WorkchainFormat::unpack(vm::CellSlice& cs, WorkchainFormat::Record_wfmt_ext& data) const { - return cs.fetch_ulong(4) == 0 - && cs.fetch_uint_to(12, data.min_addr_len) - && cs.fetch_uint_to(12, data.max_addr_len) - && cs.fetch_uint_to(12, data.addr_len_step) - && 64 <= data.min_addr_len - && data.min_addr_len <= data.max_addr_len - && data.max_addr_len <= 1023 - && data.addr_len_step <= 1023 - && cs.fetch_uint_to(32, data.workchain_type_id) - && 1 <= data.workchain_type_id - && m_ == 0; -} - -bool WorkchainFormat::cell_unpack(Ref cell_ref, WorkchainFormat::Record_wfmt_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool WorkchainFormat::pack(vm::CellBuilder& cb, const WorkchainFormat::Record_wfmt_basic& data) const { - return cb.store_long_bool(1, 4) - && cb.store_long_rchk_bool(data.vm_version, 32) - && cb.store_ulong_rchk_bool(data.vm_mode, 64) - && m_ == 1; -} - -bool WorkchainFormat::pack_wfmt_basic(vm::CellBuilder& cb, int vm_version, unsigned long long vm_mode) const { - return cb.store_long_bool(1, 4) - && cb.store_long_rchk_bool(vm_version, 32) - && cb.store_ulong_rchk_bool(vm_mode, 64) - && m_ == 1; -} - -bool WorkchainFormat::cell_pack(Ref& cell_ref, const WorkchainFormat::Record_wfmt_basic& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool WorkchainFormat::cell_pack_wfmt_basic(Ref& cell_ref, int vm_version, unsigned long long vm_mode) const { - vm::CellBuilder cb; - return pack_wfmt_basic(cb, vm_version, vm_mode) && std::move(cb).finalize_to(cell_ref); -} - -bool WorkchainFormat::pack(vm::CellBuilder& cb, const WorkchainFormat::Record_wfmt_ext& data) const { - return cb.store_long_bool(0, 4) - && cb.store_ulong_rchk_bool(data.min_addr_len, 12) - && cb.store_ulong_rchk_bool(data.max_addr_len, 12) - && cb.store_ulong_rchk_bool(data.addr_len_step, 12) - && 64 <= data.min_addr_len - && data.min_addr_len <= data.max_addr_len - && data.max_addr_len <= 1023 - && data.addr_len_step <= 1023 - && cb.store_ulong_rchk_bool(data.workchain_type_id, 32) - && 1 <= data.workchain_type_id - && m_ == 0; -} - -bool WorkchainFormat::cell_pack(Ref& cell_ref, const WorkchainFormat::Record_wfmt_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool WorkchainFormat::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case wfmt_basic: - return cs.fetch_ulong(4) == 1 - && pp.open("wfmt_basic") - && pp.fetch_int_field(cs, 32, "vm_version") - && pp.fetch_uint_field(cs, 64, "vm_mode") - && m_ == 1 - && pp.close(); - case wfmt_ext: { - int min_addr_len, max_addr_len, addr_len_step, workchain_type_id; - return cs.advance(4) - && pp.open("wfmt_ext") - && cs.fetch_uint_to(12, min_addr_len) - && pp.field_int(min_addr_len, "min_addr_len") - && cs.fetch_uint_to(12, max_addr_len) - && pp.field_int(max_addr_len, "max_addr_len") - && cs.fetch_uint_to(12, addr_len_step) - && pp.field_int(addr_len_step, "addr_len_step") - && 64 <= min_addr_len - && min_addr_len <= max_addr_len - && max_addr_len <= 1023 - && addr_len_step <= 1023 - && cs.fetch_uint_to(32, workchain_type_id) - && pp.field_int(workchain_type_id, "workchain_type_id") - && 1 <= workchain_type_id - && m_ == 0 - && pp.close(); - } - } - return pp.fail("unknown constructor for WorkchainFormat"); -} - - -// -// code for type `WorkchainDescr` -// -constexpr unsigned char WorkchainDescr::cons_tag[1]; - -int WorkchainDescr::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xa6 ? workchain : -1; -} - -bool WorkchainDescr::skip(vm::CellSlice& cs) const { - int actual_min_split, min_split, basic, flags; - return cs.advance(40) - && cs.fetch_uint_to(8, actual_min_split) - && cs.fetch_uint_to(8, min_split) - && actual_min_split <= min_split - && cs.advance(8) - && cs.fetch_bool_to(basic) - && cs.advance(2) - && cs.fetch_uint_to(13, flags) - && flags == 0 - && cs.advance(544) - && WorkchainFormat{basic}.skip(cs); -} - -bool WorkchainDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int actual_min_split, min_split, basic, flags; - return cs.fetch_ulong(8) == 0xa6 - && cs.advance(32) - && cs.fetch_uint_to(8, actual_min_split) - && cs.fetch_uint_to(8, min_split) - && actual_min_split <= min_split - && cs.advance(8) - && cs.fetch_bool_to(basic) - && cs.advance(2) - && cs.fetch_uint_to(13, flags) - && flags == 0 - && cs.advance(544) - && WorkchainFormat{basic}.validate_skip(ops, cs, weak); -} - -bool WorkchainDescr::unpack(vm::CellSlice& cs, WorkchainDescr::Record& data) const { - return cs.fetch_ulong(8) == 0xa6 - && cs.fetch_uint_to(32, data.enabled_since) - && cs.fetch_uint_to(8, data.actual_min_split) - && cs.fetch_uint_to(8, data.min_split) - && cs.fetch_uint_to(8, data.max_split) - && data.actual_min_split <= data.min_split - && cs.fetch_bool_to(data.basic) - && cs.fetch_bool_to(data.active) - && cs.fetch_bool_to(data.accept_msgs) - && cs.fetch_uint_to(13, data.flags) - && data.flags == 0 - && cs.fetch_bits_to(data.zerostate_root_hash.bits(), 256) - && cs.fetch_bits_to(data.zerostate_file_hash.bits(), 256) - && cs.fetch_uint_to(32, data.version) - && WorkchainFormat{data.basic}.fetch_to(cs, data.format); -} - -bool WorkchainDescr::cell_unpack(Ref cell_ref, WorkchainDescr::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool WorkchainDescr::pack(vm::CellBuilder& cb, const WorkchainDescr::Record& data) const { - return cb.store_long_bool(0xa6, 8) - && cb.store_ulong_rchk_bool(data.enabled_since, 32) - && cb.store_ulong_rchk_bool(data.actual_min_split, 8) - && cb.store_ulong_rchk_bool(data.min_split, 8) - && cb.store_ulong_rchk_bool(data.max_split, 8) - && data.actual_min_split <= data.min_split - && cb.store_ulong_rchk_bool(data.basic, 1) - && cb.store_ulong_rchk_bool(data.active, 1) - && cb.store_ulong_rchk_bool(data.accept_msgs, 1) - && cb.store_ulong_rchk_bool(data.flags, 13) - && data.flags == 0 - && cb.store_bits_bool(data.zerostate_root_hash.cbits(), 256) - && cb.store_bits_bool(data.zerostate_file_hash.cbits(), 256) - && cb.store_ulong_rchk_bool(data.version, 32) - && WorkchainFormat{data.basic}.store_from(cb, data.format); -} - -bool WorkchainDescr::cell_pack(Ref& cell_ref, const WorkchainDescr::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool WorkchainDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int actual_min_split, min_split, max_split, basic, flags; - return cs.fetch_ulong(8) == 0xa6 - && pp.open("workchain") - && pp.fetch_uint_field(cs, 32, "enabled_since") - && cs.fetch_uint_to(8, actual_min_split) - && pp.field_int(actual_min_split, "actual_min_split") - && cs.fetch_uint_to(8, min_split) - && pp.field_int(min_split, "min_split") - && cs.fetch_uint_to(8, max_split) - && pp.field_int(max_split, "max_split") - && actual_min_split <= min_split - && cs.fetch_bool_to(basic) - && pp.field_int(basic, "basic") - && pp.fetch_uint_field(cs, 1, "active") - && pp.fetch_uint_field(cs, 1, "accept_msgs") - && cs.fetch_uint_to(13, flags) - && pp.field_int(flags, "flags") - && flags == 0 - && pp.fetch_bits_field(cs, 256, "zerostate_root_hash") - && pp.fetch_bits_field(cs, 256, "zerostate_file_hash") - && pp.fetch_uint_field(cs, 32, "version") - && pp.field("format") - && WorkchainFormat{basic}.print_skip(pp, cs) - && pp.close(); -} - -const WorkchainDescr t_WorkchainDescr; - -// -// code for type `ComplaintPricing` -// -constexpr unsigned char ComplaintPricing::cons_tag[1]; - -int ComplaintPricing::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 26 ? complaint_prices : -1; -} - -bool ComplaintPricing::skip(vm::CellSlice& cs) const { - return cs.advance(8) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs); -} - -bool ComplaintPricing::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 26 - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); -} - -bool ComplaintPricing::unpack(vm::CellSlice& cs, ComplaintPricing::Record& data) const { - return cs.fetch_ulong(8) == 26 - && t_Grams.fetch_to(cs, data.deposit) - && t_Grams.fetch_to(cs, data.bit_price) - && t_Grams.fetch_to(cs, data.cell_price); -} - -bool ComplaintPricing::unpack_complaint_prices(vm::CellSlice& cs, Ref& deposit, Ref& bit_price, Ref& cell_price) const { - return cs.fetch_ulong(8) == 26 - && t_Grams.fetch_to(cs, deposit) - && t_Grams.fetch_to(cs, bit_price) - && t_Grams.fetch_to(cs, cell_price); -} - -bool ComplaintPricing::cell_unpack(Ref cell_ref, ComplaintPricing::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComplaintPricing::cell_unpack_complaint_prices(Ref cell_ref, Ref& deposit, Ref& bit_price, Ref& cell_price) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_complaint_prices(cs, deposit, bit_price, cell_price) && cs.empty_ext(); -} - -bool ComplaintPricing::pack(vm::CellBuilder& cb, const ComplaintPricing::Record& data) const { - return cb.store_long_bool(26, 8) - && t_Grams.store_from(cb, data.deposit) - && t_Grams.store_from(cb, data.bit_price) - && t_Grams.store_from(cb, data.cell_price); -} - -bool ComplaintPricing::pack_complaint_prices(vm::CellBuilder& cb, Ref deposit, Ref bit_price, Ref cell_price) const { - return cb.store_long_bool(26, 8) - && t_Grams.store_from(cb, deposit) - && t_Grams.store_from(cb, bit_price) - && t_Grams.store_from(cb, cell_price); -} - -bool ComplaintPricing::cell_pack(Ref& cell_ref, const ComplaintPricing::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintPricing::cell_pack_complaint_prices(Ref& cell_ref, Ref deposit, Ref bit_price, Ref cell_price) const { - vm::CellBuilder cb; - return pack_complaint_prices(cb, std::move(deposit), std::move(bit_price), std::move(cell_price)) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintPricing::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 26 - && pp.open("complaint_prices") - && pp.field("deposit") - && t_Grams.print_skip(pp, cs) - && pp.field("bit_price") - && t_Grams.print_skip(pp, cs) - && pp.field("cell_price") - && t_Grams.print_skip(pp, cs) - && pp.close(); -} - -const ComplaintPricing t_ComplaintPricing; - -// -// code for type `BlockCreateFees` -// -constexpr unsigned char BlockCreateFees::cons_tag[1]; - -int BlockCreateFees::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x6b ? block_grams_created : -1; -} - -bool BlockCreateFees::skip(vm::CellSlice& cs) const { - return cs.advance(8) - && t_Grams.skip(cs) - && t_Grams.skip(cs); -} - -bool BlockCreateFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x6b - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); -} - -bool BlockCreateFees::unpack(vm::CellSlice& cs, BlockCreateFees::Record& data) const { - return cs.fetch_ulong(8) == 0x6b - && t_Grams.fetch_to(cs, data.masterchain_block_fee) - && t_Grams.fetch_to(cs, data.basechain_block_fee); -} - -bool BlockCreateFees::unpack_block_grams_created(vm::CellSlice& cs, Ref& masterchain_block_fee, Ref& basechain_block_fee) const { - return cs.fetch_ulong(8) == 0x6b - && t_Grams.fetch_to(cs, masterchain_block_fee) - && t_Grams.fetch_to(cs, basechain_block_fee); -} - -bool BlockCreateFees::cell_unpack(Ref cell_ref, BlockCreateFees::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockCreateFees::cell_unpack_block_grams_created(Ref cell_ref, Ref& masterchain_block_fee, Ref& basechain_block_fee) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_grams_created(cs, masterchain_block_fee, basechain_block_fee) && cs.empty_ext(); -} - -bool BlockCreateFees::pack(vm::CellBuilder& cb, const BlockCreateFees::Record& data) const { - return cb.store_long_bool(0x6b, 8) - && t_Grams.store_from(cb, data.masterchain_block_fee) - && t_Grams.store_from(cb, data.basechain_block_fee); -} - -bool BlockCreateFees::pack_block_grams_created(vm::CellBuilder& cb, Ref masterchain_block_fee, Ref basechain_block_fee) const { - return cb.store_long_bool(0x6b, 8) - && t_Grams.store_from(cb, masterchain_block_fee) - && t_Grams.store_from(cb, basechain_block_fee); -} - -bool BlockCreateFees::cell_pack(Ref& cell_ref, const BlockCreateFees::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateFees::cell_pack_block_grams_created(Ref& cell_ref, Ref masterchain_block_fee, Ref basechain_block_fee) const { - vm::CellBuilder cb; - return pack_block_grams_created(cb, std::move(masterchain_block_fee), std::move(basechain_block_fee)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockCreateFees::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x6b - && pp.open("block_grams_created") - && pp.field("masterchain_block_fee") - && t_Grams.print_skip(pp, cs) - && pp.field("basechain_block_fee") - && t_Grams.print_skip(pp, cs) - && pp.close(); -} - -const BlockCreateFees t_BlockCreateFees; - -// -// code for type `StoragePrices` -// -constexpr unsigned char StoragePrices::cons_tag[1]; - -int StoragePrices::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xcc ? cons1 : -1; -} - -bool StoragePrices::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xcc - && cs.advance(288); -} - -bool StoragePrices::unpack(vm::CellSlice& cs, StoragePrices::Record& data) const { - return cs.fetch_ulong(8) == 0xcc - && cs.fetch_uint_to(32, data.utime_since) - && cs.fetch_uint_to(64, data.bit_price_ps) - && cs.fetch_uint_to(64, data.cell_price_ps) - && cs.fetch_uint_to(64, data.mc_bit_price_ps) - && cs.fetch_uint_to(64, data.mc_cell_price_ps); -} - -bool StoragePrices::cell_unpack(Ref cell_ref, StoragePrices::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool StoragePrices::pack(vm::CellBuilder& cb, const StoragePrices::Record& data) const { - return cb.store_long_bool(0xcc, 8) - && cb.store_ulong_rchk_bool(data.utime_since, 32) - && cb.store_ulong_rchk_bool(data.bit_price_ps, 64) - && cb.store_ulong_rchk_bool(data.cell_price_ps, 64) - && cb.store_ulong_rchk_bool(data.mc_bit_price_ps, 64) - && cb.store_ulong_rchk_bool(data.mc_cell_price_ps, 64); -} - -bool StoragePrices::cell_pack(Ref& cell_ref, const StoragePrices::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool StoragePrices::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xcc - && pp.open() - && pp.fetch_uint_field(cs, 32, "utime_since") - && pp.fetch_uint_field(cs, 64, "bit_price_ps") - && pp.fetch_uint_field(cs, 64, "cell_price_ps") - && pp.fetch_uint_field(cs, 64, "mc_bit_price_ps") - && pp.fetch_uint_field(cs, 64, "mc_cell_price_ps") - && pp.close(); -} - -const StoragePrices t_StoragePrices; - -// -// code for type `GasLimitsPrices` -// -constexpr unsigned char GasLimitsPrices::cons_tag[3]; - -int GasLimitsPrices::get_tag(const vm::CellSlice& cs) const { - switch (cs.bselect(6, 0x1b0000000000000ULL)) { - case 0: - return gas_flat_pfx; - case 2: - return cs.bit_at(6) ? gas_prices_ext : gas_prices; - default: - return -1; - } -} - -int GasLimitsPrices::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case gas_prices: - return cs.prefetch_ulong(8) == 0xdd ? gas_prices : -1; - case gas_prices_ext: - return cs.prefetch_ulong(8) == 0xde ? gas_prices_ext : -1; - case gas_flat_pfx: - return cs.prefetch_ulong(8) == 0xd1 ? gas_flat_pfx : -1; - } - return -1; -} - -bool GasLimitsPrices::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case gas_prices: - return cs.advance(392); - case gas_prices_ext: - return cs.advance(456); - case gas_flat_pfx: - return cs.advance(136) - && skip(cs); - } - return false; -} - -bool GasLimitsPrices::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case gas_prices: - return cs.fetch_ulong(8) == 0xdd - && cs.advance(384); - case gas_prices_ext: - return cs.fetch_ulong(8) == 0xde - && cs.advance(448); - case gas_flat_pfx: - return cs.fetch_ulong(8) == 0xd1 - && cs.advance(128) - && validate_skip(ops, cs, weak); - } - return false; -} - -bool GasLimitsPrices::unpack(vm::CellSlice& cs, GasLimitsPrices::Record_gas_prices& data) const { - return cs.fetch_ulong(8) == 0xdd - && cs.fetch_uint_to(64, data.gas_price) - && cs.fetch_uint_to(64, data.gas_limit) - && cs.fetch_uint_to(64, data.gas_credit) - && cs.fetch_uint_to(64, data.block_gas_limit) - && cs.fetch_uint_to(64, data.freeze_due_limit) - && cs.fetch_uint_to(64, data.delete_due_limit); -} - -bool GasLimitsPrices::cell_unpack(Ref cell_ref, GasLimitsPrices::Record_gas_prices& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool GasLimitsPrices::unpack(vm::CellSlice& cs, GasLimitsPrices::Record_gas_prices_ext& data) const { - return cs.fetch_ulong(8) == 0xde - && cs.fetch_uint_to(64, data.gas_price) - && cs.fetch_uint_to(64, data.gas_limit) - && cs.fetch_uint_to(64, data.special_gas_limit) - && cs.fetch_uint_to(64, data.gas_credit) - && cs.fetch_uint_to(64, data.block_gas_limit) - && cs.fetch_uint_to(64, data.freeze_due_limit) - && cs.fetch_uint_to(64, data.delete_due_limit); -} - -bool GasLimitsPrices::cell_unpack(Ref cell_ref, GasLimitsPrices::Record_gas_prices_ext& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool GasLimitsPrices::unpack(vm::CellSlice& cs, GasLimitsPrices::Record_gas_flat_pfx& data) const { - return cs.fetch_ulong(8) == 0xd1 - && cs.fetch_uint_to(64, data.flat_gas_limit) - && cs.fetch_uint_to(64, data.flat_gas_price) - && fetch_to(cs, data.other); -} - -bool GasLimitsPrices::unpack_gas_flat_pfx(vm::CellSlice& cs, unsigned long long& flat_gas_limit, unsigned long long& flat_gas_price, Ref& other) const { - return cs.fetch_ulong(8) == 0xd1 - && cs.fetch_uint_to(64, flat_gas_limit) - && cs.fetch_uint_to(64, flat_gas_price) - && fetch_to(cs, other); -} - -bool GasLimitsPrices::cell_unpack(Ref cell_ref, GasLimitsPrices::Record_gas_flat_pfx& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool GasLimitsPrices::cell_unpack_gas_flat_pfx(Ref cell_ref, unsigned long long& flat_gas_limit, unsigned long long& flat_gas_price, Ref& other) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_gas_flat_pfx(cs, flat_gas_limit, flat_gas_price, other) && cs.empty_ext(); -} - -bool GasLimitsPrices::pack(vm::CellBuilder& cb, const GasLimitsPrices::Record_gas_prices& data) const { - return cb.store_long_bool(0xdd, 8) - && cb.store_ulong_rchk_bool(data.gas_price, 64) - && cb.store_ulong_rchk_bool(data.gas_limit, 64) - && cb.store_ulong_rchk_bool(data.gas_credit, 64) - && cb.store_ulong_rchk_bool(data.block_gas_limit, 64) - && cb.store_ulong_rchk_bool(data.freeze_due_limit, 64) - && cb.store_ulong_rchk_bool(data.delete_due_limit, 64); -} - -bool GasLimitsPrices::cell_pack(Ref& cell_ref, const GasLimitsPrices::Record_gas_prices& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool GasLimitsPrices::pack(vm::CellBuilder& cb, const GasLimitsPrices::Record_gas_prices_ext& data) const { - return cb.store_long_bool(0xde, 8) - && cb.store_ulong_rchk_bool(data.gas_price, 64) - && cb.store_ulong_rchk_bool(data.gas_limit, 64) - && cb.store_ulong_rchk_bool(data.special_gas_limit, 64) - && cb.store_ulong_rchk_bool(data.gas_credit, 64) - && cb.store_ulong_rchk_bool(data.block_gas_limit, 64) - && cb.store_ulong_rchk_bool(data.freeze_due_limit, 64) - && cb.store_ulong_rchk_bool(data.delete_due_limit, 64); -} - -bool GasLimitsPrices::cell_pack(Ref& cell_ref, const GasLimitsPrices::Record_gas_prices_ext& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool GasLimitsPrices::pack(vm::CellBuilder& cb, const GasLimitsPrices::Record_gas_flat_pfx& data) const { - return cb.store_long_bool(0xd1, 8) - && cb.store_ulong_rchk_bool(data.flat_gas_limit, 64) - && cb.store_ulong_rchk_bool(data.flat_gas_price, 64) - && store_from(cb, data.other); -} - -bool GasLimitsPrices::pack_gas_flat_pfx(vm::CellBuilder& cb, unsigned long long flat_gas_limit, unsigned long long flat_gas_price, Ref other) const { - return cb.store_long_bool(0xd1, 8) - && cb.store_ulong_rchk_bool(flat_gas_limit, 64) - && cb.store_ulong_rchk_bool(flat_gas_price, 64) - && store_from(cb, other); -} - -bool GasLimitsPrices::cell_pack(Ref& cell_ref, const GasLimitsPrices::Record_gas_flat_pfx& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool GasLimitsPrices::cell_pack_gas_flat_pfx(Ref& cell_ref, unsigned long long flat_gas_limit, unsigned long long flat_gas_price, Ref other) const { - vm::CellBuilder cb; - return pack_gas_flat_pfx(cb, flat_gas_limit, flat_gas_price, std::move(other)) && std::move(cb).finalize_to(cell_ref); -} - -bool GasLimitsPrices::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case gas_prices: - return cs.fetch_ulong(8) == 0xdd - && pp.open("gas_prices") - && pp.fetch_uint_field(cs, 64, "gas_price") - && pp.fetch_uint_field(cs, 64, "gas_limit") - && pp.fetch_uint_field(cs, 64, "gas_credit") - && pp.fetch_uint_field(cs, 64, "block_gas_limit") - && pp.fetch_uint_field(cs, 64, "freeze_due_limit") - && pp.fetch_uint_field(cs, 64, "delete_due_limit") - && pp.close(); - case gas_prices_ext: - return cs.fetch_ulong(8) == 0xde - && pp.open("gas_prices_ext") - && pp.fetch_uint_field(cs, 64, "gas_price") - && pp.fetch_uint_field(cs, 64, "gas_limit") - && pp.fetch_uint_field(cs, 64, "special_gas_limit") - && pp.fetch_uint_field(cs, 64, "gas_credit") - && pp.fetch_uint_field(cs, 64, "block_gas_limit") - && pp.fetch_uint_field(cs, 64, "freeze_due_limit") - && pp.fetch_uint_field(cs, 64, "delete_due_limit") - && pp.close(); - case gas_flat_pfx: - return cs.fetch_ulong(8) == 0xd1 - && pp.open("gas_flat_pfx") - && pp.fetch_uint_field(cs, 64, "flat_gas_limit") - && pp.fetch_uint_field(cs, 64, "flat_gas_price") - && pp.field("other") - && print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for GasLimitsPrices"); -} - -const GasLimitsPrices t_GasLimitsPrices; - -// -// code for type `ParamLimits` -// -constexpr unsigned char ParamLimits::cons_tag[1]; - -int ParamLimits::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xc3 ? param_limits : -1; -} - -bool ParamLimits::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int underload, soft_limit, hard_limit; - return cs.fetch_ulong(8) == 0xc3 - && cs.fetch_uint_to(32, underload) - && cs.fetch_uint_to(32, soft_limit) - && underload <= soft_limit - && cs.fetch_uint_to(32, hard_limit) - && soft_limit <= hard_limit; -} - -bool ParamLimits::unpack(vm::CellSlice& cs, ParamLimits::Record& data) const { - return cs.fetch_ulong(8) == 0xc3 - && cs.fetch_uint_to(32, data.underload) - && cs.fetch_uint_to(32, data.soft_limit) - && data.underload <= data.soft_limit - && cs.fetch_uint_to(32, data.hard_limit) - && data.soft_limit <= data.hard_limit; -} - -bool ParamLimits::unpack_param_limits(vm::CellSlice& cs, int& underload, int& soft_limit, int& hard_limit) const { - return cs.fetch_ulong(8) == 0xc3 - && cs.fetch_uint_to(32, underload) - && cs.fetch_uint_to(32, soft_limit) - && underload <= soft_limit - && cs.fetch_uint_to(32, hard_limit) - && soft_limit <= hard_limit; -} - -bool ParamLimits::cell_unpack(Ref cell_ref, ParamLimits::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ParamLimits::cell_unpack_param_limits(Ref cell_ref, int& underload, int& soft_limit, int& hard_limit) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_param_limits(cs, underload, soft_limit, hard_limit) && cs.empty_ext(); -} - -bool ParamLimits::pack(vm::CellBuilder& cb, const ParamLimits::Record& data) const { - return cb.store_long_bool(0xc3, 8) - && cb.store_ulong_rchk_bool(data.underload, 32) - && cb.store_ulong_rchk_bool(data.soft_limit, 32) - && data.underload <= data.soft_limit - && cb.store_ulong_rchk_bool(data.hard_limit, 32) - && data.soft_limit <= data.hard_limit; -} - -bool ParamLimits::pack_param_limits(vm::CellBuilder& cb, int underload, int soft_limit, int hard_limit) const { - return cb.store_long_bool(0xc3, 8) - && cb.store_ulong_rchk_bool(underload, 32) - && cb.store_ulong_rchk_bool(soft_limit, 32) - && underload <= soft_limit - && cb.store_ulong_rchk_bool(hard_limit, 32) - && soft_limit <= hard_limit; -} - -bool ParamLimits::cell_pack(Ref& cell_ref, const ParamLimits::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ParamLimits::cell_pack_param_limits(Ref& cell_ref, int underload, int soft_limit, int hard_limit) const { - vm::CellBuilder cb; - return pack_param_limits(cb, underload, soft_limit, hard_limit) && std::move(cb).finalize_to(cell_ref); -} - -bool ParamLimits::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int underload, soft_limit, hard_limit; - return cs.fetch_ulong(8) == 0xc3 - && pp.open("param_limits") - && cs.fetch_uint_to(32, underload) - && pp.field_int(underload, "underload") - && cs.fetch_uint_to(32, soft_limit) - && pp.field_int(soft_limit, "soft_limit") - && underload <= soft_limit - && cs.fetch_uint_to(32, hard_limit) - && pp.field_int(hard_limit, "hard_limit") - && soft_limit <= hard_limit - && pp.close(); -} - -const ParamLimits t_ParamLimits; - -// -// code for type `BlockLimits` -// -constexpr unsigned char BlockLimits::cons_tag[1]; - -int BlockLimits::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x5d ? block_limits : -1; -} - -bool BlockLimits::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x5d - && t_ParamLimits.validate_skip(ops, cs, weak) - && t_ParamLimits.validate_skip(ops, cs, weak) - && t_ParamLimits.validate_skip(ops, cs, weak); -} - -bool BlockLimits::unpack(vm::CellSlice& cs, BlockLimits::Record& data) const { - return cs.fetch_ulong(8) == 0x5d - && cs.fetch_subslice_to(104, data.bytes) - && cs.fetch_subslice_to(104, data.gas) - && cs.fetch_subslice_to(104, data.lt_delta); -} - -bool BlockLimits::unpack_block_limits(vm::CellSlice& cs, Ref& bytes, Ref& gas, Ref& lt_delta) const { - return cs.fetch_ulong(8) == 0x5d - && cs.fetch_subslice_to(104, bytes) - && cs.fetch_subslice_to(104, gas) - && cs.fetch_subslice_to(104, lt_delta); -} - -bool BlockLimits::cell_unpack(Ref cell_ref, BlockLimits::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockLimits::cell_unpack_block_limits(Ref cell_ref, Ref& bytes, Ref& gas, Ref& lt_delta) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_limits(cs, bytes, gas, lt_delta) && cs.empty_ext(); -} - -bool BlockLimits::pack(vm::CellBuilder& cb, const BlockLimits::Record& data) const { - return cb.store_long_bool(0x5d, 8) - && cb.append_cellslice_chk(data.bytes, 104) - && cb.append_cellslice_chk(data.gas, 104) - && cb.append_cellslice_chk(data.lt_delta, 104); -} - -bool BlockLimits::pack_block_limits(vm::CellBuilder& cb, Ref bytes, Ref gas, Ref lt_delta) const { - return cb.store_long_bool(0x5d, 8) - && cb.append_cellslice_chk(bytes, 104) - && cb.append_cellslice_chk(gas, 104) - && cb.append_cellslice_chk(lt_delta, 104); -} - -bool BlockLimits::cell_pack(Ref& cell_ref, const BlockLimits::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockLimits::cell_pack_block_limits(Ref& cell_ref, Ref bytes, Ref gas, Ref lt_delta) const { - vm::CellBuilder cb; - return pack_block_limits(cb, std::move(bytes), std::move(gas), std::move(lt_delta)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockLimits::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x5d - && pp.open("block_limits") - && pp.field("bytes") - && t_ParamLimits.print_skip(pp, cs) - && pp.field("gas") - && t_ParamLimits.print_skip(pp, cs) - && pp.field("lt_delta") - && t_ParamLimits.print_skip(pp, cs) - && pp.close(); -} - -const BlockLimits t_BlockLimits; - -// -// code for type `MsgForwardPrices` -// -constexpr unsigned char MsgForwardPrices::cons_tag[1]; - -int MsgForwardPrices::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xea ? msg_forward_prices : -1; -} - -bool MsgForwardPrices::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xea - && cs.advance(256); -} - -bool MsgForwardPrices::unpack(vm::CellSlice& cs, MsgForwardPrices::Record& data) const { - return cs.fetch_ulong(8) == 0xea - && cs.fetch_uint_to(64, data.lump_price) - && cs.fetch_uint_to(64, data.bit_price) - && cs.fetch_uint_to(64, data.cell_price) - && cs.fetch_uint_to(32, data.ihr_price_factor) - && cs.fetch_uint_to(16, data.first_frac) - && cs.fetch_uint_to(16, data.next_frac); -} - -bool MsgForwardPrices::cell_unpack(Ref cell_ref, MsgForwardPrices::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool MsgForwardPrices::pack(vm::CellBuilder& cb, const MsgForwardPrices::Record& data) const { - return cb.store_long_bool(0xea, 8) - && cb.store_ulong_rchk_bool(data.lump_price, 64) - && cb.store_ulong_rchk_bool(data.bit_price, 64) - && cb.store_ulong_rchk_bool(data.cell_price, 64) - && cb.store_ulong_rchk_bool(data.ihr_price_factor, 32) - && cb.store_ulong_rchk_bool(data.first_frac, 16) - && cb.store_ulong_rchk_bool(data.next_frac, 16); -} - -bool MsgForwardPrices::cell_pack(Ref& cell_ref, const MsgForwardPrices::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool MsgForwardPrices::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xea - && pp.open("msg_forward_prices") - && pp.fetch_uint_field(cs, 64, "lump_price") - && pp.fetch_uint_field(cs, 64, "bit_price") - && pp.fetch_uint_field(cs, 64, "cell_price") - && pp.fetch_uint_field(cs, 32, "ihr_price_factor") - && pp.fetch_uint_field(cs, 16, "first_frac") - && pp.fetch_uint_field(cs, 16, "next_frac") - && pp.close(); -} - -const MsgForwardPrices t_MsgForwardPrices; - -// -// code for type `CatchainConfig` -// -constexpr unsigned char CatchainConfig::cons_tag[2]; - -int CatchainConfig::get_tag(const vm::CellSlice& cs) const { - switch (cs.bselect(6, 0x3000000000000ULL)) { - case 0: - return cs.bit_at(6) ? catchain_config_new : catchain_config; - default: - return -1; - } -} - -int CatchainConfig::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case catchain_config: - return cs.prefetch_ulong(8) == 0xc1 ? catchain_config : -1; - case catchain_config_new: - return cs.prefetch_ulong(8) == 0xc2 ? catchain_config_new : -1; - } - return -1; -} - -bool CatchainConfig::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case catchain_config: - return cs.advance(136); - case catchain_config_new: { - int flags; - return cs.advance(8) - && cs.fetch_uint_to(7, flags) - && flags == 0 - && cs.advance(129); - } - } - return false; -} - -bool CatchainConfig::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case catchain_config: - return cs.fetch_ulong(8) == 0xc1 - && cs.advance(128); - case catchain_config_new: { - int flags; - return cs.fetch_ulong(8) == 0xc2 - && cs.fetch_uint_to(7, flags) - && flags == 0 - && cs.advance(129); - } - } - return false; -} - -bool CatchainConfig::unpack(vm::CellSlice& cs, CatchainConfig::Record_catchain_config& data) const { - return cs.fetch_ulong(8) == 0xc1 - && cs.fetch_uint_to(32, data.mc_catchain_lifetime) - && cs.fetch_uint_to(32, data.shard_catchain_lifetime) - && cs.fetch_uint_to(32, data.shard_validators_lifetime) - && cs.fetch_uint_to(32, data.shard_validators_num); -} - -bool CatchainConfig::cell_unpack(Ref cell_ref, CatchainConfig::Record_catchain_config& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CatchainConfig::unpack(vm::CellSlice& cs, CatchainConfig::Record_catchain_config_new& data) const { - return cs.fetch_ulong(8) == 0xc2 - && cs.fetch_uint_to(7, data.flags) - && data.flags == 0 - && cs.fetch_bool_to(data.shuffle_mc_validators) - && cs.fetch_uint_to(32, data.mc_catchain_lifetime) - && cs.fetch_uint_to(32, data.shard_catchain_lifetime) - && cs.fetch_uint_to(32, data.shard_validators_lifetime) - && cs.fetch_uint_to(32, data.shard_validators_num); -} - -bool CatchainConfig::cell_unpack(Ref cell_ref, CatchainConfig::Record_catchain_config_new& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool CatchainConfig::pack(vm::CellBuilder& cb, const CatchainConfig::Record_catchain_config& data) const { - return cb.store_long_bool(0xc1, 8) - && cb.store_ulong_rchk_bool(data.mc_catchain_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_catchain_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_validators_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_validators_num, 32); -} - -bool CatchainConfig::cell_pack(Ref& cell_ref, const CatchainConfig::Record_catchain_config& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CatchainConfig::pack(vm::CellBuilder& cb, const CatchainConfig::Record_catchain_config_new& data) const { - return cb.store_long_bool(0xc2, 8) - && cb.store_ulong_rchk_bool(data.flags, 7) - && data.flags == 0 - && cb.store_ulong_rchk_bool(data.shuffle_mc_validators, 1) - && cb.store_ulong_rchk_bool(data.mc_catchain_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_catchain_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_validators_lifetime, 32) - && cb.store_ulong_rchk_bool(data.shard_validators_num, 32); -} - -bool CatchainConfig::cell_pack(Ref& cell_ref, const CatchainConfig::Record_catchain_config_new& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool CatchainConfig::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case catchain_config: - return cs.fetch_ulong(8) == 0xc1 - && pp.open("catchain_config") - && pp.fetch_uint_field(cs, 32, "mc_catchain_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_catchain_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_validators_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_validators_num") - && pp.close(); - case catchain_config_new: { - int flags; - return cs.fetch_ulong(8) == 0xc2 - && pp.open("catchain_config_new") - && cs.fetch_uint_to(7, flags) - && pp.field_int(flags, "flags") - && flags == 0 - && pp.fetch_uint_field(cs, 1, "shuffle_mc_validators") - && pp.fetch_uint_field(cs, 32, "mc_catchain_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_catchain_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_validators_lifetime") - && pp.fetch_uint_field(cs, 32, "shard_validators_num") - && pp.close(); - } - } - return pp.fail("unknown constructor for CatchainConfig"); -} - -const CatchainConfig t_CatchainConfig; - -// -// code for type `ConsensusConfig` -// -constexpr unsigned char ConsensusConfig::cons_tag[2]; - -int ConsensusConfig::get_tag(const vm::CellSlice& cs) const { - switch (cs.bselect(6, 0x60000000000000ULL)) { - case 0: - return cs.bit_at(7) ? consensus_config_new : consensus_config; - default: - return -1; - } -} - -int ConsensusConfig::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case consensus_config: - return cs.prefetch_ulong(8) == 0xd6 ? consensus_config : -1; - case consensus_config_new: - return cs.prefetch_ulong(8) == 0xd7 ? consensus_config_new : -1; - } - return -1; -} - -bool ConsensusConfig::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case consensus_config: { - int round_candidates; - return cs.advance(8) - && cs.fetch_uint_to(32, round_candidates) - && 1 <= round_candidates - && cs.advance(224); - } - case consensus_config_new: { - int flags, round_candidates; - return cs.advance(8) - && cs.fetch_uint_to(7, flags) - && flags == 0 - && cs.advance(1) - && cs.fetch_uint_to(8, round_candidates) - && 1 <= round_candidates - && cs.advance(224); - } - } - return false; -} - -bool ConsensusConfig::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case consensus_config: { - int round_candidates; - return cs.fetch_ulong(8) == 0xd6 - && cs.fetch_uint_to(32, round_candidates) - && 1 <= round_candidates - && cs.advance(224); - } - case consensus_config_new: { - int flags, round_candidates; - return cs.fetch_ulong(8) == 0xd7 - && cs.fetch_uint_to(7, flags) - && flags == 0 - && cs.advance(1) - && cs.fetch_uint_to(8, round_candidates) - && 1 <= round_candidates - && cs.advance(224); - } - } - return false; -} - -bool ConsensusConfig::unpack(vm::CellSlice& cs, ConsensusConfig::Record_consensus_config& data) const { - return cs.fetch_ulong(8) == 0xd6 - && cs.fetch_uint_to(32, data.round_candidates) - && 1 <= data.round_candidates - && cs.fetch_uint_to(32, data.next_candidate_delay_ms) - && cs.fetch_uint_to(32, data.consensus_timeout_ms) - && cs.fetch_uint_to(32, data.fast_attempts) - && cs.fetch_uint_to(32, data.attempt_duration) - && cs.fetch_uint_to(32, data.catchain_max_deps) - && cs.fetch_uint_to(32, data.max_block_bytes) - && cs.fetch_uint_to(32, data.max_collated_bytes); -} - -bool ConsensusConfig::cell_unpack(Ref cell_ref, ConsensusConfig::Record_consensus_config& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConsensusConfig::unpack(vm::CellSlice& cs, ConsensusConfig::Record_consensus_config_new& data) const { - return cs.fetch_ulong(8) == 0xd7 - && cs.fetch_uint_to(7, data.flags) - && data.flags == 0 - && cs.fetch_bool_to(data.new_catchain_ids) - && cs.fetch_uint_to(8, data.round_candidates) - && 1 <= data.round_candidates - && cs.fetch_uint_to(32, data.next_candidate_delay_ms) - && cs.fetch_uint_to(32, data.consensus_timeout_ms) - && cs.fetch_uint_to(32, data.fast_attempts) - && cs.fetch_uint_to(32, data.attempt_duration) - && cs.fetch_uint_to(32, data.catchain_max_deps) - && cs.fetch_uint_to(32, data.max_block_bytes) - && cs.fetch_uint_to(32, data.max_collated_bytes); -} - -bool ConsensusConfig::cell_unpack(Ref cell_ref, ConsensusConfig::Record_consensus_config_new& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConsensusConfig::pack(vm::CellBuilder& cb, const ConsensusConfig::Record_consensus_config& data) const { - return cb.store_long_bool(0xd6, 8) - && cb.store_ulong_rchk_bool(data.round_candidates, 32) - && 1 <= data.round_candidates - && cb.store_ulong_rchk_bool(data.next_candidate_delay_ms, 32) - && cb.store_ulong_rchk_bool(data.consensus_timeout_ms, 32) - && cb.store_ulong_rchk_bool(data.fast_attempts, 32) - && cb.store_ulong_rchk_bool(data.attempt_duration, 32) - && cb.store_ulong_rchk_bool(data.catchain_max_deps, 32) - && cb.store_ulong_rchk_bool(data.max_block_bytes, 32) - && cb.store_ulong_rchk_bool(data.max_collated_bytes, 32); -} - -bool ConsensusConfig::cell_pack(Ref& cell_ref, const ConsensusConfig::Record_consensus_config& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConsensusConfig::pack(vm::CellBuilder& cb, const ConsensusConfig::Record_consensus_config_new& data) const { - return cb.store_long_bool(0xd7, 8) - && cb.store_ulong_rchk_bool(data.flags, 7) - && data.flags == 0 - && cb.store_ulong_rchk_bool(data.new_catchain_ids, 1) - && cb.store_ulong_rchk_bool(data.round_candidates, 8) - && 1 <= data.round_candidates - && cb.store_ulong_rchk_bool(data.next_candidate_delay_ms, 32) - && cb.store_ulong_rchk_bool(data.consensus_timeout_ms, 32) - && cb.store_ulong_rchk_bool(data.fast_attempts, 32) - && cb.store_ulong_rchk_bool(data.attempt_duration, 32) - && cb.store_ulong_rchk_bool(data.catchain_max_deps, 32) - && cb.store_ulong_rchk_bool(data.max_block_bytes, 32) - && cb.store_ulong_rchk_bool(data.max_collated_bytes, 32); -} - -bool ConsensusConfig::cell_pack(Ref& cell_ref, const ConsensusConfig::Record_consensus_config_new& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConsensusConfig::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case consensus_config: { - int round_candidates; - return cs.fetch_ulong(8) == 0xd6 - && pp.open("consensus_config") - && cs.fetch_uint_to(32, round_candidates) - && pp.field_int(round_candidates, "round_candidates") - && 1 <= round_candidates - && pp.fetch_uint_field(cs, 32, "next_candidate_delay_ms") - && pp.fetch_uint_field(cs, 32, "consensus_timeout_ms") - && pp.fetch_uint_field(cs, 32, "fast_attempts") - && pp.fetch_uint_field(cs, 32, "attempt_duration") - && pp.fetch_uint_field(cs, 32, "catchain_max_deps") - && pp.fetch_uint_field(cs, 32, "max_block_bytes") - && pp.fetch_uint_field(cs, 32, "max_collated_bytes") - && pp.close(); - } - case consensus_config_new: { - int flags, round_candidates; - return cs.fetch_ulong(8) == 0xd7 - && pp.open("consensus_config_new") - && cs.fetch_uint_to(7, flags) - && pp.field_int(flags, "flags") - && flags == 0 - && pp.fetch_uint_field(cs, 1, "new_catchain_ids") - && cs.fetch_uint_to(8, round_candidates) - && pp.field_int(round_candidates, "round_candidates") - && 1 <= round_candidates - && pp.fetch_uint_field(cs, 32, "next_candidate_delay_ms") - && pp.fetch_uint_field(cs, 32, "consensus_timeout_ms") - && pp.fetch_uint_field(cs, 32, "fast_attempts") - && pp.fetch_uint_field(cs, 32, "attempt_duration") - && pp.fetch_uint_field(cs, 32, "catchain_max_deps") - && pp.fetch_uint_field(cs, 32, "max_block_bytes") - && pp.fetch_uint_field(cs, 32, "max_collated_bytes") - && pp.close(); - } - } - return pp.fail("unknown constructor for ConsensusConfig"); -} - -const ConsensusConfig t_ConsensusConfig; - -// -// code for type `ValidatorTempKey` -// -constexpr unsigned char ValidatorTempKey::cons_tag[1]; - -int ValidatorTempKey::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 3 ? validator_temp_key : -1; -} - -bool ValidatorTempKey::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 3 - && cs.advance(256) - && t_SigPubKey.validate_skip(ops, cs, weak) - && cs.advance(64); -} - -bool ValidatorTempKey::unpack(vm::CellSlice& cs, ValidatorTempKey::Record& data) const { - return cs.fetch_ulong(4) == 3 - && cs.fetch_bits_to(data.adnl_addr.bits(), 256) - && cs.fetch_subslice_to(288, data.temp_public_key) - && cs.fetch_uint_to(32, data.seqno) - && cs.fetch_uint_to(32, data.valid_until); -} - -bool ValidatorTempKey::cell_unpack(Ref cell_ref, ValidatorTempKey::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorTempKey::pack(vm::CellBuilder& cb, const ValidatorTempKey::Record& data) const { - return cb.store_long_bool(3, 4) - && cb.store_bits_bool(data.adnl_addr.cbits(), 256) - && cb.append_cellslice_chk(data.temp_public_key, 288) - && cb.store_ulong_rchk_bool(data.seqno, 32) - && cb.store_ulong_rchk_bool(data.valid_until, 32); -} - -bool ValidatorTempKey::cell_pack(Ref& cell_ref, const ValidatorTempKey::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorTempKey::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int seqno; - return cs.fetch_ulong(4) == 3 - && pp.open("validator_temp_key") - && pp.fetch_bits_field(cs, 256, "adnl_addr") - && pp.field("temp_public_key") - && t_SigPubKey.print_skip(pp, cs) - && cs.fetch_uint_to(32, seqno) - && pp.field_int(seqno, "seqno") - && pp.fetch_uint_field(cs, 32, "valid_until") - && pp.close(); -} - -const ValidatorTempKey t_ValidatorTempKey; - -// -// code for type `ValidatorSignedTempKey` -// -constexpr unsigned char ValidatorSignedTempKey::cons_tag[1]; - -int ValidatorSignedTempKey::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(4) == 4 ? signed_temp_key : -1; -} - -bool ValidatorSignedTempKey::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10004) - && t_CryptoSignature.skip(cs); -} - -bool ValidatorSignedTempKey::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 4 - && t_ValidatorTempKey.validate_skip_ref(ops, cs, weak) - && t_CryptoSignature.validate_skip(ops, cs, weak); -} - -bool ValidatorSignedTempKey::unpack(vm::CellSlice& cs, ValidatorSignedTempKey::Record& data) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_ref_to(data.key) - && t_CryptoSignature.fetch_to(cs, data.signature); -} - -bool ValidatorSignedTempKey::unpack_signed_temp_key(vm::CellSlice& cs, Ref& key, Ref& signature) const { - return cs.fetch_ulong(4) == 4 - && cs.fetch_ref_to(key) - && t_CryptoSignature.fetch_to(cs, signature); -} - -bool ValidatorSignedTempKey::cell_unpack(Ref cell_ref, ValidatorSignedTempKey::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorSignedTempKey::cell_unpack_signed_temp_key(Ref cell_ref, Ref& key, Ref& signature) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_signed_temp_key(cs, key, signature) && cs.empty_ext(); -} - -bool ValidatorSignedTempKey::pack(vm::CellBuilder& cb, const ValidatorSignedTempKey::Record& data) const { - return cb.store_long_bool(4, 4) - && cb.store_ref_bool(data.key) - && t_CryptoSignature.store_from(cb, data.signature); -} - -bool ValidatorSignedTempKey::pack_signed_temp_key(vm::CellBuilder& cb, Ref key, Ref signature) const { - return cb.store_long_bool(4, 4) - && cb.store_ref_bool(key) - && t_CryptoSignature.store_from(cb, signature); -} - -bool ValidatorSignedTempKey::cell_pack(Ref& cell_ref, const ValidatorSignedTempKey::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorSignedTempKey::cell_pack_signed_temp_key(Ref& cell_ref, Ref key, Ref signature) const { - vm::CellBuilder cb; - return pack_signed_temp_key(cb, std::move(key), std::move(signature)) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorSignedTempKey::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 4 - && pp.open("signed_temp_key") - && pp.field("key") - && t_ValidatorTempKey.print_ref(pp, cs.fetch_ref()) - && pp.field("signature") - && t_CryptoSignature.print_skip(pp, cs) - && pp.close(); -} - -const ValidatorSignedTempKey t_ValidatorSignedTempKey; - -// -// code for type `ConfigParam` -// - -int ConfigParam::get_tag(const vm::CellSlice& cs) const { - switch (m_) { - case 0: - return cons0; - case 1: - return cons1; - case 2: - return cons2; - case 3: - return cons3; - case 4: - return cons4; - case 6: - return cons6; - case 7: - return cons7; - case 8: - return cons8; - case 9: - return cons9; - case 10: - return cons10; - case 11: - return cons11; - case 12: - return cons12; - case 13: - return cons13; - case 14: - return cons14; - case 15: - return cons15; - case 16: - return cons16; - case 17: - return cons17; - case 18: - return cons18; - case 20: - return config_mc_gas_prices; - case 21: - return config_gas_prices; - case 22: - return config_mc_block_limits; - case 23: - return config_block_limits; - case 24: - return config_mc_fwd_prices; - case 25: - return config_fwd_prices; - case 28: - return cons28; - case 29: - return cons29; - case 31: - return cons31; - case 32: - return cons32; - case 33: - return cons33; - case 34: - return cons34; - case 35: - return cons35; - case 36: - return cons36; - case 37: - return cons37; - case 39: - return cons39; - default: - return -1; - } -} - -int ConfigParam::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons0: - return cons0; - case cons1: - return cons1; - case cons2: - return cons2; - case cons3: - return cons3; - case cons4: - return cons4; - case cons6: - return cons6; - case cons7: - return cons7; - case cons8: - return cons8; - case cons9: - return cons9; - case cons10: - return cons10; - case cons11: - return cons11; - case cons12: - return cons12; - case cons13: - return cons13; - case cons14: - return cons14; - case cons15: - return cons15; - case cons16: - return cons16; - case cons17: - return cons17; - case cons18: - return cons18; - case config_mc_gas_prices: - return config_mc_gas_prices; - case config_gas_prices: - return config_gas_prices; - case config_mc_block_limits: - return config_mc_block_limits; - case config_block_limits: - return config_block_limits; - case config_mc_fwd_prices: - return config_mc_fwd_prices; - case config_fwd_prices: - return config_fwd_prices; - case cons28: - return cons28; - case cons29: - return cons29; - case cons31: - return cons31; - case cons32: - return cons32; - case cons33: - return cons33; - case cons34: - return cons34; - case cons35: - return cons35; - case cons36: - return cons36; - case cons37: - return cons37; - case cons39: - return cons39; - } - return -1; -} - -bool ConfigParam::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons0: - return cs.advance(256) - && m_ == 0; - case cons1: - return cs.advance(256) - && m_ == 1; - case cons2: - return cs.advance(256) - && m_ == 2; - case cons3: - return cs.advance(256) - && m_ == 3; - case cons4: - return cs.advance(256) - && m_ == 4; - case cons6: - return t_Grams.skip(cs) - && t_Grams.skip(cs) - && m_ == 6; - case cons7: - return t_ExtraCurrencyCollection.skip(cs) - && m_ == 7; - case cons8: - return cs.advance(104) - && m_ == 8; - case cons9: - return t_Hashmap_32_True.skip(cs) - && m_ == 9; - case cons10: - return t_Hashmap_32_True.skip(cs) - && m_ == 10; - case cons11: - return cs.advance_ext(0x20008) - && m_ == 11; - case cons12: - return t_HashmapE_32_WorkchainDescr.skip(cs) - && m_ == 12; - case cons13: - return t_ComplaintPricing.skip(cs) - && m_ == 13; - case cons14: - return t_BlockCreateFees.skip(cs) - && m_ == 14; - case cons15: - return cs.advance(128) - && m_ == 15; - case cons16: { - int max_validators, max_main_validators, min_validators; - return cs.fetch_uint_to(16, max_validators) - && cs.fetch_uint_to(16, max_main_validators) - && cs.fetch_uint_to(16, min_validators) - && max_main_validators <= max_validators - && min_validators <= max_main_validators - && 1 <= min_validators - && m_ == 16; - } - case cons17: - return t_Grams.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(32) - && m_ == 17; - case cons18: - return t_Hashmap_32_StoragePrices.skip(cs) - && m_ == 18; - case config_mc_gas_prices: - return t_GasLimitsPrices.skip(cs) - && m_ == 20; - case config_gas_prices: - return t_GasLimitsPrices.skip(cs) - && m_ == 21; - case config_mc_block_limits: - return cs.advance(320) - && m_ == 22; - case config_block_limits: - return cs.advance(320) - && m_ == 23; - case config_mc_fwd_prices: - return cs.advance(264) - && m_ == 24; - case config_fwd_prices: - return cs.advance(264) - && m_ == 25; - case cons28: - return t_CatchainConfig.skip(cs) - && m_ == 28; - case cons29: - return t_ConsensusConfig.skip(cs) - && m_ == 29; - case cons31: - return t_HashmapE_256_True.skip(cs) - && m_ == 31; - case cons32: - return t_ValidatorSet.skip(cs) - && m_ == 32; - case cons33: - return t_ValidatorSet.skip(cs) - && m_ == 33; - case cons34: - return t_ValidatorSet.skip(cs) - && m_ == 34; - case cons35: - return t_ValidatorSet.skip(cs) - && m_ == 35; - case cons36: - return t_ValidatorSet.skip(cs) - && m_ == 36; - case cons37: - return t_ValidatorSet.skip(cs) - && m_ == 37; - case cons39: - return t_HashmapE_256_ValidatorSignedTempKey.skip(cs) - && m_ == 39; - } - return false; -} - -bool ConfigParam::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cons0: - return cs.advance(256) - && m_ == 0; - case cons1: - return cs.advance(256) - && m_ == 1; - case cons2: - return cs.advance(256) - && m_ == 2; - case cons3: - return cs.advance(256) - && m_ == 3; - case cons4: - return cs.advance(256) - && m_ == 4; - case cons6: - return t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && m_ == 6; - case cons7: - return t_ExtraCurrencyCollection.validate_skip(ops, cs, weak) - && m_ == 7; - case cons8: - return t_GlobalVersion.validate_skip(ops, cs, weak) - && m_ == 8; - case cons9: - return t_Hashmap_32_True.validate_skip(ops, cs, weak) - && m_ == 9; - case cons10: - return t_Hashmap_32_True.validate_skip(ops, cs, weak) - && m_ == 10; - case cons11: - return t_ConfigVotingSetup.validate_skip(ops, cs, weak) - && m_ == 11; - case cons12: - return t_HashmapE_32_WorkchainDescr.validate_skip(ops, cs, weak) - && m_ == 12; - case cons13: - return t_ComplaintPricing.validate_skip(ops, cs, weak) - && m_ == 13; - case cons14: - return t_BlockCreateFees.validate_skip(ops, cs, weak) - && m_ == 14; - case cons15: - return cs.advance(128) - && m_ == 15; - case cons16: { - int max_validators, max_main_validators, min_validators; - return cs.fetch_uint_to(16, max_validators) - && cs.fetch_uint_to(16, max_main_validators) - && cs.fetch_uint_to(16, min_validators) - && max_main_validators <= max_validators - && min_validators <= max_main_validators - && 1 <= min_validators - && m_ == 16; - } - case cons17: - return t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(32) - && m_ == 17; - case cons18: - return t_Hashmap_32_StoragePrices.validate_skip(ops, cs, weak) - && m_ == 18; - case config_mc_gas_prices: - return t_GasLimitsPrices.validate_skip(ops, cs, weak) - && m_ == 20; - case config_gas_prices: - return t_GasLimitsPrices.validate_skip(ops, cs, weak) - && m_ == 21; - case config_mc_block_limits: - return t_BlockLimits.validate_skip(ops, cs, weak) - && m_ == 22; - case config_block_limits: - return t_BlockLimits.validate_skip(ops, cs, weak) - && m_ == 23; - case config_mc_fwd_prices: - return t_MsgForwardPrices.validate_skip(ops, cs, weak) - && m_ == 24; - case config_fwd_prices: - return t_MsgForwardPrices.validate_skip(ops, cs, weak) - && m_ == 25; - case cons28: - return t_CatchainConfig.validate_skip(ops, cs, weak) - && m_ == 28; - case cons29: - return t_ConsensusConfig.validate_skip(ops, cs, weak) - && m_ == 29; - case cons31: - return t_HashmapE_256_True.validate_skip(ops, cs, weak) - && m_ == 31; - case cons32: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 32; - case cons33: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 33; - case cons34: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 34; - case cons35: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 35; - case cons36: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 36; - case cons37: - return t_ValidatorSet.validate_skip(ops, cs, weak) - && m_ == 37; - case cons39: - return t_HashmapE_256_ValidatorSignedTempKey.validate_skip(ops, cs, weak) - && m_ == 39; - } - return false; -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons0& data) const { - return cs.fetch_bits_to(data.config_addr.bits(), 256) - && m_ == 0; -} - -bool ConfigParam::unpack_cons0(vm::CellSlice& cs, td::BitArray<256>& config_addr) const { - return cs.fetch_bits_to(config_addr.bits(), 256) - && m_ == 0; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons0& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons0(Ref cell_ref, td::BitArray<256>& config_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons0(cs, config_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons1& data) const { - return cs.fetch_bits_to(data.elector_addr.bits(), 256) - && m_ == 1; -} - -bool ConfigParam::unpack_cons1(vm::CellSlice& cs, td::BitArray<256>& elector_addr) const { - return cs.fetch_bits_to(elector_addr.bits(), 256) - && m_ == 1; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons1& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons1(Ref cell_ref, td::BitArray<256>& elector_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, elector_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons2& data) const { - return cs.fetch_bits_to(data.minter_addr.bits(), 256) - && m_ == 2; -} - -bool ConfigParam::unpack_cons2(vm::CellSlice& cs, td::BitArray<256>& minter_addr) const { - return cs.fetch_bits_to(minter_addr.bits(), 256) - && m_ == 2; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons2& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons2(Ref cell_ref, td::BitArray<256>& minter_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons2(cs, minter_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons3& data) const { - return cs.fetch_bits_to(data.fee_collector_addr.bits(), 256) - && m_ == 3; -} - -bool ConfigParam::unpack_cons3(vm::CellSlice& cs, td::BitArray<256>& fee_collector_addr) const { - return cs.fetch_bits_to(fee_collector_addr.bits(), 256) - && m_ == 3; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons3& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons3(Ref cell_ref, td::BitArray<256>& fee_collector_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons3(cs, fee_collector_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons4& data) const { - return cs.fetch_bits_to(data.dns_root_addr.bits(), 256) - && m_ == 4; -} - -bool ConfigParam::unpack_cons4(vm::CellSlice& cs, td::BitArray<256>& dns_root_addr) const { - return cs.fetch_bits_to(dns_root_addr.bits(), 256) - && m_ == 4; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons4& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons4(Ref cell_ref, td::BitArray<256>& dns_root_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons4(cs, dns_root_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons6& data) const { - return t_Grams.fetch_to(cs, data.mint_new_price) - && t_Grams.fetch_to(cs, data.mint_add_price) - && m_ == 6; -} - -bool ConfigParam::unpack_cons6(vm::CellSlice& cs, Ref& mint_new_price, Ref& mint_add_price) const { - return t_Grams.fetch_to(cs, mint_new_price) - && t_Grams.fetch_to(cs, mint_add_price) - && m_ == 6; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons6& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons6(Ref cell_ref, Ref& mint_new_price, Ref& mint_add_price) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons6(cs, mint_new_price, mint_add_price) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons7& data) const { - return t_ExtraCurrencyCollection.fetch_to(cs, data.to_mint) - && m_ == 7; -} - -bool ConfigParam::unpack_cons7(vm::CellSlice& cs, Ref& to_mint) const { - return t_ExtraCurrencyCollection.fetch_to(cs, to_mint) - && m_ == 7; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons7& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons7(Ref cell_ref, Ref& to_mint) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons7(cs, to_mint) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons8& data) const { - return cs.fetch_subslice_to(104, data.x) - && m_ == 8; -} - -bool ConfigParam::unpack_cons8(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(104, x) - && m_ == 8; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons8& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons8(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons8(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons9& data) const { - return t_Hashmap_32_True.fetch_to(cs, data.mandatory_params) - && m_ == 9; -} - -bool ConfigParam::unpack_cons9(vm::CellSlice& cs, Ref& mandatory_params) const { - return t_Hashmap_32_True.fetch_to(cs, mandatory_params) - && m_ == 9; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons9& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons9(Ref cell_ref, Ref& mandatory_params) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons9(cs, mandatory_params) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons10& data) const { - return t_Hashmap_32_True.fetch_to(cs, data.critical_params) - && m_ == 10; -} - -bool ConfigParam::unpack_cons10(vm::CellSlice& cs, Ref& critical_params) const { - return t_Hashmap_32_True.fetch_to(cs, critical_params) - && m_ == 10; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons10& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons10(Ref cell_ref, Ref& critical_params) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons10(cs, critical_params) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons11& data) const { - return cs.fetch_subslice_ext_to(0x20008, data.x) - && m_ == 11; -} - -bool ConfigParam::unpack_cons11(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_ext_to(0x20008, x) - && m_ == 11; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons11& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons11(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons11(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons12& data) const { - return t_HashmapE_32_WorkchainDescr.fetch_to(cs, data.workchains) - && m_ == 12; -} - -bool ConfigParam::unpack_cons12(vm::CellSlice& cs, Ref& workchains) const { - return t_HashmapE_32_WorkchainDescr.fetch_to(cs, workchains) - && m_ == 12; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons12& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons12(Ref cell_ref, Ref& workchains) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons12(cs, workchains) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons13& data) const { - return t_ComplaintPricing.fetch_to(cs, data.x) - && m_ == 13; -} - -bool ConfigParam::unpack_cons13(vm::CellSlice& cs, Ref& x) const { - return t_ComplaintPricing.fetch_to(cs, x) - && m_ == 13; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons13& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons13(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons13(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons14& data) const { - return t_BlockCreateFees.fetch_to(cs, data.x) - && m_ == 14; -} - -bool ConfigParam::unpack_cons14(vm::CellSlice& cs, Ref& x) const { - return t_BlockCreateFees.fetch_to(cs, x) - && m_ == 14; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons14& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons14(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons14(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons15& data) const { - return cs.fetch_uint_to(32, data.validators_elected_for) - && cs.fetch_uint_to(32, data.elections_start_before) - && cs.fetch_uint_to(32, data.elections_end_before) - && cs.fetch_uint_to(32, data.stake_held_for) - && m_ == 15; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons15& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons16& data) const { - return cs.fetch_uint_to(16, data.max_validators) - && cs.fetch_uint_to(16, data.max_main_validators) - && cs.fetch_uint_to(16, data.min_validators) - && data.max_main_validators <= data.max_validators - && data.min_validators <= data.max_main_validators - && 1 <= data.min_validators - && m_ == 16; -} - -bool ConfigParam::unpack_cons16(vm::CellSlice& cs, int& max_validators, int& max_main_validators, int& min_validators) const { - return cs.fetch_uint_to(16, max_validators) - && cs.fetch_uint_to(16, max_main_validators) - && cs.fetch_uint_to(16, min_validators) - && max_main_validators <= max_validators - && min_validators <= max_main_validators - && 1 <= min_validators - && m_ == 16; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons16& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons16(Ref cell_ref, int& max_validators, int& max_main_validators, int& min_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons16(cs, max_validators, max_main_validators, min_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons17& data) const { - return t_Grams.fetch_to(cs, data.min_stake) - && t_Grams.fetch_to(cs, data.max_stake) - && t_Grams.fetch_to(cs, data.min_total_stake) - && cs.fetch_uint_to(32, data.max_stake_factor) - && m_ == 17; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons17& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons18& data) const { - return t_Hashmap_32_StoragePrices.fetch_to(cs, data.x) - && m_ == 18; -} - -bool ConfigParam::unpack_cons18(vm::CellSlice& cs, Ref& x) const { - return t_Hashmap_32_StoragePrices.fetch_to(cs, x) - && m_ == 18; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons18& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons18(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons18(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_mc_gas_prices& data) const { - return t_GasLimitsPrices.fetch_to(cs, data.x) - && m_ == 20; -} - -bool ConfigParam::unpack_config_mc_gas_prices(vm::CellSlice& cs, Ref& x) const { - return t_GasLimitsPrices.fetch_to(cs, x) - && m_ == 20; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_mc_gas_prices& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_mc_gas_prices(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_mc_gas_prices(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_gas_prices& data) const { - return t_GasLimitsPrices.fetch_to(cs, data.x) - && m_ == 21; -} - -bool ConfigParam::unpack_config_gas_prices(vm::CellSlice& cs, Ref& x) const { - return t_GasLimitsPrices.fetch_to(cs, x) - && m_ == 21; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_gas_prices& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_gas_prices(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_gas_prices(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_mc_block_limits& data) const { - return cs.fetch_subslice_to(320, data.x) - && m_ == 22; -} - -bool ConfigParam::unpack_config_mc_block_limits(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(320, x) - && m_ == 22; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_mc_block_limits& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_mc_block_limits(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_mc_block_limits(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_block_limits& data) const { - return cs.fetch_subslice_to(320, data.x) - && m_ == 23; -} - -bool ConfigParam::unpack_config_block_limits(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(320, x) - && m_ == 23; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_block_limits& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_block_limits(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_block_limits(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_mc_fwd_prices& data) const { - return cs.fetch_subslice_to(264, data.x) - && m_ == 24; -} - -bool ConfigParam::unpack_config_mc_fwd_prices(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(264, x) - && m_ == 24; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_mc_fwd_prices& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_mc_fwd_prices(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_mc_fwd_prices(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_config_fwd_prices& data) const { - return cs.fetch_subslice_to(264, data.x) - && m_ == 25; -} - -bool ConfigParam::unpack_config_fwd_prices(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_subslice_to(264, x) - && m_ == 25; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_config_fwd_prices& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_config_fwd_prices(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_config_fwd_prices(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons28& data) const { - return t_CatchainConfig.fetch_to(cs, data.x) - && m_ == 28; -} - -bool ConfigParam::unpack_cons28(vm::CellSlice& cs, Ref& x) const { - return t_CatchainConfig.fetch_to(cs, x) - && m_ == 28; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons28& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons28(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons28(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons29& data) const { - return t_ConsensusConfig.fetch_to(cs, data.x) - && m_ == 29; -} - -bool ConfigParam::unpack_cons29(vm::CellSlice& cs, Ref& x) const { - return t_ConsensusConfig.fetch_to(cs, x) - && m_ == 29; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons29& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons29(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons29(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons31& data) const { - return t_HashmapE_256_True.fetch_to(cs, data.fundamental_smc_addr) - && m_ == 31; -} - -bool ConfigParam::unpack_cons31(vm::CellSlice& cs, Ref& fundamental_smc_addr) const { - return t_HashmapE_256_True.fetch_to(cs, fundamental_smc_addr) - && m_ == 31; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons31& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons31(Ref cell_ref, Ref& fundamental_smc_addr) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons31(cs, fundamental_smc_addr) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons32& data) const { - return t_ValidatorSet.fetch_to(cs, data.prev_validators) - && m_ == 32; -} - -bool ConfigParam::unpack_cons32(vm::CellSlice& cs, Ref& prev_validators) const { - return t_ValidatorSet.fetch_to(cs, prev_validators) - && m_ == 32; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons32& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons32(Ref cell_ref, Ref& prev_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons32(cs, prev_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons33& data) const { - return t_ValidatorSet.fetch_to(cs, data.prev_temp_validators) - && m_ == 33; -} - -bool ConfigParam::unpack_cons33(vm::CellSlice& cs, Ref& prev_temp_validators) const { - return t_ValidatorSet.fetch_to(cs, prev_temp_validators) - && m_ == 33; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons33& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons33(Ref cell_ref, Ref& prev_temp_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons33(cs, prev_temp_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons34& data) const { - return t_ValidatorSet.fetch_to(cs, data.cur_validators) - && m_ == 34; -} - -bool ConfigParam::unpack_cons34(vm::CellSlice& cs, Ref& cur_validators) const { - return t_ValidatorSet.fetch_to(cs, cur_validators) - && m_ == 34; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons34& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons34(Ref cell_ref, Ref& cur_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons34(cs, cur_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons35& data) const { - return t_ValidatorSet.fetch_to(cs, data.cur_temp_validators) - && m_ == 35; -} - -bool ConfigParam::unpack_cons35(vm::CellSlice& cs, Ref& cur_temp_validators) const { - return t_ValidatorSet.fetch_to(cs, cur_temp_validators) - && m_ == 35; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons35& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons35(Ref cell_ref, Ref& cur_temp_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons35(cs, cur_temp_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons36& data) const { - return t_ValidatorSet.fetch_to(cs, data.next_validators) - && m_ == 36; -} - -bool ConfigParam::unpack_cons36(vm::CellSlice& cs, Ref& next_validators) const { - return t_ValidatorSet.fetch_to(cs, next_validators) - && m_ == 36; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons36& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons36(Ref cell_ref, Ref& next_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons36(cs, next_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons37& data) const { - return t_ValidatorSet.fetch_to(cs, data.next_temp_validators) - && m_ == 37; -} - -bool ConfigParam::unpack_cons37(vm::CellSlice& cs, Ref& next_temp_validators) const { - return t_ValidatorSet.fetch_to(cs, next_temp_validators) - && m_ == 37; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons37& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons37(Ref cell_ref, Ref& next_temp_validators) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons37(cs, next_temp_validators) && cs.empty_ext(); -} - -bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons39& data) const { - return t_HashmapE_256_ValidatorSignedTempKey.fetch_to(cs, data.x) - && m_ == 39; -} - -bool ConfigParam::unpack_cons39(vm::CellSlice& cs, Ref& x) const { - return t_HashmapE_256_ValidatorSignedTempKey.fetch_to(cs, x) - && m_ == 39; -} - -bool ConfigParam::cell_unpack(Ref cell_ref, ConfigParam::Record_cons39& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ConfigParam::cell_unpack_cons39(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons39(cs, x) && cs.empty_ext(); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons0& data) const { - return cb.store_bits_bool(data.config_addr.cbits(), 256) - && m_ == 0; -} - -bool ConfigParam::pack_cons0(vm::CellBuilder& cb, td::BitArray<256> config_addr) const { - return cb.store_bits_bool(config_addr.cbits(), 256) - && m_ == 0; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons0& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons0(Ref& cell_ref, td::BitArray<256> config_addr) const { - vm::CellBuilder cb; - return pack_cons0(cb, config_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons1& data) const { - return cb.store_bits_bool(data.elector_addr.cbits(), 256) - && m_ == 1; -} - -bool ConfigParam::pack_cons1(vm::CellBuilder& cb, td::BitArray<256> elector_addr) const { - return cb.store_bits_bool(elector_addr.cbits(), 256) - && m_ == 1; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons1& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons1(Ref& cell_ref, td::BitArray<256> elector_addr) const { - vm::CellBuilder cb; - return pack_cons1(cb, elector_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons2& data) const { - return cb.store_bits_bool(data.minter_addr.cbits(), 256) - && m_ == 2; -} - -bool ConfigParam::pack_cons2(vm::CellBuilder& cb, td::BitArray<256> minter_addr) const { - return cb.store_bits_bool(minter_addr.cbits(), 256) - && m_ == 2; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons2& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons2(Ref& cell_ref, td::BitArray<256> minter_addr) const { - vm::CellBuilder cb; - return pack_cons2(cb, minter_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons3& data) const { - return cb.store_bits_bool(data.fee_collector_addr.cbits(), 256) - && m_ == 3; -} - -bool ConfigParam::pack_cons3(vm::CellBuilder& cb, td::BitArray<256> fee_collector_addr) const { - return cb.store_bits_bool(fee_collector_addr.cbits(), 256) - && m_ == 3; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons3& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons3(Ref& cell_ref, td::BitArray<256> fee_collector_addr) const { - vm::CellBuilder cb; - return pack_cons3(cb, fee_collector_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons4& data) const { - return cb.store_bits_bool(data.dns_root_addr.cbits(), 256) - && m_ == 4; -} - -bool ConfigParam::pack_cons4(vm::CellBuilder& cb, td::BitArray<256> dns_root_addr) const { - return cb.store_bits_bool(dns_root_addr.cbits(), 256) - && m_ == 4; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons4& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons4(Ref& cell_ref, td::BitArray<256> dns_root_addr) const { - vm::CellBuilder cb; - return pack_cons4(cb, dns_root_addr) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons6& data) const { - return t_Grams.store_from(cb, data.mint_new_price) - && t_Grams.store_from(cb, data.mint_add_price) - && m_ == 6; -} - -bool ConfigParam::pack_cons6(vm::CellBuilder& cb, Ref mint_new_price, Ref mint_add_price) const { - return t_Grams.store_from(cb, mint_new_price) - && t_Grams.store_from(cb, mint_add_price) - && m_ == 6; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons6& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons6(Ref& cell_ref, Ref mint_new_price, Ref mint_add_price) const { - vm::CellBuilder cb; - return pack_cons6(cb, std::move(mint_new_price), std::move(mint_add_price)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons7& data) const { - return t_ExtraCurrencyCollection.store_from(cb, data.to_mint) - && m_ == 7; -} - -bool ConfigParam::pack_cons7(vm::CellBuilder& cb, Ref to_mint) const { - return t_ExtraCurrencyCollection.store_from(cb, to_mint) - && m_ == 7; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons7& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons7(Ref& cell_ref, Ref to_mint) const { - vm::CellBuilder cb; - return pack_cons7(cb, std::move(to_mint)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons8& data) const { - return cb.append_cellslice_chk(data.x, 104) - && m_ == 8; -} - -bool ConfigParam::pack_cons8(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 104) - && m_ == 8; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons8& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons8(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons8(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons9& data) const { - return t_Hashmap_32_True.store_from(cb, data.mandatory_params) - && m_ == 9; -} - -bool ConfigParam::pack_cons9(vm::CellBuilder& cb, Ref mandatory_params) const { - return t_Hashmap_32_True.store_from(cb, mandatory_params) - && m_ == 9; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons9& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons9(Ref& cell_ref, Ref mandatory_params) const { - vm::CellBuilder cb; - return pack_cons9(cb, std::move(mandatory_params)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons10& data) const { - return t_Hashmap_32_True.store_from(cb, data.critical_params) - && m_ == 10; -} - -bool ConfigParam::pack_cons10(vm::CellBuilder& cb, Ref critical_params) const { - return t_Hashmap_32_True.store_from(cb, critical_params) - && m_ == 10; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons10& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons10(Ref& cell_ref, Ref critical_params) const { - vm::CellBuilder cb; - return pack_cons10(cb, std::move(critical_params)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons11& data) const { - return cb.append_cellslice_chk(data.x, 0x20008) - && m_ == 11; -} - -bool ConfigParam::pack_cons11(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 0x20008) - && m_ == 11; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons11& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons11(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons11(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons12& data) const { - return t_HashmapE_32_WorkchainDescr.store_from(cb, data.workchains) - && m_ == 12; -} - -bool ConfigParam::pack_cons12(vm::CellBuilder& cb, Ref workchains) const { - return t_HashmapE_32_WorkchainDescr.store_from(cb, workchains) - && m_ == 12; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons12& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons12(Ref& cell_ref, Ref workchains) const { - vm::CellBuilder cb; - return pack_cons12(cb, std::move(workchains)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons13& data) const { - return t_ComplaintPricing.store_from(cb, data.x) - && m_ == 13; -} - -bool ConfigParam::pack_cons13(vm::CellBuilder& cb, Ref x) const { - return t_ComplaintPricing.store_from(cb, x) - && m_ == 13; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons13& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons13(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons13(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons14& data) const { - return t_BlockCreateFees.store_from(cb, data.x) - && m_ == 14; -} - -bool ConfigParam::pack_cons14(vm::CellBuilder& cb, Ref x) const { - return t_BlockCreateFees.store_from(cb, x) - && m_ == 14; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons14& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons14(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons14(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons15& data) const { - return cb.store_ulong_rchk_bool(data.validators_elected_for, 32) - && cb.store_ulong_rchk_bool(data.elections_start_before, 32) - && cb.store_ulong_rchk_bool(data.elections_end_before, 32) - && cb.store_ulong_rchk_bool(data.stake_held_for, 32) - && m_ == 15; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons15& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons16& data) const { - return cb.store_ulong_rchk_bool(data.max_validators, 16) - && cb.store_ulong_rchk_bool(data.max_main_validators, 16) - && cb.store_ulong_rchk_bool(data.min_validators, 16) - && data.max_main_validators <= data.max_validators - && data.min_validators <= data.max_main_validators - && 1 <= data.min_validators - && m_ == 16; -} - -bool ConfigParam::pack_cons16(vm::CellBuilder& cb, int max_validators, int max_main_validators, int min_validators) const { - return cb.store_ulong_rchk_bool(max_validators, 16) - && cb.store_ulong_rchk_bool(max_main_validators, 16) - && cb.store_ulong_rchk_bool(min_validators, 16) - && max_main_validators <= max_validators - && min_validators <= max_main_validators - && 1 <= min_validators - && m_ == 16; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons16& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons16(Ref& cell_ref, int max_validators, int max_main_validators, int min_validators) const { - vm::CellBuilder cb; - return pack_cons16(cb, max_validators, max_main_validators, min_validators) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons17& data) const { - return t_Grams.store_from(cb, data.min_stake) - && t_Grams.store_from(cb, data.max_stake) - && t_Grams.store_from(cb, data.min_total_stake) - && cb.store_ulong_rchk_bool(data.max_stake_factor, 32) - && m_ == 17; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons17& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons18& data) const { - return t_Hashmap_32_StoragePrices.store_from(cb, data.x) - && m_ == 18; -} - -bool ConfigParam::pack_cons18(vm::CellBuilder& cb, Ref x) const { - return t_Hashmap_32_StoragePrices.store_from(cb, x) - && m_ == 18; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons18& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons18(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons18(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_mc_gas_prices& data) const { - return t_GasLimitsPrices.store_from(cb, data.x) - && m_ == 20; -} - -bool ConfigParam::pack_config_mc_gas_prices(vm::CellBuilder& cb, Ref x) const { - return t_GasLimitsPrices.store_from(cb, x) - && m_ == 20; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_mc_gas_prices& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_mc_gas_prices(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_mc_gas_prices(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_gas_prices& data) const { - return t_GasLimitsPrices.store_from(cb, data.x) - && m_ == 21; -} - -bool ConfigParam::pack_config_gas_prices(vm::CellBuilder& cb, Ref x) const { - return t_GasLimitsPrices.store_from(cb, x) - && m_ == 21; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_gas_prices& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_gas_prices(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_gas_prices(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_mc_block_limits& data) const { - return cb.append_cellslice_chk(data.x, 320) - && m_ == 22; -} - -bool ConfigParam::pack_config_mc_block_limits(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 320) - && m_ == 22; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_mc_block_limits& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_mc_block_limits(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_mc_block_limits(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_block_limits& data) const { - return cb.append_cellslice_chk(data.x, 320) - && m_ == 23; -} - -bool ConfigParam::pack_config_block_limits(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 320) - && m_ == 23; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_block_limits& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_block_limits(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_block_limits(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_mc_fwd_prices& data) const { - return cb.append_cellslice_chk(data.x, 264) - && m_ == 24; -} - -bool ConfigParam::pack_config_mc_fwd_prices(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 264) - && m_ == 24; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_mc_fwd_prices& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_mc_fwd_prices(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_mc_fwd_prices(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_config_fwd_prices& data) const { - return cb.append_cellslice_chk(data.x, 264) - && m_ == 25; -} - -bool ConfigParam::pack_config_fwd_prices(vm::CellBuilder& cb, Ref x) const { - return cb.append_cellslice_chk(x, 264) - && m_ == 25; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_config_fwd_prices& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_config_fwd_prices(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_config_fwd_prices(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons28& data) const { - return t_CatchainConfig.store_from(cb, data.x) - && m_ == 28; -} - -bool ConfigParam::pack_cons28(vm::CellBuilder& cb, Ref x) const { - return t_CatchainConfig.store_from(cb, x) - && m_ == 28; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons28& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons28(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons28(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons29& data) const { - return t_ConsensusConfig.store_from(cb, data.x) - && m_ == 29; -} - -bool ConfigParam::pack_cons29(vm::CellBuilder& cb, Ref x) const { - return t_ConsensusConfig.store_from(cb, x) - && m_ == 29; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons29& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons29(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons29(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons31& data) const { - return t_HashmapE_256_True.store_from(cb, data.fundamental_smc_addr) - && m_ == 31; -} - -bool ConfigParam::pack_cons31(vm::CellBuilder& cb, Ref fundamental_smc_addr) const { - return t_HashmapE_256_True.store_from(cb, fundamental_smc_addr) - && m_ == 31; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons31& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons31(Ref& cell_ref, Ref fundamental_smc_addr) const { - vm::CellBuilder cb; - return pack_cons31(cb, std::move(fundamental_smc_addr)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons32& data) const { - return t_ValidatorSet.store_from(cb, data.prev_validators) - && m_ == 32; -} - -bool ConfigParam::pack_cons32(vm::CellBuilder& cb, Ref prev_validators) const { - return t_ValidatorSet.store_from(cb, prev_validators) - && m_ == 32; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons32& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons32(Ref& cell_ref, Ref prev_validators) const { - vm::CellBuilder cb; - return pack_cons32(cb, std::move(prev_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons33& data) const { - return t_ValidatorSet.store_from(cb, data.prev_temp_validators) - && m_ == 33; -} - -bool ConfigParam::pack_cons33(vm::CellBuilder& cb, Ref prev_temp_validators) const { - return t_ValidatorSet.store_from(cb, prev_temp_validators) - && m_ == 33; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons33& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons33(Ref& cell_ref, Ref prev_temp_validators) const { - vm::CellBuilder cb; - return pack_cons33(cb, std::move(prev_temp_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons34& data) const { - return t_ValidatorSet.store_from(cb, data.cur_validators) - && m_ == 34; -} - -bool ConfigParam::pack_cons34(vm::CellBuilder& cb, Ref cur_validators) const { - return t_ValidatorSet.store_from(cb, cur_validators) - && m_ == 34; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons34& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons34(Ref& cell_ref, Ref cur_validators) const { - vm::CellBuilder cb; - return pack_cons34(cb, std::move(cur_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons35& data) const { - return t_ValidatorSet.store_from(cb, data.cur_temp_validators) - && m_ == 35; -} - -bool ConfigParam::pack_cons35(vm::CellBuilder& cb, Ref cur_temp_validators) const { - return t_ValidatorSet.store_from(cb, cur_temp_validators) - && m_ == 35; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons35& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons35(Ref& cell_ref, Ref cur_temp_validators) const { - vm::CellBuilder cb; - return pack_cons35(cb, std::move(cur_temp_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons36& data) const { - return t_ValidatorSet.store_from(cb, data.next_validators) - && m_ == 36; -} - -bool ConfigParam::pack_cons36(vm::CellBuilder& cb, Ref next_validators) const { - return t_ValidatorSet.store_from(cb, next_validators) - && m_ == 36; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons36& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons36(Ref& cell_ref, Ref next_validators) const { - vm::CellBuilder cb; - return pack_cons36(cb, std::move(next_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons37& data) const { - return t_ValidatorSet.store_from(cb, data.next_temp_validators) - && m_ == 37; -} - -bool ConfigParam::pack_cons37(vm::CellBuilder& cb, Ref next_temp_validators) const { - return t_ValidatorSet.store_from(cb, next_temp_validators) - && m_ == 37; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons37& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons37(Ref& cell_ref, Ref next_temp_validators) const { - vm::CellBuilder cb; - return pack_cons37(cb, std::move(next_temp_validators)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons39& data) const { - return t_HashmapE_256_ValidatorSignedTempKey.store_from(cb, data.x) - && m_ == 39; -} - -bool ConfigParam::pack_cons39(vm::CellBuilder& cb, Ref x) const { - return t_HashmapE_256_ValidatorSignedTempKey.store_from(cb, x) - && m_ == 39; -} - -bool ConfigParam::cell_pack(Ref& cell_ref, const ConfigParam::Record_cons39& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::cell_pack_cons39(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons39(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool ConfigParam::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cons0: - return pp.open() - && pp.fetch_bits_field(cs, 256, "config_addr") - && m_ == 0 - && pp.close(); - case cons1: - return pp.open() - && pp.fetch_bits_field(cs, 256, "elector_addr") - && m_ == 1 - && pp.close(); - case cons2: - return pp.open() - && pp.fetch_bits_field(cs, 256, "minter_addr") - && m_ == 2 - && pp.close(); - case cons3: - return pp.open() - && pp.fetch_bits_field(cs, 256, "fee_collector_addr") - && m_ == 3 - && pp.close(); - case cons4: - return pp.open() - && pp.fetch_bits_field(cs, 256, "dns_root_addr") - && m_ == 4 - && pp.close(); - case cons6: - return pp.open() - && pp.field("mint_new_price") - && t_Grams.print_skip(pp, cs) - && pp.field("mint_add_price") - && t_Grams.print_skip(pp, cs) - && m_ == 6 - && pp.close(); - case cons7: - return pp.open() - && pp.field("to_mint") - && t_ExtraCurrencyCollection.print_skip(pp, cs) - && m_ == 7 - && pp.close(); - case cons8: - return pp.open() - && pp.field() - && t_GlobalVersion.print_skip(pp, cs) - && m_ == 8 - && pp.close(); - case cons9: - return pp.open() - && pp.field("mandatory_params") - && t_Hashmap_32_True.print_skip(pp, cs) - && m_ == 9 - && pp.close(); - case cons10: - return pp.open() - && pp.field("critical_params") - && t_Hashmap_32_True.print_skip(pp, cs) - && m_ == 10 - && pp.close(); - case cons11: - return pp.open() - && pp.field() - && t_ConfigVotingSetup.print_skip(pp, cs) - && m_ == 11 - && pp.close(); - case cons12: - return pp.open() - && pp.field("workchains") - && t_HashmapE_32_WorkchainDescr.print_skip(pp, cs) - && m_ == 12 - && pp.close(); - case cons13: - return pp.open() - && pp.field() - && t_ComplaintPricing.print_skip(pp, cs) - && m_ == 13 - && pp.close(); - case cons14: - return pp.open() - && pp.field() - && t_BlockCreateFees.print_skip(pp, cs) - && m_ == 14 - && pp.close(); - case cons15: - return pp.open() - && pp.fetch_uint_field(cs, 32, "validators_elected_for") - && pp.fetch_uint_field(cs, 32, "elections_start_before") - && pp.fetch_uint_field(cs, 32, "elections_end_before") - && pp.fetch_uint_field(cs, 32, "stake_held_for") - && m_ == 15 - && pp.close(); - case cons16: { - int max_validators, max_main_validators, min_validators; - return pp.open() - && cs.fetch_uint_to(16, max_validators) - && pp.field_int(max_validators, "max_validators") - && cs.fetch_uint_to(16, max_main_validators) - && pp.field_int(max_main_validators, "max_main_validators") - && cs.fetch_uint_to(16, min_validators) - && pp.field_int(min_validators, "min_validators") - && max_main_validators <= max_validators - && min_validators <= max_main_validators - && 1 <= min_validators - && m_ == 16 - && pp.close(); - } - case cons17: - return pp.open() - && pp.field("min_stake") - && t_Grams.print_skip(pp, cs) - && pp.field("max_stake") - && t_Grams.print_skip(pp, cs) - && pp.field("min_total_stake") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "max_stake_factor") - && m_ == 17 - && pp.close(); - case cons18: - return pp.open() - && pp.field() - && t_Hashmap_32_StoragePrices.print_skip(pp, cs) - && m_ == 18 - && pp.close(); - case config_mc_gas_prices: - return pp.open("config_mc_gas_prices") - && pp.field() - && t_GasLimitsPrices.print_skip(pp, cs) - && m_ == 20 - && pp.close(); - case config_gas_prices: - return pp.open("config_gas_prices") - && pp.field() - && t_GasLimitsPrices.print_skip(pp, cs) - && m_ == 21 - && pp.close(); - case config_mc_block_limits: - return pp.open("config_mc_block_limits") - && pp.field() - && t_BlockLimits.print_skip(pp, cs) - && m_ == 22 - && pp.close(); - case config_block_limits: - return pp.open("config_block_limits") - && pp.field() - && t_BlockLimits.print_skip(pp, cs) - && m_ == 23 - && pp.close(); - case config_mc_fwd_prices: - return pp.open("config_mc_fwd_prices") - && pp.field() - && t_MsgForwardPrices.print_skip(pp, cs) - && m_ == 24 - && pp.close(); - case config_fwd_prices: - return pp.open("config_fwd_prices") - && pp.field() - && t_MsgForwardPrices.print_skip(pp, cs) - && m_ == 25 - && pp.close(); - case cons28: - return pp.open() - && pp.field() - && t_CatchainConfig.print_skip(pp, cs) - && m_ == 28 - && pp.close(); - case cons29: - return pp.open() - && pp.field() - && t_ConsensusConfig.print_skip(pp, cs) - && m_ == 29 - && pp.close(); - case cons31: - return pp.open() - && pp.field("fundamental_smc_addr") - && t_HashmapE_256_True.print_skip(pp, cs) - && m_ == 31 - && pp.close(); - case cons32: - return pp.open() - && pp.field("prev_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 32 - && pp.close(); - case cons33: - return pp.open() - && pp.field("prev_temp_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 33 - && pp.close(); - case cons34: - return pp.open() - && pp.field("cur_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 34 - && pp.close(); - case cons35: - return pp.open() - && pp.field("cur_temp_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 35 - && pp.close(); - case cons36: - return pp.open() - && pp.field("next_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 36 - && pp.close(); - case cons37: - return pp.open() - && pp.field("next_temp_validators") - && t_ValidatorSet.print_skip(pp, cs) - && m_ == 37 - && pp.close(); - case cons39: - return pp.open() - && pp.field() - && t_HashmapE_256_ValidatorSignedTempKey.print_skip(pp, cs) - && m_ == 39 - && pp.close(); - } - return pp.fail("unknown constructor for ConfigParam"); -} - - -// -// code for type `BlockSignaturesPure` -// - -int BlockSignaturesPure::check_tag(const vm::CellSlice& cs) const { - return block_signatures_pure; -} - -bool BlockSignaturesPure::skip(vm::CellSlice& cs) const { - return cs.advance(96) - && t_HashmapE_16_CryptoSignaturePair.skip(cs); -} - -bool BlockSignaturesPure::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(96) - && t_HashmapE_16_CryptoSignaturePair.validate_skip(ops, cs, weak); -} - -bool BlockSignaturesPure::unpack(vm::CellSlice& cs, BlockSignaturesPure::Record& data) const { - return cs.fetch_uint_to(32, data.sig_count) - && cs.fetch_uint_to(64, data.sig_weight) - && t_HashmapE_16_CryptoSignaturePair.fetch_to(cs, data.signatures); -} - -bool BlockSignaturesPure::unpack_block_signatures_pure(vm::CellSlice& cs, unsigned& sig_count, unsigned long long& sig_weight, Ref& signatures) const { - return cs.fetch_uint_to(32, sig_count) - && cs.fetch_uint_to(64, sig_weight) - && t_HashmapE_16_CryptoSignaturePair.fetch_to(cs, signatures); -} - -bool BlockSignaturesPure::cell_unpack(Ref cell_ref, BlockSignaturesPure::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockSignaturesPure::cell_unpack_block_signatures_pure(Ref cell_ref, unsigned& sig_count, unsigned long long& sig_weight, Ref& signatures) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_signatures_pure(cs, sig_count, sig_weight, signatures) && cs.empty_ext(); -} - -bool BlockSignaturesPure::pack(vm::CellBuilder& cb, const BlockSignaturesPure::Record& data) const { - return cb.store_ulong_rchk_bool(data.sig_count, 32) - && cb.store_ulong_rchk_bool(data.sig_weight, 64) - && t_HashmapE_16_CryptoSignaturePair.store_from(cb, data.signatures); -} - -bool BlockSignaturesPure::pack_block_signatures_pure(vm::CellBuilder& cb, unsigned sig_count, unsigned long long sig_weight, Ref signatures) const { - return cb.store_ulong_rchk_bool(sig_count, 32) - && cb.store_ulong_rchk_bool(sig_weight, 64) - && t_HashmapE_16_CryptoSignaturePair.store_from(cb, signatures); -} - -bool BlockSignaturesPure::cell_pack(Ref& cell_ref, const BlockSignaturesPure::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockSignaturesPure::cell_pack_block_signatures_pure(Ref& cell_ref, unsigned sig_count, unsigned long long sig_weight, Ref signatures) const { - vm::CellBuilder cb; - return pack_block_signatures_pure(cb, sig_count, sig_weight, std::move(signatures)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockSignaturesPure::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("block_signatures_pure") - && pp.fetch_uint_field(cs, 32, "sig_count") - && pp.fetch_uint_field(cs, 64, "sig_weight") - && pp.field("signatures") - && t_HashmapE_16_CryptoSignaturePair.print_skip(pp, cs) - && pp.close(); -} - -const BlockSignaturesPure t_BlockSignaturesPure; - -// -// code for type `BlockSignatures` -// -constexpr unsigned char BlockSignatures::cons_tag[1]; - -int BlockSignatures::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 17 ? block_signatures : -1; -} - -bool BlockSignatures::skip(vm::CellSlice& cs) const { - return cs.advance(72) - && t_BlockSignaturesPure.skip(cs); -} - -bool BlockSignatures::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 17 - && cs.advance(64) - && t_BlockSignaturesPure.validate_skip(ops, cs, weak); -} - -bool BlockSignatures::unpack(vm::CellSlice& cs, BlockSignatures::Record& data) const { - return cs.fetch_ulong(8) == 17 - && cs.fetch_subslice_to(64, data.validator_info) - && t_BlockSignaturesPure.fetch_to(cs, data.pure_signatures); -} - -bool BlockSignatures::unpack_block_signatures(vm::CellSlice& cs, Ref& validator_info, Ref& pure_signatures) const { - return cs.fetch_ulong(8) == 17 - && cs.fetch_subslice_to(64, validator_info) - && t_BlockSignaturesPure.fetch_to(cs, pure_signatures); -} - -bool BlockSignatures::cell_unpack(Ref cell_ref, BlockSignatures::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockSignatures::cell_unpack_block_signatures(Ref cell_ref, Ref& validator_info, Ref& pure_signatures) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_signatures(cs, validator_info, pure_signatures) && cs.empty_ext(); -} - -bool BlockSignatures::pack(vm::CellBuilder& cb, const BlockSignatures::Record& data) const { - return cb.store_long_bool(17, 8) - && cb.append_cellslice_chk(data.validator_info, 64) - && t_BlockSignaturesPure.store_from(cb, data.pure_signatures); -} - -bool BlockSignatures::pack_block_signatures(vm::CellBuilder& cb, Ref validator_info, Ref pure_signatures) const { - return cb.store_long_bool(17, 8) - && cb.append_cellslice_chk(validator_info, 64) - && t_BlockSignaturesPure.store_from(cb, pure_signatures); -} - -bool BlockSignatures::cell_pack(Ref& cell_ref, const BlockSignatures::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockSignatures::cell_pack_block_signatures(Ref& cell_ref, Ref validator_info, Ref pure_signatures) const { - vm::CellBuilder cb; - return pack_block_signatures(cb, std::move(validator_info), std::move(pure_signatures)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockSignatures::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 17 - && pp.open("block_signatures") - && pp.field("validator_info") - && t_ValidatorBaseInfo.print_skip(pp, cs) - && pp.field("pure_signatures") - && t_BlockSignaturesPure.print_skip(pp, cs) - && pp.close(); -} - -const BlockSignatures t_BlockSignatures; - -// -// code for type `BlockProof` -// -constexpr unsigned char BlockProof::cons_tag[1]; - -int BlockProof::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xc3 ? block_proof : -1; -} - -bool BlockProof::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10290) - && t_Maybe_Ref_BlockSignatures.skip(cs); -} - -bool BlockProof::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xc3 - && t_BlockIdExt.validate_skip(ops, cs, weak) - && cs.advance_refs(1) - && t_Maybe_Ref_BlockSignatures.validate_skip(ops, cs, weak); -} - -bool BlockProof::unpack(vm::CellSlice& cs, BlockProof::Record& data) const { - return cs.fetch_ulong(8) == 0xc3 - && cs.fetch_subslice_to(648, data.proof_for) - && cs.fetch_ref_to(data.root) - && t_Maybe_Ref_BlockSignatures.fetch_to(cs, data.signatures); -} - -bool BlockProof::unpack_block_proof(vm::CellSlice& cs, Ref& proof_for, Ref& root, Ref& signatures) const { - return cs.fetch_ulong(8) == 0xc3 - && cs.fetch_subslice_to(648, proof_for) - && cs.fetch_ref_to(root) - && t_Maybe_Ref_BlockSignatures.fetch_to(cs, signatures); -} - -bool BlockProof::cell_unpack(Ref cell_ref, BlockProof::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool BlockProof::cell_unpack_block_proof(Ref cell_ref, Ref& proof_for, Ref& root, Ref& signatures) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_block_proof(cs, proof_for, root, signatures) && cs.empty_ext(); -} - -bool BlockProof::pack(vm::CellBuilder& cb, const BlockProof::Record& data) const { - return cb.store_long_bool(0xc3, 8) - && cb.append_cellslice_chk(data.proof_for, 648) - && cb.store_ref_bool(data.root) - && t_Maybe_Ref_BlockSignatures.store_from(cb, data.signatures); -} - -bool BlockProof::pack_block_proof(vm::CellBuilder& cb, Ref proof_for, Ref root, Ref signatures) const { - return cb.store_long_bool(0xc3, 8) - && cb.append_cellslice_chk(proof_for, 648) - && cb.store_ref_bool(root) - && t_Maybe_Ref_BlockSignatures.store_from(cb, signatures); -} - -bool BlockProof::cell_pack(Ref& cell_ref, const BlockProof::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockProof::cell_pack_block_proof(Ref& cell_ref, Ref proof_for, Ref root, Ref signatures) const { - vm::CellBuilder cb; - return pack_block_proof(cb, std::move(proof_for), std::move(root), std::move(signatures)) && std::move(cb).finalize_to(cell_ref); -} - -bool BlockProof::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xc3 - && pp.open("block_proof") - && pp.field("proof_for") - && t_BlockIdExt.print_skip(pp, cs) - && pp.field("root") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.field("signatures") - && t_Maybe_Ref_BlockSignatures.print_skip(pp, cs) - && pp.close(); -} - -const BlockProof t_BlockProof; - -// -// code for type `ProofChain` -// - -int ProofChain::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 2 2 - return m_ ? chain_link : chain_empty; -} - -int ProofChain::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chain_empty: - return chain_empty; - case chain_link: - return chain_link; - } - return -1; -} - -bool ProofChain::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chain_empty: - return m_ == 0; - case chain_link: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(1) - && (!n || cs.advance_refs(1)); - } - } - return false; -} - -bool ProofChain::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case chain_empty: - return m_ == 0; - case chain_link: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(1) - && (!n || ProofChain{n}.validate_skip_ref(ops, cs, weak)); - } - } - return false; -} - -bool ProofChain::unpack(vm::CellSlice& cs, ProofChain::Record_chain_empty& data) const { - return m_ == 0; -} - -bool ProofChain::unpack_chain_empty(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool ProofChain::cell_unpack(Ref cell_ref, ProofChain::Record_chain_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProofChain::cell_unpack_chain_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chain_empty(cs) && cs.empty_ext(); -} - -bool ProofChain::unpack(vm::CellSlice& cs, ProofChain::Record_chain_link& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.root) - && (!data.n || cs.fetch_ref_to(data.prev)); -} - -bool ProofChain::unpack_chain_link(vm::CellSlice& cs, int& n, Ref& root, Ref& prev) const { - return add_r1(n, 1, m_) - && cs.fetch_ref_to(root) - && (!n || cs.fetch_ref_to(prev)); -} - -bool ProofChain::cell_unpack(Ref cell_ref, ProofChain::Record_chain_link& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProofChain::cell_unpack_chain_link(Ref cell_ref, int& n, Ref& root, Ref& prev) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chain_link(cs, n, root, prev) && cs.empty_ext(); -} - -bool ProofChain::pack(vm::CellBuilder& cb, const ProofChain::Record_chain_empty& data) const { - return m_ == 0; -} - -bool ProofChain::pack_chain_empty(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool ProofChain::cell_pack(Ref& cell_ref, const ProofChain::Record_chain_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProofChain::cell_pack_chain_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_chain_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ProofChain::pack(vm::CellBuilder& cb, const ProofChain::Record_chain_link& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.root) - && (!n || cb.store_ref_bool(data.prev)); -} - -bool ProofChain::pack_chain_link(vm::CellBuilder& cb, Ref root, Ref prev) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(root) - && (!n || cb.store_ref_bool(prev)); -} - -bool ProofChain::cell_pack(Ref& cell_ref, const ProofChain::Record_chain_link& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProofChain::cell_pack_chain_link(Ref& cell_ref, Ref root, Ref prev) const { - vm::CellBuilder cb; - return pack_chain_link(cb, std::move(root), std::move(prev)) && std::move(cb).finalize_to(cell_ref); -} - -bool ProofChain::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chain_empty: - return pp.cons("chain_empty") - && m_ == 0; - case chain_link: { - int n; - return pp.open("chain_link") - && add_r1(n, 1, m_) - && pp.field("root") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && (!n || (pp.field("prev") && ProofChain{n}.print_ref(pp, cs.fetch_ref()))) - && pp.close(); - } - } - return pp.fail("unknown constructor for ProofChain"); -} - - -// -// code for type `TopBlockDescr` -// -constexpr unsigned char TopBlockDescr::cons_tag[1]; - -int TopBlockDescr::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xd5 ? top_block_descr : -1; -} - -bool TopBlockDescr::skip(vm::CellSlice& cs) const { - int len; - return cs.advance(656) - && t_Maybe_Ref_BlockSignatures.skip(cs) - && cs.fetch_uint_to(8, len) - && 1 <= len - && len <= 8 - && ProofChain{len}.skip(cs); -} - -bool TopBlockDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len; - return cs.fetch_ulong(8) == 0xd5 - && t_BlockIdExt.validate_skip(ops, cs, weak) - && t_Maybe_Ref_BlockSignatures.validate_skip(ops, cs, weak) - && cs.fetch_uint_to(8, len) - && 1 <= len - && len <= 8 - && ProofChain{len}.validate_skip(ops, cs, weak); -} - -bool TopBlockDescr::unpack(vm::CellSlice& cs, TopBlockDescr::Record& data) const { - return cs.fetch_ulong(8) == 0xd5 - && cs.fetch_subslice_to(648, data.proof_for) - && t_Maybe_Ref_BlockSignatures.fetch_to(cs, data.signatures) - && cs.fetch_uint_to(8, data.len) - && 1 <= data.len - && data.len <= 8 - && ProofChain{data.len}.fetch_to(cs, data.chain); -} - -bool TopBlockDescr::cell_unpack(Ref cell_ref, TopBlockDescr::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TopBlockDescr::pack(vm::CellBuilder& cb, const TopBlockDescr::Record& data) const { - return cb.store_long_bool(0xd5, 8) - && cb.append_cellslice_chk(data.proof_for, 648) - && t_Maybe_Ref_BlockSignatures.store_from(cb, data.signatures) - && cb.store_ulong_rchk_bool(data.len, 8) - && 1 <= data.len - && data.len <= 8 - && ProofChain{data.len}.store_from(cb, data.chain); -} - -bool TopBlockDescr::cell_pack(Ref& cell_ref, const TopBlockDescr::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TopBlockDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int len; - return cs.fetch_ulong(8) == 0xd5 - && pp.open("top_block_descr") - && pp.field("proof_for") - && t_BlockIdExt.print_skip(pp, cs) - && pp.field("signatures") - && t_Maybe_Ref_BlockSignatures.print_skip(pp, cs) - && cs.fetch_uint_to(8, len) - && pp.field_int(len, "len") - && 1 <= len - && len <= 8 - && pp.field("chain") - && ProofChain{len}.print_skip(pp, cs) - && pp.close(); -} - -const TopBlockDescr t_TopBlockDescr; - -// -// code for type `TopBlockDescrSet` -// -constexpr unsigned TopBlockDescrSet::cons_tag[1]; - -int TopBlockDescrSet::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x4ac789f3 ? top_block_descr_set : -1; -} - -bool TopBlockDescrSet::skip(vm::CellSlice& cs) const { - return cs.advance(32) - && t_HashmapE_96_Ref_TopBlockDescr.skip(cs); -} - -bool TopBlockDescrSet::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x4ac789f3 - && t_HashmapE_96_Ref_TopBlockDescr.validate_skip(ops, cs, weak); -} - -bool TopBlockDescrSet::unpack(vm::CellSlice& cs, TopBlockDescrSet::Record& data) const { - return cs.fetch_ulong(32) == 0x4ac789f3 - && t_HashmapE_96_Ref_TopBlockDescr.fetch_to(cs, data.collection); -} - -bool TopBlockDescrSet::unpack_top_block_descr_set(vm::CellSlice& cs, Ref& collection) const { - return cs.fetch_ulong(32) == 0x4ac789f3 - && t_HashmapE_96_Ref_TopBlockDescr.fetch_to(cs, collection); -} - -bool TopBlockDescrSet::cell_unpack(Ref cell_ref, TopBlockDescrSet::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TopBlockDescrSet::cell_unpack_top_block_descr_set(Ref cell_ref, Ref& collection) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_top_block_descr_set(cs, collection) && cs.empty_ext(); -} - -bool TopBlockDescrSet::pack(vm::CellBuilder& cb, const TopBlockDescrSet::Record& data) const { - return cb.store_long_bool(0x4ac789f3, 32) - && t_HashmapE_96_Ref_TopBlockDescr.store_from(cb, data.collection); -} - -bool TopBlockDescrSet::pack_top_block_descr_set(vm::CellBuilder& cb, Ref collection) const { - return cb.store_long_bool(0x4ac789f3, 32) - && t_HashmapE_96_Ref_TopBlockDescr.store_from(cb, collection); -} - -bool TopBlockDescrSet::cell_pack(Ref& cell_ref, const TopBlockDescrSet::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TopBlockDescrSet::cell_pack_top_block_descr_set(Ref& cell_ref, Ref collection) const { - vm::CellBuilder cb; - return pack_top_block_descr_set(cb, std::move(collection)) && std::move(cb).finalize_to(cell_ref); -} - -bool TopBlockDescrSet::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x4ac789f3 - && pp.open("top_block_descr_set") - && pp.field("collection") - && t_HashmapE_96_Ref_TopBlockDescr.print_skip(pp, cs) - && pp.close(); -} - -const TopBlockDescrSet t_TopBlockDescrSet; - -// -// code for type `ProducerInfo` -// -constexpr unsigned char ProducerInfo::cons_tag[1]; - -int ProducerInfo::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x34 ? prod_info : -1; -} - -bool ProducerInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x34 - && cs.advance(640) - && t_MERKLE_PROOF_Block.validate_skip_ref(ops, cs, weak) - && t_MERKLE_PROOF_ShardState.validate_skip_ref(ops, cs, weak); -} - -bool ProducerInfo::unpack(vm::CellSlice& cs, ProducerInfo::Record& data) const { - return cs.fetch_ulong(8) == 0x34 - && cs.fetch_uint_to(32, data.utime) - && cs.fetch_subslice_to(608, data.mc_blk_ref) - && cs.fetch_ref_to(data.state_proof) - && cs.fetch_ref_to(data.prod_proof); -} - -bool ProducerInfo::cell_unpack(Ref cell_ref, ProducerInfo::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProducerInfo::pack(vm::CellBuilder& cb, const ProducerInfo::Record& data) const { - return cb.store_long_bool(0x34, 8) - && cb.store_ulong_rchk_bool(data.utime, 32) - && cb.append_cellslice_chk(data.mc_blk_ref, 608) - && cb.store_ref_bool(data.state_proof) - && cb.store_ref_bool(data.prod_proof); -} - -bool ProducerInfo::cell_pack(Ref& cell_ref, const ProducerInfo::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProducerInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x34 - && pp.open("prod_info") - && pp.fetch_uint_field(cs, 32, "utime") - && pp.field("mc_blk_ref") - && t_ExtBlkRef.print_skip(pp, cs) - && pp.field("state_proof") - && t_MERKLE_PROOF_Block.print_ref(pp, cs.fetch_ref()) - && pp.field("prod_proof") - && t_MERKLE_PROOF_ShardState.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const ProducerInfo t_ProducerInfo; - -// -// code for type `ComplaintDescr` -// -constexpr unsigned ComplaintDescr::cons_tag[2]; - -int ComplaintDescr::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case no_blk_gen: - return cs.prefetch_ulong(32) == 0x450e8bd9 ? no_blk_gen : -1; - case no_blk_gen_diff: - return cs.prefetch_ulong(32) == 0xc737b0caU ? no_blk_gen_diff : -1; - } - return -1; -} - -bool ComplaintDescr::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case no_blk_gen: - return cs.advance_ext(0x10040); - case no_blk_gen_diff: - return cs.advance_ext(0x20020); - } - return false; -} - -bool ComplaintDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case no_blk_gen: - return cs.fetch_ulong(32) == 0x450e8bd9 - && cs.advance(32) - && t_ProducerInfo.validate_skip_ref(ops, cs, weak); - case no_blk_gen_diff: - return cs.fetch_ulong(32) == 0xc737b0caU - && t_ProducerInfo.validate_skip_ref(ops, cs, weak) - && t_ProducerInfo.validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool ComplaintDescr::unpack(vm::CellSlice& cs, ComplaintDescr::Record_no_blk_gen& data) const { - return cs.fetch_ulong(32) == 0x450e8bd9 - && cs.fetch_uint_to(32, data.from_utime) - && cs.fetch_ref_to(data.prod_info); -} - -bool ComplaintDescr::unpack_no_blk_gen(vm::CellSlice& cs, unsigned& from_utime, Ref& prod_info) const { - return cs.fetch_ulong(32) == 0x450e8bd9 - && cs.fetch_uint_to(32, from_utime) - && cs.fetch_ref_to(prod_info); -} - -bool ComplaintDescr::cell_unpack(Ref cell_ref, ComplaintDescr::Record_no_blk_gen& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComplaintDescr::cell_unpack_no_blk_gen(Ref cell_ref, unsigned& from_utime, Ref& prod_info) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_no_blk_gen(cs, from_utime, prod_info) && cs.empty_ext(); -} - -bool ComplaintDescr::unpack(vm::CellSlice& cs, ComplaintDescr::Record_no_blk_gen_diff& data) const { - return cs.fetch_ulong(32) == 0xc737b0caU - && cs.fetch_ref_to(data.prod_info_old) - && cs.fetch_ref_to(data.prod_info_new); -} - -bool ComplaintDescr::unpack_no_blk_gen_diff(vm::CellSlice& cs, Ref& prod_info_old, Ref& prod_info_new) const { - return cs.fetch_ulong(32) == 0xc737b0caU - && cs.fetch_ref_to(prod_info_old) - && cs.fetch_ref_to(prod_info_new); -} - -bool ComplaintDescr::cell_unpack(Ref cell_ref, ComplaintDescr::Record_no_blk_gen_diff& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ComplaintDescr::cell_unpack_no_blk_gen_diff(Ref cell_ref, Ref& prod_info_old, Ref& prod_info_new) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_no_blk_gen_diff(cs, prod_info_old, prod_info_new) && cs.empty_ext(); -} - -bool ComplaintDescr::pack(vm::CellBuilder& cb, const ComplaintDescr::Record_no_blk_gen& data) const { - return cb.store_long_bool(0x450e8bd9, 32) - && cb.store_ulong_rchk_bool(data.from_utime, 32) - && cb.store_ref_bool(data.prod_info); -} - -bool ComplaintDescr::pack_no_blk_gen(vm::CellBuilder& cb, unsigned from_utime, Ref prod_info) const { - return cb.store_long_bool(0x450e8bd9, 32) - && cb.store_ulong_rchk_bool(from_utime, 32) - && cb.store_ref_bool(prod_info); -} - -bool ComplaintDescr::cell_pack(Ref& cell_ref, const ComplaintDescr::Record_no_blk_gen& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintDescr::cell_pack_no_blk_gen(Ref& cell_ref, unsigned from_utime, Ref prod_info) const { - vm::CellBuilder cb; - return pack_no_blk_gen(cb, from_utime, std::move(prod_info)) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintDescr::pack(vm::CellBuilder& cb, const ComplaintDescr::Record_no_blk_gen_diff& data) const { - return cb.store_long_bool(0xc737b0caU, 32) - && cb.store_ref_bool(data.prod_info_old) - && cb.store_ref_bool(data.prod_info_new); -} - -bool ComplaintDescr::pack_no_blk_gen_diff(vm::CellBuilder& cb, Ref prod_info_old, Ref prod_info_new) const { - return cb.store_long_bool(0xc737b0caU, 32) - && cb.store_ref_bool(prod_info_old) - && cb.store_ref_bool(prod_info_new); -} - -bool ComplaintDescr::cell_pack(Ref& cell_ref, const ComplaintDescr::Record_no_blk_gen_diff& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintDescr::cell_pack_no_blk_gen_diff(Ref& cell_ref, Ref prod_info_old, Ref prod_info_new) const { - vm::CellBuilder cb; - return pack_no_blk_gen_diff(cb, std::move(prod_info_old), std::move(prod_info_new)) && std::move(cb).finalize_to(cell_ref); -} - -bool ComplaintDescr::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case no_blk_gen: - return cs.fetch_ulong(32) == 0x450e8bd9 - && pp.open("no_blk_gen") - && pp.fetch_uint_field(cs, 32, "from_utime") - && pp.field("prod_info") - && t_ProducerInfo.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case no_blk_gen_diff: - return cs.fetch_ulong(32) == 0xc737b0caU - && pp.open("no_blk_gen_diff") - && pp.field("prod_info_old") - && t_ProducerInfo.print_ref(pp, cs.fetch_ref()) - && pp.field("prod_info_new") - && t_ProducerInfo.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for ComplaintDescr"); -} - -const ComplaintDescr t_ComplaintDescr; - -// -// code for type `ValidatorComplaint` -// -constexpr unsigned char ValidatorComplaint::cons_tag[1]; - -int ValidatorComplaint::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0xbc ? validator_complaint : -1; -} - -bool ValidatorComplaint::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10230) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(32); -} - -bool ValidatorComplaint::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0xbc - && cs.advance(256) - && t_ComplaintDescr.validate_skip_ref(ops, cs, weak) - && cs.advance(296) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(32); -} - -bool ValidatorComplaint::unpack(vm::CellSlice& cs, ValidatorComplaint::Record& data) const { - return cs.fetch_ulong(8) == 0xbc - && cs.fetch_bits_to(data.validator_pubkey.bits(), 256) - && cs.fetch_ref_to(data.description) - && cs.fetch_uint_to(32, data.created_at) - && cs.fetch_uint_to(8, data.severity) - && cs.fetch_uint256_to(256, data.reward_addr) - && t_Grams.fetch_to(cs, data.paid) - && t_Grams.fetch_to(cs, data.suggested_fine) - && cs.fetch_uint_to(32, data.suggested_fine_part); -} - -bool ValidatorComplaint::cell_unpack(Ref cell_ref, ValidatorComplaint::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorComplaint::pack(vm::CellBuilder& cb, const ValidatorComplaint::Record& data) const { - return cb.store_long_bool(0xbc, 8) - && cb.store_bits_bool(data.validator_pubkey.cbits(), 256) - && cb.store_ref_bool(data.description) - && cb.store_ulong_rchk_bool(data.created_at, 32) - && cb.store_ulong_rchk_bool(data.severity, 8) - && cb.store_int256_bool(data.reward_addr, 256, false) - && t_Grams.store_from(cb, data.paid) - && t_Grams.store_from(cb, data.suggested_fine) - && cb.store_ulong_rchk_bool(data.suggested_fine_part, 32); -} - -bool ValidatorComplaint::cell_pack(Ref& cell_ref, const ValidatorComplaint::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorComplaint::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0xbc - && pp.open("validator_complaint") - && pp.fetch_bits_field(cs, 256, "validator_pubkey") - && pp.field("description") - && t_ComplaintDescr.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 32, "created_at") - && pp.fetch_uint_field(cs, 8, "severity") - && pp.fetch_uint256_field(cs, 256, "reward_addr") - && pp.field("paid") - && t_Grams.print_skip(pp, cs) - && pp.field("suggested_fine") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "suggested_fine_part") - && pp.close(); -} - -const ValidatorComplaint t_ValidatorComplaint; - -// -// code for type `ValidatorComplaintStatus` -// -constexpr unsigned char ValidatorComplaintStatus::cons_tag[1]; - -int ValidatorComplaintStatus::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(8) == 0x2d ? complaint_status : -1; -} - -bool ValidatorComplaintStatus::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x10008) - && t_HashmapE_16_True.skip(cs) - && cs.advance(320); -} - -bool ValidatorComplaintStatus::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(8) == 0x2d - && t_ValidatorComplaint.validate_skip_ref(ops, cs, weak) - && t_HashmapE_16_True.validate_skip(ops, cs, weak) - && cs.advance(320); -} - -bool ValidatorComplaintStatus::unpack(vm::CellSlice& cs, ValidatorComplaintStatus::Record& data) const { - return cs.fetch_ulong(8) == 0x2d - && cs.fetch_ref_to(data.complaint) - && t_HashmapE_16_True.fetch_to(cs, data.voters) - && cs.fetch_uint256_to(256, data.vset_id) - && cs.fetch_int_to(64, data.weight_remaining); -} - -bool ValidatorComplaintStatus::cell_unpack(Ref cell_ref, ValidatorComplaintStatus::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ValidatorComplaintStatus::pack(vm::CellBuilder& cb, const ValidatorComplaintStatus::Record& data) const { - return cb.store_long_bool(0x2d, 8) - && cb.store_ref_bool(data.complaint) - && t_HashmapE_16_True.store_from(cb, data.voters) - && cb.store_int256_bool(data.vset_id, 256, false) - && cb.store_long_rchk_bool(data.weight_remaining, 64); -} - -bool ValidatorComplaintStatus::cell_pack(Ref& cell_ref, const ValidatorComplaintStatus::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ValidatorComplaintStatus::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0x2d - && pp.open("complaint_status") - && pp.field("complaint") - && t_ValidatorComplaint.print_ref(pp, cs.fetch_ref()) - && pp.field("voters") - && t_HashmapE_16_True.print_skip(pp, cs) - && pp.fetch_uint256_field(cs, 256, "vset_id") - && pp.fetch_int_field(cs, 64, "weight_remaining") - && pp.close(); -} - -const ValidatorComplaintStatus t_ValidatorComplaintStatus; - -// -// code for type `VmCellSlice` -// - -int VmCellSlice::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool VmCellSlice::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int st_bits, end_bits, st_ref, end_ref; - return cs.advance_refs(1) - && cs.fetch_uint_to(10, st_bits) - && cs.fetch_uint_to(10, end_bits) - && st_bits <= end_bits - && cs.fetch_uint_leq(4, st_ref) - && cs.fetch_uint_leq(4, end_ref) - && st_ref <= end_ref; -} - -bool VmCellSlice::unpack(vm::CellSlice& cs, VmCellSlice::Record& data) const { - return cs.fetch_ref_to(data.cell) - && cs.fetch_uint_to(10, data.st_bits) - && cs.fetch_uint_to(10, data.end_bits) - && data.st_bits <= data.end_bits - && cs.fetch_uint_leq(4, data.st_ref) - && cs.fetch_uint_leq(4, data.end_ref) - && data.st_ref <= data.end_ref; -} - -bool VmCellSlice::cell_unpack(Ref cell_ref, VmCellSlice::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCellSlice::pack(vm::CellBuilder& cb, const VmCellSlice::Record& data) const { - return cb.store_ref_bool(data.cell) - && cb.store_ulong_rchk_bool(data.st_bits, 10) - && cb.store_ulong_rchk_bool(data.end_bits, 10) - && data.st_bits <= data.end_bits - && cb.store_uint_leq(4, data.st_ref) - && cb.store_uint_leq(4, data.end_ref) - && data.st_ref <= data.end_ref; -} - -bool VmCellSlice::cell_pack(Ref& cell_ref, const VmCellSlice::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCellSlice::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int st_bits, end_bits, st_ref, end_ref; - return pp.open() - && pp.field("cell") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && cs.fetch_uint_to(10, st_bits) - && pp.field_int(st_bits, "st_bits") - && cs.fetch_uint_to(10, end_bits) - && pp.field_int(end_bits, "end_bits") - && st_bits <= end_bits - && cs.fetch_uint_leq(4, st_ref) - && pp.field_int(st_ref, "st_ref") - && cs.fetch_uint_leq(4, end_ref) - && pp.field_int(end_ref, "end_ref") - && st_ref <= end_ref - && pp.close(); -} - -const VmCellSlice t_VmCellSlice; - -// -// code for type `VmTupleRef` -// - -int VmTupleRef::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 3 3 - // static inline size_t nat_abs(int x) { return (x > 1) * 2 + (x & 1); } - static signed char ctab[4] = { vm_tupref_nil, vm_tupref_single, vm_tupref_any, vm_tupref_any }; - return ctab[nat_abs(m_)]; -} - -int VmTupleRef::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tupref_nil: - return vm_tupref_nil; - case vm_tupref_single: - return vm_tupref_single; - case vm_tupref_any: - return vm_tupref_any; - } - return -1; -} - -bool VmTupleRef::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tupref_nil: - return m_ == 0; - case vm_tupref_single: - return cs.advance_refs(1) - && m_ == 1; - case vm_tupref_any: { - int n; - return add_r1(n, 2, m_) - && cs.advance_refs(1); - } - } - return false; -} - -bool VmTupleRef::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vm_tupref_nil: - return m_ == 0; - case vm_tupref_single: - return t_VmStackValue.validate_skip_ref(ops, cs, weak) - && m_ == 1; - case vm_tupref_any: { - int n; - return add_r1(n, 2, m_) - && VmTuple{n + 2}.validate_skip_ref(ops, cs, weak); - } - } - return false; -} - -bool VmTupleRef::unpack(vm::CellSlice& cs, VmTupleRef::Record_vm_tupref_nil& data) const { - return m_ == 0; -} - -bool VmTupleRef::unpack_vm_tupref_nil(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool VmTupleRef::cell_unpack(Ref cell_ref, VmTupleRef::Record_vm_tupref_nil& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmTupleRef::cell_unpack_vm_tupref_nil(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_tupref_nil(cs) && cs.empty_ext(); -} - -bool VmTupleRef::unpack(vm::CellSlice& cs, VmTupleRef::Record_vm_tupref_single& data) const { - return cs.fetch_ref_to(data.entry) - && m_ == 1; -} - -bool VmTupleRef::unpack_vm_tupref_single(vm::CellSlice& cs, Ref& entry) const { - return cs.fetch_ref_to(entry) - && m_ == 1; -} - -bool VmTupleRef::cell_unpack(Ref cell_ref, VmTupleRef::Record_vm_tupref_single& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmTupleRef::cell_unpack_vm_tupref_single(Ref cell_ref, Ref& entry) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_tupref_single(cs, entry) && cs.empty_ext(); -} - -bool VmTupleRef::unpack(vm::CellSlice& cs, VmTupleRef::Record_vm_tupref_any& data) const { - return add_r1(data.n, 2, m_) - && cs.fetch_ref_to(data.ref); -} - -bool VmTupleRef::unpack_vm_tupref_any(vm::CellSlice& cs, int& n, Ref& ref) const { - return add_r1(n, 2, m_) - && cs.fetch_ref_to(ref); -} - -bool VmTupleRef::cell_unpack(Ref cell_ref, VmTupleRef::Record_vm_tupref_any& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmTupleRef::cell_unpack_vm_tupref_any(Ref cell_ref, int& n, Ref& ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_tupref_any(cs, n, ref) && cs.empty_ext(); -} - -bool VmTupleRef::pack(vm::CellBuilder& cb, const VmTupleRef::Record_vm_tupref_nil& data) const { - return m_ == 0; -} - -bool VmTupleRef::pack_vm_tupref_nil(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool VmTupleRef::cell_pack(Ref& cell_ref, const VmTupleRef::Record_vm_tupref_nil& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::cell_pack_vm_tupref_nil(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vm_tupref_nil(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::pack(vm::CellBuilder& cb, const VmTupleRef::Record_vm_tupref_single& data) const { - return cb.store_ref_bool(data.entry) - && m_ == 1; -} - -bool VmTupleRef::pack_vm_tupref_single(vm::CellBuilder& cb, Ref entry) const { - return cb.store_ref_bool(entry) - && m_ == 1; -} - -bool VmTupleRef::cell_pack(Ref& cell_ref, const VmTupleRef::Record_vm_tupref_single& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::cell_pack_vm_tupref_single(Ref& cell_ref, Ref entry) const { - vm::CellBuilder cb; - return pack_vm_tupref_single(cb, std::move(entry)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::pack(vm::CellBuilder& cb, const VmTupleRef::Record_vm_tupref_any& data) const { - int n; - return add_r1(n, 2, m_) - && cb.store_ref_bool(data.ref); -} - -bool VmTupleRef::pack_vm_tupref_any(vm::CellBuilder& cb, Ref ref) const { - int n; - return add_r1(n, 2, m_) - && cb.store_ref_bool(ref); -} - -bool VmTupleRef::cell_pack(Ref& cell_ref, const VmTupleRef::Record_vm_tupref_any& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::cell_pack_vm_tupref_any(Ref& cell_ref, Ref ref) const { - vm::CellBuilder cb; - return pack_vm_tupref_any(cb, std::move(ref)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTupleRef::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tupref_nil: - return pp.cons("vm_tupref_nil") - && m_ == 0; - case vm_tupref_single: - return pp.open("vm_tupref_single") - && pp.field("entry") - && t_VmStackValue.print_ref(pp, cs.fetch_ref()) - && m_ == 1 - && pp.close(); - case vm_tupref_any: { - int n; - return pp.open("vm_tupref_any") - && add_r1(n, 2, m_) - && pp.field("ref") - && VmTuple{n + 2}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - } - return pp.fail("unknown constructor for VmTupleRef"); -} - - -// -// code for type `VmTuple` -// - -int VmTuple::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 1 2 2 2 - return m_ ? vm_tuple_tcons : vm_tuple_nil; -} - -int VmTuple::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tuple_nil: - return vm_tuple_nil; - case vm_tuple_tcons: - return vm_tuple_tcons; - } - return -1; -} - -bool VmTuple::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tuple_nil: - return m_ == 0; - case vm_tuple_tcons: { - int n; - return add_r1(n, 1, m_) - && VmTupleRef{n}.skip(cs) - && cs.advance_refs(1); - } - } - return false; -} - -bool VmTuple::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vm_tuple_nil: - return m_ == 0; - case vm_tuple_tcons: { - int n; - return add_r1(n, 1, m_) - && VmTupleRef{n}.validate_skip(ops, cs, weak) - && t_VmStackValue.validate_skip_ref(ops, cs, weak); - } - } - return false; -} - -bool VmTuple::unpack(vm::CellSlice& cs, VmTuple::Record_vm_tuple_nil& data) const { - return m_ == 0; -} - -bool VmTuple::unpack_vm_tuple_nil(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool VmTuple::cell_unpack(Ref cell_ref, VmTuple::Record_vm_tuple_nil& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmTuple::cell_unpack_vm_tuple_nil(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_tuple_nil(cs) && cs.empty_ext(); -} - -bool VmTuple::unpack(vm::CellSlice& cs, VmTuple::Record_vm_tuple_tcons& data) const { - return add_r1(data.n, 1, m_) - && VmTupleRef{data.n}.fetch_to(cs, data.head) - && cs.fetch_ref_to(data.tail); -} - -bool VmTuple::unpack_vm_tuple_tcons(vm::CellSlice& cs, int& n, Ref& head, Ref& tail) const { - return add_r1(n, 1, m_) - && VmTupleRef{n}.fetch_to(cs, head) - && cs.fetch_ref_to(tail); -} - -bool VmTuple::cell_unpack(Ref cell_ref, VmTuple::Record_vm_tuple_tcons& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmTuple::cell_unpack_vm_tuple_tcons(Ref cell_ref, int& n, Ref& head, Ref& tail) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_tuple_tcons(cs, n, head, tail) && cs.empty_ext(); -} - -bool VmTuple::pack(vm::CellBuilder& cb, const VmTuple::Record_vm_tuple_nil& data) const { - return m_ == 0; -} - -bool VmTuple::pack_vm_tuple_nil(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool VmTuple::cell_pack(Ref& cell_ref, const VmTuple::Record_vm_tuple_nil& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTuple::cell_pack_vm_tuple_nil(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vm_tuple_nil(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTuple::pack(vm::CellBuilder& cb, const VmTuple::Record_vm_tuple_tcons& data) const { - int n; - return add_r1(n, 1, m_) - && VmTupleRef{n}.store_from(cb, data.head) - && cb.store_ref_bool(data.tail); -} - -bool VmTuple::pack_vm_tuple_tcons(vm::CellBuilder& cb, Ref head, Ref tail) const { - int n; - return add_r1(n, 1, m_) - && VmTupleRef{n}.store_from(cb, head) - && cb.store_ref_bool(tail); -} - -bool VmTuple::cell_pack(Ref& cell_ref, const VmTuple::Record_vm_tuple_tcons& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTuple::cell_pack_vm_tuple_tcons(Ref& cell_ref, Ref head, Ref tail) const { - vm::CellBuilder cb; - return pack_vm_tuple_tcons(cb, std::move(head), std::move(tail)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmTuple::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_tuple_nil: - return pp.cons("vm_tuple_nil") - && m_ == 0; - case vm_tuple_tcons: { - int n; - return pp.open("vm_tuple_tcons") - && add_r1(n, 1, m_) - && pp.field("head") - && VmTupleRef{n}.print_skip(pp, cs) - && pp.field("tail") - && t_VmStackValue.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - } - return pp.fail("unknown constructor for VmTuple"); -} - - -// -// code for type `VmStackValue` -// -constexpr char VmStackValue::cons_len[9]; -constexpr unsigned short VmStackValue::cons_tag[9]; - -int VmStackValue::get_tag(const vm::CellSlice& cs) const { - switch (cs.bselect(6, 7)) { - case 0: - if (cs.bit_at(6)) { - if (cs.bit_at(7)) { - return vm_stk_cell; - } else { - return cs.bit_at(8) ? vm_stk_nan : vm_stk_int; - } - } else { - return cs.bit_at(7) ? vm_stk_tinyint : vm_stk_null; - } - case 1: - if (cs.bit_at(6)) { - return cs.bit_at(7) ? vm_stk_tuple : vm_stk_cont; - } else { - return cs.bit_at(7) ? vm_stk_builder : vm_stk_slice; - } - default: - return -1; - } -} - -int VmStackValue::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_null: - return cs.prefetch_ulong(8) == 0 ? vm_stk_null : -1; - case vm_stk_tinyint: - return cs.prefetch_ulong(8) == 1 ? vm_stk_tinyint : -1; - case vm_stk_int: - return cs.prefetch_ulong(15) == 0x100 ? vm_stk_int : -1; - case vm_stk_nan: - return cs.prefetch_ulong(16) == 0x2ff ? vm_stk_nan : -1; - case vm_stk_cell: - return cs.prefetch_ulong(8) == 3 ? vm_stk_cell : -1; - case vm_stk_slice: - return cs.prefetch_ulong(8) == 4 ? vm_stk_slice : -1; - case vm_stk_builder: - return cs.prefetch_ulong(8) == 5 ? vm_stk_builder : -1; - case vm_stk_cont: - return cs.prefetch_ulong(8) == 6 ? vm_stk_cont : -1; - case vm_stk_tuple: - return cs.prefetch_ulong(8) == 7 ? vm_stk_tuple : -1; - } - return -1; -} - -bool VmStackValue::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_null: - return cs.advance(8); - case vm_stk_tinyint: - return cs.advance(72); - case vm_stk_int: - return cs.advance(272); - case vm_stk_nan: - return cs.advance(16); - case vm_stk_cell: - return cs.advance_ext(0x10008); - case vm_stk_slice: - return cs.advance_ext(0x10022); - case vm_stk_builder: - return cs.advance_ext(0x10008); - case vm_stk_cont: - return cs.advance(8) - && t_VmCont.skip(cs); - case vm_stk_tuple: { - int len; - return cs.advance(8) - && cs.fetch_uint_to(16, len) - && VmTuple{len}.skip(cs); - } - } - return false; -} - -bool VmStackValue::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vm_stk_null: - return cs.fetch_ulong(8) == 0; - case vm_stk_tinyint: - return cs.fetch_ulong(8) == 1 - && cs.advance(64); - case vm_stk_int: - return cs.fetch_ulong(15) == 0x100 - && cs.advance(257); - case vm_stk_nan: - return cs.fetch_ulong(16) == 0x2ff; - case vm_stk_cell: - return cs.fetch_ulong(8) == 3 - && cs.advance_refs(1); - case vm_stk_slice: - return cs.fetch_ulong(8) == 4 - && t_VmCellSlice.validate_skip(ops, cs, weak); - case vm_stk_builder: - return cs.fetch_ulong(8) == 5 - && cs.advance_refs(1); - case vm_stk_cont: - return cs.fetch_ulong(8) == 6 - && t_VmCont.validate_skip(ops, cs, weak); - case vm_stk_tuple: { - int len; - return cs.fetch_ulong(8) == 7 - && cs.fetch_uint_to(16, len) - && VmTuple{len}.validate_skip(ops, cs, weak); - } - } - return false; -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_null& data) const { - return cs.fetch_ulong(8) == 0; -} - -bool VmStackValue::unpack_vm_stk_null(vm::CellSlice& cs) const { - return cs.fetch_ulong(8) == 0; -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_null& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_null(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_null(cs) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_tinyint& data) const { - return cs.fetch_ulong(8) == 1 - && cs.fetch_int_to(64, data.value); -} - -bool VmStackValue::unpack_vm_stk_tinyint(vm::CellSlice& cs, long long& value) const { - return cs.fetch_ulong(8) == 1 - && cs.fetch_int_to(64, value); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_tinyint& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_tinyint(Ref cell_ref, long long& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_tinyint(cs, value) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_int& data) const { - return cs.fetch_ulong(15) == 0x100 - && cs.fetch_int256_to(257, data.value); -} - -bool VmStackValue::unpack_vm_stk_int(vm::CellSlice& cs, RefInt256& value) const { - return cs.fetch_ulong(15) == 0x100 - && cs.fetch_int256_to(257, value); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_int& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_int(Ref cell_ref, RefInt256& value) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_int(cs, value) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_nan& data) const { - return cs.fetch_ulong(16) == 0x2ff; -} - -bool VmStackValue::unpack_vm_stk_nan(vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x2ff; -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_nan& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_nan(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_nan(cs) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_cell& data) const { - return cs.fetch_ulong(8) == 3 - && cs.fetch_ref_to(data.cell); -} - -bool VmStackValue::unpack_vm_stk_cell(vm::CellSlice& cs, Ref& cell) const { - return cs.fetch_ulong(8) == 3 - && cs.fetch_ref_to(cell); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_cell& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_cell(Ref cell_ref, Ref& cell) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_cell(cs, cell) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_slice& data) const { - return cs.fetch_ulong(8) == 4 - && cs.fetch_subslice_ext_to(0x1001a, data.x); -} - -bool VmStackValue::unpack_vm_stk_slice(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_ulong(8) == 4 - && cs.fetch_subslice_ext_to(0x1001a, x); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_slice& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_slice(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_slice(cs, x) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_builder& data) const { - return cs.fetch_ulong(8) == 5 - && cs.fetch_ref_to(data.cell); -} - -bool VmStackValue::unpack_vm_stk_builder(vm::CellSlice& cs, Ref& cell) const { - return cs.fetch_ulong(8) == 5 - && cs.fetch_ref_to(cell); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_builder& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_builder(Ref cell_ref, Ref& cell) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_builder(cs, cell) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_cont& data) const { - return cs.fetch_ulong(8) == 6 - && t_VmCont.fetch_to(cs, data.cont); -} - -bool VmStackValue::unpack_vm_stk_cont(vm::CellSlice& cs, Ref& cont) const { - return cs.fetch_ulong(8) == 6 - && t_VmCont.fetch_to(cs, cont); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_cont& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_cont(Ref cell_ref, Ref& cont) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_cont(cs, cont) && cs.empty_ext(); -} - -bool VmStackValue::unpack(vm::CellSlice& cs, VmStackValue::Record_vm_stk_tuple& data) const { - return cs.fetch_ulong(8) == 7 - && cs.fetch_uint_to(16, data.len) - && VmTuple{data.len}.fetch_to(cs, data.data); -} - -bool VmStackValue::unpack_vm_stk_tuple(vm::CellSlice& cs, int& len, Ref& data) const { - return cs.fetch_ulong(8) == 7 - && cs.fetch_uint_to(16, len) - && VmTuple{len}.fetch_to(cs, data); -} - -bool VmStackValue::cell_unpack(Ref cell_ref, VmStackValue::Record_vm_stk_tuple& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackValue::cell_unpack_vm_stk_tuple(Ref cell_ref, int& len, Ref& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_tuple(cs, len, data) && cs.empty_ext(); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_null& data) const { - return cb.store_long_bool(0, 8); -} - -bool VmStackValue::pack_vm_stk_null(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 8); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_null& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_null(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vm_stk_null(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_tinyint& data) const { - return cb.store_long_bool(1, 8) - && cb.store_long_rchk_bool(data.value, 64); -} - -bool VmStackValue::pack_vm_stk_tinyint(vm::CellBuilder& cb, long long value) const { - return cb.store_long_bool(1, 8) - && cb.store_long_rchk_bool(value, 64); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_tinyint& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_tinyint(Ref& cell_ref, long long value) const { - vm::CellBuilder cb; - return pack_vm_stk_tinyint(cb, value) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_int& data) const { - return cb.store_long_bool(0x100, 15) - && cb.store_int256_bool(data.value, 257); -} - -bool VmStackValue::pack_vm_stk_int(vm::CellBuilder& cb, RefInt256 value) const { - return cb.store_long_bool(0x100, 15) - && cb.store_int256_bool(value, 257); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_int& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_int(Ref& cell_ref, RefInt256 value) const { - vm::CellBuilder cb; - return pack_vm_stk_int(cb, std::move(value)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_nan& data) const { - return cb.store_long_bool(0x2ff, 16); -} - -bool VmStackValue::pack_vm_stk_nan(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x2ff, 16); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_nan& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_nan(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vm_stk_nan(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_cell& data) const { - return cb.store_long_bool(3, 8) - && cb.store_ref_bool(data.cell); -} - -bool VmStackValue::pack_vm_stk_cell(vm::CellBuilder& cb, Ref cell) const { - return cb.store_long_bool(3, 8) - && cb.store_ref_bool(cell); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_cell& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_cell(Ref& cell_ref, Ref cell) const { - vm::CellBuilder cb; - return pack_vm_stk_cell(cb, std::move(cell)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_slice& data) const { - return cb.store_long_bool(4, 8) - && cb.append_cellslice_chk(data.x, 0x1001a); -} - -bool VmStackValue::pack_vm_stk_slice(vm::CellBuilder& cb, Ref x) const { - return cb.store_long_bool(4, 8) - && cb.append_cellslice_chk(x, 0x1001a); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_slice& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_slice(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_vm_stk_slice(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_builder& data) const { - return cb.store_long_bool(5, 8) - && cb.store_ref_bool(data.cell); -} - -bool VmStackValue::pack_vm_stk_builder(vm::CellBuilder& cb, Ref cell) const { - return cb.store_long_bool(5, 8) - && cb.store_ref_bool(cell); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_builder& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_builder(Ref& cell_ref, Ref cell) const { - vm::CellBuilder cb; - return pack_vm_stk_builder(cb, std::move(cell)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_cont& data) const { - return cb.store_long_bool(6, 8) - && t_VmCont.store_from(cb, data.cont); -} - -bool VmStackValue::pack_vm_stk_cont(vm::CellBuilder& cb, Ref cont) const { - return cb.store_long_bool(6, 8) - && t_VmCont.store_from(cb, cont); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_cont& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_cont(Ref& cell_ref, Ref cont) const { - vm::CellBuilder cb; - return pack_vm_stk_cont(cb, std::move(cont)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::pack(vm::CellBuilder& cb, const VmStackValue::Record_vm_stk_tuple& data) const { - return cb.store_long_bool(7, 8) - && cb.store_ulong_rchk_bool(data.len, 16) - && VmTuple{data.len}.store_from(cb, data.data); -} - -bool VmStackValue::pack_vm_stk_tuple(vm::CellBuilder& cb, int len, Ref data) const { - return cb.store_long_bool(7, 8) - && cb.store_ulong_rchk_bool(len, 16) - && VmTuple{len}.store_from(cb, data); -} - -bool VmStackValue::cell_pack(Ref& cell_ref, const VmStackValue::Record_vm_stk_tuple& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::cell_pack_vm_stk_tuple(Ref& cell_ref, int len, Ref data) const { - vm::CellBuilder cb; - return pack_vm_stk_tuple(cb, len, std::move(data)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackValue::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_null: - return cs.fetch_ulong(8) == 0 - && pp.cons("vm_stk_null"); - case vm_stk_tinyint: - return cs.fetch_ulong(8) == 1 - && pp.open("vm_stk_tinyint") - && pp.fetch_int_field(cs, 64, "value") - && pp.close(); - case vm_stk_int: - return cs.fetch_ulong(15) == 0x100 - && pp.open("vm_stk_int") - && pp.fetch_int256_field(cs, 257, "value") - && pp.close(); - case vm_stk_nan: - return cs.fetch_ulong(16) == 0x2ff - && pp.cons("vm_stk_nan"); - case vm_stk_cell: - return cs.fetch_ulong(8) == 3 - && pp.open("vm_stk_cell") - && pp.field("cell") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vm_stk_slice: - return cs.fetch_ulong(8) == 4 - && pp.open("vm_stk_slice") - && pp.field() - && t_VmCellSlice.print_skip(pp, cs) - && pp.close(); - case vm_stk_builder: - return cs.fetch_ulong(8) == 5 - && pp.open("vm_stk_builder") - && pp.field("cell") - && t_Anything.print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vm_stk_cont: - return cs.fetch_ulong(8) == 6 - && pp.open("vm_stk_cont") - && pp.field("cont") - && t_VmCont.print_skip(pp, cs) - && pp.close(); - case vm_stk_tuple: { - int len; - return cs.fetch_ulong(8) == 7 - && pp.open("vm_stk_tuple") - && cs.fetch_uint_to(16, len) - && pp.field_int(len, "len") - && pp.field("data") - && VmTuple{len}.print_skip(pp, cs) - && pp.close(); - } - } - return pp.fail("unknown constructor for VmStackValue"); -} - -const VmStackValue t_VmStackValue; - -// -// code for type `VmStack` -// - -int VmStack::check_tag(const vm::CellSlice& cs) const { - return vm_stack; -} - -bool VmStack::skip(vm::CellSlice& cs) const { - int depth; - return cs.fetch_uint_to(24, depth) - && VmStackList{depth}.skip(cs); -} - -bool VmStack::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int depth; - return cs.fetch_uint_to(24, depth) - && VmStackList{depth}.validate_skip(ops, cs, weak); -} - -bool VmStack::unpack(vm::CellSlice& cs, VmStack::Record& data) const { - return cs.fetch_uint_to(24, data.depth) - && VmStackList{data.depth}.fetch_to(cs, data.stack); -} - -bool VmStack::unpack_vm_stack(vm::CellSlice& cs, int& depth, Ref& stack) const { - return cs.fetch_uint_to(24, depth) - && VmStackList{depth}.fetch_to(cs, stack); -} - -bool VmStack::cell_unpack(Ref cell_ref, VmStack::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStack::cell_unpack_vm_stack(Ref cell_ref, int& depth, Ref& stack) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stack(cs, depth, stack) && cs.empty_ext(); -} - -bool VmStack::pack(vm::CellBuilder& cb, const VmStack::Record& data) const { - return cb.store_ulong_rchk_bool(data.depth, 24) - && VmStackList{data.depth}.store_from(cb, data.stack); -} - -bool VmStack::pack_vm_stack(vm::CellBuilder& cb, int depth, Ref stack) const { - return cb.store_ulong_rchk_bool(depth, 24) - && VmStackList{depth}.store_from(cb, stack); -} - -bool VmStack::cell_pack(Ref& cell_ref, const VmStack::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStack::cell_pack_vm_stack(Ref& cell_ref, int depth, Ref stack) const { - vm::CellBuilder cb; - return pack_vm_stack(cb, depth, std::move(stack)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStack::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int depth; - return pp.open("vm_stack") - && cs.fetch_uint_to(24, depth) - && pp.field_int(depth, "depth") - && pp.field("stack") - && VmStackList{depth}.print_skip(pp, cs) - && pp.close(); -} - -const VmStack t_VmStack; - -// -// code for type `VmStackList` -// - -int VmStackList::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 2 1 1 1 - return m_ ? vm_stk_cons : vm_stk_nil; -} - -int VmStackList::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_cons: - return vm_stk_cons; - case vm_stk_nil: - return vm_stk_nil; - } - return -1; -} - -bool VmStackList::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_cons: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(1) - && t_VmStackValue.skip(cs); - } - case vm_stk_nil: - return m_ == 0; - } - return false; -} - -bool VmStackList::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vm_stk_cons: { - int n; - return add_r1(n, 1, m_) - && VmStackList{n}.validate_skip_ref(ops, cs, weak) - && t_VmStackValue.validate_skip(ops, cs, weak); - } - case vm_stk_nil: - return m_ == 0; - } - return false; -} - -bool VmStackList::unpack(vm::CellSlice& cs, VmStackList::Record_vm_stk_cons& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.rest) - && t_VmStackValue.fetch_to(cs, data.tos); -} - -bool VmStackList::unpack_vm_stk_cons(vm::CellSlice& cs, int& n, Ref& rest, Ref& tos) const { - return add_r1(n, 1, m_) - && cs.fetch_ref_to(rest) - && t_VmStackValue.fetch_to(cs, tos); -} - -bool VmStackList::cell_unpack(Ref cell_ref, VmStackList::Record_vm_stk_cons& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackList::cell_unpack_vm_stk_cons(Ref cell_ref, int& n, Ref& rest, Ref& tos) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_cons(cs, n, rest, tos) && cs.empty_ext(); -} - -bool VmStackList::unpack(vm::CellSlice& cs, VmStackList::Record_vm_stk_nil& data) const { - return m_ == 0; -} - -bool VmStackList::unpack_vm_stk_nil(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool VmStackList::cell_unpack(Ref cell_ref, VmStackList::Record_vm_stk_nil& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmStackList::cell_unpack_vm_stk_nil(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vm_stk_nil(cs) && cs.empty_ext(); -} - -bool VmStackList::pack(vm::CellBuilder& cb, const VmStackList::Record_vm_stk_cons& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.rest) - && t_VmStackValue.store_from(cb, data.tos); -} - -bool VmStackList::pack_vm_stk_cons(vm::CellBuilder& cb, Ref rest, Ref tos) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(rest) - && t_VmStackValue.store_from(cb, tos); -} - -bool VmStackList::cell_pack(Ref& cell_ref, const VmStackList::Record_vm_stk_cons& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackList::cell_pack_vm_stk_cons(Ref& cell_ref, Ref rest, Ref tos) const { - vm::CellBuilder cb; - return pack_vm_stk_cons(cb, std::move(rest), std::move(tos)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackList::pack(vm::CellBuilder& cb, const VmStackList::Record_vm_stk_nil& data) const { - return m_ == 0; -} - -bool VmStackList::pack_vm_stk_nil(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool VmStackList::cell_pack(Ref& cell_ref, const VmStackList::Record_vm_stk_nil& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackList::cell_pack_vm_stk_nil(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vm_stk_nil(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmStackList::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vm_stk_cons: { - int n; - return pp.open("vm_stk_cons") - && add_r1(n, 1, m_) - && pp.field("rest") - && VmStackList{n}.print_ref(pp, cs.fetch_ref()) - && pp.field("tos") - && t_VmStackValue.print_skip(pp, cs) - && pp.close(); - } - case vm_stk_nil: - return pp.cons("vm_stk_nil") - && m_ == 0; - } - return pp.fail("unknown constructor for VmStackList"); -} - - -// -// code for type `VmSaveList` -// - -int VmSaveList::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool VmSaveList::skip(vm::CellSlice& cs) const { - return t_HashmapE_4_VmStackValue.skip(cs); -} - -bool VmSaveList::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_4_VmStackValue.validate_skip(ops, cs, weak); -} - -bool VmSaveList::unpack(vm::CellSlice& cs, VmSaveList::Record& data) const { - return t_HashmapE_4_VmStackValue.fetch_to(cs, data.cregs); -} - -bool VmSaveList::unpack_cons1(vm::CellSlice& cs, Ref& cregs) const { - return t_HashmapE_4_VmStackValue.fetch_to(cs, cregs); -} - -bool VmSaveList::cell_unpack(Ref cell_ref, VmSaveList::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmSaveList::cell_unpack_cons1(Ref cell_ref, Ref& cregs) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, cregs) && cs.empty_ext(); -} - -bool VmSaveList::pack(vm::CellBuilder& cb, const VmSaveList::Record& data) const { - return t_HashmapE_4_VmStackValue.store_from(cb, data.cregs); -} - -bool VmSaveList::pack_cons1(vm::CellBuilder& cb, Ref cregs) const { - return t_HashmapE_4_VmStackValue.store_from(cb, cregs); -} - -bool VmSaveList::cell_pack(Ref& cell_ref, const VmSaveList::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmSaveList::cell_pack_cons1(Ref& cell_ref, Ref cregs) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(cregs)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmSaveList::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("cregs") - && t_HashmapE_4_VmStackValue.print_skip(pp, cs) - && pp.close(); -} - -const VmSaveList t_VmSaveList; - -// -// code for auxiliary type `VmGasLimits_aux` -// - -int VmGasLimits_aux::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool VmGasLimits_aux::unpack(vm::CellSlice& cs, VmGasLimits_aux::Record& data) const { - return cs.fetch_int_to(64, data.max_limit) - && cs.fetch_int_to(64, data.cur_limit) - && cs.fetch_int_to(64, data.credit); -} - -bool VmGasLimits_aux::unpack_cons1(vm::CellSlice& cs, long long& max_limit, long long& cur_limit, long long& credit) const { - return cs.fetch_int_to(64, max_limit) - && cs.fetch_int_to(64, cur_limit) - && cs.fetch_int_to(64, credit); -} - -bool VmGasLimits_aux::cell_unpack(Ref cell_ref, VmGasLimits_aux::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmGasLimits_aux::cell_unpack_cons1(Ref cell_ref, long long& max_limit, long long& cur_limit, long long& credit) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, max_limit, cur_limit, credit) && cs.empty_ext(); -} - -bool VmGasLimits_aux::pack(vm::CellBuilder& cb, const VmGasLimits_aux::Record& data) const { - return cb.store_long_rchk_bool(data.max_limit, 64) - && cb.store_long_rchk_bool(data.cur_limit, 64) - && cb.store_long_rchk_bool(data.credit, 64); -} - -bool VmGasLimits_aux::pack_cons1(vm::CellBuilder& cb, long long max_limit, long long cur_limit, long long credit) const { - return cb.store_long_rchk_bool(max_limit, 64) - && cb.store_long_rchk_bool(cur_limit, 64) - && cb.store_long_rchk_bool(credit, 64); -} - -bool VmGasLimits_aux::cell_pack(Ref& cell_ref, const VmGasLimits_aux::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmGasLimits_aux::cell_pack_cons1(Ref& cell_ref, long long max_limit, long long cur_limit, long long credit) const { - vm::CellBuilder cb; - return pack_cons1(cb, max_limit, cur_limit, credit) && std::move(cb).finalize_to(cell_ref); -} - -bool VmGasLimits_aux::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.fetch_int_field(cs, 64, "max_limit") - && pp.fetch_int_field(cs, 64, "cur_limit") - && pp.fetch_int_field(cs, 64, "credit") - && pp.close(); -} - -const VmGasLimits_aux t_VmGasLimits_aux; - -// -// code for type `VmGasLimits` -// - -int VmGasLimits::check_tag(const vm::CellSlice& cs) const { - return gas_limits; -} - -bool VmGasLimits::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) - && t_VmGasLimits_aux.validate_skip_ref(ops, cs, weak); -} - -bool VmGasLimits::unpack(vm::CellSlice& cs, VmGasLimits::Record& data) const { - return cs.fetch_int_to(64, data.remaining) - && t_VmGasLimits_aux.cell_unpack(cs.fetch_ref(), data.r1); -} - -bool VmGasLimits::cell_unpack(Ref cell_ref, VmGasLimits::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmGasLimits::pack(vm::CellBuilder& cb, const VmGasLimits::Record& data) const { - Ref tmp_cell; - return cb.store_long_rchk_bool(data.remaining, 64) - && t_VmGasLimits_aux.cell_pack(tmp_cell, data.r1) - && cb.store_ref_bool(std::move(tmp_cell)); -} - -bool VmGasLimits::cell_pack(Ref& cell_ref, const VmGasLimits::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmGasLimits::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("gas_limits") - && pp.fetch_int_field(cs, 64, "remaining") - && pp.field() - && t_VmGasLimits_aux.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const VmGasLimits t_VmGasLimits; - -// -// code for type `VmLibraries` -// - -int VmLibraries::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool VmLibraries::skip(vm::CellSlice& cs) const { - return t_HashmapE_256_Ref_Cell.skip(cs); -} - -bool VmLibraries::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_256_Ref_Cell.validate_skip(ops, cs, weak); -} - -bool VmLibraries::unpack(vm::CellSlice& cs, VmLibraries::Record& data) const { - return t_HashmapE_256_Ref_Cell.fetch_to(cs, data.libraries); -} - -bool VmLibraries::unpack_cons1(vm::CellSlice& cs, Ref& libraries) const { - return t_HashmapE_256_Ref_Cell.fetch_to(cs, libraries); -} - -bool VmLibraries::cell_unpack(Ref cell_ref, VmLibraries::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmLibraries::cell_unpack_cons1(Ref cell_ref, Ref& libraries) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, libraries) && cs.empty_ext(); -} - -bool VmLibraries::pack(vm::CellBuilder& cb, const VmLibraries::Record& data) const { - return t_HashmapE_256_Ref_Cell.store_from(cb, data.libraries); -} - -bool VmLibraries::pack_cons1(vm::CellBuilder& cb, Ref libraries) const { - return t_HashmapE_256_Ref_Cell.store_from(cb, libraries); -} - -bool VmLibraries::cell_pack(Ref& cell_ref, const VmLibraries::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmLibraries::cell_pack_cons1(Ref& cell_ref, Ref libraries) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(libraries)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmLibraries::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field("libraries") - && t_HashmapE_256_Ref_Cell.print_skip(pp, cs) - && pp.close(); -} - -const VmLibraries t_VmLibraries; - -// -// code for type `VmControlData` -// - -int VmControlData::check_tag(const vm::CellSlice& cs) const { - return vm_ctl_data; -} - -bool VmControlData::skip(vm::CellSlice& cs) const { - return t_Maybe_uint13.skip(cs) - && t_Maybe_VmStack.skip(cs) - && t_VmSaveList.skip(cs) - && t_Maybe_int16.skip(cs); -} - -bool VmControlData::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_uint13.validate_skip(ops, cs, weak) - && t_Maybe_VmStack.validate_skip(ops, cs, weak) - && t_VmSaveList.validate_skip(ops, cs, weak) - && t_Maybe_int16.validate_skip(ops, cs, weak); -} - -bool VmControlData::unpack(vm::CellSlice& cs, VmControlData::Record& data) const { - return t_Maybe_uint13.fetch_to(cs, data.nargs) - && t_Maybe_VmStack.fetch_to(cs, data.stack) - && t_VmSaveList.fetch_to(cs, data.save) - && t_Maybe_int16.fetch_to(cs, data.cp); -} - -bool VmControlData::cell_unpack(Ref cell_ref, VmControlData::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmControlData::pack(vm::CellBuilder& cb, const VmControlData::Record& data) const { - return t_Maybe_uint13.store_from(cb, data.nargs) - && t_Maybe_VmStack.store_from(cb, data.stack) - && t_VmSaveList.store_from(cb, data.save) - && t_Maybe_int16.store_from(cb, data.cp); -} - -bool VmControlData::cell_pack(Ref& cell_ref, const VmControlData::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmControlData::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("vm_ctl_data") - && pp.field("nargs") - && t_Maybe_uint13.print_skip(pp, cs) - && pp.field("stack") - && t_Maybe_VmStack.print_skip(pp, cs) - && pp.field("save") - && t_VmSaveList.print_skip(pp, cs) - && pp.field("cp") - && t_Maybe_int16.print_skip(pp, cs) - && pp.close(); -} - -const VmControlData t_VmControlData; - -// -// code for type `VmCont` -// -constexpr char VmCont::cons_len[10]; -constexpr unsigned char VmCont::cons_tag[10]; - -int VmCont::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vmc_std: - return cs.have(2) ? vmc_std : -1; - case vmc_envelope: - return cs.have(2) ? vmc_envelope : -1; - case vmc_quit: - return cs.have(4) ? vmc_quit : -1; - case vmc_quit_exc: - return cs.have(4) ? vmc_quit_exc : -1; - case vmc_repeat: - return cs.prefetch_ulong(5) == 20 ? vmc_repeat : -1; - case vmc_until: - return cs.have(6) ? vmc_until : -1; - case vmc_again: - return cs.have(6) ? vmc_again : -1; - case vmc_while_cond: - return cs.have(6) ? vmc_while_cond : -1; - case vmc_while_body: - return cs.prefetch_ulong(6) == 0x33 ? vmc_while_body : -1; - case vmc_pushint: - return cs.have(4) ? vmc_pushint : -1; - } - return -1; -} - -bool VmCont::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vmc_std: - return cs.advance(2) - && t_VmControlData.skip(cs) - && cs.advance_ext(0x1001a); - case vmc_envelope: - return cs.advance(2) - && t_VmControlData.skip(cs) - && cs.advance_refs(1); - case vmc_quit: - return cs.advance(36); - case vmc_quit_exc: - return cs.advance(4); - case vmc_repeat: - return cs.advance_ext(0x20044); - case vmc_until: - return cs.advance_ext(0x20006); - case vmc_again: - return cs.advance_ext(0x10006); - case vmc_while_cond: - return cs.advance_ext(0x30006); - case vmc_while_body: - return cs.advance_ext(0x30006); - case vmc_pushint: - return cs.advance_ext(0x10024); - } - return false; -} - -bool VmCont::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case vmc_std: - return cs.advance(2) - && t_VmControlData.validate_skip(ops, cs, weak) - && t_VmCellSlice.validate_skip(ops, cs, weak); - case vmc_envelope: - return cs.advance(2) - && t_VmControlData.validate_skip(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - case vmc_quit: - return cs.advance(36); - case vmc_quit_exc: - return cs.advance(4); - case vmc_repeat: - return cs.fetch_ulong(5) == 20 - && cs.advance(63) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - case vmc_until: - return cs.advance(6) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - case vmc_again: - return cs.advance(6) - && validate_skip_ref(ops, cs, weak); - case vmc_while_cond: - return cs.advance(6) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - case vmc_while_body: - return cs.fetch_ulong(6) == 0x33 - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak) - && validate_skip_ref(ops, cs, weak); - case vmc_pushint: - return cs.advance(36) - && validate_skip_ref(ops, cs, weak); - } - return false; -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_std& data) const { - return cs.fetch_ulong(2) == 0 - && t_VmControlData.fetch_to(cs, data.cdata) - && cs.fetch_subslice_ext_to(0x1001a, data.code); -} - -bool VmCont::unpack_vmc_std(vm::CellSlice& cs, Ref& cdata, Ref& code) const { - return cs.fetch_ulong(2) == 0 - && t_VmControlData.fetch_to(cs, cdata) - && cs.fetch_subslice_ext_to(0x1001a, code); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_std& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_std(Ref cell_ref, Ref& cdata, Ref& code) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_std(cs, cdata, code) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_envelope& data) const { - return cs.fetch_ulong(2) == 1 - && t_VmControlData.fetch_to(cs, data.cdata) - && cs.fetch_ref_to(data.next); -} - -bool VmCont::unpack_vmc_envelope(vm::CellSlice& cs, Ref& cdata, Ref& next) const { - return cs.fetch_ulong(2) == 1 - && t_VmControlData.fetch_to(cs, cdata) - && cs.fetch_ref_to(next); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_envelope& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_envelope(Ref cell_ref, Ref& cdata, Ref& next) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_envelope(cs, cdata, next) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_quit& data) const { - return cs.fetch_ulong(4) == 8 - && cs.fetch_int_to(32, data.exit_code); -} - -bool VmCont::unpack_vmc_quit(vm::CellSlice& cs, int& exit_code) const { - return cs.fetch_ulong(4) == 8 - && cs.fetch_int_to(32, exit_code); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_quit& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_quit(Ref cell_ref, int& exit_code) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_quit(cs, exit_code) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_quit_exc& data) const { - return cs.fetch_ulong(4) == 9; -} - -bool VmCont::unpack_vmc_quit_exc(vm::CellSlice& cs) const { - return cs.fetch_ulong(4) == 9; -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_quit_exc& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_quit_exc(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_quit_exc(cs) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_repeat& data) const { - return cs.fetch_ulong(5) == 20 - && cs.fetch_uint_to(63, data.count) - && cs.fetch_ref_to(data.body) - && cs.fetch_ref_to(data.after); -} - -bool VmCont::unpack_vmc_repeat(vm::CellSlice& cs, long long& count, Ref& body, Ref& after) const { - return cs.fetch_ulong(5) == 20 - && cs.fetch_uint_to(63, count) - && cs.fetch_ref_to(body) - && cs.fetch_ref_to(after); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_repeat& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_repeat(Ref cell_ref, long long& count, Ref& body, Ref& after) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_repeat(cs, count, body, after) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_until& data) const { - return cs.fetch_ulong(6) == 0x30 - && cs.fetch_ref_to(data.body) - && cs.fetch_ref_to(data.after); -} - -bool VmCont::unpack_vmc_until(vm::CellSlice& cs, Ref& body, Ref& after) const { - return cs.fetch_ulong(6) == 0x30 - && cs.fetch_ref_to(body) - && cs.fetch_ref_to(after); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_until& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_until(Ref cell_ref, Ref& body, Ref& after) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_until(cs, body, after) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_again& data) const { - return cs.fetch_ulong(6) == 0x31 - && cs.fetch_ref_to(data.body); -} - -bool VmCont::unpack_vmc_again(vm::CellSlice& cs, Ref& body) const { - return cs.fetch_ulong(6) == 0x31 - && cs.fetch_ref_to(body); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_again& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_again(Ref cell_ref, Ref& body) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_again(cs, body) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_while_cond& data) const { - return cs.fetch_ulong(6) == 0x32 - && cs.fetch_ref_to(data.cond) - && cs.fetch_ref_to(data.body) - && cs.fetch_ref_to(data.after); -} - -bool VmCont::unpack_vmc_while_cond(vm::CellSlice& cs, Ref& cond, Ref& body, Ref& after) const { - return cs.fetch_ulong(6) == 0x32 - && cs.fetch_ref_to(cond) - && cs.fetch_ref_to(body) - && cs.fetch_ref_to(after); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_while_cond& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_while_cond(Ref cell_ref, Ref& cond, Ref& body, Ref& after) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_while_cond(cs, cond, body, after) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_while_body& data) const { - return cs.fetch_ulong(6) == 0x33 - && cs.fetch_ref_to(data.cond) - && cs.fetch_ref_to(data.body) - && cs.fetch_ref_to(data.after); -} - -bool VmCont::unpack_vmc_while_body(vm::CellSlice& cs, Ref& cond, Ref& body, Ref& after) const { - return cs.fetch_ulong(6) == 0x33 - && cs.fetch_ref_to(cond) - && cs.fetch_ref_to(body) - && cs.fetch_ref_to(after); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_while_body& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_while_body(Ref cell_ref, Ref& cond, Ref& body, Ref& after) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_while_body(cs, cond, body, after) && cs.empty_ext(); -} - -bool VmCont::unpack(vm::CellSlice& cs, VmCont::Record_vmc_pushint& data) const { - return cs.fetch_ulong(4) == 15 - && cs.fetch_int_to(32, data.value) - && cs.fetch_ref_to(data.next); -} - -bool VmCont::unpack_vmc_pushint(vm::CellSlice& cs, int& value, Ref& next) const { - return cs.fetch_ulong(4) == 15 - && cs.fetch_int_to(32, value) - && cs.fetch_ref_to(next); -} - -bool VmCont::cell_unpack(Ref cell_ref, VmCont::Record_vmc_pushint& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool VmCont::cell_unpack_vmc_pushint(Ref cell_ref, int& value, Ref& next) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_vmc_pushint(cs, value, next) && cs.empty_ext(); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_std& data) const { - return cb.store_long_bool(0, 2) - && t_VmControlData.store_from(cb, data.cdata) - && cb.append_cellslice_chk(data.code, 0x1001a); -} - -bool VmCont::pack_vmc_std(vm::CellBuilder& cb, Ref cdata, Ref code) const { - return cb.store_long_bool(0, 2) - && t_VmControlData.store_from(cb, cdata) - && cb.append_cellslice_chk(code, 0x1001a); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_std& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_std(Ref& cell_ref, Ref cdata, Ref code) const { - vm::CellBuilder cb; - return pack_vmc_std(cb, std::move(cdata), std::move(code)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_envelope& data) const { - return cb.store_long_bool(1, 2) - && t_VmControlData.store_from(cb, data.cdata) - && cb.store_ref_bool(data.next); -} - -bool VmCont::pack_vmc_envelope(vm::CellBuilder& cb, Ref cdata, Ref next) const { - return cb.store_long_bool(1, 2) - && t_VmControlData.store_from(cb, cdata) - && cb.store_ref_bool(next); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_envelope& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_envelope(Ref& cell_ref, Ref cdata, Ref next) const { - vm::CellBuilder cb; - return pack_vmc_envelope(cb, std::move(cdata), std::move(next)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_quit& data) const { - return cb.store_long_bool(8, 4) - && cb.store_long_rchk_bool(data.exit_code, 32); -} - -bool VmCont::pack_vmc_quit(vm::CellBuilder& cb, int exit_code) const { - return cb.store_long_bool(8, 4) - && cb.store_long_rchk_bool(exit_code, 32); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_quit& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_quit(Ref& cell_ref, int exit_code) const { - vm::CellBuilder cb; - return pack_vmc_quit(cb, exit_code) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_quit_exc& data) const { - return cb.store_long_bool(9, 4); -} - -bool VmCont::pack_vmc_quit_exc(vm::CellBuilder& cb) const { - return cb.store_long_bool(9, 4); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_quit_exc& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_quit_exc(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_vmc_quit_exc(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_repeat& data) const { - return cb.store_long_bool(20, 5) - && cb.store_ulong_rchk_bool(data.count, 63) - && cb.store_ref_bool(data.body) - && cb.store_ref_bool(data.after); -} - -bool VmCont::pack_vmc_repeat(vm::CellBuilder& cb, long long count, Ref body, Ref after) const { - return cb.store_long_bool(20, 5) - && cb.store_ulong_rchk_bool(count, 63) - && cb.store_ref_bool(body) - && cb.store_ref_bool(after); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_repeat& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_repeat(Ref& cell_ref, long long count, Ref body, Ref after) const { - vm::CellBuilder cb; - return pack_vmc_repeat(cb, count, std::move(body), std::move(after)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_until& data) const { - return cb.store_long_bool(0x30, 6) - && cb.store_ref_bool(data.body) - && cb.store_ref_bool(data.after); -} - -bool VmCont::pack_vmc_until(vm::CellBuilder& cb, Ref body, Ref after) const { - return cb.store_long_bool(0x30, 6) - && cb.store_ref_bool(body) - && cb.store_ref_bool(after); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_until& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_until(Ref& cell_ref, Ref body, Ref after) const { - vm::CellBuilder cb; - return pack_vmc_until(cb, std::move(body), std::move(after)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_again& data) const { - return cb.store_long_bool(0x31, 6) - && cb.store_ref_bool(data.body); -} - -bool VmCont::pack_vmc_again(vm::CellBuilder& cb, Ref body) const { - return cb.store_long_bool(0x31, 6) - && cb.store_ref_bool(body); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_again& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_again(Ref& cell_ref, Ref body) const { - vm::CellBuilder cb; - return pack_vmc_again(cb, std::move(body)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_while_cond& data) const { - return cb.store_long_bool(0x32, 6) - && cb.store_ref_bool(data.cond) - && cb.store_ref_bool(data.body) - && cb.store_ref_bool(data.after); -} - -bool VmCont::pack_vmc_while_cond(vm::CellBuilder& cb, Ref cond, Ref body, Ref after) const { - return cb.store_long_bool(0x32, 6) - && cb.store_ref_bool(cond) - && cb.store_ref_bool(body) - && cb.store_ref_bool(after); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_while_cond& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_while_cond(Ref& cell_ref, Ref cond, Ref body, Ref after) const { - vm::CellBuilder cb; - return pack_vmc_while_cond(cb, std::move(cond), std::move(body), std::move(after)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_while_body& data) const { - return cb.store_long_bool(0x33, 6) - && cb.store_ref_bool(data.cond) - && cb.store_ref_bool(data.body) - && cb.store_ref_bool(data.after); -} - -bool VmCont::pack_vmc_while_body(vm::CellBuilder& cb, Ref cond, Ref body, Ref after) const { - return cb.store_long_bool(0x33, 6) - && cb.store_ref_bool(cond) - && cb.store_ref_bool(body) - && cb.store_ref_bool(after); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_while_body& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_while_body(Ref& cell_ref, Ref cond, Ref body, Ref after) const { - vm::CellBuilder cb; - return pack_vmc_while_body(cb, std::move(cond), std::move(body), std::move(after)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::pack(vm::CellBuilder& cb, const VmCont::Record_vmc_pushint& data) const { - return cb.store_long_bool(15, 4) - && cb.store_long_rchk_bool(data.value, 32) - && cb.store_ref_bool(data.next); -} - -bool VmCont::pack_vmc_pushint(vm::CellBuilder& cb, int value, Ref next) const { - return cb.store_long_bool(15, 4) - && cb.store_long_rchk_bool(value, 32) - && cb.store_ref_bool(next); -} - -bool VmCont::cell_pack(Ref& cell_ref, const VmCont::Record_vmc_pushint& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::cell_pack_vmc_pushint(Ref& cell_ref, int value, Ref next) const { - vm::CellBuilder cb; - return pack_vmc_pushint(cb, value, std::move(next)) && std::move(cb).finalize_to(cell_ref); -} - -bool VmCont::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case vmc_std: - return cs.advance(2) - && pp.open("vmc_std") - && pp.field("cdata") - && t_VmControlData.print_skip(pp, cs) - && pp.field("code") - && t_VmCellSlice.print_skip(pp, cs) - && pp.close(); - case vmc_envelope: - return cs.advance(2) - && pp.open("vmc_envelope") - && pp.field("cdata") - && t_VmControlData.print_skip(pp, cs) - && pp.field("next") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_quit: - return cs.advance(4) - && pp.open("vmc_quit") - && pp.fetch_int_field(cs, 32, "exit_code") - && pp.close(); - case vmc_quit_exc: - return cs.advance(4) - && pp.cons("vmc_quit_exc"); - case vmc_repeat: - return cs.fetch_ulong(5) == 20 - && pp.open("vmc_repeat") - && pp.fetch_uint_field(cs, 63, "count") - && pp.field("body") - && print_ref(pp, cs.fetch_ref()) - && pp.field("after") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_until: - return cs.advance(6) - && pp.open("vmc_until") - && pp.field("body") - && print_ref(pp, cs.fetch_ref()) - && pp.field("after") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_again: - return cs.advance(6) - && pp.open("vmc_again") - && pp.field("body") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_while_cond: - return cs.advance(6) - && pp.open("vmc_while_cond") - && pp.field("cond") - && print_ref(pp, cs.fetch_ref()) - && pp.field("body") - && print_ref(pp, cs.fetch_ref()) - && pp.field("after") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_while_body: - return cs.fetch_ulong(6) == 0x33 - && pp.open("vmc_while_body") - && pp.field("cond") - && print_ref(pp, cs.fetch_ref()) - && pp.field("body") - && print_ref(pp, cs.fetch_ref()) - && pp.field("after") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - case vmc_pushint: - return cs.advance(4) - && pp.open("vmc_pushint") - && pp.fetch_int_field(cs, 32, "value") - && pp.field("next") - && print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - return pp.fail("unknown constructor for VmCont"); -} - -const VmCont t_VmCont; - -// -// code for type `DNS_RecordSet` -// - -int DNS_RecordSet::check_tag(const vm::CellSlice& cs) const { - return cons1; -} - -bool DNS_RecordSet::skip(vm::CellSlice& cs) const { - return t_HashmapE_16_Ref_DNSRecord.skip(cs); -} - -bool DNS_RecordSet::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_HashmapE_16_Ref_DNSRecord.validate_skip(ops, cs, weak); -} - -bool DNS_RecordSet::unpack(vm::CellSlice& cs, DNS_RecordSet::Record& data) const { - return t_HashmapE_16_Ref_DNSRecord.fetch_to(cs, data.x); -} - -bool DNS_RecordSet::unpack_cons1(vm::CellSlice& cs, Ref& x) const { - return t_HashmapE_16_Ref_DNSRecord.fetch_to(cs, x); -} - -bool DNS_RecordSet::cell_unpack(Ref cell_ref, DNS_RecordSet::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DNS_RecordSet::cell_unpack_cons1(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cons1(cs, x) && cs.empty_ext(); -} - -bool DNS_RecordSet::pack(vm::CellBuilder& cb, const DNS_RecordSet::Record& data) const { - return t_HashmapE_16_Ref_DNSRecord.store_from(cb, data.x); -} - -bool DNS_RecordSet::pack_cons1(vm::CellBuilder& cb, Ref x) const { - return t_HashmapE_16_Ref_DNSRecord.store_from(cb, x); -} - -bool DNS_RecordSet::cell_pack(Ref& cell_ref, const DNS_RecordSet::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DNS_RecordSet::cell_pack_cons1(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_cons1(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool DNS_RecordSet::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open() - && pp.field() - && t_HashmapE_16_Ref_DNSRecord.print_skip(pp, cs) - && pp.close(); -} - -const DNS_RecordSet t_DNS_RecordSet; - -// -// code for type `TextChunkRef` -// - -int TextChunkRef::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 2 1 1 1 - return m_ ? chunk_ref : chunk_ref_empty; -} - -int TextChunkRef::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chunk_ref: - return chunk_ref; - case chunk_ref_empty: - return chunk_ref_empty; - } - return -1; -} - -bool TextChunkRef::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chunk_ref: { - int n; - return add_r1(n, 1, m_) - && cs.advance_refs(1); - } - case chunk_ref_empty: - return m_ == 0; - } - return false; -} - -bool TextChunkRef::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case chunk_ref: { - int n; - return add_r1(n, 1, m_) - && TextChunks{n + 1}.validate_skip_ref(ops, cs, weak); - } - case chunk_ref_empty: - return m_ == 0; - } - return false; -} - -bool TextChunkRef::unpack(vm::CellSlice& cs, TextChunkRef::Record_chunk_ref& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_ref_to(data.ref); -} - -bool TextChunkRef::unpack_chunk_ref(vm::CellSlice& cs, int& n, Ref& ref) const { - return add_r1(n, 1, m_) - && cs.fetch_ref_to(ref); -} - -bool TextChunkRef::cell_unpack(Ref cell_ref, TextChunkRef::Record_chunk_ref& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TextChunkRef::cell_unpack_chunk_ref(Ref cell_ref, int& n, Ref& ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chunk_ref(cs, n, ref) && cs.empty_ext(); -} - -bool TextChunkRef::unpack(vm::CellSlice& cs, TextChunkRef::Record_chunk_ref_empty& data) const { - return m_ == 0; -} - -bool TextChunkRef::unpack_chunk_ref_empty(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool TextChunkRef::cell_unpack(Ref cell_ref, TextChunkRef::Record_chunk_ref_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TextChunkRef::cell_unpack_chunk_ref_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chunk_ref_empty(cs) && cs.empty_ext(); -} - -bool TextChunkRef::pack(vm::CellBuilder& cb, const TextChunkRef::Record_chunk_ref& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(data.ref); -} - -bool TextChunkRef::pack_chunk_ref(vm::CellBuilder& cb, Ref ref) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ref_bool(ref); -} - -bool TextChunkRef::cell_pack(Ref& cell_ref, const TextChunkRef::Record_chunk_ref& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunkRef::cell_pack_chunk_ref(Ref& cell_ref, Ref ref) const { - vm::CellBuilder cb; - return pack_chunk_ref(cb, std::move(ref)) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunkRef::pack(vm::CellBuilder& cb, const TextChunkRef::Record_chunk_ref_empty& data) const { - return m_ == 0; -} - -bool TextChunkRef::pack_chunk_ref_empty(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool TextChunkRef::cell_pack(Ref& cell_ref, const TextChunkRef::Record_chunk_ref_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunkRef::cell_pack_chunk_ref_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_chunk_ref_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunkRef::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chunk_ref: { - int n; - return pp.open("chunk_ref") - && add_r1(n, 1, m_) - && pp.field("ref") - && TextChunks{n + 1}.print_ref(pp, cs.fetch_ref()) - && pp.close(); - } - case chunk_ref_empty: - return pp.cons("chunk_ref_empty") - && m_ == 0; - } - return pp.fail("unknown constructor for TextChunkRef"); -} - - -// -// code for type `TextChunks` -// - -int TextChunks::get_tag(const vm::CellSlice& cs) const { - // distinguish by parameter `m_` using 2 1 1 1 - return m_ ? text_chunk : text_chunk_empty; -} - -int TextChunks::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case text_chunk: - return text_chunk; - case text_chunk_empty: - return text_chunk_empty; - } - return -1; -} - -bool TextChunks::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case text_chunk: { - int n, len; - return add_r1(n, 1, m_) - && cs.fetch_uint_to(8, len) - && cs.advance(8 * len) - && TextChunkRef{n}.skip(cs); - } - case text_chunk_empty: - return m_ == 0; - } - return false; -} - -bool TextChunks::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case text_chunk: { - int n, len; - return add_r1(n, 1, m_) - && cs.fetch_uint_to(8, len) - && cs.advance(8 * len) - && TextChunkRef{n}.validate_skip(ops, cs, weak); - } - case text_chunk_empty: - return m_ == 0; - } - return false; -} - -bool TextChunks::unpack(vm::CellSlice& cs, TextChunks::Record_text_chunk& data) const { - return add_r1(data.n, 1, m_) - && cs.fetch_uint_to(8, data.len) - && cs.fetch_bitstring_to(8 * data.len, data.data) - && TextChunkRef{data.n}.fetch_to(cs, data.next); -} - -bool TextChunks::cell_unpack(Ref cell_ref, TextChunks::Record_text_chunk& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TextChunks::unpack(vm::CellSlice& cs, TextChunks::Record_text_chunk_empty& data) const { - return m_ == 0; -} - -bool TextChunks::unpack_text_chunk_empty(vm::CellSlice& cs) const { - return m_ == 0; -} - -bool TextChunks::cell_unpack(Ref cell_ref, TextChunks::Record_text_chunk_empty& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool TextChunks::cell_unpack_text_chunk_empty(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_text_chunk_empty(cs) && cs.empty_ext(); -} - -bool TextChunks::pack(vm::CellBuilder& cb, const TextChunks::Record_text_chunk& data) const { - int n; - return add_r1(n, 1, m_) - && cb.store_ulong_rchk_bool(data.len, 8) - && cb.append_bitstring_chk(data.data, 8 * data.len) - && TextChunkRef{n}.store_from(cb, data.next); -} - -bool TextChunks::cell_pack(Ref& cell_ref, const TextChunks::Record_text_chunk& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunks::pack(vm::CellBuilder& cb, const TextChunks::Record_text_chunk_empty& data) const { - return m_ == 0; -} - -bool TextChunks::pack_text_chunk_empty(vm::CellBuilder& cb) const { - return m_ == 0; -} - -bool TextChunks::cell_pack(Ref& cell_ref, const TextChunks::Record_text_chunk_empty& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunks::cell_pack_text_chunk_empty(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_text_chunk_empty(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool TextChunks::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case text_chunk: { - int n, len; - return pp.open("text_chunk") - && add_r1(n, 1, m_) - && cs.fetch_uint_to(8, len) - && pp.field_int(len, "len") - && pp.fetch_bits_field(cs, 8 * len, "data") - && pp.field("next") - && TextChunkRef{n}.print_skip(pp, cs) - && pp.close(); - } - case text_chunk_empty: - return pp.cons("text_chunk_empty") - && m_ == 0; - } - return pp.fail("unknown constructor for TextChunks"); -} - - -// -// code for type `Text` -// - -int Text::check_tag(const vm::CellSlice& cs) const { - return text; -} - -bool Text::skip(vm::CellSlice& cs) const { - int chunks; - return cs.fetch_uint_to(8, chunks) - && TextChunks{chunks}.skip(cs); -} - -bool Text::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int chunks; - return cs.fetch_uint_to(8, chunks) - && TextChunks{chunks}.validate_skip(ops, cs, weak); -} - -bool Text::unpack(vm::CellSlice& cs, Text::Record& data) const { - return cs.fetch_uint_to(8, data.chunks) - && TextChunks{data.chunks}.fetch_to(cs, data.rest); -} - -bool Text::unpack_text(vm::CellSlice& cs, int& chunks, Ref& rest) const { - return cs.fetch_uint_to(8, chunks) - && TextChunks{chunks}.fetch_to(cs, rest); -} - -bool Text::cell_unpack(Ref cell_ref, Text::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Text::cell_unpack_text(Ref cell_ref, int& chunks, Ref& rest) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_text(cs, chunks, rest) && cs.empty_ext(); -} - -bool Text::pack(vm::CellBuilder& cb, const Text::Record& data) const { - return cb.store_ulong_rchk_bool(data.chunks, 8) - && TextChunks{data.chunks}.store_from(cb, data.rest); -} - -bool Text::pack_text(vm::CellBuilder& cb, int chunks, Ref rest) const { - return cb.store_ulong_rchk_bool(chunks, 8) - && TextChunks{chunks}.store_from(cb, rest); -} - -bool Text::cell_pack(Ref& cell_ref, const Text::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Text::cell_pack_text(Ref& cell_ref, int chunks, Ref rest) const { - vm::CellBuilder cb; - return pack_text(cb, chunks, std::move(rest)) && std::move(cb).finalize_to(cell_ref); -} - -bool Text::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int chunks; - return pp.open("text") - && cs.fetch_uint_to(8, chunks) - && pp.field_int(chunks, "chunks") - && pp.field("rest") - && TextChunks{chunks}.print_skip(pp, cs) - && pp.close(); -} - -const Text t_Text; - -// -// code for type `ProtoList` -// - -int ProtoList::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case proto_list_nil: - return cs.have(1) ? proto_list_nil : -1; - case proto_list_next: - return cs.have(1) ? proto_list_next : -1; - } - return -1; -} - -bool ProtoList::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case proto_list_nil: - return cs.advance(1); - case proto_list_next: - return cs.advance(17) - && skip(cs); - } - return false; -} - -bool ProtoList::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case proto_list_nil: - return cs.advance(1); - case proto_list_next: - return cs.advance(1) - && t_Protocol.validate_skip(ops, cs, weak) - && validate_skip(ops, cs, weak); - } - return false; -} - -bool ProtoList::unpack(vm::CellSlice& cs, ProtoList::Record_proto_list_nil& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool ProtoList::unpack_proto_list_nil(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool ProtoList::cell_unpack(Ref cell_ref, ProtoList::Record_proto_list_nil& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProtoList::cell_unpack_proto_list_nil(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_proto_list_nil(cs) && cs.empty_ext(); -} - -bool ProtoList::unpack(vm::CellSlice& cs, ProtoList::Record_proto_list_next& data) const { - return cs.fetch_ulong(1) == 1 - && t_Protocol.fetch_enum_to(cs, data.head) - && fetch_to(cs, data.tail); -} - -bool ProtoList::unpack_proto_list_next(vm::CellSlice& cs, char& head, Ref& tail) const { - return cs.fetch_ulong(1) == 1 - && t_Protocol.fetch_enum_to(cs, head) - && fetch_to(cs, tail); -} - -bool ProtoList::cell_unpack(Ref cell_ref, ProtoList::Record_proto_list_next& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ProtoList::cell_unpack_proto_list_next(Ref cell_ref, char& head, Ref& tail) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_proto_list_next(cs, head, tail) && cs.empty_ext(); -} - -bool ProtoList::pack(vm::CellBuilder& cb, const ProtoList::Record_proto_list_nil& data) const { - return cb.store_long_bool(0, 1); -} - -bool ProtoList::pack_proto_list_nil(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool ProtoList::cell_pack(Ref& cell_ref, const ProtoList::Record_proto_list_nil& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProtoList::cell_pack_proto_list_nil(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_proto_list_nil(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ProtoList::pack(vm::CellBuilder& cb, const ProtoList::Record_proto_list_next& data) const { - return cb.store_long_bool(1, 1) - && t_Protocol.store_enum_from(cb, data.head) - && store_from(cb, data.tail); -} - -bool ProtoList::pack_proto_list_next(vm::CellBuilder& cb, char head, Ref tail) const { - return cb.store_long_bool(1, 1) - && t_Protocol.store_enum_from(cb, head) - && store_from(cb, tail); -} - -bool ProtoList::cell_pack(Ref& cell_ref, const ProtoList::Record_proto_list_next& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ProtoList::cell_pack_proto_list_next(Ref& cell_ref, char head, Ref tail) const { - vm::CellBuilder cb; - return pack_proto_list_next(cb, head, std::move(tail)) && std::move(cb).finalize_to(cell_ref); -} - -bool ProtoList::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case proto_list_nil: - return cs.advance(1) - && pp.cons("proto_list_nil"); - case proto_list_next: - return cs.advance(1) - && pp.open("proto_list_next") - && pp.field("head") - && t_Protocol.print_skip(pp, cs) - && pp.field("tail") - && print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for ProtoList"); -} - -const ProtoList t_ProtoList; - -// -// code for type `Protocol` -// -constexpr unsigned short Protocol::cons_tag[1]; - -int Protocol::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(16) == 0x4854 ? proto_http : -1; -} - -bool Protocol::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(16) == 0x4854; -} - -bool Protocol::fetch_enum_to(vm::CellSlice& cs, char& value) const { - value = (cs.fetch_ulong(16) == 0x4854) ? 0 : -1; - return !value; -} - -bool Protocol::store_enum_from(vm::CellBuilder& cb, int value) const { - return !value && cb.store_long_bool(0x4854, 16); -} - -bool Protocol::unpack(vm::CellSlice& cs, Protocol::Record& data) const { - return cs.fetch_ulong(16) == 0x4854; -} - -bool Protocol::unpack_proto_http(vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x4854; -} - -bool Protocol::cell_unpack(Ref cell_ref, Protocol::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool Protocol::cell_unpack_proto_http(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_proto_http(cs) && cs.empty_ext(); -} - -bool Protocol::pack(vm::CellBuilder& cb, const Protocol::Record& data) const { - return cb.store_long_bool(0x4854, 16); -} - -bool Protocol::pack_proto_http(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x4854, 16); -} - -bool Protocol::cell_pack(Ref& cell_ref, const Protocol::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool Protocol::cell_pack_proto_http(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_proto_http(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool Protocol::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x4854 - && pp.cons("proto_http"); -} - -const Protocol t_Protocol; - -// -// code for type `DNSRecord` -// -constexpr unsigned short DNSRecord::cons_tag[4]; - -int DNSRecord::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case dns_text: - return cs.prefetch_ulong(16) == 0x1eda ? dns_text : -1; - case dns_next_resolver: - return cs.prefetch_ulong(16) == 0xba93 ? dns_next_resolver : -1; - case dns_adnl_address: - return cs.prefetch_ulong(16) == 0xad01 ? dns_adnl_address : -1; - case dns_smc_address: - return cs.prefetch_ulong(16) == 0x9fd3 ? dns_smc_address : -1; - } - return -1; -} - -bool DNSRecord::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case dns_text: - return cs.advance(16) - && t_Text.skip(cs); - case dns_next_resolver: - return cs.advance(16) - && t_MsgAddressInt.skip(cs); - case dns_adnl_address: { - int flags; - return cs.advance(272) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_ProtoList.skip(cs)); - } - case dns_smc_address: { - int flags; - return cs.advance(16) - && t_MsgAddressInt.skip(cs) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_SmcCapList.skip(cs)); - } - } - return false; -} - -bool DNSRecord::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case dns_text: - return cs.fetch_ulong(16) == 0x1eda - && t_Text.validate_skip(ops, cs, weak); - case dns_next_resolver: - return cs.fetch_ulong(16) == 0xba93 - && t_MsgAddressInt.validate_skip(ops, cs, weak); - case dns_adnl_address: { - int flags; - return cs.fetch_ulong(16) == 0xad01 - && cs.advance(256) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_ProtoList.validate_skip(ops, cs, weak)); - } - case dns_smc_address: { - int flags; - return cs.fetch_ulong(16) == 0x9fd3 - && t_MsgAddressInt.validate_skip(ops, cs, weak) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_SmcCapList.validate_skip(ops, cs, weak)); - } - } - return false; -} - -bool DNSRecord::unpack(vm::CellSlice& cs, DNSRecord::Record_dns_text& data) const { - return cs.fetch_ulong(16) == 0x1eda - && t_Text.fetch_to(cs, data.x); -} - -bool DNSRecord::unpack_dns_text(vm::CellSlice& cs, Ref& x) const { - return cs.fetch_ulong(16) == 0x1eda - && t_Text.fetch_to(cs, x); -} - -bool DNSRecord::cell_unpack(Ref cell_ref, DNSRecord::Record_dns_text& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DNSRecord::cell_unpack_dns_text(Ref cell_ref, Ref& x) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_dns_text(cs, x) && cs.empty_ext(); -} - -bool DNSRecord::unpack(vm::CellSlice& cs, DNSRecord::Record_dns_next_resolver& data) const { - return cs.fetch_ulong(16) == 0xba93 - && t_MsgAddressInt.fetch_to(cs, data.resolver); -} - -bool DNSRecord::unpack_dns_next_resolver(vm::CellSlice& cs, Ref& resolver) const { - return cs.fetch_ulong(16) == 0xba93 - && t_MsgAddressInt.fetch_to(cs, resolver); -} - -bool DNSRecord::cell_unpack(Ref cell_ref, DNSRecord::Record_dns_next_resolver& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DNSRecord::cell_unpack_dns_next_resolver(Ref cell_ref, Ref& resolver) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_dns_next_resolver(cs, resolver) && cs.empty_ext(); -} - -bool DNSRecord::unpack(vm::CellSlice& cs, DNSRecord::Record_dns_adnl_address& data) const { - return cs.fetch_ulong(16) == 0xad01 - && cs.fetch_bits_to(data.adnl_addr.bits(), 256) - && cs.fetch_uint_to(8, data.flags) - && data.flags <= 1 - && (!(data.flags & 1) || t_ProtoList.fetch_to(cs, data.proto_list)); -} - -bool DNSRecord::unpack_dns_adnl_address(vm::CellSlice& cs, td::BitArray<256>& adnl_addr, int& flags, Ref& proto_list) const { - return cs.fetch_ulong(16) == 0xad01 - && cs.fetch_bits_to(adnl_addr.bits(), 256) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_ProtoList.fetch_to(cs, proto_list)); -} - -bool DNSRecord::cell_unpack(Ref cell_ref, DNSRecord::Record_dns_adnl_address& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DNSRecord::cell_unpack_dns_adnl_address(Ref cell_ref, td::BitArray<256>& adnl_addr, int& flags, Ref& proto_list) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_dns_adnl_address(cs, adnl_addr, flags, proto_list) && cs.empty_ext(); -} - -bool DNSRecord::unpack(vm::CellSlice& cs, DNSRecord::Record_dns_smc_address& data) const { - return cs.fetch_ulong(16) == 0x9fd3 - && t_MsgAddressInt.fetch_to(cs, data.smc_addr) - && cs.fetch_uint_to(8, data.flags) - && data.flags <= 1 - && (!(data.flags & 1) || t_SmcCapList.fetch_to(cs, data.cap_list)); -} - -bool DNSRecord::unpack_dns_smc_address(vm::CellSlice& cs, Ref& smc_addr, int& flags, Ref& cap_list) const { - return cs.fetch_ulong(16) == 0x9fd3 - && t_MsgAddressInt.fetch_to(cs, smc_addr) - && cs.fetch_uint_to(8, flags) - && flags <= 1 - && (!(flags & 1) || t_SmcCapList.fetch_to(cs, cap_list)); -} - -bool DNSRecord::cell_unpack(Ref cell_ref, DNSRecord::Record_dns_smc_address& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool DNSRecord::cell_unpack_dns_smc_address(Ref cell_ref, Ref& smc_addr, int& flags, Ref& cap_list) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_dns_smc_address(cs, smc_addr, flags, cap_list) && cs.empty_ext(); -} - -bool DNSRecord::pack(vm::CellBuilder& cb, const DNSRecord::Record_dns_text& data) const { - return cb.store_long_bool(0x1eda, 16) - && t_Text.store_from(cb, data.x); -} - -bool DNSRecord::pack_dns_text(vm::CellBuilder& cb, Ref x) const { - return cb.store_long_bool(0x1eda, 16) - && t_Text.store_from(cb, x); -} - -bool DNSRecord::cell_pack(Ref& cell_ref, const DNSRecord::Record_dns_text& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::cell_pack_dns_text(Ref& cell_ref, Ref x) const { - vm::CellBuilder cb; - return pack_dns_text(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::pack(vm::CellBuilder& cb, const DNSRecord::Record_dns_next_resolver& data) const { - return cb.store_long_bool(0xba93, 16) - && t_MsgAddressInt.store_from(cb, data.resolver); -} - -bool DNSRecord::pack_dns_next_resolver(vm::CellBuilder& cb, Ref resolver) const { - return cb.store_long_bool(0xba93, 16) - && t_MsgAddressInt.store_from(cb, resolver); -} - -bool DNSRecord::cell_pack(Ref& cell_ref, const DNSRecord::Record_dns_next_resolver& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::cell_pack_dns_next_resolver(Ref& cell_ref, Ref resolver) const { - vm::CellBuilder cb; - return pack_dns_next_resolver(cb, std::move(resolver)) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::pack(vm::CellBuilder& cb, const DNSRecord::Record_dns_adnl_address& data) const { - return cb.store_long_bool(0xad01, 16) - && cb.store_bits_bool(data.adnl_addr.cbits(), 256) - && cb.store_ulong_rchk_bool(data.flags, 8) - && data.flags <= 1 - && (!(data.flags & 1) || t_ProtoList.store_from(cb, data.proto_list)); -} - -bool DNSRecord::pack_dns_adnl_address(vm::CellBuilder& cb, td::BitArray<256> adnl_addr, int flags, Ref proto_list) const { - return cb.store_long_bool(0xad01, 16) - && cb.store_bits_bool(adnl_addr.cbits(), 256) - && cb.store_ulong_rchk_bool(flags, 8) - && flags <= 1 - && (!(flags & 1) || t_ProtoList.store_from(cb, proto_list)); -} - -bool DNSRecord::cell_pack(Ref& cell_ref, const DNSRecord::Record_dns_adnl_address& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::cell_pack_dns_adnl_address(Ref& cell_ref, td::BitArray<256> adnl_addr, int flags, Ref proto_list) const { - vm::CellBuilder cb; - return pack_dns_adnl_address(cb, adnl_addr, flags, std::move(proto_list)) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::pack(vm::CellBuilder& cb, const DNSRecord::Record_dns_smc_address& data) const { - return cb.store_long_bool(0x9fd3, 16) - && t_MsgAddressInt.store_from(cb, data.smc_addr) - && cb.store_ulong_rchk_bool(data.flags, 8) - && data.flags <= 1 - && (!(data.flags & 1) || t_SmcCapList.store_from(cb, data.cap_list)); -} - -bool DNSRecord::pack_dns_smc_address(vm::CellBuilder& cb, Ref smc_addr, int flags, Ref cap_list) const { - return cb.store_long_bool(0x9fd3, 16) - && t_MsgAddressInt.store_from(cb, smc_addr) - && cb.store_ulong_rchk_bool(flags, 8) - && flags <= 1 - && (!(flags & 1) || t_SmcCapList.store_from(cb, cap_list)); -} - -bool DNSRecord::cell_pack(Ref& cell_ref, const DNSRecord::Record_dns_smc_address& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::cell_pack_dns_smc_address(Ref& cell_ref, Ref smc_addr, int flags, Ref cap_list) const { - vm::CellBuilder cb; - return pack_dns_smc_address(cb, std::move(smc_addr), flags, std::move(cap_list)) && std::move(cb).finalize_to(cell_ref); -} - -bool DNSRecord::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case dns_text: - return cs.fetch_ulong(16) == 0x1eda - && pp.open("dns_text") - && pp.field() - && t_Text.print_skip(pp, cs) - && pp.close(); - case dns_next_resolver: - return cs.fetch_ulong(16) == 0xba93 - && pp.open("dns_next_resolver") - && pp.field("resolver") - && t_MsgAddressInt.print_skip(pp, cs) - && pp.close(); - case dns_adnl_address: { - int flags; - return cs.fetch_ulong(16) == 0xad01 - && pp.open("dns_adnl_address") - && pp.fetch_bits_field(cs, 256, "adnl_addr") - && cs.fetch_uint_to(8, flags) - && pp.field_int(flags, "flags") - && flags <= 1 - && (!(flags & 1) || (pp.field("proto_list") && t_ProtoList.print_skip(pp, cs))) - && pp.close(); - } - case dns_smc_address: { - int flags; - return cs.fetch_ulong(16) == 0x9fd3 - && pp.open("dns_smc_address") - && pp.field("smc_addr") - && t_MsgAddressInt.print_skip(pp, cs) - && cs.fetch_uint_to(8, flags) - && pp.field_int(flags, "flags") - && flags <= 1 - && (!(flags & 1) || (pp.field("cap_list") && t_SmcCapList.print_skip(pp, cs))) - && pp.close(); - } - } - return pp.fail("unknown constructor for DNSRecord"); -} - -const DNSRecord t_DNSRecord; - -// -// code for type `SmcCapList` -// - -int SmcCapList::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_list_nil: - return cs.have(1) ? cap_list_nil : -1; - case cap_list_next: - return cs.have(1) ? cap_list_next : -1; - } - return -1; -} - -bool SmcCapList::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_list_nil: - return cs.advance(1); - case cap_list_next: - return cs.advance(1) - && t_SmcCapability.skip(cs) - && skip(cs); - } - return false; -} - -bool SmcCapList::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cap_list_nil: - return cs.advance(1); - case cap_list_next: - return cs.advance(1) - && t_SmcCapability.validate_skip(ops, cs, weak) - && validate_skip(ops, cs, weak); - } - return false; -} - -bool SmcCapList::unpack(vm::CellSlice& cs, SmcCapList::Record_cap_list_nil& data) const { - return cs.fetch_ulong(1) == 0; -} - -bool SmcCapList::unpack_cap_list_nil(vm::CellSlice& cs) const { - return cs.fetch_ulong(1) == 0; -} - -bool SmcCapList::cell_unpack(Ref cell_ref, SmcCapList::Record_cap_list_nil& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapList::cell_unpack_cap_list_nil(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_list_nil(cs) && cs.empty_ext(); -} - -bool SmcCapList::unpack(vm::CellSlice& cs, SmcCapList::Record_cap_list_next& data) const { - return cs.fetch_ulong(1) == 1 - && t_SmcCapability.fetch_to(cs, data.head) - && fetch_to(cs, data.tail); -} - -bool SmcCapList::unpack_cap_list_next(vm::CellSlice& cs, Ref& head, Ref& tail) const { - return cs.fetch_ulong(1) == 1 - && t_SmcCapability.fetch_to(cs, head) - && fetch_to(cs, tail); -} - -bool SmcCapList::cell_unpack(Ref cell_ref, SmcCapList::Record_cap_list_next& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapList::cell_unpack_cap_list_next(Ref cell_ref, Ref& head, Ref& tail) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_list_next(cs, head, tail) && cs.empty_ext(); -} - -bool SmcCapList::pack(vm::CellBuilder& cb, const SmcCapList::Record_cap_list_nil& data) const { - return cb.store_long_bool(0, 1); -} - -bool SmcCapList::pack_cap_list_nil(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 1); -} - -bool SmcCapList::cell_pack(Ref& cell_ref, const SmcCapList::Record_cap_list_nil& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapList::cell_pack_cap_list_nil(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cap_list_nil(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapList::pack(vm::CellBuilder& cb, const SmcCapList::Record_cap_list_next& data) const { - return cb.store_long_bool(1, 1) - && t_SmcCapability.store_from(cb, data.head) - && store_from(cb, data.tail); -} - -bool SmcCapList::pack_cap_list_next(vm::CellBuilder& cb, Ref head, Ref tail) const { - return cb.store_long_bool(1, 1) - && t_SmcCapability.store_from(cb, head) - && store_from(cb, tail); -} - -bool SmcCapList::cell_pack(Ref& cell_ref, const SmcCapList::Record_cap_list_next& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapList::cell_pack_cap_list_next(Ref& cell_ref, Ref head, Ref tail) const { - vm::CellBuilder cb; - return pack_cap_list_next(cb, std::move(head), std::move(tail)) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapList::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_list_nil: - return cs.advance(1) - && pp.cons("cap_list_nil"); - case cap_list_next: - return cs.advance(1) - && pp.open("cap_list_next") - && pp.field("head") - && t_SmcCapability.print_skip(pp, cs) - && pp.field("tail") - && print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for SmcCapList"); -} - -const SmcCapList t_SmcCapList; - -// -// code for type `SmcCapability` -// -constexpr char SmcCapability::cons_len[4]; -constexpr unsigned short SmcCapability::cons_tag[4]; - -int SmcCapability::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_method_seqno: - return cs.prefetch_ulong(16) == 0x5371 ? cap_method_seqno : -1; - case cap_method_pubkey: - return cs.prefetch_ulong(16) == 0x71f4 ? cap_method_pubkey : -1; - case cap_is_wallet: - return cs.prefetch_ulong(16) == 0x2177 ? cap_is_wallet : -1; - case cap_name: - return cs.prefetch_ulong(8) == 0xff ? cap_name : -1; - } - return -1; -} - -bool SmcCapability::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_method_seqno: - return cs.advance(16); - case cap_method_pubkey: - return cs.advance(16); - case cap_is_wallet: - return cs.advance(16); - case cap_name: - return cs.advance(8) - && t_Text.skip(cs); - } - return false; -} - -bool SmcCapability::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case cap_method_seqno: - return cs.fetch_ulong(16) == 0x5371; - case cap_method_pubkey: - return cs.fetch_ulong(16) == 0x71f4; - case cap_is_wallet: - return cs.fetch_ulong(16) == 0x2177; - case cap_name: - return cs.fetch_ulong(8) == 0xff - && t_Text.validate_skip(ops, cs, weak); - } - return false; -} - -bool SmcCapability::unpack(vm::CellSlice& cs, SmcCapability::Record_cap_method_seqno& data) const { - return cs.fetch_ulong(16) == 0x5371; -} - -bool SmcCapability::unpack_cap_method_seqno(vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x5371; -} - -bool SmcCapability::cell_unpack(Ref cell_ref, SmcCapability::Record_cap_method_seqno& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapability::cell_unpack_cap_method_seqno(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_method_seqno(cs) && cs.empty_ext(); -} - -bool SmcCapability::unpack(vm::CellSlice& cs, SmcCapability::Record_cap_method_pubkey& data) const { - return cs.fetch_ulong(16) == 0x71f4; -} - -bool SmcCapability::unpack_cap_method_pubkey(vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x71f4; -} - -bool SmcCapability::cell_unpack(Ref cell_ref, SmcCapability::Record_cap_method_pubkey& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapability::cell_unpack_cap_method_pubkey(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_method_pubkey(cs) && cs.empty_ext(); -} - -bool SmcCapability::unpack(vm::CellSlice& cs, SmcCapability::Record_cap_is_wallet& data) const { - return cs.fetch_ulong(16) == 0x2177; -} - -bool SmcCapability::unpack_cap_is_wallet(vm::CellSlice& cs) const { - return cs.fetch_ulong(16) == 0x2177; -} - -bool SmcCapability::cell_unpack(Ref cell_ref, SmcCapability::Record_cap_is_wallet& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapability::cell_unpack_cap_is_wallet(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_is_wallet(cs) && cs.empty_ext(); -} - -bool SmcCapability::unpack(vm::CellSlice& cs, SmcCapability::Record_cap_name& data) const { - return cs.fetch_ulong(8) == 0xff - && t_Text.fetch_to(cs, data.name); -} - -bool SmcCapability::unpack_cap_name(vm::CellSlice& cs, Ref& name) const { - return cs.fetch_ulong(8) == 0xff - && t_Text.fetch_to(cs, name); -} - -bool SmcCapability::cell_unpack(Ref cell_ref, SmcCapability::Record_cap_name& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool SmcCapability::cell_unpack_cap_name(Ref cell_ref, Ref& name) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_cap_name(cs, name) && cs.empty_ext(); -} - -bool SmcCapability::pack(vm::CellBuilder& cb, const SmcCapability::Record_cap_method_seqno& data) const { - return cb.store_long_bool(0x5371, 16); -} - -bool SmcCapability::pack_cap_method_seqno(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x5371, 16); -} - -bool SmcCapability::cell_pack(Ref& cell_ref, const SmcCapability::Record_cap_method_seqno& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::cell_pack_cap_method_seqno(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cap_method_seqno(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::pack(vm::CellBuilder& cb, const SmcCapability::Record_cap_method_pubkey& data) const { - return cb.store_long_bool(0x71f4, 16); -} - -bool SmcCapability::pack_cap_method_pubkey(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x71f4, 16); -} - -bool SmcCapability::cell_pack(Ref& cell_ref, const SmcCapability::Record_cap_method_pubkey& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::cell_pack_cap_method_pubkey(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cap_method_pubkey(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::pack(vm::CellBuilder& cb, const SmcCapability::Record_cap_is_wallet& data) const { - return cb.store_long_bool(0x2177, 16); -} - -bool SmcCapability::pack_cap_is_wallet(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x2177, 16); -} - -bool SmcCapability::cell_pack(Ref& cell_ref, const SmcCapability::Record_cap_is_wallet& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::cell_pack_cap_is_wallet(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_cap_is_wallet(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::pack(vm::CellBuilder& cb, const SmcCapability::Record_cap_name& data) const { - return cb.store_long_bool(0xff, 8) - && t_Text.store_from(cb, data.name); -} - -bool SmcCapability::pack_cap_name(vm::CellBuilder& cb, Ref name) const { - return cb.store_long_bool(0xff, 8) - && t_Text.store_from(cb, name); -} - -bool SmcCapability::cell_pack(Ref& cell_ref, const SmcCapability::Record_cap_name& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::cell_pack_cap_name(Ref& cell_ref, Ref name) const { - vm::CellBuilder cb; - return pack_cap_name(cb, std::move(name)) && std::move(cb).finalize_to(cell_ref); -} - -bool SmcCapability::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case cap_method_seqno: - return cs.fetch_ulong(16) == 0x5371 - && pp.cons("cap_method_seqno"); - case cap_method_pubkey: - return cs.fetch_ulong(16) == 0x71f4 - && pp.cons("cap_method_pubkey"); - case cap_is_wallet: - return cs.fetch_ulong(16) == 0x2177 - && pp.cons("cap_is_wallet"); - case cap_name: - return cs.fetch_ulong(8) == 0xff - && pp.open("cap_name") - && pp.field("name") - && t_Text.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for SmcCapability"); -} - -const SmcCapability t_SmcCapability; - -// -// code for type `ChanConfig` -// - -int ChanConfig::check_tag(const vm::CellSlice& cs) const { - return chan_config; -} - -bool ChanConfig::skip(vm::CellSlice& cs) const { - return cs.advance_ext(0x20280) - && t_Grams.skip(cs); -} - -bool ChanConfig::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(576) - && t_MsgAddressInt.validate_skip_ref(ops, cs, weak) - && t_MsgAddressInt.validate_skip_ref(ops, cs, weak) - && cs.advance(64) - && t_Grams.validate_skip(ops, cs, weak); -} - -bool ChanConfig::unpack(vm::CellSlice& cs, ChanConfig::Record& data) const { - return cs.fetch_uint_to(32, data.init_timeout) - && cs.fetch_uint_to(32, data.close_timeout) - && cs.fetch_bits_to(data.a_key.bits(), 256) - && cs.fetch_bits_to(data.b_key.bits(), 256) - && cs.fetch_ref_to(data.a_addr) - && cs.fetch_ref_to(data.b_addr) - && cs.fetch_uint_to(64, data.channel_id) - && t_Grams.fetch_to(cs, data.min_A_extra); -} - -bool ChanConfig::cell_unpack(Ref cell_ref, ChanConfig::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanConfig::pack(vm::CellBuilder& cb, const ChanConfig::Record& data) const { - return cb.store_ulong_rchk_bool(data.init_timeout, 32) - && cb.store_ulong_rchk_bool(data.close_timeout, 32) - && cb.store_bits_bool(data.a_key.cbits(), 256) - && cb.store_bits_bool(data.b_key.cbits(), 256) - && cb.store_ref_bool(data.a_addr) - && cb.store_ref_bool(data.b_addr) - && cb.store_ulong_rchk_bool(data.channel_id, 64) - && t_Grams.store_from(cb, data.min_A_extra); -} - -bool ChanConfig::cell_pack(Ref& cell_ref, const ChanConfig::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanConfig::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("chan_config") - && pp.fetch_uint_field(cs, 32, "init_timeout") - && pp.fetch_uint_field(cs, 32, "close_timeout") - && pp.fetch_bits_field(cs, 256, "a_key") - && pp.fetch_bits_field(cs, 256, "b_key") - && pp.field("a_addr") - && t_MsgAddressInt.print_ref(pp, cs.fetch_ref()) - && pp.field("b_addr") - && t_MsgAddressInt.print_ref(pp, cs.fetch_ref()) - && pp.fetch_uint_field(cs, 64, "channel_id") - && pp.field("min_A_extra") - && t_Grams.print_skip(pp, cs) - && pp.close(); -} - -const ChanConfig t_ChanConfig; - -// -// code for type `ChanState` -// - -int ChanState::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_state_init: - return cs.have(3) ? chan_state_init : -1; - case chan_state_close: - return cs.have(3) ? chan_state_close : -1; - case chan_state_payout: - return cs.prefetch_ulong(3) == 2 ? chan_state_payout : -1; - } - return -1; -} - -bool ChanState::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_state_init: - return cs.advance(5) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(32) - && t_Grams.skip(cs) - && t_Grams.skip(cs); - case chan_state_close: - return cs.advance(5) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(32) - && t_Grams.skip(cs) - && t_Grams.skip(cs); - case chan_state_payout: - return cs.advance(3) - && t_Grams.skip(cs) - && t_Grams.skip(cs); - } - return false; -} - -bool ChanState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case chan_state_init: - return cs.advance(5) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(32) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case chan_state_close: - return cs.advance(5) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(32) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - case chan_state_payout: - return cs.fetch_ulong(3) == 2 - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); - } - return false; -} - -bool ChanState::unpack(vm::CellSlice& cs, ChanState::Record_chan_state_init& data) const { - return cs.fetch_ulong(3) == 0 - && cs.fetch_bool_to(data.signed_A) - && cs.fetch_bool_to(data.signed_B) - && t_Grams.fetch_to(cs, data.min_A) - && t_Grams.fetch_to(cs, data.min_B) - && cs.fetch_uint_to(32, data.expire_at) - && t_Grams.fetch_to(cs, data.A) - && t_Grams.fetch_to(cs, data.B); -} - -bool ChanState::cell_unpack(Ref cell_ref, ChanState::Record_chan_state_init& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanState::unpack(vm::CellSlice& cs, ChanState::Record_chan_state_close& data) const { - return cs.fetch_ulong(3) == 1 - && cs.fetch_bool_to(data.signed_A) - && cs.fetch_bool_to(data.signed_B) - && t_Grams.fetch_to(cs, data.promise_A) - && t_Grams.fetch_to(cs, data.promise_B) - && cs.fetch_uint_to(32, data.expire_at) - && t_Grams.fetch_to(cs, data.A) - && t_Grams.fetch_to(cs, data.B); -} - -bool ChanState::cell_unpack(Ref cell_ref, ChanState::Record_chan_state_close& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanState::unpack(vm::CellSlice& cs, ChanState::Record_chan_state_payout& data) const { - return cs.fetch_ulong(3) == 2 - && t_Grams.fetch_to(cs, data.A) - && t_Grams.fetch_to(cs, data.B); -} - -bool ChanState::unpack_chan_state_payout(vm::CellSlice& cs, Ref& A, Ref& B) const { - return cs.fetch_ulong(3) == 2 - && t_Grams.fetch_to(cs, A) - && t_Grams.fetch_to(cs, B); -} - -bool ChanState::cell_unpack(Ref cell_ref, ChanState::Record_chan_state_payout& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanState::cell_unpack_chan_state_payout(Ref cell_ref, Ref& A, Ref& B) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_state_payout(cs, A, B) && cs.empty_ext(); -} - -bool ChanState::pack(vm::CellBuilder& cb, const ChanState::Record_chan_state_init& data) const { - return cb.store_long_bool(0, 3) - && cb.store_ulong_rchk_bool(data.signed_A, 1) - && cb.store_ulong_rchk_bool(data.signed_B, 1) - && t_Grams.store_from(cb, data.min_A) - && t_Grams.store_from(cb, data.min_B) - && cb.store_ulong_rchk_bool(data.expire_at, 32) - && t_Grams.store_from(cb, data.A) - && t_Grams.store_from(cb, data.B); -} - -bool ChanState::cell_pack(Ref& cell_ref, const ChanState::Record_chan_state_init& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanState::pack(vm::CellBuilder& cb, const ChanState::Record_chan_state_close& data) const { - return cb.store_long_bool(1, 3) - && cb.store_ulong_rchk_bool(data.signed_A, 1) - && cb.store_ulong_rchk_bool(data.signed_B, 1) - && t_Grams.store_from(cb, data.promise_A) - && t_Grams.store_from(cb, data.promise_B) - && cb.store_ulong_rchk_bool(data.expire_at, 32) - && t_Grams.store_from(cb, data.A) - && t_Grams.store_from(cb, data.B); -} - -bool ChanState::cell_pack(Ref& cell_ref, const ChanState::Record_chan_state_close& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanState::pack(vm::CellBuilder& cb, const ChanState::Record_chan_state_payout& data) const { - return cb.store_long_bool(2, 3) - && t_Grams.store_from(cb, data.A) - && t_Grams.store_from(cb, data.B); -} - -bool ChanState::pack_chan_state_payout(vm::CellBuilder& cb, Ref A, Ref B) const { - return cb.store_long_bool(2, 3) - && t_Grams.store_from(cb, A) - && t_Grams.store_from(cb, B); -} - -bool ChanState::cell_pack(Ref& cell_ref, const ChanState::Record_chan_state_payout& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanState::cell_pack_chan_state_payout(Ref& cell_ref, Ref A, Ref B) const { - vm::CellBuilder cb; - return pack_chan_state_payout(cb, std::move(A), std::move(B)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanState::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_state_init: - return cs.advance(3) - && pp.open("chan_state_init") - && pp.fetch_uint_field(cs, 1, "signed_A") - && pp.fetch_uint_field(cs, 1, "signed_B") - && pp.field("min_A") - && t_Grams.print_skip(pp, cs) - && pp.field("min_B") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "expire_at") - && pp.field("A") - && t_Grams.print_skip(pp, cs) - && pp.field("B") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case chan_state_close: - return cs.advance(3) - && pp.open("chan_state_close") - && pp.fetch_uint_field(cs, 1, "signed_A") - && pp.fetch_uint_field(cs, 1, "signed_B") - && pp.field("promise_A") - && t_Grams.print_skip(pp, cs) - && pp.field("promise_B") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 32, "expire_at") - && pp.field("A") - && t_Grams.print_skip(pp, cs) - && pp.field("B") - && t_Grams.print_skip(pp, cs) - && pp.close(); - case chan_state_payout: - return cs.fetch_ulong(3) == 2 - && pp.open("chan_state_payout") - && pp.field("A") - && t_Grams.print_skip(pp, cs) - && pp.field("B") - && t_Grams.print_skip(pp, cs) - && pp.close(); - } - return pp.fail("unknown constructor for ChanState"); -} - -const ChanState t_ChanState; - -// -// code for type `ChanPromise` -// - -int ChanPromise::check_tag(const vm::CellSlice& cs) const { - return chan_promise; -} - -bool ChanPromise::skip(vm::CellSlice& cs) const { - return cs.advance(64) - && t_Grams.skip(cs) - && t_Grams.skip(cs); -} - -bool ChanPromise::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak); -} - -bool ChanPromise::unpack(vm::CellSlice& cs, ChanPromise::Record& data) const { - return cs.fetch_uint_to(64, data.channel_id) - && t_Grams.fetch_to(cs, data.promise_A) - && t_Grams.fetch_to(cs, data.promise_B); -} - -bool ChanPromise::unpack_chan_promise(vm::CellSlice& cs, unsigned long long& channel_id, Ref& promise_A, Ref& promise_B) const { - return cs.fetch_uint_to(64, channel_id) - && t_Grams.fetch_to(cs, promise_A) - && t_Grams.fetch_to(cs, promise_B); -} - -bool ChanPromise::cell_unpack(Ref cell_ref, ChanPromise::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanPromise::cell_unpack_chan_promise(Ref cell_ref, unsigned long long& channel_id, Ref& promise_A, Ref& promise_B) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_promise(cs, channel_id, promise_A, promise_B) && cs.empty_ext(); -} - -bool ChanPromise::pack(vm::CellBuilder& cb, const ChanPromise::Record& data) const { - return cb.store_ulong_rchk_bool(data.channel_id, 64) - && t_Grams.store_from(cb, data.promise_A) - && t_Grams.store_from(cb, data.promise_B); -} - -bool ChanPromise::pack_chan_promise(vm::CellBuilder& cb, unsigned long long channel_id, Ref promise_A, Ref promise_B) const { - return cb.store_ulong_rchk_bool(channel_id, 64) - && t_Grams.store_from(cb, promise_A) - && t_Grams.store_from(cb, promise_B); -} - -bool ChanPromise::cell_pack(Ref& cell_ref, const ChanPromise::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanPromise::cell_pack_chan_promise(Ref& cell_ref, unsigned long long channel_id, Ref promise_A, Ref promise_B) const { - vm::CellBuilder cb; - return pack_chan_promise(cb, channel_id, std::move(promise_A), std::move(promise_B)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanPromise::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("chan_promise") - && pp.fetch_uint_field(cs, 64, "channel_id") - && pp.field("promise_A") - && t_Grams.print_skip(pp, cs) - && pp.field("promise_B") - && t_Grams.print_skip(pp, cs) - && pp.close(); -} - -const ChanPromise t_ChanPromise; - -// -// code for type `ChanSignedPromise` -// - -int ChanSignedPromise::check_tag(const vm::CellSlice& cs) const { - return chan_signed_promise; -} - -bool ChanSignedPromise::skip(vm::CellSlice& cs) const { - return t_Maybe_Ref_bits512.skip(cs) - && t_ChanPromise.skip(cs); -} - -bool ChanSignedPromise::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_Ref_bits512.validate_skip(ops, cs, weak) - && t_ChanPromise.validate_skip(ops, cs, weak); -} - -bool ChanSignedPromise::unpack(vm::CellSlice& cs, ChanSignedPromise::Record& data) const { - return t_Maybe_Ref_bits512.fetch_to(cs, data.sig) - && t_ChanPromise.fetch_to(cs, data.promise); -} - -bool ChanSignedPromise::unpack_chan_signed_promise(vm::CellSlice& cs, Ref& sig, Ref& promise) const { - return t_Maybe_Ref_bits512.fetch_to(cs, sig) - && t_ChanPromise.fetch_to(cs, promise); -} - -bool ChanSignedPromise::cell_unpack(Ref cell_ref, ChanSignedPromise::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanSignedPromise::cell_unpack_chan_signed_promise(Ref cell_ref, Ref& sig, Ref& promise) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_signed_promise(cs, sig, promise) && cs.empty_ext(); -} - -bool ChanSignedPromise::pack(vm::CellBuilder& cb, const ChanSignedPromise::Record& data) const { - return t_Maybe_Ref_bits512.store_from(cb, data.sig) - && t_ChanPromise.store_from(cb, data.promise); -} - -bool ChanSignedPromise::pack_chan_signed_promise(vm::CellBuilder& cb, Ref sig, Ref promise) const { - return t_Maybe_Ref_bits512.store_from(cb, sig) - && t_ChanPromise.store_from(cb, promise); -} - -bool ChanSignedPromise::cell_pack(Ref& cell_ref, const ChanSignedPromise::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanSignedPromise::cell_pack_chan_signed_promise(Ref& cell_ref, Ref sig, Ref promise) const { - vm::CellBuilder cb; - return pack_chan_signed_promise(cb, std::move(sig), std::move(promise)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanSignedPromise::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("chan_signed_promise") - && pp.field("sig") - && t_Maybe_Ref_bits512.print_skip(pp, cs) - && pp.field("promise") - && t_ChanPromise.print_skip(pp, cs) - && pp.close(); -} - -const ChanSignedPromise t_ChanSignedPromise; - -// -// code for type `ChanMsg` -// -constexpr unsigned ChanMsg::cons_tag[4]; - -int ChanMsg::check_tag(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_msg_init: - return cs.prefetch_ulong(32) == 0x27317822 ? chan_msg_init : -1; - case chan_msg_close: - return cs.prefetch_ulong(32) == 0xf28ae183U ? chan_msg_close : -1; - case chan_msg_timeout: - return cs.prefetch_ulong(32) == 0x43278a28 ? chan_msg_timeout : -1; - case chan_msg_payout: - return cs.prefetch_ulong(32) == 0x37fe7810 ? chan_msg_payout : -1; - } - return -1; -} - -bool ChanMsg::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_msg_init: - return cs.advance(32) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && cs.advance(64); - case chan_msg_close: - return cs.advance(32) - && t_Grams.skip(cs) - && t_Grams.skip(cs) - && t_ChanSignedPromise.skip(cs); - case chan_msg_timeout: - return cs.advance(32); - case chan_msg_payout: - return cs.advance(32); - } - return false; -} - -bool ChanMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case chan_msg_init: - return cs.fetch_ulong(32) == 0x27317822 - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && cs.advance(64); - case chan_msg_close: - return cs.fetch_ulong(32) == 0xf28ae183U - && t_Grams.validate_skip(ops, cs, weak) - && t_Grams.validate_skip(ops, cs, weak) - && t_ChanSignedPromise.validate_skip(ops, cs, weak); - case chan_msg_timeout: - return cs.fetch_ulong(32) == 0x43278a28; - case chan_msg_payout: - return cs.fetch_ulong(32) == 0x37fe7810; - } - return false; -} - -bool ChanMsg::unpack(vm::CellSlice& cs, ChanMsg::Record_chan_msg_init& data) const { - return cs.fetch_ulong(32) == 0x27317822 - && t_Grams.fetch_to(cs, data.inc_A) - && t_Grams.fetch_to(cs, data.inc_B) - && t_Grams.fetch_to(cs, data.min_A) - && t_Grams.fetch_to(cs, data.min_B) - && cs.fetch_uint_to(64, data.channel_id); -} - -bool ChanMsg::cell_unpack(Ref cell_ref, ChanMsg::Record_chan_msg_init& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanMsg::unpack(vm::CellSlice& cs, ChanMsg::Record_chan_msg_close& data) const { - return cs.fetch_ulong(32) == 0xf28ae183U - && t_Grams.fetch_to(cs, data.extra_A) - && t_Grams.fetch_to(cs, data.extra_B) - && t_ChanSignedPromise.fetch_to(cs, data.promise); -} - -bool ChanMsg::unpack_chan_msg_close(vm::CellSlice& cs, Ref& extra_A, Ref& extra_B, Ref& promise) const { - return cs.fetch_ulong(32) == 0xf28ae183U - && t_Grams.fetch_to(cs, extra_A) - && t_Grams.fetch_to(cs, extra_B) - && t_ChanSignedPromise.fetch_to(cs, promise); -} - -bool ChanMsg::cell_unpack(Ref cell_ref, ChanMsg::Record_chan_msg_close& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanMsg::cell_unpack_chan_msg_close(Ref cell_ref, Ref& extra_A, Ref& extra_B, Ref& promise) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_msg_close(cs, extra_A, extra_B, promise) && cs.empty_ext(); -} - -bool ChanMsg::unpack(vm::CellSlice& cs, ChanMsg::Record_chan_msg_timeout& data) const { - return cs.fetch_ulong(32) == 0x43278a28; -} - -bool ChanMsg::unpack_chan_msg_timeout(vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x43278a28; -} - -bool ChanMsg::cell_unpack(Ref cell_ref, ChanMsg::Record_chan_msg_timeout& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanMsg::cell_unpack_chan_msg_timeout(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_msg_timeout(cs) && cs.empty_ext(); -} - -bool ChanMsg::unpack(vm::CellSlice& cs, ChanMsg::Record_chan_msg_payout& data) const { - return cs.fetch_ulong(32) == 0x37fe7810; -} - -bool ChanMsg::unpack_chan_msg_payout(vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x37fe7810; -} - -bool ChanMsg::cell_unpack(Ref cell_ref, ChanMsg::Record_chan_msg_payout& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanMsg::cell_unpack_chan_msg_payout(Ref cell_ref) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_msg_payout(cs) && cs.empty_ext(); -} - -bool ChanMsg::pack(vm::CellBuilder& cb, const ChanMsg::Record_chan_msg_init& data) const { - return cb.store_long_bool(0x27317822, 32) - && t_Grams.store_from(cb, data.inc_A) - && t_Grams.store_from(cb, data.inc_B) - && t_Grams.store_from(cb, data.min_A) - && t_Grams.store_from(cb, data.min_B) - && cb.store_ulong_rchk_bool(data.channel_id, 64); -} - -bool ChanMsg::cell_pack(Ref& cell_ref, const ChanMsg::Record_chan_msg_init& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::pack(vm::CellBuilder& cb, const ChanMsg::Record_chan_msg_close& data) const { - return cb.store_long_bool(0xf28ae183U, 32) - && t_Grams.store_from(cb, data.extra_A) - && t_Grams.store_from(cb, data.extra_B) - && t_ChanSignedPromise.store_from(cb, data.promise); -} - -bool ChanMsg::pack_chan_msg_close(vm::CellBuilder& cb, Ref extra_A, Ref extra_B, Ref promise) const { - return cb.store_long_bool(0xf28ae183U, 32) - && t_Grams.store_from(cb, extra_A) - && t_Grams.store_from(cb, extra_B) - && t_ChanSignedPromise.store_from(cb, promise); -} - -bool ChanMsg::cell_pack(Ref& cell_ref, const ChanMsg::Record_chan_msg_close& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::cell_pack_chan_msg_close(Ref& cell_ref, Ref extra_A, Ref extra_B, Ref promise) const { - vm::CellBuilder cb; - return pack_chan_msg_close(cb, std::move(extra_A), std::move(extra_B), std::move(promise)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::pack(vm::CellBuilder& cb, const ChanMsg::Record_chan_msg_timeout& data) const { - return cb.store_long_bool(0x43278a28, 32); -} - -bool ChanMsg::pack_chan_msg_timeout(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x43278a28, 32); -} - -bool ChanMsg::cell_pack(Ref& cell_ref, const ChanMsg::Record_chan_msg_timeout& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::cell_pack_chan_msg_timeout(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_chan_msg_timeout(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::pack(vm::CellBuilder& cb, const ChanMsg::Record_chan_msg_payout& data) const { - return cb.store_long_bool(0x37fe7810, 32); -} - -bool ChanMsg::pack_chan_msg_payout(vm::CellBuilder& cb) const { - return cb.store_long_bool(0x37fe7810, 32); -} - -bool ChanMsg::cell_pack(Ref& cell_ref, const ChanMsg::Record_chan_msg_payout& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::cell_pack_chan_msg_payout(Ref& cell_ref) const { - vm::CellBuilder cb; - return pack_chan_msg_payout(cb) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanMsg::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case chan_msg_init: - return cs.fetch_ulong(32) == 0x27317822 - && pp.open("chan_msg_init") - && pp.field("inc_A") - && t_Grams.print_skip(pp, cs) - && pp.field("inc_B") - && t_Grams.print_skip(pp, cs) - && pp.field("min_A") - && t_Grams.print_skip(pp, cs) - && pp.field("min_B") - && t_Grams.print_skip(pp, cs) - && pp.fetch_uint_field(cs, 64, "channel_id") - && pp.close(); - case chan_msg_close: - return cs.fetch_ulong(32) == 0xf28ae183U - && pp.open("chan_msg_close") - && pp.field("extra_A") - && t_Grams.print_skip(pp, cs) - && pp.field("extra_B") - && t_Grams.print_skip(pp, cs) - && pp.field("promise") - && t_ChanSignedPromise.print_skip(pp, cs) - && pp.close(); - case chan_msg_timeout: - return cs.fetch_ulong(32) == 0x43278a28 - && pp.cons("chan_msg_timeout"); - case chan_msg_payout: - return cs.fetch_ulong(32) == 0x37fe7810 - && pp.cons("chan_msg_payout"); - } - return pp.fail("unknown constructor for ChanMsg"); -} - -const ChanMsg t_ChanMsg; - -// -// code for type `ChanSignedMsg` -// - -int ChanSignedMsg::check_tag(const vm::CellSlice& cs) const { - return chan_signed_msg; -} - -bool ChanSignedMsg::skip(vm::CellSlice& cs) const { - return t_Maybe_Ref_bits512.skip(cs) - && t_Maybe_Ref_bits512.skip(cs) - && t_ChanMsg.skip(cs); -} - -bool ChanSignedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_Ref_bits512.validate_skip(ops, cs, weak) - && t_Maybe_Ref_bits512.validate_skip(ops, cs, weak) - && t_ChanMsg.validate_skip(ops, cs, weak); -} - -bool ChanSignedMsg::unpack(vm::CellSlice& cs, ChanSignedMsg::Record& data) const { - return t_Maybe_Ref_bits512.fetch_to(cs, data.sig_A) - && t_Maybe_Ref_bits512.fetch_to(cs, data.sig_B) - && t_ChanMsg.fetch_to(cs, data.msg); -} - -bool ChanSignedMsg::unpack_chan_signed_msg(vm::CellSlice& cs, Ref& sig_A, Ref& sig_B, Ref& msg) const { - return t_Maybe_Ref_bits512.fetch_to(cs, sig_A) - && t_Maybe_Ref_bits512.fetch_to(cs, sig_B) - && t_ChanMsg.fetch_to(cs, msg); -} - -bool ChanSignedMsg::cell_unpack(Ref cell_ref, ChanSignedMsg::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanSignedMsg::cell_unpack_chan_signed_msg(Ref cell_ref, Ref& sig_A, Ref& sig_B, Ref& msg) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_signed_msg(cs, sig_A, sig_B, msg) && cs.empty_ext(); -} - -bool ChanSignedMsg::pack(vm::CellBuilder& cb, const ChanSignedMsg::Record& data) const { - return t_Maybe_Ref_bits512.store_from(cb, data.sig_A) - && t_Maybe_Ref_bits512.store_from(cb, data.sig_B) - && t_ChanMsg.store_from(cb, data.msg); -} - -bool ChanSignedMsg::pack_chan_signed_msg(vm::CellBuilder& cb, Ref sig_A, Ref sig_B, Ref msg) const { - return t_Maybe_Ref_bits512.store_from(cb, sig_A) - && t_Maybe_Ref_bits512.store_from(cb, sig_B) - && t_ChanMsg.store_from(cb, msg); -} - -bool ChanSignedMsg::cell_pack(Ref& cell_ref, const ChanSignedMsg::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanSignedMsg::cell_pack_chan_signed_msg(Ref& cell_ref, Ref sig_A, Ref sig_B, Ref msg) const { - vm::CellBuilder cb; - return pack_chan_signed_msg(cb, std::move(sig_A), std::move(sig_B), std::move(msg)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanSignedMsg::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("chan_signed_msg") - && pp.field("sig_A") - && t_Maybe_Ref_bits512.print_skip(pp, cs) - && pp.field("sig_B") - && t_Maybe_Ref_bits512.print_skip(pp, cs) - && pp.field("msg") - && t_ChanMsg.print_skip(pp, cs) - && pp.close(); -} - -const ChanSignedMsg t_ChanSignedMsg; - -// -// code for type `ChanOp` -// -constexpr unsigned ChanOp::cons_tag[1]; - -int ChanOp::check_tag(const vm::CellSlice& cs) const { - return cs.prefetch_ulong(32) == 0x912838d1U ? chan_op_cmd : -1; -} - -bool ChanOp::skip(vm::CellSlice& cs) const { - return cs.advance(32) - && t_ChanSignedMsg.skip(cs); -} - -bool ChanOp::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(32) == 0x912838d1U - && t_ChanSignedMsg.validate_skip(ops, cs, weak); -} - -bool ChanOp::unpack(vm::CellSlice& cs, ChanOp::Record& data) const { - return cs.fetch_ulong(32) == 0x912838d1U - && t_ChanSignedMsg.fetch_to(cs, data.msg); -} - -bool ChanOp::unpack_chan_op_cmd(vm::CellSlice& cs, Ref& msg) const { - return cs.fetch_ulong(32) == 0x912838d1U - && t_ChanSignedMsg.fetch_to(cs, msg); -} - -bool ChanOp::cell_unpack(Ref cell_ref, ChanOp::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanOp::cell_unpack_chan_op_cmd(Ref cell_ref, Ref& msg) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_op_cmd(cs, msg) && cs.empty_ext(); -} - -bool ChanOp::pack(vm::CellBuilder& cb, const ChanOp::Record& data) const { - return cb.store_long_bool(0x912838d1U, 32) - && t_ChanSignedMsg.store_from(cb, data.msg); -} - -bool ChanOp::pack_chan_op_cmd(vm::CellBuilder& cb, Ref msg) const { - return cb.store_long_bool(0x912838d1U, 32) - && t_ChanSignedMsg.store_from(cb, msg); -} - -bool ChanOp::cell_pack(Ref& cell_ref, const ChanOp::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanOp::cell_pack_chan_op_cmd(Ref& cell_ref, Ref msg) const { - vm::CellBuilder cb; - return pack_chan_op_cmd(cb, std::move(msg)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanOp::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return cs.fetch_ulong(32) == 0x912838d1U - && pp.open("chan_op_cmd") - && pp.field("msg") - && t_ChanSignedMsg.print_skip(pp, cs) - && pp.close(); -} - -const ChanOp t_ChanOp; - -// -// code for type `ChanData` -// - -int ChanData::check_tag(const vm::CellSlice& cs) const { - return chan_data; -} - -bool ChanData::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_ChanConfig.validate_skip_ref(ops, cs, weak) - && t_ChanState.validate_skip_ref(ops, cs, weak); -} - -bool ChanData::unpack(vm::CellSlice& cs, ChanData::Record& data) const { - return cs.fetch_ref_to(data.config) - && cs.fetch_ref_to(data.state); -} - -bool ChanData::unpack_chan_data(vm::CellSlice& cs, Ref& config, Ref& state) const { - return cs.fetch_ref_to(config) - && cs.fetch_ref_to(state); -} - -bool ChanData::cell_unpack(Ref cell_ref, ChanData::Record& data) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack(cs, data) && cs.empty_ext(); -} - -bool ChanData::cell_unpack_chan_data(Ref cell_ref, Ref& config, Ref& state) const { - if (cell_ref.is_null()) { return false; } - auto cs = load_cell_slice(std::move(cell_ref)); - return unpack_chan_data(cs, config, state) && cs.empty_ext(); -} - -bool ChanData::pack(vm::CellBuilder& cb, const ChanData::Record& data) const { - return cb.store_ref_bool(data.config) - && cb.store_ref_bool(data.state); -} - -bool ChanData::pack_chan_data(vm::CellBuilder& cb, Ref config, Ref state) const { - return cb.store_ref_bool(config) - && cb.store_ref_bool(state); -} - -bool ChanData::cell_pack(Ref& cell_ref, const ChanData::Record& data) const { - vm::CellBuilder cb; - return pack(cb, data) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanData::cell_pack_chan_data(Ref& cell_ref, Ref config, Ref state) const { - vm::CellBuilder cb; - return pack_chan_data(cb, std::move(config), std::move(state)) && std::move(cb).finalize_to(cell_ref); -} - -bool ChanData::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return pp.open("chan_data") - && pp.field("config") - && t_ChanConfig.print_ref(pp, cs.fetch_ref()) - && pp.field("state") - && t_ChanState.print_ref(pp, cs.fetch_ref()) - && pp.close(); -} - -const ChanData t_ChanData; - -// definitions of constant types used - -const NatWidth t_natwidth_1{1}; -const NatWidth t_natwidth_9{9}; -const NatLeq t_natleq_30{30}; -const Maybe t_Maybe_Anycast{t_Anycast}; -const Int t_int8{8}; -const Bits t_bits256{256}; -const Int t_int32{32}; -const VarUInteger t_VarUInteger_16{16}; -const VarUInteger t_VarUInteger_32{32}; -const HashmapE t_HashmapE_32_VarUInteger_32{32, t_VarUInteger_32}; -const UInt t_uint64{64}; -const UInt t_uint32{32}; -const NatWidth t_natwidth_5{5}; -const Maybe t_Maybe_natwidth_5{t_natwidth_5}; -const Maybe t_Maybe_TickTock{t_TickTock}; -const Maybe t_Maybe_Ref_Cell{t_RefCell}; -const HashmapE t_HashmapE_256_SimpleLib{256, t_SimpleLib}; -const RefT t_Ref_StateInit{t_StateInit}; -const Either t_Either_StateInit_Ref_StateInit{t_StateInit, t_Ref_StateInit}; -const Maybe t_Maybe_Either_StateInit_Ref_StateInit{t_Either_StateInit_Ref_StateInit}; -const Message t_Message_Any{t_Anything}; -const NatLeq t_natleq_96{96}; -const RefT t_Ref_Message_Any{t_Message_Any}; -const RefT t_Ref_Transaction{t_Transaction}; -const RefT t_Ref_MsgEnvelope{t_MsgEnvelope}; -const HashmapAugE t_HashmapAugE_256_InMsg_ImportFees{256, t_InMsg, t_ImportFees}; -const RefT t_Ref_InMsg{t_InMsg}; -const UInt t_uint63{63}; -const HashmapAugE t_HashmapAugE_256_OutMsg_CurrencyCollection{256, t_OutMsg, t_CurrencyCollection}; -const HashmapAugE t_HashmapAugE_352_EnqueuedMsg_uint64{352, t_EnqueuedMsg, t_uint64}; -const HashmapE t_HashmapE_96_ProcessedUpto{96, t_ProcessedUpto}; -const HashmapE t_HashmapE_320_IhrPendingSince{320, t_IhrPendingSince}; -const VarUInteger t_VarUInteger_7{7}; -const Maybe t_Maybe_Grams{t_Grams}; -const RefT t_Ref_Account{t_Account}; -const HashmapAugE t_HashmapAugE_256_ShardAccount_DepthBalanceInfo{256, t_ShardAccount, t_DepthBalanceInfo}; -const UInt t_uint15{15}; -const Maybe t_Maybe_Ref_Message_Any{t_Ref_Message_Any}; -const HashmapE t_HashmapE_15_Ref_Message_Any{15, t_Ref_Message_Any}; -const RefT t_Ref_TYPE_1614{t_Transaction_aux}; -const HASH_UPDATE t_HASH_UPDATE_Account{t_Account}; -const RefT t_Ref_HASH_UPDATE_Account{t_HASH_UPDATE_Account}; -const RefT t_Ref_TransactionDescr{t_TransactionDescr}; -const UInt t_uint16{16}; -const HashmapAug t_HashmapAug_64_Ref_Transaction_CurrencyCollection{64, t_Ref_Transaction, t_CurrencyCollection}; -const HashmapAugE t_HashmapAugE_256_AccountBlock_CurrencyCollection{256, t_AccountBlock, t_CurrencyCollection}; -const VarUInteger t_VarUInteger_3{3}; -const Maybe t_Maybe_VarUInteger_3{t_VarUInteger_3}; -const Maybe t_Maybe_int32{t_int32}; -const RefT t_Ref_TYPE_1626{t_TrComputePhase_aux}; -const Maybe t_Maybe_TrStoragePhase{t_TrStoragePhase}; -const Maybe t_Maybe_TrCreditPhase{t_TrCreditPhase}; -const RefT t_Ref_TrActionPhase{t_TrActionPhase}; -const Maybe t_Maybe_Ref_TrActionPhase{t_Ref_TrActionPhase}; -const Maybe t_Maybe_TrBouncePhase{t_TrBouncePhase}; -const NatWidth t_natwidth_6{6}; -const NatWidth t_natwidth_8{8}; -const MessageRelaxed t_MessageRelaxed_Any{t_Anything}; -const RefT t_Ref_MessageRelaxed_Any{t_MessageRelaxed_Any}; -const NatWidth t_natwidth_7{7}; -const NatLeq t_natleq_60{60}; -const RefT t_Ref_OutMsgQueueInfo{t_OutMsgQueueInfo}; -const RefT t_Ref_ShardAccounts{t_ShardAccounts}; -const HashmapE t_HashmapE_256_LibDescr{256, t_LibDescr}; -const Maybe t_Maybe_BlkMasterInfo{t_BlkMasterInfo}; -const RefT t_Ref_TYPE_1640{t_ShardStateUnsplit_aux}; -const RefT t_Ref_McStateExtra{t_McStateExtra}; -const Maybe t_Maybe_Ref_McStateExtra{t_Ref_McStateExtra}; -const RefT t_Ref_ShardStateUnsplit{t_ShardStateUnsplit}; -const Hashmap t_Hashmap_256_True{256, t_True}; -const RefT t_Ref_BlkMasterInfo{t_BlkMasterInfo}; -const BlkPrevInfo t_BlkPrevInfo_0{0}; -const RefT t_Ref_BlkPrevInfo_0{t_BlkPrevInfo_0}; -const RefT t_Ref_ExtBlkRef{t_ExtBlkRef}; -const RefT t_Ref_BlockInfo{t_BlockInfo}; -const RefT t_Ref_ValueFlow{t_ValueFlow}; -const MERKLE_UPDATE t_MERKLE_UPDATE_ShardState{t_ShardState}; -const RefT t_Ref_MERKLE_UPDATE_ShardState{t_MERKLE_UPDATE_ShardState}; -const RefT t_Ref_BlockExtra{t_BlockExtra}; -const RefT t_Ref_InMsgDescr{t_InMsgDescr}; -const RefT t_Ref_OutMsgDescr{t_OutMsgDescr}; -const RefT t_Ref_ShardAccountBlocks{t_ShardAccountBlocks}; -const RefT t_Ref_McBlockExtra{t_McBlockExtra}; -const Maybe t_Maybe_Ref_McBlockExtra{t_Ref_McBlockExtra}; -const RefT t_Ref_TYPE_1651{t_ValueFlow_aux}; -const RefT t_Ref_TYPE_1652{t_ValueFlow_aux1}; -const NatWidth t_natwidth_3{3}; -const RefT t_Ref_TYPE_1656{t_ShardDescr_aux}; -const BinTree t_BinTree_ShardDescr{t_ShardDescr}; -const RefT t_Ref_BinTree_ShardDescr{t_BinTree_ShardDescr}; -const HashmapE t_HashmapE_32_Ref_BinTree_ShardDescr{32, t_Ref_BinTree_ShardDescr}; -const HashmapAugE t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated{96, t_ShardFeeCreated, t_ShardFeeCreated}; -const Hashmap t_Hashmap_32_Ref_Cell{32, t_RefCell}; -const RefT t_Ref_Hashmap_32_Ref_Cell{t_Hashmap_32_Ref_Cell}; -const HashmapAugE t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt{32, t_KeyExtBlkRef, t_KeyMaxLt}; -const HashmapE t_HashmapE_256_CreatorStats{256, t_CreatorStats}; -const HashmapAugE t_HashmapAugE_256_CreatorStats_uint32{256, t_CreatorStats, t_uint32}; -const NatWidth t_natwidth_16{16}; -const Maybe t_Maybe_ExtBlkRef{t_ExtBlkRef}; -const RefT t_Ref_TYPE_1670{t_McStateExtra_aux}; -const RefT t_Ref_SignedCertificate{t_SignedCertificate}; -const HashmapE t_HashmapE_16_CryptoSignaturePair{16, t_CryptoSignaturePair}; -const Maybe t_Maybe_Ref_InMsg{t_Ref_InMsg}; -const RefT t_Ref_TYPE_1678{t_McBlockExtra_aux}; -const Hashmap t_Hashmap_16_ValidatorDescr{16, t_ValidatorDescr}; -const HashmapE t_HashmapE_16_ValidatorDescr{16, t_ValidatorDescr}; -const Hashmap t_Hashmap_32_True{32, t_True}; -const UInt t_uint8{8}; -const RefT t_Ref_ConfigProposalSetup{t_ConfigProposalSetup}; -const UInt t_uint256{256}; -const Maybe t_Maybe_uint256{t_uint256}; -const RefT t_Ref_ConfigProposal{t_ConfigProposal}; -const HashmapE t_HashmapE_16_True{16, t_True}; -const Int t_int64{64}; -const NatWidth t_natwidth_12{12}; -const NatWidth t_natwidth_32{32}; -const NatWidth t_natwidth_13{13}; -const HashmapE t_HashmapE_32_WorkchainDescr{32, t_WorkchainDescr}; -const Hashmap t_Hashmap_32_StoragePrices{32, t_StoragePrices}; -const HashmapE t_HashmapE_256_True{256, t_True}; -const RefT t_Ref_ValidatorTempKey{t_ValidatorTempKey}; -const HashmapE t_HashmapE_256_ValidatorSignedTempKey{256, t_ValidatorSignedTempKey}; -const RefT t_Ref_BlockSignatures{t_BlockSignatures}; -const Maybe t_Maybe_Ref_BlockSignatures{t_Ref_BlockSignatures}; -const RefT t_Ref_TopBlockDescr{t_TopBlockDescr}; -const HashmapE t_HashmapE_96_Ref_TopBlockDescr{96, t_Ref_TopBlockDescr}; -const MERKLE_PROOF t_MERKLE_PROOF_Block{t_Block}; -const RefT t_Ref_MERKLE_PROOF_Block{t_MERKLE_PROOF_Block}; -const MERKLE_PROOF t_MERKLE_PROOF_ShardState{t_ShardState}; -const RefT t_Ref_MERKLE_PROOF_ShardState{t_MERKLE_PROOF_ShardState}; -const RefT t_Ref_ProducerInfo{t_ProducerInfo}; -const RefT t_Ref_ComplaintDescr{t_ComplaintDescr}; -const RefT t_Ref_ValidatorComplaint{t_ValidatorComplaint}; -const Int t_int257{257}; -const NatWidth t_natwidth_10{10}; -const NatLeq t_natleq_4{4}; -const RefT t_Ref_VmStackValue{t_VmStackValue}; -const NatWidth t_natwidth_24{24}; -const HashmapE t_HashmapE_4_VmStackValue{4, t_VmStackValue}; -const RefT t_Ref_TYPE_1717{t_VmGasLimits_aux}; -const HashmapE t_HashmapE_256_Ref_Cell{256, t_RefCell}; -const UInt t_uint13{13}; -const Maybe t_Maybe_uint13{t_uint13}; -const Maybe t_Maybe_VmStack{t_VmStack}; -const Int t_int16{16}; -const Maybe t_Maybe_int16{t_int16}; -const RefT t_Ref_VmCont{t_VmCont}; -const RefT t_Ref_DNSRecord{t_DNSRecord}; -const HashmapE t_HashmapE_16_Ref_DNSRecord{16, t_Ref_DNSRecord}; -const RefT t_Ref_MsgAddressInt{t_MsgAddressInt}; -const Bits t_bits512{512}; -const RefT t_Ref_bits512{t_bits512}; -const Maybe t_Maybe_Ref_bits512{t_Ref_bits512}; -const RefT t_Ref_ChanConfig{t_ChanConfig}; -const RefT t_Ref_ChanState{t_ChanState}; - -// definition of type name registration function -bool register_simple_types(std::function func) { - return func("Unit", &t_Unit) - && func("True", &t_True) - && func("Bool", &t_Bool) - && func("BoolFalse", &t_BoolFalse) - && func("BoolTrue", &t_BoolTrue) - && func("Bit", &t_Bit) - && func("Unary", &t_Unary) - && func("MsgAddressExt", &t_MsgAddressExt) - && func("Anycast", &t_Anycast) - && func("MsgAddressInt", &t_MsgAddressInt) - && func("MsgAddress", &t_MsgAddress) - && func("Grams", &t_Grams) - && func("ExtraCurrencyCollection", &t_ExtraCurrencyCollection) - && func("CurrencyCollection", &t_CurrencyCollection) - && func("CommonMsgInfo", &t_CommonMsgInfo) - && func("CommonMsgInfoRelaxed", &t_CommonMsgInfoRelaxed) - && func("TickTock", &t_TickTock) - && func("SimpleLib", &t_SimpleLib) - && func("StateInit", &t_StateInit) - && func("MessageAny", &t_MessageAny) - && func("IntermediateAddress", &t_IntermediateAddress) - && func("MsgEnvelope", &t_MsgEnvelope) - && func("Transaction", &t_Transaction) - && func("InMsg", &t_InMsg) - && func("ImportFees", &t_ImportFees) - && func("InMsgDescr", &t_InMsgDescr) - && func("OutMsg", &t_OutMsg) - && func("EnqueuedMsg", &t_EnqueuedMsg) - && func("OutMsgDescr", &t_OutMsgDescr) - && func("OutMsgQueue", &t_OutMsgQueue) - && func("ProcessedUpto", &t_ProcessedUpto) - && func("ProcessedInfo", &t_ProcessedInfo) - && func("IhrPendingSince", &t_IhrPendingSince) - && func("IhrPendingInfo", &t_IhrPendingInfo) - && func("OutMsgQueueInfo", &t_OutMsgQueueInfo) - && func("StorageUsed", &t_StorageUsed) - && func("StorageUsedShort", &t_StorageUsedShort) - && func("StorageInfo", &t_StorageInfo) - && func("Account", &t_Account) - && func("AccountStorage", &t_AccountStorage) - && func("AccountState", &t_AccountState) - && func("AccountStatus", &t_AccountStatus) - && func("ShardAccount", &t_ShardAccount) - && func("DepthBalanceInfo", &t_DepthBalanceInfo) - && func("ShardAccounts", &t_ShardAccounts) - && func("TransactionDescr", &t_TransactionDescr) - && func("AccountBlock", &t_AccountBlock) - && func("ShardAccountBlocks", &t_ShardAccountBlocks) - && func("AccStatusChange", &t_AccStatusChange) - && func("TrStoragePhase", &t_TrStoragePhase) - && func("TrCreditPhase", &t_TrCreditPhase) - && func("ComputeSkipReason", &t_ComputeSkipReason) - && func("TrComputePhase", &t_TrComputePhase) - && func("TrActionPhase", &t_TrActionPhase) - && func("TrBouncePhase", &t_TrBouncePhase) - && func("SplitMergeInfo", &t_SplitMergeInfo) - && func("SmartContractInfo", &t_SmartContractInfo) - && func("OutAction", &t_OutAction) - && func("LibRef", &t_LibRef) - && func("OutListNode", &t_OutListNode) - && func("ShardIdent", &t_ShardIdent) - && func("ExtBlkRef", &t_ExtBlkRef) - && func("BlockIdExt", &t_BlockIdExt) - && func("BlkMasterInfo", &t_BlkMasterInfo) - && func("LibDescr", &t_LibDescr) - && func("McStateExtra", &t_McStateExtra) - && func("ShardStateUnsplit", &t_ShardStateUnsplit) - && func("ShardState", &t_ShardState) - && func("GlobalVersion", &t_GlobalVersion) - && func("BlockInfo", &t_BlockInfo) - && func("ValueFlow", &t_ValueFlow) - && func("BlockExtra", &t_BlockExtra) - && func("Block", &t_Block) - && func("McBlockExtra", &t_McBlockExtra) - && func("FutureSplitMerge", &t_FutureSplitMerge) - && func("ShardDescr", &t_ShardDescr) - && func("ShardHashes", &t_ShardHashes) - && func("ShardFeeCreated", &t_ShardFeeCreated) - && func("ShardFees", &t_ShardFees) - && func("ConfigParams", &t_ConfigParams) - && func("ValidatorInfo", &t_ValidatorInfo) - && func("ValidatorBaseInfo", &t_ValidatorBaseInfo) - && func("KeyMaxLt", &t_KeyMaxLt) - && func("KeyExtBlkRef", &t_KeyExtBlkRef) - && func("OldMcBlocksInfo", &t_OldMcBlocksInfo) - && func("Counters", &t_Counters) - && func("CreatorStats", &t_CreatorStats) - && func("BlockCreateStats", &t_BlockCreateStats) - && func("SigPubKey", &t_SigPubKey) - && func("CryptoSignatureSimple", &t_CryptoSignatureSimple) - && func("CryptoSignature", &t_CryptoSignature) - && func("CryptoSignaturePair", &t_CryptoSignaturePair) - && func("Certificate", &t_Certificate) - && func("CertificateEnv", &t_CertificateEnv) - && func("SignedCertificate", &t_SignedCertificate) - && func("ValidatorDescr", &t_ValidatorDescr) - && func("ValidatorSet", &t_ValidatorSet) - && func("ConfigProposalSetup", &t_ConfigProposalSetup) - && func("ConfigVotingSetup", &t_ConfigVotingSetup) - && func("ConfigProposal", &t_ConfigProposal) - && func("ConfigProposalStatus", &t_ConfigProposalStatus) - && func("WorkchainDescr", &t_WorkchainDescr) - && func("ComplaintPricing", &t_ComplaintPricing) - && func("BlockCreateFees", &t_BlockCreateFees) - && func("StoragePrices", &t_StoragePrices) - && func("GasLimitsPrices", &t_GasLimitsPrices) - && func("ParamLimits", &t_ParamLimits) - && func("BlockLimits", &t_BlockLimits) - && func("MsgForwardPrices", &t_MsgForwardPrices) - && func("CatchainConfig", &t_CatchainConfig) - && func("ConsensusConfig", &t_ConsensusConfig) - && func("ValidatorTempKey", &t_ValidatorTempKey) - && func("ValidatorSignedTempKey", &t_ValidatorSignedTempKey) - && func("BlockSignaturesPure", &t_BlockSignaturesPure) - && func("BlockSignatures", &t_BlockSignatures) - && func("BlockProof", &t_BlockProof) - && func("TopBlockDescr", &t_TopBlockDescr) - && func("TopBlockDescrSet", &t_TopBlockDescrSet) - && func("ProducerInfo", &t_ProducerInfo) - && func("ComplaintDescr", &t_ComplaintDescr) - && func("ValidatorComplaint", &t_ValidatorComplaint) - && func("ValidatorComplaintStatus", &t_ValidatorComplaintStatus) - && func("VmStackValue", &t_VmStackValue) - && func("VmCellSlice", &t_VmCellSlice) - && func("VmCont", &t_VmCont) - && func("VmStack", &t_VmStack) - && func("VmSaveList", &t_VmSaveList) - && func("VmGasLimits", &t_VmGasLimits) - && func("VmLibraries", &t_VmLibraries) - && func("VmControlData", &t_VmControlData) - && func("DNSRecord", &t_DNSRecord) - && func("DNS_RecordSet", &t_DNS_RecordSet) - && func("Text", &t_Text) - && func("ProtoList", &t_ProtoList) - && func("Protocol", &t_Protocol) - && func("SmcCapList", &t_SmcCapList) - && func("SmcCapability", &t_SmcCapability) - && func("ChanConfig", &t_ChanConfig) - && func("ChanState", &t_ChanState) - && func("ChanPromise", &t_ChanPromise) - && func("ChanSignedPromise", &t_ChanSignedPromise) - && func("ChanMsg", &t_ChanMsg) - && func("ChanSignedMsg", &t_ChanSignedMsg) - && func("ChanOp", &t_ChanOp) - && func("ChanData", &t_ChanData); -} - - -} // namespace gen - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-auto.h b/submodules/ton/tonlib-src/crypto/block/block-auto.h deleted file mode 100644 index 2ed50170..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-auto.h +++ /dev/null @@ -1,9837 +0,0 @@ -#pragma once -#include -/* - * - * AUTO-GENERATED FROM `block.tlb` - * - */ -// uses built-in type `#` -// uses built-in type `##` -// uses built-in type `#<` -// uses built-in type `#<=` -// uses built-in type `Any` -// uses built-in type `Cell` -// uses built-in type `int` -// uses built-in type `uint` -// uses built-in type `bits` -// uses built-in type `int8` -// uses built-in type `uint8` -// uses built-in type `uint13` -// uses built-in type `uint15` -// uses built-in type `int16` -// uses built-in type `uint16` -// uses built-in type `int32` -// uses built-in type `uint32` -// uses built-in type `uint63` -// uses built-in type `int64` -// uses built-in type `uint64` -// uses built-in type `uint256` -// uses built-in type `int257` -// uses built-in type `bits256` -// uses built-in type `bits512` - -namespace block { - -namespace gen { -using namespace ::tlb; -using td::Ref; -using vm::CellSlice; -using vm::Cell; -using td::RefInt256; - -// -// headers for type `Unit` -// - -struct Unit final : TLB_Complex { - enum { unit }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Unit type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 0; - } - bool skip(vm::CellSlice& cs) const override { - return true; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return true; - } - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_unit(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_unit(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_unit(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_unit(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Unit"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Unit t_Unit; - -// -// headers for type `True` -// - -struct True final : TLB_Complex { - enum { true1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef True type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 0; - } - bool skip(vm::CellSlice& cs) const override { - return true; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return true; - } - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_true1(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_true1(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_true1(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_true1(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "True"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const True t_True; - -// -// headers for type `Bool` -// - -struct Bool final : TLB_Complex { - enum { bool_false, bool_true }; - static constexpr int cons_len_exact = 1; - struct Record_bool_false { - typedef Bool type_class; - }; - struct Record_bool_true { - typedef Bool type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 1; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(1); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(1); - } - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record_bool_false& data) const; - bool unpack_bool_false(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_bool_false& data) const; - bool cell_unpack_bool_false(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_bool_false& data) const; - bool pack_bool_false(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_bool_false& data) const; - bool cell_pack_bool_false(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_bool_true& data) const; - bool unpack_bool_true(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_bool_true& data) const; - bool cell_unpack_bool_true(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_bool_true& data) const; - bool pack_bool_true(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_bool_true& data) const; - bool cell_pack_bool_true(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Bool"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const Bool t_Bool; - -// -// headers for type `BoolFalse` -// - -struct BoolFalse final : TLB_Complex { - enum { bool_false }; - static constexpr int cons_len_exact = 1; - struct Record { - typedef BoolFalse type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 1; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(1); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_bool_false(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_bool_false(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_bool_false(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_bool_false(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BoolFalse"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const BoolFalse t_BoolFalse; - -// -// headers for type `BoolTrue` -// - -struct BoolTrue final : TLB_Complex { - enum { bool_true }; - static constexpr int cons_len_exact = 1; - static constexpr unsigned char cons_tag[1] = { 1 }; - struct Record { - typedef BoolTrue type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 1; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(1); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_bool_true(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_bool_true(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_bool_true(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_bool_true(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BoolTrue"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const BoolTrue t_BoolTrue; - -// -// headers for type `Maybe` -// - -struct Maybe final : TLB_Complex { - enum { nothing, just }; - static constexpr int cons_len_exact = 1; - const TLB &X_; - Maybe(const TLB& X) : X_(X) {} - struct Record_nothing { - typedef Maybe type_class; - }; - struct Record_just { - typedef Maybe type_class; - Ref value; // value : X - Record_just() = default; - Record_just(Ref _value) : value(std::move(_value)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_nothing& data) const; - bool unpack_nothing(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_nothing& data) const; - bool cell_unpack_nothing(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_nothing& data) const; - bool pack_nothing(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_nothing& data) const; - bool cell_pack_nothing(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_just& data) const; - bool unpack_just(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_just& data) const; - bool cell_unpack_just(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_just& data) const; - bool pack_just(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_just& data) const; - bool cell_pack_just(Ref& cell_ref, Ref value) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Maybe " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `Either` -// - -struct Either final : TLB_Complex { - enum { left, right }; - static constexpr int cons_len_exact = 1; - const TLB &X_, &Y_; - Either(const TLB& X, const TLB& Y) : X_(X), Y_(Y) {} - struct Record_left { - typedef Either type_class; - Ref value; // value : X - Record_left() = default; - Record_left(Ref _value) : value(std::move(_value)) {} - }; - struct Record_right { - typedef Either type_class; - Ref value; // value : Y - Record_right() = default; - Record_right(Ref _value) : value(std::move(_value)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_left& data) const; - bool unpack_left(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_left& data) const; - bool cell_unpack_left(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_left& data) const; - bool pack_left(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_left& data) const; - bool cell_pack_left(Ref& cell_ref, Ref value) const; - bool unpack(vm::CellSlice& cs, Record_right& data) const; - bool unpack_right(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_right& data) const; - bool cell_unpack_right(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_right& data) const; - bool pack_right(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_right& data) const; - bool cell_pack_right(Ref& cell_ref, Ref value) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Either " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `Both` -// - -struct Both final : TLB_Complex { - enum { pair }; - static constexpr int cons_len_exact = 0; - const TLB &X_, &Y_; - Both(const TLB& X, const TLB& Y) : X_(X), Y_(Y) {} - struct Record { - typedef Both type_class; - Ref first; // first : X - Ref second; // second : Y - Record() = default; - Record(Ref _first, Ref _second) : first(std::move(_first)), second(std::move(_second)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_pair(vm::CellSlice& cs, Ref& first, Ref& second) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_pair(Ref cell_ref, Ref& first, Ref& second) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_pair(vm::CellBuilder& cb, Ref first, Ref second) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_pair(Ref& cell_ref, Ref first, Ref second) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Both " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -// -// headers for type `Bit` -// - -struct Bit final : TLB_Complex { - enum { bit }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Bit type_class; - bool x; // ## 1 - Record() = default; - Record(bool _x) : x(_x) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 1; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(1); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(1); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_bit(vm::CellSlice& cs, bool& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_bit(Ref cell_ref, bool& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_bit(vm::CellBuilder& cb, bool x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_bit(Ref& cell_ref, bool x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Bit"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Bit t_Bit; - -// -// headers for type `Hashmap` -// - -struct Hashmap final : TLB_Complex { - enum { hm_edge }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_; - Hashmap(int m, const TLB& X) : m_(m), X_(X) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Hashmap " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Hashmap::Record { - typedef Hashmap type_class; - int n; // n : # - int l; // l : # - int m; // m : # - Ref label; // label : HmLabel ~l n - Ref node; // node : HashmapNode m X - Record() = default; - Record(Ref _label, Ref _node) : n(-1), l(-1), m(-1), label(std::move(_label)), node(std::move(_node)) {} -}; - -// -// headers for type `HashmapNode` -// - -struct HashmapNode final : TLB_Complex { - enum { hmn_leaf, hmn_fork }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_; - HashmapNode(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_hmn_leaf { - typedef HashmapNode type_class; - Ref value; // value : X - Record_hmn_leaf() = default; - Record_hmn_leaf(Ref _value) : value(std::move(_value)) {} - }; - struct Record_hmn_fork; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_hmn_leaf& data) const; - bool unpack_hmn_leaf(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_hmn_leaf& data) const; - bool cell_unpack_hmn_leaf(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_hmn_leaf& data) const; - bool pack_hmn_leaf(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_hmn_leaf& data) const; - bool cell_pack_hmn_leaf(Ref& cell_ref, Ref value) const; - bool unpack(vm::CellSlice& cs, Record_hmn_fork& data) const; - bool unpack_hmn_fork(vm::CellSlice& cs, int& n, Ref& left, Ref& right) const; - bool cell_unpack(Ref cell_ref, Record_hmn_fork& data) const; - bool cell_unpack_hmn_fork(Ref cell_ref, int& n, Ref& left, Ref& right) const; - bool pack(vm::CellBuilder& cb, const Record_hmn_fork& data) const; - bool pack_hmn_fork(vm::CellBuilder& cb, Ref left, Ref right) const; - bool cell_pack(Ref& cell_ref, const Record_hmn_fork& data) const; - bool cell_pack_hmn_fork(Ref& cell_ref, Ref left, Ref right) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HashmapNode " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct HashmapNode::Record_hmn_fork { - typedef HashmapNode type_class; - int n; // n : # - Ref left; // left : ^(Hashmap n X) - Ref right; // right : ^(Hashmap n X) - Record_hmn_fork() = default; - Record_hmn_fork(Ref _left, Ref _right) : n(-1), left(std::move(_left)), right(std::move(_right)) {} -}; - -// -// headers for type `HmLabel` -// - -struct HmLabel final : TLB_Complex { - enum { hml_short, hml_long, hml_same }; - static constexpr char cons_len[3] = { 1, 2, 2 }; - static constexpr unsigned char cons_tag[3] = { 0, 2, 3 }; - int n_; - HmLabel(int n) : n_(n) {} - struct Record_hml_short; - struct Record_hml_long; - struct Record_hml_same; - bool skip(vm::CellSlice& cs) const override; - bool skip(vm::CellSlice& cs, int& m_) const; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool validate_skip(int *ops, vm::CellSlice& cs, bool weak, int& m_) const; - bool fetch_to(vm::CellSlice& cs, Ref& res, int& m_) const; - bool unpack(vm::CellSlice& cs, Record_hml_short& data, int& m_) const; - bool cell_unpack(Ref cell_ref, Record_hml_short& data, int& m_) const; - bool pack(vm::CellBuilder& cb, const Record_hml_short& data, int& m_) const; - bool cell_pack(Ref& cell_ref, const Record_hml_short& data, int& m_) const; - bool unpack(vm::CellSlice& cs, Record_hml_long& data, int& m_) const; - bool unpack_hml_long(vm::CellSlice& cs, int& m, int& n, Ref& s, int& m_) const; - bool cell_unpack(Ref cell_ref, Record_hml_long& data, int& m_) const; - bool cell_unpack_hml_long(Ref cell_ref, int& m, int& n, Ref& s, int& m_) const; - bool pack(vm::CellBuilder& cb, const Record_hml_long& data, int& m_) const; - bool pack_hml_long(vm::CellBuilder& cb, int n, Ref s, int& m_) const; - bool cell_pack(Ref& cell_ref, const Record_hml_long& data, int& m_) const; - bool cell_pack_hml_long(Ref& cell_ref, int n, Ref s, int& m_) const; - bool unpack(vm::CellSlice& cs, Record_hml_same& data, int& m_) const; - bool unpack_hml_same(vm::CellSlice& cs, int& m, bool& v, int& n, int& m_) const; - bool cell_unpack(Ref cell_ref, Record_hml_same& data, int& m_) const; - bool cell_unpack_hml_same(Ref cell_ref, int& m, bool& v, int& n, int& m_) const; - bool pack(vm::CellBuilder& cb, const Record_hml_same& data, int& m_) const; - bool pack_hml_same(vm::CellBuilder& cb, bool v, int n, int& m_) const; - bool cell_pack(Ref& cell_ref, const Record_hml_same& data, int& m_) const; - bool cell_pack_hml_same(Ref& cell_ref, bool v, int n, int& m_) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs, int& m_) const; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HmLabel ~m_ " << n_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 13); - } -}; - -struct HmLabel::Record_hml_short { - typedef HmLabel type_class; - int m; // m : # - int n; // n : # - Ref len; // len : Unary ~n - Ref s; // s : n * Bit - Record_hml_short() = default; - Record_hml_short(Ref _len, Ref _s) : m(-1), n(-1), len(std::move(_len)), s(std::move(_s)) {} -}; - -struct HmLabel::Record_hml_long { - typedef HmLabel type_class; - int m; // m : # - int n; // n : #<= m - Ref s; // s : n * Bit - Record_hml_long() = default; - Record_hml_long(int _n, Ref _s) : m(-1), n(_n), s(std::move(_s)) {} -}; - -struct HmLabel::Record_hml_same { - typedef HmLabel type_class; - int m; // m : # - bool v; // v : Bit - int n; // n : #<= m - Record_hml_same() = default; - Record_hml_same(bool _v, int _n) : m(-1), v(_v), n(_n) {} -}; - -// -// headers for type `Unary` -// - -struct Unary final : TLB_Complex { - enum { unary_zero, unary_succ }; - static constexpr int cons_len_exact = 1; - struct Record_unary_zero { - typedef Unary type_class; - }; - struct Record_unary_succ { - typedef Unary type_class; - int n; // n : # - Ref x; // x : Unary ~n - Record_unary_succ() = default; - Record_unary_succ(Ref _x) : n(-1), x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool skip(vm::CellSlice& cs, int& m_) const; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool validate_skip(int *ops, vm::CellSlice& cs, bool weak, int& m_) const; - bool fetch_to(vm::CellSlice& cs, Ref& res, int& m_) const; - bool unpack(vm::CellSlice& cs, Record_unary_zero& data, int& m_) const; - bool unpack_unary_zero(vm::CellSlice& cs, int& m_) const; - bool cell_unpack(Ref cell_ref, Record_unary_zero& data, int& m_) const; - bool cell_unpack_unary_zero(Ref cell_ref, int& m_) const; - bool pack(vm::CellBuilder& cb, const Record_unary_zero& data, int& m_) const; - bool pack_unary_zero(vm::CellBuilder& cb, int& m_) const; - bool cell_pack(Ref& cell_ref, const Record_unary_zero& data, int& m_) const; - bool cell_pack_unary_zero(Ref& cell_ref, int& m_) const; - bool unpack(vm::CellSlice& cs, Record_unary_succ& data, int& m_) const; - bool unpack_unary_succ(vm::CellSlice& cs, int& n, Ref& x, int& m_) const; - bool cell_unpack(Ref cell_ref, Record_unary_succ& data, int& m_) const; - bool cell_unpack_unary_succ(Ref cell_ref, int& n, Ref& x, int& m_) const; - bool pack(vm::CellBuilder& cb, const Record_unary_succ& data, int& m_) const; - bool pack_unary_succ(vm::CellBuilder& cb, Ref x, int& m_) const; - bool cell_pack(Ref& cell_ref, const Record_unary_succ& data, int& m_) const; - bool cell_pack_unary_succ(Ref& cell_ref, Ref x, int& m_) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs, int& m_) const; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Unary ~m_)"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const Unary t_Unary; - -// -// headers for type `HashmapE` -// - -struct HashmapE final : TLB_Complex { - enum { hme_empty, hme_root }; - static constexpr int cons_len_exact = 1; - int m_; - const TLB &X_; - HashmapE(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_hme_empty { - typedef HashmapE type_class; - }; - struct Record_hme_root { - typedef HashmapE type_class; - int n; // n : # - Ref root; // root : ^(Hashmap n X) - Record_hme_root() = default; - Record_hme_root(Ref _root) : n(-1), root(std::move(_root)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_hme_empty& data) const; - bool unpack_hme_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_hme_empty& data) const; - bool cell_unpack_hme_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_hme_empty& data) const; - bool pack_hme_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_hme_empty& data) const; - bool cell_pack_hme_empty(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_hme_root& data) const; - bool unpack_hme_root(vm::CellSlice& cs, int& n, Ref& root) const; - bool cell_unpack(Ref cell_ref, Record_hme_root& data) const; - bool cell_unpack_hme_root(Ref cell_ref, int& n, Ref& root) const; - bool pack(vm::CellBuilder& cb, const Record_hme_root& data) const; - bool pack_hme_root(vm::CellBuilder& cb, Ref root) const; - bool cell_pack(Ref& cell_ref, const Record_hme_root& data) const; - bool cell_pack_hme_root(Ref& cell_ref, Ref root) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HashmapE " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `BitstringSet` -// - -struct BitstringSet final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - int m_; - BitstringSet(int m) : m_(m) {} - struct Record { - typedef BitstringSet type_class; - int n; // n : # - Ref x; // Hashmap n True - Record() = default; - Record(Ref _x) : n(-1), x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, int& n, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, int& n, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(BitstringSet " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -// -// headers for type `HashmapAug` -// - -struct HashmapAug final : TLB_Complex { - enum { ahm_edge }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_, &Y_; - HashmapAug(int m, const TLB& X, const TLB& Y) : m_(m), X_(X), Y_(Y) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HashmapAug " << m_ << " " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct HashmapAug::Record { - typedef HashmapAug type_class; - int n; // n : # - int l; // l : # - int m; // m : # - Ref label; // label : HmLabel ~l n - Ref node; // node : HashmapAugNode m X Y - Record() = default; - Record(Ref _label, Ref _node) : n(-1), l(-1), m(-1), label(std::move(_label)), node(std::move(_node)) {} -}; - -// -// headers for type `HashmapAugNode` -// - -struct HashmapAugNode final : TLB_Complex { - enum { ahmn_leaf, ahmn_fork }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_, &Y_; - HashmapAugNode(int m, const TLB& X, const TLB& Y) : m_(m), X_(X), Y_(Y) {} - struct Record_ahmn_leaf { - typedef HashmapAugNode type_class; - Ref extra; // extra : Y - Ref value; // value : X - Record_ahmn_leaf() = default; - Record_ahmn_leaf(Ref _extra, Ref _value) : extra(std::move(_extra)), value(std::move(_value)) {} - }; - struct Record_ahmn_fork; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_ahmn_leaf& data) const; - bool unpack_ahmn_leaf(vm::CellSlice& cs, Ref& extra, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_ahmn_leaf& data) const; - bool cell_unpack_ahmn_leaf(Ref cell_ref, Ref& extra, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_ahmn_leaf& data) const; - bool pack_ahmn_leaf(vm::CellBuilder& cb, Ref extra, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_ahmn_leaf& data) const; - bool cell_pack_ahmn_leaf(Ref& cell_ref, Ref extra, Ref value) const; - bool unpack(vm::CellSlice& cs, Record_ahmn_fork& data) const; - bool cell_unpack(Ref cell_ref, Record_ahmn_fork& data) const; - bool pack(vm::CellBuilder& cb, const Record_ahmn_fork& data) const; - bool cell_pack(Ref& cell_ref, const Record_ahmn_fork& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HashmapAugNode " << m_ << " " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct HashmapAugNode::Record_ahmn_fork { - typedef HashmapAugNode type_class; - int n; // n : # - Ref left; // left : ^(HashmapAug n X Y) - Ref right; // right : ^(HashmapAug n X Y) - Ref extra; // extra : Y - Record_ahmn_fork() = default; - Record_ahmn_fork(Ref _left, Ref _right, Ref _extra) : n(-1), left(std::move(_left)), right(std::move(_right)), extra(std::move(_extra)) {} -}; - -// -// headers for type `HashmapAugE` -// - -struct HashmapAugE final : TLB_Complex { - enum { ahme_empty, ahme_root }; - static constexpr int cons_len_exact = 1; - int m_; - const TLB &X_, &Y_; - HashmapAugE(int m, const TLB& X, const TLB& Y) : m_(m), X_(X), Y_(Y) {} - struct Record_ahme_empty { - typedef HashmapAugE type_class; - Ref extra; // extra : Y - Record_ahme_empty() = default; - Record_ahme_empty(Ref _extra) : extra(std::move(_extra)) {} - }; - struct Record_ahme_root; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_ahme_empty& data) const; - bool unpack_ahme_empty(vm::CellSlice& cs, Ref& extra) const; - bool cell_unpack(Ref cell_ref, Record_ahme_empty& data) const; - bool cell_unpack_ahme_empty(Ref cell_ref, Ref& extra) const; - bool pack(vm::CellBuilder& cb, const Record_ahme_empty& data) const; - bool pack_ahme_empty(vm::CellBuilder& cb, Ref extra) const; - bool cell_pack(Ref& cell_ref, const Record_ahme_empty& data) const; - bool cell_pack_ahme_empty(Ref& cell_ref, Ref extra) const; - bool unpack(vm::CellSlice& cs, Record_ahme_root& data) const; - bool unpack_ahme_root(vm::CellSlice& cs, int& n, Ref& root, Ref& extra) const; - bool cell_unpack(Ref cell_ref, Record_ahme_root& data) const; - bool cell_unpack_ahme_root(Ref cell_ref, int& n, Ref& root, Ref& extra) const; - bool pack(vm::CellBuilder& cb, const Record_ahme_root& data) const; - bool pack_ahme_root(vm::CellBuilder& cb, Ref root, Ref extra) const; - bool cell_pack(Ref& cell_ref, const Record_ahme_root& data) const; - bool cell_pack_ahme_root(Ref& cell_ref, Ref root, Ref extra) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HashmapAugE " << m_ << " " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct HashmapAugE::Record_ahme_root { - typedef HashmapAugE type_class; - int n; // n : # - Ref root; // root : ^(HashmapAug n X Y) - Ref extra; // extra : Y - Record_ahme_root() = default; - Record_ahme_root(Ref _root, Ref _extra) : n(-1), root(std::move(_root)), extra(std::move(_extra)) {} -}; - -// -// headers for type `VarHashmap` -// - -struct VarHashmap final : TLB_Complex { - enum { vhm_edge }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_; - VarHashmap(int m, const TLB& X) : m_(m), X_(X) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarHashmap " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VarHashmap::Record { - typedef VarHashmap type_class; - int n; // n : # - int l; // l : # - int m; // m : # - Ref label; // label : HmLabel ~l n - Ref node; // node : VarHashmapNode m X - Record() = default; - Record(Ref _label, Ref _node) : n(-1), l(-1), m(-1), label(std::move(_label)), node(std::move(_node)) {} -}; - -// -// headers for type `VarHashmapNode` -// - -struct VarHashmapNode final : TLB_Complex { - enum { vhmn_leaf, vhmn_fork, vhmn_cont }; - static constexpr char cons_len[3] = { 2, 2, 1 }; - static constexpr unsigned char cons_tag[3] = { 0, 1, 1 }; - int m_; - const TLB &X_; - VarHashmapNode(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_vhmn_leaf { - typedef VarHashmapNode type_class; - Ref value; // value : X - Record_vhmn_leaf() = default; - Record_vhmn_leaf(Ref _value) : value(std::move(_value)) {} - }; - struct Record_vhmn_fork; - struct Record_vhmn_cont; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vhmn_leaf& data) const; - bool unpack_vhmn_leaf(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_vhmn_leaf& data) const; - bool cell_unpack_vhmn_leaf(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_vhmn_leaf& data) const; - bool pack_vhmn_leaf(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_vhmn_leaf& data) const; - bool cell_pack_vhmn_leaf(Ref& cell_ref, Ref value) const; - bool unpack(vm::CellSlice& cs, Record_vhmn_fork& data) const; - bool cell_unpack(Ref cell_ref, Record_vhmn_fork& data) const; - bool pack(vm::CellBuilder& cb, const Record_vhmn_fork& data) const; - bool cell_pack(Ref& cell_ref, const Record_vhmn_fork& data) const; - bool unpack(vm::CellSlice& cs, Record_vhmn_cont& data) const; - bool cell_unpack(Ref cell_ref, Record_vhmn_cont& data) const; - bool pack(vm::CellBuilder& cb, const Record_vhmn_cont& data) const; - bool cell_pack(Ref& cell_ref, const Record_vhmn_cont& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarHashmapNode " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 7); - } -}; - -struct VarHashmapNode::Record_vhmn_fork { - typedef VarHashmapNode type_class; - int n; // n : # - Ref left; // left : ^(VarHashmap n X) - Ref right; // right : ^(VarHashmap n X) - Ref value; // value : Maybe X - Record_vhmn_fork() = default; - Record_vhmn_fork(Ref _left, Ref _right, Ref _value) : n(-1), left(std::move(_left)), right(std::move(_right)), value(std::move(_value)) {} -}; - -struct VarHashmapNode::Record_vhmn_cont { - typedef VarHashmapNode type_class; - int n; // n : # - bool branch; // branch : Bit - Ref child; // child : ^(VarHashmap n X) - Ref value; // value : X - Record_vhmn_cont() = default; - Record_vhmn_cont(bool _branch, Ref _child, Ref _value) : n(-1), branch(_branch), child(std::move(_child)), value(std::move(_value)) {} -}; - -// -// headers for type `VarHashmapE` -// - -struct VarHashmapE final : TLB_Complex { - enum { vhme_empty, vhme_root }; - static constexpr int cons_len_exact = 1; - int m_; - const TLB &X_; - VarHashmapE(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_vhme_empty { - typedef VarHashmapE type_class; - }; - struct Record_vhme_root { - typedef VarHashmapE type_class; - int n; // n : # - Ref root; // root : ^(VarHashmap n X) - Record_vhme_root() = default; - Record_vhme_root(Ref _root) : n(-1), root(std::move(_root)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vhme_empty& data) const; - bool unpack_vhme_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vhme_empty& data) const; - bool cell_unpack_vhme_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vhme_empty& data) const; - bool pack_vhme_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vhme_empty& data) const; - bool cell_pack_vhme_empty(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vhme_root& data) const; - bool unpack_vhme_root(vm::CellSlice& cs, int& n, Ref& root) const; - bool cell_unpack(Ref cell_ref, Record_vhme_root& data) const; - bool cell_unpack_vhme_root(Ref cell_ref, int& n, Ref& root) const; - bool pack(vm::CellBuilder& cb, const Record_vhme_root& data) const; - bool pack_vhme_root(vm::CellBuilder& cb, Ref root) const; - bool cell_pack(Ref& cell_ref, const Record_vhme_root& data) const; - bool cell_pack_vhme_root(Ref& cell_ref, Ref root) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarHashmapE " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `PfxHashmap` -// - -struct PfxHashmap final : TLB_Complex { - enum { phm_edge }; - static constexpr int cons_len_exact = 0; - int m_; - const TLB &X_; - PfxHashmap(int m, const TLB& X) : m_(m), X_(X) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(PfxHashmap " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct PfxHashmap::Record { - typedef PfxHashmap type_class; - int n; // n : # - int l; // l : # - int m; // m : # - Ref label; // label : HmLabel ~l n - Ref node; // node : PfxHashmapNode m X - Record() = default; - Record(Ref _label, Ref _node) : n(-1), l(-1), m(-1), label(std::move(_label)), node(std::move(_node)) {} -}; - -// -// headers for type `PfxHashmapNode` -// - -struct PfxHashmapNode final : TLB_Complex { - enum { phmn_leaf, phmn_fork }; - static constexpr int cons_len_exact = 1; - int m_; - const TLB &X_; - PfxHashmapNode(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_phmn_leaf { - typedef PfxHashmapNode type_class; - Ref value; // value : X - Record_phmn_leaf() = default; - Record_phmn_leaf(Ref _value) : value(std::move(_value)) {} - }; - struct Record_phmn_fork; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_phmn_leaf& data) const; - bool unpack_phmn_leaf(vm::CellSlice& cs, Ref& value) const; - bool cell_unpack(Ref cell_ref, Record_phmn_leaf& data) const; - bool cell_unpack_phmn_leaf(Ref cell_ref, Ref& value) const; - bool pack(vm::CellBuilder& cb, const Record_phmn_leaf& data) const; - bool pack_phmn_leaf(vm::CellBuilder& cb, Ref value) const; - bool cell_pack(Ref& cell_ref, const Record_phmn_leaf& data) const; - bool cell_pack_phmn_leaf(Ref& cell_ref, Ref value) const; - bool unpack(vm::CellSlice& cs, Record_phmn_fork& data) const; - bool unpack_phmn_fork(vm::CellSlice& cs, int& n, Ref& left, Ref& right) const; - bool cell_unpack(Ref cell_ref, Record_phmn_fork& data) const; - bool cell_unpack_phmn_fork(Ref cell_ref, int& n, Ref& left, Ref& right) const; - bool pack(vm::CellBuilder& cb, const Record_phmn_fork& data) const; - bool pack_phmn_fork(vm::CellBuilder& cb, Ref left, Ref right) const; - bool cell_pack(Ref& cell_ref, const Record_phmn_fork& data) const; - bool cell_pack_phmn_fork(Ref& cell_ref, Ref left, Ref right) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(PfxHashmapNode " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct PfxHashmapNode::Record_phmn_fork { - typedef PfxHashmapNode type_class; - int n; // n : # - Ref left; // left : ^(PfxHashmap n X) - Ref right; // right : ^(PfxHashmap n X) - Record_phmn_fork() = default; - Record_phmn_fork(Ref _left, Ref _right) : n(-1), left(std::move(_left)), right(std::move(_right)) {} -}; - -// -// headers for type `PfxHashmapE` -// - -struct PfxHashmapE final : TLB_Complex { - enum { phme_empty, phme_root }; - static constexpr int cons_len_exact = 1; - int m_; - const TLB &X_; - PfxHashmapE(int m, const TLB& X) : m_(m), X_(X) {} - struct Record_phme_empty { - typedef PfxHashmapE type_class; - }; - struct Record_phme_root { - typedef PfxHashmapE type_class; - int n; // n : # - Ref root; // root : ^(PfxHashmap n X) - Record_phme_root() = default; - Record_phme_root(Ref _root) : n(-1), root(std::move(_root)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_phme_empty& data) const; - bool unpack_phme_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_phme_empty& data) const; - bool cell_unpack_phme_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_phme_empty& data) const; - bool pack_phme_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_phme_empty& data) const; - bool cell_pack_phme_empty(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_phme_root& data) const; - bool unpack_phme_root(vm::CellSlice& cs, int& n, Ref& root) const; - bool cell_unpack(Ref cell_ref, Record_phme_root& data) const; - bool cell_unpack_phme_root(Ref cell_ref, int& n, Ref& root) const; - bool pack(vm::CellBuilder& cb, const Record_phme_root& data) const; - bool pack_phme_root(vm::CellBuilder& cb, Ref root) const; - bool cell_pack(Ref& cell_ref, const Record_phme_root& data) const; - bool cell_pack_phme_root(Ref& cell_ref, Ref root) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(PfxHashmapE " << m_ << " " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `MsgAddressExt` -// - -struct MsgAddressExt final : TLB_Complex { - enum { addr_none, addr_extern }; - static constexpr int cons_len_exact = 2; - struct Record_addr_none { - typedef MsgAddressExt type_class; - }; - struct Record_addr_extern { - typedef MsgAddressExt type_class; - int len; // len : ## 9 - Ref external_address; // external_address : bits len - Record_addr_extern() = default; - Record_addr_extern(int _len, Ref _external_address) : len(_len), external_address(std::move(_external_address)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_addr_none& data) const; - bool unpack_addr_none(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_addr_none& data) const; - bool cell_unpack_addr_none(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_addr_none& data) const; - bool pack_addr_none(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_addr_none& data) const; - bool cell_pack_addr_none(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_addr_extern& data) const; - bool unpack_addr_extern(vm::CellSlice& cs, int& len, Ref& external_address) const; - bool cell_unpack(Ref cell_ref, Record_addr_extern& data) const; - bool cell_unpack_addr_extern(Ref cell_ref, int& len, Ref& external_address) const; - bool pack(vm::CellBuilder& cb, const Record_addr_extern& data) const; - bool pack_addr_extern(vm::CellBuilder& cb, int len, Ref external_address) const; - bool cell_pack(Ref& cell_ref, const Record_addr_extern& data) const; - bool cell_pack_addr_extern(Ref& cell_ref, int len, Ref external_address) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MsgAddressExt"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 3); - } -}; - -extern const MsgAddressExt t_MsgAddressExt; - -// -// headers for type `Anycast` -// - -struct Anycast final : TLB_Complex { - enum { anycast_info }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Anycast type_class; - int depth; // depth : #<= 30 - Ref rewrite_pfx; // rewrite_pfx : bits depth - Record() = default; - Record(int _depth, Ref _rewrite_pfx) : depth(_depth), rewrite_pfx(std::move(_rewrite_pfx)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_anycast_info(vm::CellSlice& cs, int& depth, Ref& rewrite_pfx) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_anycast_info(Ref cell_ref, int& depth, Ref& rewrite_pfx) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_anycast_info(vm::CellBuilder& cb, int depth, Ref rewrite_pfx) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_anycast_info(Ref& cell_ref, int depth, Ref rewrite_pfx) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Anycast"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Anycast t_Anycast; - -// -// headers for type `MsgAddressInt` -// - -struct MsgAddressInt final : TLB_Complex { - enum { addr_std, addr_var }; - static constexpr int cons_len_exact = 2; - static constexpr unsigned char cons_tag[2] = { 2, 3 }; - struct Record_addr_std; - struct Record_addr_var; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_addr_std& data) const; - bool unpack_addr_std(vm::CellSlice& cs, Ref& anycast, int& workchain_id, td::BitArray<256>& address) const; - bool cell_unpack(Ref cell_ref, Record_addr_std& data) const; - bool cell_unpack_addr_std(Ref cell_ref, Ref& anycast, int& workchain_id, td::BitArray<256>& address) const; - bool pack(vm::CellBuilder& cb, const Record_addr_std& data) const; - bool pack_addr_std(vm::CellBuilder& cb, Ref anycast, int workchain_id, td::BitArray<256> address) const; - bool cell_pack(Ref& cell_ref, const Record_addr_std& data) const; - bool cell_pack_addr_std(Ref& cell_ref, Ref anycast, int workchain_id, td::BitArray<256> address) const; - bool unpack(vm::CellSlice& cs, Record_addr_var& data) const; - bool cell_unpack(Ref cell_ref, Record_addr_var& data) const; - bool pack(vm::CellBuilder& cb, const Record_addr_var& data) const; - bool cell_pack(Ref& cell_ref, const Record_addr_var& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MsgAddressInt"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 12); - } -}; - -struct MsgAddressInt::Record_addr_std { - typedef MsgAddressInt type_class; - Ref anycast; // anycast : Maybe Anycast - int workchain_id; // workchain_id : int8 - td::BitArray<256> address; // address : bits256 - Record_addr_std() = default; - Record_addr_std(Ref _anycast, int _workchain_id, const td::BitArray<256>& _address) : anycast(std::move(_anycast)), workchain_id(_workchain_id), address(_address) {} -}; - -struct MsgAddressInt::Record_addr_var { - typedef MsgAddressInt type_class; - Ref anycast; // anycast : Maybe Anycast - int addr_len; // addr_len : ## 9 - int workchain_id; // workchain_id : int32 - Ref address; // address : bits addr_len - Record_addr_var() = default; - Record_addr_var(Ref _anycast, int _addr_len, int _workchain_id, Ref _address) : anycast(std::move(_anycast)), addr_len(_addr_len), workchain_id(_workchain_id), address(std::move(_address)) {} -}; - -extern const MsgAddressInt t_MsgAddressInt; - -// -// headers for type `MsgAddress` -// - -struct MsgAddress final : TLB_Complex { - enum { cons2, cons1 }; - static constexpr int cons_len_exact = 0; - struct Record_cons1 { - typedef MsgAddress type_class; - Ref x; // MsgAddressInt - Record_cons1() = default; - Record_cons1(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons2 { - typedef MsgAddress type_class; - Ref x; // MsgAddressExt - Record_cons2() = default; - Record_cons2(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cons1& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons1& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons1& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons1& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons2& data) const; - bool unpack_cons2(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons2& data) const; - bool cell_unpack_cons2(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons2& data) const; - bool pack_cons2(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons2& data) const; - bool cell_pack_cons2(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MsgAddress"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const MsgAddress t_MsgAddress; - -// -// headers for type `VarUInteger` -// - -struct VarUInteger final : TLB_Complex { - enum { var_uint }; - static constexpr int cons_len_exact = 0; - int m_; - VarUInteger(int m) : m_(m) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_var_uint(vm::CellSlice& cs, int& n, int& len, RefInt256& value) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_var_uint(Ref cell_ref, int& n, int& len, RefInt256& value) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_var_uint(vm::CellBuilder& cb, int len, RefInt256 value) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_var_uint(Ref& cell_ref, int len, RefInt256 value) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarUInteger " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VarUInteger::Record { - typedef VarUInteger type_class; - int n; // n : # - int len; // len : #< n - RefInt256 value; // value : uint (8 * len) - Record() = default; - Record(int _len, RefInt256 _value) : n(-1), len(_len), value(std::move(_value)) {} -}; - -// -// headers for type `VarInteger` -// - -struct VarInteger final : TLB_Complex { - enum { var_int }; - static constexpr int cons_len_exact = 0; - int m_; - VarInteger(int m) : m_(m) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_var_int(vm::CellSlice& cs, int& n, int& len, RefInt256& value) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_var_int(Ref cell_ref, int& n, int& len, RefInt256& value) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_var_int(vm::CellBuilder& cb, int len, RefInt256 value) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_var_int(Ref& cell_ref, int len, RefInt256 value) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarInteger " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VarInteger::Record { - typedef VarInteger type_class; - int n; // n : # - int len; // len : #< n - RefInt256 value; // value : int (8 * len) - Record() = default; - Record(int _len, RefInt256 _value) : n(-1), len(_len), value(std::move(_value)) {} -}; - -// -// headers for type `Grams` -// - -struct Grams final : TLB_Complex { - enum { nanograms }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Grams type_class; - Ref amount; // amount : VarUInteger 16 - Record() = default; - Record(Ref _amount) : amount(std::move(_amount)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_nanograms(vm::CellSlice& cs, Ref& amount) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_nanograms(Ref cell_ref, Ref& amount) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_nanograms(vm::CellBuilder& cb, Ref amount) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_nanograms(Ref& cell_ref, Ref amount) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Grams"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Grams t_Grams; - -// -// headers for type `ExtraCurrencyCollection` -// - -struct ExtraCurrencyCollection final : TLB_Complex { - enum { extra_currencies }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ExtraCurrencyCollection type_class; - Ref dict; // dict : HashmapE 32 (VarUInteger 32) - Record() = default; - Record(Ref _dict) : dict(std::move(_dict)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_extra_currencies(vm::CellSlice& cs, Ref& dict) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_extra_currencies(Ref cell_ref, Ref& dict) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_extra_currencies(vm::CellBuilder& cb, Ref dict) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_extra_currencies(Ref& cell_ref, Ref dict) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ExtraCurrencyCollection"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ExtraCurrencyCollection t_ExtraCurrencyCollection; - -// -// headers for type `CurrencyCollection` -// - -struct CurrencyCollection final : TLB_Complex { - enum { currencies }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef CurrencyCollection type_class; - Ref grams; // grams : Grams - Ref other; // other : ExtraCurrencyCollection - Record() = default; - Record(Ref _grams, Ref _other) : grams(std::move(_grams)), other(std::move(_other)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_currencies(vm::CellSlice& cs, Ref& grams, Ref& other) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_currencies(Ref cell_ref, Ref& grams, Ref& other) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_currencies(vm::CellBuilder& cb, Ref grams, Ref other) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_currencies(Ref& cell_ref, Ref grams, Ref other) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CurrencyCollection"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const CurrencyCollection t_CurrencyCollection; - -// -// headers for type `CommonMsgInfo` -// - -struct CommonMsgInfo final : TLB_Complex { - enum { int_msg_info, ext_in_msg_info, ext_out_msg_info }; - static constexpr char cons_len[3] = { 1, 2, 2 }; - static constexpr unsigned char cons_tag[3] = { 0, 2, 3 }; - struct Record_int_msg_info; - struct Record_ext_in_msg_info; - struct Record_ext_out_msg_info; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_int_msg_info& data) const; - bool cell_unpack(Ref cell_ref, Record_int_msg_info& data) const; - bool pack(vm::CellBuilder& cb, const Record_int_msg_info& data) const; - bool cell_pack(Ref& cell_ref, const Record_int_msg_info& data) const; - bool unpack(vm::CellSlice& cs, Record_ext_in_msg_info& data) const; - bool unpack_ext_in_msg_info(vm::CellSlice& cs, Ref& src, Ref& dest, Ref& import_fee) const; - bool cell_unpack(Ref cell_ref, Record_ext_in_msg_info& data) const; - bool cell_unpack_ext_in_msg_info(Ref cell_ref, Ref& src, Ref& dest, Ref& import_fee) const; - bool pack(vm::CellBuilder& cb, const Record_ext_in_msg_info& data) const; - bool pack_ext_in_msg_info(vm::CellBuilder& cb, Ref src, Ref dest, Ref import_fee) const; - bool cell_pack(Ref& cell_ref, const Record_ext_in_msg_info& data) const; - bool cell_pack_ext_in_msg_info(Ref& cell_ref, Ref src, Ref dest, Ref import_fee) const; - bool unpack(vm::CellSlice& cs, Record_ext_out_msg_info& data) const; - bool cell_unpack(Ref cell_ref, Record_ext_out_msg_info& data) const; - bool pack(vm::CellBuilder& cb, const Record_ext_out_msg_info& data) const; - bool cell_pack(Ref& cell_ref, const Record_ext_out_msg_info& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CommonMsgInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 13); - } -}; - -struct CommonMsgInfo::Record_int_msg_info { - typedef CommonMsgInfo type_class; - bool ihr_disabled; // ihr_disabled : Bool - bool bounce; // bounce : Bool - bool bounced; // bounced : Bool - Ref src; // src : MsgAddressInt - Ref dest; // dest : MsgAddressInt - Ref value; // value : CurrencyCollection - Ref ihr_fee; // ihr_fee : Grams - Ref fwd_fee; // fwd_fee : Grams - unsigned long long created_lt; // created_lt : uint64 - unsigned created_at; // created_at : uint32 - Record_int_msg_info() = default; - Record_int_msg_info(bool _ihr_disabled, bool _bounce, bool _bounced, Ref _src, Ref _dest, Ref _value, Ref _ihr_fee, Ref _fwd_fee, unsigned long long _created_lt, unsigned _created_at) : ihr_disabled(_ihr_disabled), bounce(_bounce), bounced(_bounced), src(std::move(_src)), dest(std::move(_dest)), value(std::move(_value)), ihr_fee(std::move(_ihr_fee)), fwd_fee(std::move(_fwd_fee)), created_lt(_created_lt), created_at(_created_at) {} -}; - -struct CommonMsgInfo::Record_ext_in_msg_info { - typedef CommonMsgInfo type_class; - Ref src; // src : MsgAddressExt - Ref dest; // dest : MsgAddressInt - Ref import_fee; // import_fee : Grams - Record_ext_in_msg_info() = default; - Record_ext_in_msg_info(Ref _src, Ref _dest, Ref _import_fee) : src(std::move(_src)), dest(std::move(_dest)), import_fee(std::move(_import_fee)) {} -}; - -struct CommonMsgInfo::Record_ext_out_msg_info { - typedef CommonMsgInfo type_class; - Ref src; // src : MsgAddressInt - Ref dest; // dest : MsgAddressExt - unsigned long long created_lt; // created_lt : uint64 - unsigned created_at; // created_at : uint32 - Record_ext_out_msg_info() = default; - Record_ext_out_msg_info(Ref _src, Ref _dest, unsigned long long _created_lt, unsigned _created_at) : src(std::move(_src)), dest(std::move(_dest)), created_lt(_created_lt), created_at(_created_at) {} -}; - -extern const CommonMsgInfo t_CommonMsgInfo; - -// -// headers for type `CommonMsgInfoRelaxed` -// - -struct CommonMsgInfoRelaxed final : TLB_Complex { - enum { int_msg_info, ext_out_msg_info }; - static constexpr char cons_len[2] = { 1, 2 }; - static constexpr unsigned char cons_tag[2] = { 0, 3 }; - struct Record_int_msg_info; - struct Record_ext_out_msg_info; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_int_msg_info& data) const; - bool cell_unpack(Ref cell_ref, Record_int_msg_info& data) const; - bool pack(vm::CellBuilder& cb, const Record_int_msg_info& data) const; - bool cell_pack(Ref& cell_ref, const Record_int_msg_info& data) const; - bool unpack(vm::CellSlice& cs, Record_ext_out_msg_info& data) const; - bool cell_unpack(Ref cell_ref, Record_ext_out_msg_info& data) const; - bool pack(vm::CellBuilder& cb, const Record_ext_out_msg_info& data) const; - bool cell_pack(Ref& cell_ref, const Record_ext_out_msg_info& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CommonMsgInfoRelaxed"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct CommonMsgInfoRelaxed::Record_int_msg_info { - typedef CommonMsgInfoRelaxed type_class; - bool ihr_disabled; // ihr_disabled : Bool - bool bounce; // bounce : Bool - bool bounced; // bounced : Bool - Ref src; // src : MsgAddress - Ref dest; // dest : MsgAddressInt - Ref value; // value : CurrencyCollection - Ref ihr_fee; // ihr_fee : Grams - Ref fwd_fee; // fwd_fee : Grams - unsigned long long created_lt; // created_lt : uint64 - unsigned created_at; // created_at : uint32 - Record_int_msg_info() = default; - Record_int_msg_info(bool _ihr_disabled, bool _bounce, bool _bounced, Ref _src, Ref _dest, Ref _value, Ref _ihr_fee, Ref _fwd_fee, unsigned long long _created_lt, unsigned _created_at) : ihr_disabled(_ihr_disabled), bounce(_bounce), bounced(_bounced), src(std::move(_src)), dest(std::move(_dest)), value(std::move(_value)), ihr_fee(std::move(_ihr_fee)), fwd_fee(std::move(_fwd_fee)), created_lt(_created_lt), created_at(_created_at) {} -}; - -struct CommonMsgInfoRelaxed::Record_ext_out_msg_info { - typedef CommonMsgInfoRelaxed type_class; - Ref src; // src : MsgAddress - Ref dest; // dest : MsgAddressExt - unsigned long long created_lt; // created_lt : uint64 - unsigned created_at; // created_at : uint32 - Record_ext_out_msg_info() = default; - Record_ext_out_msg_info(Ref _src, Ref _dest, unsigned long long _created_lt, unsigned _created_at) : src(std::move(_src)), dest(std::move(_dest)), created_lt(_created_lt), created_at(_created_at) {} -}; - -extern const CommonMsgInfoRelaxed t_CommonMsgInfoRelaxed; - -// -// headers for type `TickTock` -// - -struct TickTock final : TLB_Complex { - enum { tick_tock }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef TickTock type_class; - bool tick; // tick : Bool - bool tock; // tock : Bool - Record() = default; - Record(bool _tick, bool _tock) : tick(_tick), tock(_tock) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 2; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(2); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(2); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_tick_tock(vm::CellSlice& cs, bool& tick, bool& tock) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_tick_tock(Ref cell_ref, bool& tick, bool& tock) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_tick_tock(vm::CellBuilder& cb, bool tick, bool tock) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_tick_tock(Ref& cell_ref, bool tick, bool tock) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TickTock"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const TickTock t_TickTock; - -// -// headers for type `StateInit` -// - -struct StateInit final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "StateInit"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct StateInit::Record { - typedef StateInit type_class; - Ref split_depth; // split_depth : Maybe (## 5) - Ref special; // special : Maybe TickTock - Ref code; // code : Maybe ^Cell - Ref data; // data : Maybe ^Cell - Ref library; // library : HashmapE 256 SimpleLib - Record() = default; - Record(Ref _split_depth, Ref _special, Ref _code, Ref _data, Ref _library) : split_depth(std::move(_split_depth)), special(std::move(_special)), code(std::move(_code)), data(std::move(_data)), library(std::move(_library)) {} -}; - -extern const StateInit t_StateInit; - -// -// headers for type `SimpleLib` -// - -struct SimpleLib final : TLB_Complex { - enum { simple_lib }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef SimpleLib type_class; - bool public1; // public : Bool - Ref root; // root : ^Cell - Record() = default; - Record(bool _public1, Ref _root) : public1(_public1), root(std::move(_root)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x10001; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10001); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_simple_lib(vm::CellSlice& cs, bool& public1, Ref& root) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_simple_lib(Ref cell_ref, bool& public1, Ref& root) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_simple_lib(vm::CellBuilder& cb, bool public1, Ref root) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_simple_lib(Ref& cell_ref, bool public1, Ref root) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SimpleLib"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const SimpleLib t_SimpleLib; - -// -// headers for type `Message` -// - -struct Message final : TLB_Complex { - enum { message }; - static constexpr int cons_len_exact = 0; - const TLB &X_; - Message(const TLB& X) : X_(X) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_message(vm::CellSlice& cs, Ref& info, Ref& init, Ref& body) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_message(Ref cell_ref, Ref& info, Ref& init, Ref& body) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_message(vm::CellBuilder& cb, Ref info, Ref init, Ref body) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_message(Ref& cell_ref, Ref info, Ref init, Ref body) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(Message " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Message::Record { - typedef Message type_class; - Ref info; // info : CommonMsgInfo - Ref init; // init : Maybe (Either StateInit ^StateInit) - Ref body; // body : Either X ^X - Record() = default; - Record(Ref _info, Ref _init, Ref _body) : info(std::move(_info)), init(std::move(_init)), body(std::move(_body)) {} -}; - -// -// headers for type `MessageRelaxed` -// - -struct MessageRelaxed final : TLB_Complex { - enum { message }; - static constexpr int cons_len_exact = 0; - const TLB &X_; - MessageRelaxed(const TLB& X) : X_(X) {} - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_message(vm::CellSlice& cs, Ref& info, Ref& init, Ref& body) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_message(Ref cell_ref, Ref& info, Ref& init, Ref& body) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_message(vm::CellBuilder& cb, Ref info, Ref init, Ref body) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_message(Ref& cell_ref, Ref info, Ref init, Ref body) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(MessageRelaxed " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct MessageRelaxed::Record { - typedef MessageRelaxed type_class; - Ref info; // info : CommonMsgInfoRelaxed - Ref init; // init : Maybe (Either StateInit ^StateInit) - Ref body; // body : Either X ^X - Record() = default; - Record(Ref _info, Ref _init, Ref _body) : info(std::move(_info)), init(std::move(_init)), body(std::move(_body)) {} -}; - -// -// headers for type `MessageAny` -// - -struct MessageAny final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef MessageAny type_class; - Ref x; // Message Any - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MessageAny"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const MessageAny t_MessageAny; - -// -// headers for type `IntermediateAddress` -// - -struct IntermediateAddress final : TLB_Complex { - enum { interm_addr_regular, interm_addr_simple, interm_addr_ext }; - static constexpr char cons_len[3] = { 1, 2, 2 }; - static constexpr unsigned char cons_tag[3] = { 0, 2, 3 }; - struct Record_interm_addr_regular { - typedef IntermediateAddress type_class; - int use_dest_bits; // use_dest_bits : #<= 96 - Record_interm_addr_regular() = default; - Record_interm_addr_regular(int _use_dest_bits) : use_dest_bits(_use_dest_bits) {} - }; - struct Record_interm_addr_simple { - typedef IntermediateAddress type_class; - int workchain_id; // workchain_id : int8 - unsigned long long addr_pfx; // addr_pfx : uint64 - Record_interm_addr_simple() = default; - Record_interm_addr_simple(int _workchain_id, unsigned long long _addr_pfx) : workchain_id(_workchain_id), addr_pfx(_addr_pfx) {} - }; - struct Record_interm_addr_ext { - typedef IntermediateAddress type_class; - int workchain_id; // workchain_id : int32 - unsigned long long addr_pfx; // addr_pfx : uint64 - Record_interm_addr_ext() = default; - Record_interm_addr_ext(int _workchain_id, unsigned long long _addr_pfx) : workchain_id(_workchain_id), addr_pfx(_addr_pfx) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_interm_addr_regular& data) const; - bool unpack_interm_addr_regular(vm::CellSlice& cs, int& use_dest_bits) const; - bool cell_unpack(Ref cell_ref, Record_interm_addr_regular& data) const; - bool cell_unpack_interm_addr_regular(Ref cell_ref, int& use_dest_bits) const; - bool pack(vm::CellBuilder& cb, const Record_interm_addr_regular& data) const; - bool pack_interm_addr_regular(vm::CellBuilder& cb, int use_dest_bits) const; - bool cell_pack(Ref& cell_ref, const Record_interm_addr_regular& data) const; - bool cell_pack_interm_addr_regular(Ref& cell_ref, int use_dest_bits) const; - bool unpack(vm::CellSlice& cs, Record_interm_addr_simple& data) const; - bool unpack_interm_addr_simple(vm::CellSlice& cs, int& workchain_id, unsigned long long& addr_pfx) const; - bool cell_unpack(Ref cell_ref, Record_interm_addr_simple& data) const; - bool cell_unpack_interm_addr_simple(Ref cell_ref, int& workchain_id, unsigned long long& addr_pfx) const; - bool pack(vm::CellBuilder& cb, const Record_interm_addr_simple& data) const; - bool pack_interm_addr_simple(vm::CellBuilder& cb, int workchain_id, unsigned long long addr_pfx) const; - bool cell_pack(Ref& cell_ref, const Record_interm_addr_simple& data) const; - bool cell_pack_interm_addr_simple(Ref& cell_ref, int workchain_id, unsigned long long addr_pfx) const; - bool unpack(vm::CellSlice& cs, Record_interm_addr_ext& data) const; - bool unpack_interm_addr_ext(vm::CellSlice& cs, int& workchain_id, unsigned long long& addr_pfx) const; - bool cell_unpack(Ref cell_ref, Record_interm_addr_ext& data) const; - bool cell_unpack_interm_addr_ext(Ref cell_ref, int& workchain_id, unsigned long long& addr_pfx) const; - bool pack(vm::CellBuilder& cb, const Record_interm_addr_ext& data) const; - bool pack_interm_addr_ext(vm::CellBuilder& cb, int workchain_id, unsigned long long addr_pfx) const; - bool cell_pack(Ref& cell_ref, const Record_interm_addr_ext& data) const; - bool cell_pack_interm_addr_ext(Ref& cell_ref, int workchain_id, unsigned long long addr_pfx) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "IntermediateAddress"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 13); - } -}; - -extern const IntermediateAddress t_IntermediateAddress; - -// -// headers for type `MsgEnvelope` -// - -struct MsgEnvelope final : TLB_Complex { - enum { msg_envelope }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 4 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MsgEnvelope"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct MsgEnvelope::Record { - typedef MsgEnvelope type_class; - Ref cur_addr; // cur_addr : IntermediateAddress - Ref next_addr; // next_addr : IntermediateAddress - Ref fwd_fee_remaining; // fwd_fee_remaining : Grams - Ref msg; // msg : ^(Message Any) - Record() = default; - Record(Ref _cur_addr, Ref _next_addr, Ref _fwd_fee_remaining, Ref _msg) : cur_addr(std::move(_cur_addr)), next_addr(std::move(_next_addr)), fwd_fee_remaining(std::move(_fwd_fee_remaining)), msg(std::move(_msg)) {} -}; - -extern const MsgEnvelope t_MsgEnvelope; - -// -// headers for type `InMsg` -// - -struct InMsg final : TLB_Complex { - enum { msg_import_ext, msg_import_ihr, msg_import_imm, msg_import_fin, msg_import_tr, msg_discard_fin, msg_discard_tr }; - static constexpr int cons_len_exact = 3; - static constexpr unsigned char cons_tag[7] = { 0, 2, 3, 4, 5, 6, 7 }; - struct Record_msg_import_ext { - typedef InMsg type_class; - Ref msg; // msg : ^(Message Any) - Ref transaction; // transaction : ^Transaction - Record_msg_import_ext() = default; - Record_msg_import_ext(Ref _msg, Ref _transaction) : msg(std::move(_msg)), transaction(std::move(_transaction)) {} - }; - struct Record_msg_import_ihr; - struct Record_msg_import_imm; - struct Record_msg_import_fin; - struct Record_msg_import_tr; - struct Record_msg_discard_fin; - struct Record_msg_discard_tr; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_msg_import_ext& data) const; - bool unpack_msg_import_ext(vm::CellSlice& cs, Ref& msg, Ref& transaction) const; - bool cell_unpack(Ref cell_ref, Record_msg_import_ext& data) const; - bool cell_unpack_msg_import_ext(Ref cell_ref, Ref& msg, Ref& transaction) const; - bool pack(vm::CellBuilder& cb, const Record_msg_import_ext& data) const; - bool pack_msg_import_ext(vm::CellBuilder& cb, Ref msg, Ref transaction) const; - bool cell_pack(Ref& cell_ref, const Record_msg_import_ext& data) const; - bool cell_pack_msg_import_ext(Ref& cell_ref, Ref msg, Ref transaction) const; - bool unpack(vm::CellSlice& cs, Record_msg_import_ihr& data) const; - bool cell_unpack(Ref cell_ref, Record_msg_import_ihr& data) const; - bool pack(vm::CellBuilder& cb, const Record_msg_import_ihr& data) const; - bool cell_pack(Ref& cell_ref, const Record_msg_import_ihr& data) const; - bool unpack(vm::CellSlice& cs, Record_msg_import_imm& data) const; - bool unpack_msg_import_imm(vm::CellSlice& cs, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const; - bool cell_unpack(Ref cell_ref, Record_msg_import_imm& data) const; - bool cell_unpack_msg_import_imm(Ref cell_ref, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const; - bool pack(vm::CellBuilder& cb, const Record_msg_import_imm& data) const; - bool pack_msg_import_imm(vm::CellBuilder& cb, Ref in_msg, Ref transaction, Ref fwd_fee) const; - bool cell_pack(Ref& cell_ref, const Record_msg_import_imm& data) const; - bool cell_pack_msg_import_imm(Ref& cell_ref, Ref in_msg, Ref transaction, Ref fwd_fee) const; - bool unpack(vm::CellSlice& cs, Record_msg_import_fin& data) const; - bool unpack_msg_import_fin(vm::CellSlice& cs, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const; - bool cell_unpack(Ref cell_ref, Record_msg_import_fin& data) const; - bool cell_unpack_msg_import_fin(Ref cell_ref, Ref& in_msg, Ref& transaction, Ref& fwd_fee) const; - bool pack(vm::CellBuilder& cb, const Record_msg_import_fin& data) const; - bool pack_msg_import_fin(vm::CellBuilder& cb, Ref in_msg, Ref transaction, Ref fwd_fee) const; - bool cell_pack(Ref& cell_ref, const Record_msg_import_fin& data) const; - bool cell_pack_msg_import_fin(Ref& cell_ref, Ref in_msg, Ref transaction, Ref fwd_fee) const; - bool unpack(vm::CellSlice& cs, Record_msg_import_tr& data) const; - bool unpack_msg_import_tr(vm::CellSlice& cs, Ref& in_msg, Ref& out_msg, Ref& transit_fee) const; - bool cell_unpack(Ref cell_ref, Record_msg_import_tr& data) const; - bool cell_unpack_msg_import_tr(Ref cell_ref, Ref& in_msg, Ref& out_msg, Ref& transit_fee) const; - bool pack(vm::CellBuilder& cb, const Record_msg_import_tr& data) const; - bool pack_msg_import_tr(vm::CellBuilder& cb, Ref in_msg, Ref out_msg, Ref transit_fee) const; - bool cell_pack(Ref& cell_ref, const Record_msg_import_tr& data) const; - bool cell_pack_msg_import_tr(Ref& cell_ref, Ref in_msg, Ref out_msg, Ref transit_fee) const; - bool unpack(vm::CellSlice& cs, Record_msg_discard_fin& data) const; - bool unpack_msg_discard_fin(vm::CellSlice& cs, Ref& in_msg, unsigned long long& transaction_id, Ref& fwd_fee) const; - bool cell_unpack(Ref cell_ref, Record_msg_discard_fin& data) const; - bool cell_unpack_msg_discard_fin(Ref cell_ref, Ref& in_msg, unsigned long long& transaction_id, Ref& fwd_fee) const; - bool pack(vm::CellBuilder& cb, const Record_msg_discard_fin& data) const; - bool pack_msg_discard_fin(vm::CellBuilder& cb, Ref in_msg, unsigned long long transaction_id, Ref fwd_fee) const; - bool cell_pack(Ref& cell_ref, const Record_msg_discard_fin& data) const; - bool cell_pack_msg_discard_fin(Ref& cell_ref, Ref in_msg, unsigned long long transaction_id, Ref fwd_fee) const; - bool unpack(vm::CellSlice& cs, Record_msg_discard_tr& data) const; - bool cell_unpack(Ref cell_ref, Record_msg_discard_tr& data) const; - bool pack(vm::CellBuilder& cb, const Record_msg_discard_tr& data) const; - bool cell_pack(Ref& cell_ref, const Record_msg_discard_tr& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "InMsg"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(3, 0xfd); - } -}; - -struct InMsg::Record_msg_import_ihr { - typedef InMsg type_class; - Ref msg; // msg : ^(Message Any) - Ref transaction; // transaction : ^Transaction - Ref ihr_fee; // ihr_fee : Grams - Ref proof_created; // proof_created : ^Cell - Record_msg_import_ihr() = default; - Record_msg_import_ihr(Ref _msg, Ref _transaction, Ref _ihr_fee, Ref _proof_created) : msg(std::move(_msg)), transaction(std::move(_transaction)), ihr_fee(std::move(_ihr_fee)), proof_created(std::move(_proof_created)) {} -}; - -struct InMsg::Record_msg_import_imm { - typedef InMsg type_class; - Ref in_msg; // in_msg : ^MsgEnvelope - Ref transaction; // transaction : ^Transaction - Ref fwd_fee; // fwd_fee : Grams - Record_msg_import_imm() = default; - Record_msg_import_imm(Ref _in_msg, Ref _transaction, Ref _fwd_fee) : in_msg(std::move(_in_msg)), transaction(std::move(_transaction)), fwd_fee(std::move(_fwd_fee)) {} -}; - -struct InMsg::Record_msg_import_fin { - typedef InMsg type_class; - Ref in_msg; // in_msg : ^MsgEnvelope - Ref transaction; // transaction : ^Transaction - Ref fwd_fee; // fwd_fee : Grams - Record_msg_import_fin() = default; - Record_msg_import_fin(Ref _in_msg, Ref _transaction, Ref _fwd_fee) : in_msg(std::move(_in_msg)), transaction(std::move(_transaction)), fwd_fee(std::move(_fwd_fee)) {} -}; - -struct InMsg::Record_msg_import_tr { - typedef InMsg type_class; - Ref in_msg; // in_msg : ^MsgEnvelope - Ref out_msg; // out_msg : ^MsgEnvelope - Ref transit_fee; // transit_fee : Grams - Record_msg_import_tr() = default; - Record_msg_import_tr(Ref _in_msg, Ref _out_msg, Ref _transit_fee) : in_msg(std::move(_in_msg)), out_msg(std::move(_out_msg)), transit_fee(std::move(_transit_fee)) {} -}; - -struct InMsg::Record_msg_discard_fin { - typedef InMsg type_class; - Ref in_msg; // in_msg : ^MsgEnvelope - unsigned long long transaction_id; // transaction_id : uint64 - Ref fwd_fee; // fwd_fee : Grams - Record_msg_discard_fin() = default; - Record_msg_discard_fin(Ref _in_msg, unsigned long long _transaction_id, Ref _fwd_fee) : in_msg(std::move(_in_msg)), transaction_id(_transaction_id), fwd_fee(std::move(_fwd_fee)) {} -}; - -struct InMsg::Record_msg_discard_tr { - typedef InMsg type_class; - Ref in_msg; // in_msg : ^MsgEnvelope - unsigned long long transaction_id; // transaction_id : uint64 - Ref fwd_fee; // fwd_fee : Grams - Ref proof_delivered; // proof_delivered : ^Cell - Record_msg_discard_tr() = default; - Record_msg_discard_tr(Ref _in_msg, unsigned long long _transaction_id, Ref _fwd_fee, Ref _proof_delivered) : in_msg(std::move(_in_msg)), transaction_id(_transaction_id), fwd_fee(std::move(_fwd_fee)), proof_delivered(std::move(_proof_delivered)) {} -}; - -extern const InMsg t_InMsg; - -// -// headers for type `ImportFees` -// - -struct ImportFees final : TLB_Complex { - enum { import_fees }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ImportFees type_class; - Ref fees_collected; // fees_collected : Grams - Ref value_imported; // value_imported : CurrencyCollection - Record() = default; - Record(Ref _fees_collected, Ref _value_imported) : fees_collected(std::move(_fees_collected)), value_imported(std::move(_value_imported)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_import_fees(vm::CellSlice& cs, Ref& fees_collected, Ref& value_imported) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_import_fees(Ref cell_ref, Ref& fees_collected, Ref& value_imported) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_import_fees(vm::CellBuilder& cb, Ref fees_collected, Ref value_imported) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_import_fees(Ref& cell_ref, Ref fees_collected, Ref value_imported) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ImportFees"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ImportFees t_ImportFees; - -// -// headers for type `InMsgDescr` -// - -struct InMsgDescr final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef InMsgDescr type_class; - Ref x; // HashmapAugE 256 InMsg ImportFees - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "InMsgDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const InMsgDescr t_InMsgDescr; - -// -// headers for type `OutMsg` -// - -struct OutMsg final : TLB_Complex { - enum { msg_export_ext, msg_export_new, msg_export_imm, msg_export_tr, msg_export_deq_imm, msg_export_deq, msg_export_deq_short, msg_export_tr_req }; - static constexpr char cons_len[8] = { 3, 3, 3, 3, 3, 4, 4, 3 }; - static constexpr unsigned char cons_tag[8] = { 0, 1, 2, 3, 4, 12, 13, 7 }; - struct Record_msg_export_ext { - typedef OutMsg type_class; - Ref msg; // msg : ^(Message Any) - Ref transaction; // transaction : ^Transaction - Record_msg_export_ext() = default; - Record_msg_export_ext(Ref _msg, Ref _transaction) : msg(std::move(_msg)), transaction(std::move(_transaction)) {} - }; - struct Record_msg_export_imm; - struct Record_msg_export_new { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - Ref transaction; // transaction : ^Transaction - Record_msg_export_new() = default; - Record_msg_export_new(Ref _out_msg, Ref _transaction) : out_msg(std::move(_out_msg)), transaction(std::move(_transaction)) {} - }; - struct Record_msg_export_tr { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - Ref imported; // imported : ^InMsg - Record_msg_export_tr() = default; - Record_msg_export_tr(Ref _out_msg, Ref _imported) : out_msg(std::move(_out_msg)), imported(std::move(_imported)) {} - }; - struct Record_msg_export_deq { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - long long import_block_lt; // import_block_lt : uint63 - Record_msg_export_deq() = default; - Record_msg_export_deq(Ref _out_msg, long long _import_block_lt) : out_msg(std::move(_out_msg)), import_block_lt(_import_block_lt) {} - }; - struct Record_msg_export_deq_short; - struct Record_msg_export_tr_req { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - Ref imported; // imported : ^InMsg - Record_msg_export_tr_req() = default; - Record_msg_export_tr_req(Ref _out_msg, Ref _imported) : out_msg(std::move(_out_msg)), imported(std::move(_imported)) {} - }; - struct Record_msg_export_deq_imm { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - Ref reimport; // reimport : ^InMsg - Record_msg_export_deq_imm() = default; - Record_msg_export_deq_imm(Ref _out_msg, Ref _reimport) : out_msg(std::move(_out_msg)), reimport(std::move(_reimport)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_msg_export_ext& data) const; - bool unpack_msg_export_ext(vm::CellSlice& cs, Ref& msg, Ref& transaction) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_ext& data) const; - bool cell_unpack_msg_export_ext(Ref cell_ref, Ref& msg, Ref& transaction) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_ext& data) const; - bool pack_msg_export_ext(vm::CellBuilder& cb, Ref msg, Ref transaction) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_ext& data) const; - bool cell_pack_msg_export_ext(Ref& cell_ref, Ref msg, Ref transaction) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_imm& data) const; - bool unpack_msg_export_imm(vm::CellSlice& cs, Ref& out_msg, Ref& transaction, Ref& reimport) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_imm& data) const; - bool cell_unpack_msg_export_imm(Ref cell_ref, Ref& out_msg, Ref& transaction, Ref& reimport) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_imm& data) const; - bool pack_msg_export_imm(vm::CellBuilder& cb, Ref out_msg, Ref transaction, Ref reimport) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_imm& data) const; - bool cell_pack_msg_export_imm(Ref& cell_ref, Ref out_msg, Ref transaction, Ref reimport) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_new& data) const; - bool unpack_msg_export_new(vm::CellSlice& cs, Ref& out_msg, Ref& transaction) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_new& data) const; - bool cell_unpack_msg_export_new(Ref cell_ref, Ref& out_msg, Ref& transaction) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_new& data) const; - bool pack_msg_export_new(vm::CellBuilder& cb, Ref out_msg, Ref transaction) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_new& data) const; - bool cell_pack_msg_export_new(Ref& cell_ref, Ref out_msg, Ref transaction) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_tr& data) const; - bool unpack_msg_export_tr(vm::CellSlice& cs, Ref& out_msg, Ref& imported) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_tr& data) const; - bool cell_unpack_msg_export_tr(Ref cell_ref, Ref& out_msg, Ref& imported) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_tr& data) const; - bool pack_msg_export_tr(vm::CellBuilder& cb, Ref out_msg, Ref imported) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_tr& data) const; - bool cell_pack_msg_export_tr(Ref& cell_ref, Ref out_msg, Ref imported) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_deq& data) const; - bool unpack_msg_export_deq(vm::CellSlice& cs, Ref& out_msg, long long& import_block_lt) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_deq& data) const; - bool cell_unpack_msg_export_deq(Ref cell_ref, Ref& out_msg, long long& import_block_lt) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_deq& data) const; - bool pack_msg_export_deq(vm::CellBuilder& cb, Ref out_msg, long long import_block_lt) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_deq& data) const; - bool cell_pack_msg_export_deq(Ref& cell_ref, Ref out_msg, long long import_block_lt) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_deq_short& data) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_deq_short& data) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_deq_short& data) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_deq_short& data) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_tr_req& data) const; - bool unpack_msg_export_tr_req(vm::CellSlice& cs, Ref& out_msg, Ref& imported) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_tr_req& data) const; - bool cell_unpack_msg_export_tr_req(Ref cell_ref, Ref& out_msg, Ref& imported) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_tr_req& data) const; - bool pack_msg_export_tr_req(vm::CellBuilder& cb, Ref out_msg, Ref imported) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_tr_req& data) const; - bool cell_pack_msg_export_tr_req(Ref& cell_ref, Ref out_msg, Ref imported) const; - bool unpack(vm::CellSlice& cs, Record_msg_export_deq_imm& data) const; - bool unpack_msg_export_deq_imm(vm::CellSlice& cs, Ref& out_msg, Ref& reimport) const; - bool cell_unpack(Ref cell_ref, Record_msg_export_deq_imm& data) const; - bool cell_unpack_msg_export_deq_imm(Ref cell_ref, Ref& out_msg, Ref& reimport) const; - bool pack(vm::CellBuilder& cb, const Record_msg_export_deq_imm& data) const; - bool pack_msg_export_deq_imm(vm::CellBuilder& cb, Ref out_msg, Ref reimport) const; - bool cell_pack(Ref& cell_ref, const Record_msg_export_deq_imm& data) const; - bool cell_pack_msg_export_deq_imm(Ref& cell_ref, Ref out_msg, Ref reimport) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutMsg"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect_ext(4, 0x7155); - } -}; - -struct OutMsg::Record_msg_export_imm { - typedef OutMsg type_class; - Ref out_msg; // out_msg : ^MsgEnvelope - Ref transaction; // transaction : ^Transaction - Ref reimport; // reimport : ^InMsg - Record_msg_export_imm() = default; - Record_msg_export_imm(Ref _out_msg, Ref _transaction, Ref _reimport) : out_msg(std::move(_out_msg)), transaction(std::move(_transaction)), reimport(std::move(_reimport)) {} -}; - -struct OutMsg::Record_msg_export_deq_short { - typedef OutMsg type_class; - td::BitArray<256> msg_env_hash; // msg_env_hash : bits256 - int next_workchain; // next_workchain : int32 - unsigned long long next_addr_pfx; // next_addr_pfx : uint64 - unsigned long long import_block_lt; // import_block_lt : uint64 - Record_msg_export_deq_short() = default; - Record_msg_export_deq_short(const td::BitArray<256>& _msg_env_hash, int _next_workchain, unsigned long long _next_addr_pfx, unsigned long long _import_block_lt) : msg_env_hash(_msg_env_hash), next_workchain(_next_workchain), next_addr_pfx(_next_addr_pfx), import_block_lt(_import_block_lt) {} -}; - -extern const OutMsg t_OutMsg; - -// -// headers for type `EnqueuedMsg` -// - -struct EnqueuedMsg final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef EnqueuedMsg type_class; - unsigned long long enqueued_lt; // enqueued_lt : uint64 - Ref out_msg; // out_msg : ^MsgEnvelope - Record() = default; - Record(unsigned long long _enqueued_lt, Ref _out_msg) : enqueued_lt(_enqueued_lt), out_msg(std::move(_out_msg)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x10040; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10040); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, unsigned long long& enqueued_lt, Ref& out_msg) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, unsigned long long& enqueued_lt, Ref& out_msg) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, unsigned long long enqueued_lt, Ref out_msg) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, unsigned long long enqueued_lt, Ref out_msg) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "EnqueuedMsg"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const EnqueuedMsg t_EnqueuedMsg; - -// -// headers for type `OutMsgDescr` -// - -struct OutMsgDescr final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef OutMsgDescr type_class; - Ref x; // HashmapAugE 256 OutMsg CurrencyCollection - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutMsgDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const OutMsgDescr t_OutMsgDescr; - -// -// headers for type `OutMsgQueue` -// - -struct OutMsgQueue final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef OutMsgQueue type_class; - Ref x; // HashmapAugE 352 EnqueuedMsg uint64 - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutMsgQueue"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const OutMsgQueue t_OutMsgQueue; - -// -// headers for type `ProcessedUpto` -// - -struct ProcessedUpto final : TLB_Complex { - enum { processed_upto }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ProcessedUpto type_class; - unsigned long long last_msg_lt; // last_msg_lt : uint64 - td::BitArray<256> last_msg_hash; // last_msg_hash : bits256 - Record() = default; - Record(unsigned long long _last_msg_lt, const td::BitArray<256>& _last_msg_hash) : last_msg_lt(_last_msg_lt), last_msg_hash(_last_msg_hash) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 320; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(320); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(320); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_processed_upto(vm::CellSlice& cs, unsigned long long& last_msg_lt, td::BitArray<256>& last_msg_hash) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_processed_upto(Ref cell_ref, unsigned long long& last_msg_lt, td::BitArray<256>& last_msg_hash) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_processed_upto(vm::CellBuilder& cb, unsigned long long last_msg_lt, td::BitArray<256> last_msg_hash) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_processed_upto(Ref& cell_ref, unsigned long long last_msg_lt, td::BitArray<256> last_msg_hash) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ProcessedUpto"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ProcessedUpto t_ProcessedUpto; - -// -// headers for type `ProcessedInfo` -// - -struct ProcessedInfo final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ProcessedInfo type_class; - Ref x; // HashmapE 96 ProcessedUpto - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ProcessedInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ProcessedInfo t_ProcessedInfo; - -// -// headers for type `IhrPendingSince` -// - -struct IhrPendingSince final : TLB_Complex { - enum { ihr_pending }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef IhrPendingSince type_class; - unsigned long long import_lt; // import_lt : uint64 - Record() = default; - Record(unsigned long long _import_lt) : import_lt(_import_lt) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 64; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(64); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(64); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_ihr_pending(vm::CellSlice& cs, unsigned long long& import_lt) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_ihr_pending(Ref cell_ref, unsigned long long& import_lt) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_ihr_pending(vm::CellBuilder& cb, unsigned long long import_lt) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_ihr_pending(Ref& cell_ref, unsigned long long import_lt) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "IhrPendingSince"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const IhrPendingSince t_IhrPendingSince; - -// -// headers for type `IhrPendingInfo` -// - -struct IhrPendingInfo final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef IhrPendingInfo type_class; - Ref x; // HashmapE 320 IhrPendingSince - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "IhrPendingInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const IhrPendingInfo t_IhrPendingInfo; - -// -// headers for type `OutMsgQueueInfo` -// - -struct OutMsgQueueInfo final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& out_queue, Ref& proc_info, Ref& ihr_pending) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& out_queue, Ref& proc_info, Ref& ihr_pending) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref out_queue, Ref proc_info, Ref ihr_pending) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref out_queue, Ref proc_info, Ref ihr_pending) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutMsgQueueInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct OutMsgQueueInfo::Record { - typedef OutMsgQueueInfo type_class; - Ref out_queue; // out_queue : OutMsgQueue - Ref proc_info; // proc_info : ProcessedInfo - Ref ihr_pending; // ihr_pending : IhrPendingInfo - Record() = default; - Record(Ref _out_queue, Ref _proc_info, Ref _ihr_pending) : out_queue(std::move(_out_queue)), proc_info(std::move(_proc_info)), ihr_pending(std::move(_ihr_pending)) {} -}; - -extern const OutMsgQueueInfo t_OutMsgQueueInfo; - -// -// headers for type `StorageUsed` -// - -struct StorageUsed final : TLB_Complex { - enum { storage_used }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_storage_used(vm::CellSlice& cs, Ref& cells, Ref& bits, Ref& public_cells) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_storage_used(Ref cell_ref, Ref& cells, Ref& bits, Ref& public_cells) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_storage_used(vm::CellBuilder& cb, Ref cells, Ref bits, Ref public_cells) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_storage_used(Ref& cell_ref, Ref cells, Ref bits, Ref public_cells) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "StorageUsed"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct StorageUsed::Record { - typedef StorageUsed type_class; - Ref cells; // cells : VarUInteger 7 - Ref bits; // bits : VarUInteger 7 - Ref public_cells; // public_cells : VarUInteger 7 - Record() = default; - Record(Ref _cells, Ref _bits, Ref _public_cells) : cells(std::move(_cells)), bits(std::move(_bits)), public_cells(std::move(_public_cells)) {} -}; - -extern const StorageUsed t_StorageUsed; - -// -// headers for type `StorageUsedShort` -// - -struct StorageUsedShort final : TLB_Complex { - enum { storage_used_short }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef StorageUsedShort type_class; - Ref cells; // cells : VarUInteger 7 - Ref bits; // bits : VarUInteger 7 - Record() = default; - Record(Ref _cells, Ref _bits) : cells(std::move(_cells)), bits(std::move(_bits)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_storage_used_short(vm::CellSlice& cs, Ref& cells, Ref& bits) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_storage_used_short(Ref cell_ref, Ref& cells, Ref& bits) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_storage_used_short(vm::CellBuilder& cb, Ref cells, Ref bits) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_storage_used_short(Ref& cell_ref, Ref cells, Ref bits) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "StorageUsedShort"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const StorageUsedShort t_StorageUsedShort; - -// -// headers for type `StorageInfo` -// - -struct StorageInfo final : TLB_Complex { - enum { storage_info }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_storage_info(vm::CellSlice& cs, Ref& used, unsigned& last_paid, Ref& due_payment) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_storage_info(Ref cell_ref, Ref& used, unsigned& last_paid, Ref& due_payment) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_storage_info(vm::CellBuilder& cb, Ref used, unsigned last_paid, Ref due_payment) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_storage_info(Ref& cell_ref, Ref used, unsigned last_paid, Ref due_payment) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "StorageInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct StorageInfo::Record { - typedef StorageInfo type_class; - Ref used; // used : StorageUsed - unsigned last_paid; // last_paid : uint32 - Ref due_payment; // due_payment : Maybe Grams - Record() = default; - Record(Ref _used, unsigned _last_paid, Ref _due_payment) : used(std::move(_used)), last_paid(_last_paid), due_payment(std::move(_due_payment)) {} -}; - -extern const StorageInfo t_StorageInfo; - -// -// headers for type `Account` -// - -struct Account final : TLB_Complex { - enum { account_none, account }; - static constexpr int cons_len_exact = 1; - struct Record_account_none { - typedef Account type_class; - }; - struct Record_account; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_account_none& data) const; - bool unpack_account_none(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_account_none& data) const; - bool cell_unpack_account_none(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_account_none& data) const; - bool pack_account_none(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_account_none& data) const; - bool cell_pack_account_none(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_account& data) const; - bool unpack_account(vm::CellSlice& cs, Ref& addr, Ref& storage_stat, Ref& storage) const; - bool cell_unpack(Ref cell_ref, Record_account& data) const; - bool cell_unpack_account(Ref cell_ref, Ref& addr, Ref& storage_stat, Ref& storage) const; - bool pack(vm::CellBuilder& cb, const Record_account& data) const; - bool pack_account(vm::CellBuilder& cb, Ref addr, Ref storage_stat, Ref storage) const; - bool cell_pack(Ref& cell_ref, const Record_account& data) const; - bool cell_pack_account(Ref& cell_ref, Ref addr, Ref storage_stat, Ref storage) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Account"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct Account::Record_account { - typedef Account type_class; - Ref addr; // addr : MsgAddressInt - Ref storage_stat; // storage_stat : StorageInfo - Ref storage; // storage : AccountStorage - Record_account() = default; - Record_account(Ref _addr, Ref _storage_stat, Ref _storage) : addr(std::move(_addr)), storage_stat(std::move(_storage_stat)), storage(std::move(_storage)) {} -}; - -extern const Account t_Account; - -// -// headers for type `AccountStorage` -// - -struct AccountStorage final : TLB_Complex { - enum { account_storage }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_account_storage(vm::CellSlice& cs, unsigned long long& last_trans_lt, Ref& balance, Ref& state) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_account_storage(Ref cell_ref, unsigned long long& last_trans_lt, Ref& balance, Ref& state) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_account_storage(vm::CellBuilder& cb, unsigned long long last_trans_lt, Ref balance, Ref state) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_account_storage(Ref& cell_ref, unsigned long long last_trans_lt, Ref balance, Ref state) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "AccountStorage"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct AccountStorage::Record { - typedef AccountStorage type_class; - unsigned long long last_trans_lt; // last_trans_lt : uint64 - Ref balance; // balance : CurrencyCollection - Ref state; // state : AccountState - Record() = default; - Record(unsigned long long _last_trans_lt, Ref _balance, Ref _state) : last_trans_lt(_last_trans_lt), balance(std::move(_balance)), state(std::move(_state)) {} -}; - -extern const AccountStorage t_AccountStorage; - -// -// headers for type `AccountState` -// - -struct AccountState final : TLB_Complex { - enum { account_uninit, account_frozen, account_active }; - static constexpr char cons_len[3] = { 2, 2, 1 }; - static constexpr unsigned char cons_tag[3] = { 0, 1, 1 }; - struct Record_account_uninit { - typedef AccountState type_class; - }; - struct Record_account_active { - typedef AccountState type_class; - Ref x; // StateInit - Record_account_active() = default; - Record_account_active(Ref _x) : x(std::move(_x)) {} - }; - struct Record_account_frozen { - typedef AccountState type_class; - td::BitArray<256> state_hash; // state_hash : bits256 - Record_account_frozen() = default; - Record_account_frozen(const td::BitArray<256>& _state_hash) : state_hash(_state_hash) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_account_uninit& data) const; - bool unpack_account_uninit(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_account_uninit& data) const; - bool cell_unpack_account_uninit(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_account_uninit& data) const; - bool pack_account_uninit(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_account_uninit& data) const; - bool cell_pack_account_uninit(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_account_active& data) const; - bool unpack_account_active(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_account_active& data) const; - bool cell_unpack_account_active(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_account_active& data) const; - bool pack_account_active(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_account_active& data) const; - bool cell_pack_account_active(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_account_frozen& data) const; - bool unpack_account_frozen(vm::CellSlice& cs, td::BitArray<256>& state_hash) const; - bool cell_unpack(Ref cell_ref, Record_account_frozen& data) const; - bool cell_unpack_account_frozen(Ref cell_ref, td::BitArray<256>& state_hash) const; - bool pack(vm::CellBuilder& cb, const Record_account_frozen& data) const; - bool pack_account_frozen(vm::CellBuilder& cb, td::BitArray<256> state_hash) const; - bool cell_pack(Ref& cell_ref, const Record_account_frozen& data) const; - bool cell_pack_account_frozen(Ref& cell_ref, td::BitArray<256> state_hash) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "AccountState"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 7); - } -}; - -extern const AccountState t_AccountState; - -// -// headers for type `AccountStatus` -// - -struct AccountStatus final : TLB_Complex { - enum { acc_state_uninit, acc_state_frozen, acc_state_active, acc_state_nonexist }; - static constexpr int cons_len_exact = 2; - struct Record_acc_state_uninit { - typedef AccountStatus type_class; - }; - struct Record_acc_state_frozen { - typedef AccountStatus type_class; - }; - struct Record_acc_state_active { - typedef AccountStatus type_class; - }; - struct Record_acc_state_nonexist { - typedef AccountStatus type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 2; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(2); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(2); - } - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record_acc_state_uninit& data) const; - bool unpack_acc_state_uninit(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acc_state_uninit& data) const; - bool cell_unpack_acc_state_uninit(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acc_state_uninit& data) const; - bool pack_acc_state_uninit(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acc_state_uninit& data) const; - bool cell_pack_acc_state_uninit(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_acc_state_frozen& data) const; - bool unpack_acc_state_frozen(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acc_state_frozen& data) const; - bool cell_unpack_acc_state_frozen(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acc_state_frozen& data) const; - bool pack_acc_state_frozen(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acc_state_frozen& data) const; - bool cell_pack_acc_state_frozen(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_acc_state_active& data) const; - bool unpack_acc_state_active(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acc_state_active& data) const; - bool cell_unpack_acc_state_active(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acc_state_active& data) const; - bool pack_acc_state_active(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acc_state_active& data) const; - bool cell_pack_acc_state_active(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_acc_state_nonexist& data) const; - bool unpack_acc_state_nonexist(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acc_state_nonexist& data) const; - bool cell_unpack_acc_state_nonexist(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acc_state_nonexist& data) const; - bool pack_acc_state_nonexist(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acc_state_nonexist& data) const; - bool cell_pack_acc_state_nonexist(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "AccountStatus"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } -}; - -extern const AccountStatus t_AccountStatus; - -// -// headers for type `ShardAccount` -// - -struct ShardAccount final : TLB_Complex { - enum { account_descr }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 0x10140; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10140); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_account_descr(vm::CellSlice& cs, Ref& account, td::BitArray<256>& last_trans_hash, unsigned long long& last_trans_lt) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_account_descr(Ref cell_ref, Ref& account, td::BitArray<256>& last_trans_hash, unsigned long long& last_trans_lt) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_account_descr(vm::CellBuilder& cb, Ref account, td::BitArray<256> last_trans_hash, unsigned long long last_trans_lt) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_account_descr(Ref& cell_ref, Ref account, td::BitArray<256> last_trans_hash, unsigned long long last_trans_lt) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardAccount"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ShardAccount::Record { - typedef ShardAccount type_class; - Ref account; // account : ^Account - td::BitArray<256> last_trans_hash; // last_trans_hash : bits256 - unsigned long long last_trans_lt; // last_trans_lt : uint64 - Record() = default; - Record(Ref _account, const td::BitArray<256>& _last_trans_hash, unsigned long long _last_trans_lt) : account(std::move(_account)), last_trans_hash(_last_trans_hash), last_trans_lt(_last_trans_lt) {} -}; - -extern const ShardAccount t_ShardAccount; - -// -// headers for type `DepthBalanceInfo` -// - -struct DepthBalanceInfo final : TLB_Complex { - enum { depth_balance }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef DepthBalanceInfo type_class; - int split_depth; // split_depth : #<= 30 - Ref balance; // balance : CurrencyCollection - Record() = default; - Record(int _split_depth, Ref _balance) : split_depth(_split_depth), balance(std::move(_balance)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_depth_balance(vm::CellSlice& cs, int& split_depth, Ref& balance) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_depth_balance(Ref cell_ref, int& split_depth, Ref& balance) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_depth_balance(vm::CellBuilder& cb, int split_depth, Ref balance) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_depth_balance(Ref& cell_ref, int split_depth, Ref balance) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "DepthBalanceInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const DepthBalanceInfo t_DepthBalanceInfo; - -// -// headers for type `ShardAccounts` -// - -struct ShardAccounts final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardAccounts type_class; - Ref x; // HashmapAugE 256 ShardAccount DepthBalanceInfo - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardAccounts"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardAccounts t_ShardAccounts; - -// -// headers for auxiliary type `Transaction_aux` -// - -struct Transaction_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Transaction_aux type_class; - Ref in_msg; // in_msg : Maybe ^(Message Any) - Ref out_msgs; // out_msgs : HashmapE 15 ^(Message Any) - Record() = default; - Record(Ref _in_msg, Ref _out_msgs) : in_msg(std::move(_in_msg)), out_msgs(std::move(_out_msgs)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& in_msg, Ref& out_msgs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& in_msg, Ref& out_msgs) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref in_msg, Ref out_msgs) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref in_msg, Ref out_msgs) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Transaction_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Transaction_aux t_Transaction_aux; - -// -// headers for type `Transaction` -// - -struct Transaction final : TLB_Complex { - enum { transaction }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 7 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Transaction"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Transaction::Record { - typedef Transaction type_class; - td::BitArray<256> account_addr; // account_addr : bits256 - unsigned long long lt; // lt : uint64 - td::BitArray<256> prev_trans_hash; // prev_trans_hash : bits256 - unsigned long long prev_trans_lt; // prev_trans_lt : uint64 - unsigned now; // now : uint32 - int outmsg_cnt; // outmsg_cnt : uint15 - char orig_status; // orig_status : AccountStatus - char end_status; // end_status : AccountStatus - Transaction_aux::Record r1; // ^[$_ in_msg:(Maybe ^(Message Any)) out_msgs:(HashmapE 15 ^(Message Any)) ] - Ref total_fees; // total_fees : CurrencyCollection - Ref state_update; // state_update : ^(HASH_UPDATE Account) - Ref description; // description : ^TransactionDescr - Record() = default; - Record(const td::BitArray<256>& _account_addr, unsigned long long _lt, const td::BitArray<256>& _prev_trans_hash, unsigned long long _prev_trans_lt, unsigned _now, int _outmsg_cnt, char _orig_status, char _end_status, const Transaction_aux::Record& _r1, Ref _total_fees, Ref _state_update, Ref _description) : account_addr(_account_addr), lt(_lt), prev_trans_hash(_prev_trans_hash), prev_trans_lt(_prev_trans_lt), now(_now), outmsg_cnt(_outmsg_cnt), orig_status(_orig_status), end_status(_end_status), r1(_r1), total_fees(std::move(_total_fees)), state_update(std::move(_state_update)), description(std::move(_description)) {} -}; - -extern const Transaction t_Transaction; - -// -// headers for type `MERKLE_UPDATE` -// - -struct MERKLE_UPDATE final : TLB_Complex { - enum { _merkle_update }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 2 }; - const TLB &X_; - MERKLE_UPDATE(const TLB& X) : X_(X) {} - struct Record; - bool always_special() const override { - return true; - } - int get_size(const vm::CellSlice& cs) const override { - return 0x20208; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x20208); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(MERKLE_UPDATE " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct MERKLE_UPDATE::Record { - typedef MERKLE_UPDATE type_class; - td::BitArray<256> old_hash; // old_hash : bits256 - td::BitArray<256> new_hash; // new_hash : bits256 - Ref old; // old : ^X - Ref new1; // new : ^X - Record() = default; - Record(const td::BitArray<256>& _old_hash, const td::BitArray<256>& _new_hash, Ref _old, Ref _new1) : old_hash(_old_hash), new_hash(_new_hash), old(std::move(_old)), new1(std::move(_new1)) {} -}; - -// -// headers for type `HASH_UPDATE` -// - -struct HASH_UPDATE final : TLB_Complex { - enum { update_hashes }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x72 }; - const TLB &X_; - HASH_UPDATE(const TLB& X) : X_(X) {} - struct Record { - typedef HASH_UPDATE type_class; - td::BitArray<256> old_hash; // old_hash : bits256 - td::BitArray<256> new_hash; // new_hash : bits256 - Record() = default; - Record(const td::BitArray<256>& _old_hash, const td::BitArray<256>& _new_hash) : old_hash(_old_hash), new_hash(_new_hash) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 520; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(520); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_update_hashes(vm::CellSlice& cs, td::BitArray<256>& old_hash, td::BitArray<256>& new_hash) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_update_hashes(Ref cell_ref, td::BitArray<256>& old_hash, td::BitArray<256>& new_hash) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_update_hashes(vm::CellBuilder& cb, td::BitArray<256> old_hash, td::BitArray<256> new_hash) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_update_hashes(Ref& cell_ref, td::BitArray<256> old_hash, td::BitArray<256> new_hash) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(HASH_UPDATE " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -// -// headers for type `MERKLE_PROOF` -// - -struct MERKLE_PROOF final : TLB_Complex { - enum { _merkle_proof }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 3 }; - const TLB &X_; - MERKLE_PROOF(const TLB& X) : X_(X) {} - struct Record; - bool always_special() const override { - return true; - } - int get_size(const vm::CellSlice& cs) const override { - return 0x10118; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10118); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack__merkle_proof(vm::CellSlice& cs, td::BitArray<256>& virtual_hash, int& depth, Ref& virtual_root) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack__merkle_proof(Ref cell_ref, td::BitArray<256>& virtual_hash, int& depth, Ref& virtual_root) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack__merkle_proof(vm::CellBuilder& cb, td::BitArray<256> virtual_hash, int depth, Ref virtual_root) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack__merkle_proof(Ref& cell_ref, td::BitArray<256> virtual_hash, int depth, Ref virtual_root) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(MERKLE_PROOF " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct MERKLE_PROOF::Record { - typedef MERKLE_PROOF type_class; - td::BitArray<256> virtual_hash; // virtual_hash : bits256 - int depth; // depth : uint16 - Ref virtual_root; // virtual_root : ^X - Record() = default; - Record(const td::BitArray<256>& _virtual_hash, int _depth, Ref _virtual_root) : virtual_hash(_virtual_hash), depth(_depth), virtual_root(std::move(_virtual_root)) {} -}; - -// -// headers for type `AccountBlock` -// - -struct AccountBlock final : TLB_Complex { - enum { acc_trans }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 5 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_acc_trans(vm::CellSlice& cs, td::BitArray<256>& account_addr, Ref& transactions, Ref& state_update) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_acc_trans(Ref cell_ref, td::BitArray<256>& account_addr, Ref& transactions, Ref& state_update) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_acc_trans(vm::CellBuilder& cb, td::BitArray<256> account_addr, Ref transactions, Ref state_update) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_acc_trans(Ref& cell_ref, td::BitArray<256> account_addr, Ref transactions, Ref state_update) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "AccountBlock"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct AccountBlock::Record { - typedef AccountBlock type_class; - td::BitArray<256> account_addr; // account_addr : bits256 - Ref transactions; // transactions : HashmapAug 64 ^Transaction CurrencyCollection - Ref state_update; // state_update : ^(HASH_UPDATE Account) - Record() = default; - Record(const td::BitArray<256>& _account_addr, Ref _transactions, Ref _state_update) : account_addr(_account_addr), transactions(std::move(_transactions)), state_update(std::move(_state_update)) {} -}; - -extern const AccountBlock t_AccountBlock; - -// -// headers for type `ShardAccountBlocks` -// - -struct ShardAccountBlocks final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardAccountBlocks type_class; - Ref x; // HashmapAugE 256 AccountBlock CurrencyCollection - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardAccountBlocks"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardAccountBlocks t_ShardAccountBlocks; - -// -// headers for type `TrStoragePhase` -// - -struct TrStoragePhase final : TLB_Complex { - enum { tr_phase_storage }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_tr_phase_storage(vm::CellSlice& cs, Ref& storage_fees_collected, Ref& storage_fees_due, char& status_change) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_tr_phase_storage(Ref cell_ref, Ref& storage_fees_collected, Ref& storage_fees_due, char& status_change) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_tr_phase_storage(vm::CellBuilder& cb, Ref storage_fees_collected, Ref storage_fees_due, char status_change) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_tr_phase_storage(Ref& cell_ref, Ref storage_fees_collected, Ref storage_fees_due, char status_change) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrStoragePhase"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct TrStoragePhase::Record { - typedef TrStoragePhase type_class; - Ref storage_fees_collected; // storage_fees_collected : Grams - Ref storage_fees_due; // storage_fees_due : Maybe Grams - char status_change; // status_change : AccStatusChange - Record() = default; - Record(Ref _storage_fees_collected, Ref _storage_fees_due, char _status_change) : storage_fees_collected(std::move(_storage_fees_collected)), storage_fees_due(std::move(_storage_fees_due)), status_change(_status_change) {} -}; - -extern const TrStoragePhase t_TrStoragePhase; - -// -// headers for type `AccStatusChange` -// - -struct AccStatusChange final : TLB_Complex { - enum { acst_unchanged, acst_frozen, acst_deleted }; - static constexpr char cons_len[3] = { 1, 2, 2 }; - static constexpr unsigned char cons_tag[3] = { 0, 2, 3 }; - struct Record_acst_unchanged { - typedef AccStatusChange type_class; - }; - struct Record_acst_frozen { - typedef AccStatusChange type_class; - }; - struct Record_acst_deleted { - typedef AccStatusChange type_class; - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record_acst_unchanged& data) const; - bool unpack_acst_unchanged(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acst_unchanged& data) const; - bool cell_unpack_acst_unchanged(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acst_unchanged& data) const; - bool pack_acst_unchanged(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acst_unchanged& data) const; - bool cell_pack_acst_unchanged(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_acst_frozen& data) const; - bool unpack_acst_frozen(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acst_frozen& data) const; - bool cell_unpack_acst_frozen(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acst_frozen& data) const; - bool pack_acst_frozen(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acst_frozen& data) const; - bool cell_pack_acst_frozen(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_acst_deleted& data) const; - bool unpack_acst_deleted(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_acst_deleted& data) const; - bool cell_unpack_acst_deleted(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_acst_deleted& data) const; - bool pack_acst_deleted(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_acst_deleted& data) const; - bool cell_pack_acst_deleted(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "AccStatusChange"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect_ext(2, 13); - } -}; - -extern const AccStatusChange t_AccStatusChange; - -// -// headers for type `TrCreditPhase` -// - -struct TrCreditPhase final : TLB_Complex { - enum { tr_phase_credit }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef TrCreditPhase type_class; - Ref due_fees_collected; // due_fees_collected : Maybe Grams - Ref credit; // credit : CurrencyCollection - Record() = default; - Record(Ref _due_fees_collected, Ref _credit) : due_fees_collected(std::move(_due_fees_collected)), credit(std::move(_credit)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_tr_phase_credit(vm::CellSlice& cs, Ref& due_fees_collected, Ref& credit) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_tr_phase_credit(Ref cell_ref, Ref& due_fees_collected, Ref& credit) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_tr_phase_credit(vm::CellBuilder& cb, Ref due_fees_collected, Ref credit) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_tr_phase_credit(Ref& cell_ref, Ref due_fees_collected, Ref credit) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrCreditPhase"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const TrCreditPhase t_TrCreditPhase; - -// -// headers for auxiliary type `TrComputePhase_aux` -// - -struct TrComputePhase_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrComputePhase_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct TrComputePhase_aux::Record { - typedef TrComputePhase_aux type_class; - Ref gas_used; // gas_used : VarUInteger 7 - Ref gas_limit; // gas_limit : VarUInteger 7 - Ref gas_credit; // gas_credit : Maybe (VarUInteger 3) - int mode; // mode : int8 - int exit_code; // exit_code : int32 - Ref exit_arg; // exit_arg : Maybe int32 - unsigned vm_steps; // vm_steps : uint32 - td::BitArray<256> vm_init_state_hash; // vm_init_state_hash : bits256 - td::BitArray<256> vm_final_state_hash; // vm_final_state_hash : bits256 - Record() = default; - Record(Ref _gas_used, Ref _gas_limit, Ref _gas_credit, int _mode, int _exit_code, Ref _exit_arg, unsigned _vm_steps, const td::BitArray<256>& _vm_init_state_hash, const td::BitArray<256>& _vm_final_state_hash) : gas_used(std::move(_gas_used)), gas_limit(std::move(_gas_limit)), gas_credit(std::move(_gas_credit)), mode(_mode), exit_code(_exit_code), exit_arg(std::move(_exit_arg)), vm_steps(_vm_steps), vm_init_state_hash(_vm_init_state_hash), vm_final_state_hash(_vm_final_state_hash) {} -}; - -extern const TrComputePhase_aux t_TrComputePhase_aux; - -// -// headers for type `TrComputePhase` -// - -struct TrComputePhase final : TLB_Complex { - enum { tr_phase_compute_skipped, tr_phase_compute_vm }; - static constexpr int cons_len_exact = 1; - struct Record_tr_phase_compute_skipped { - typedef TrComputePhase type_class; - char reason; // reason : ComputeSkipReason - Record_tr_phase_compute_skipped() = default; - Record_tr_phase_compute_skipped(char _reason) : reason(_reason) {} - }; - struct Record_tr_phase_compute_vm; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_tr_phase_compute_skipped& data) const; - bool unpack_tr_phase_compute_skipped(vm::CellSlice& cs, char& reason) const; - bool cell_unpack(Ref cell_ref, Record_tr_phase_compute_skipped& data) const; - bool cell_unpack_tr_phase_compute_skipped(Ref cell_ref, char& reason) const; - bool pack(vm::CellBuilder& cb, const Record_tr_phase_compute_skipped& data) const; - bool pack_tr_phase_compute_skipped(vm::CellBuilder& cb, char reason) const; - bool cell_pack(Ref& cell_ref, const Record_tr_phase_compute_skipped& data) const; - bool cell_pack_tr_phase_compute_skipped(Ref& cell_ref, char reason) const; - bool unpack(vm::CellSlice& cs, Record_tr_phase_compute_vm& data) const; - bool cell_unpack(Ref cell_ref, Record_tr_phase_compute_vm& data) const; - bool pack(vm::CellBuilder& cb, const Record_tr_phase_compute_vm& data) const; - bool cell_pack(Ref& cell_ref, const Record_tr_phase_compute_vm& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrComputePhase"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct TrComputePhase::Record_tr_phase_compute_vm { - typedef TrComputePhase type_class; - bool success; // success : Bool - bool msg_state_used; // msg_state_used : Bool - bool account_activated; // account_activated : Bool - Ref gas_fees; // gas_fees : Grams - TrComputePhase_aux::Record r1; // ^[$_ gas_used:(VarUInteger 7) gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3)) mode:int8 exit_code:int32 exit_arg:(Maybe int32) vm_steps:uint32 vm_init_state_hash:bits256 vm_final_state_hash:bits256 ] - Record_tr_phase_compute_vm() = default; - Record_tr_phase_compute_vm(bool _success, bool _msg_state_used, bool _account_activated, Ref _gas_fees, const TrComputePhase_aux::Record& _r1) : success(_success), msg_state_used(_msg_state_used), account_activated(_account_activated), gas_fees(std::move(_gas_fees)), r1(_r1) {} -}; - -extern const TrComputePhase t_TrComputePhase; - -// -// headers for type `ComputeSkipReason` -// - -struct ComputeSkipReason final : TLB_Complex { - enum { cskip_no_state, cskip_bad_state, cskip_no_gas }; - static constexpr int cons_len_exact = 2; - struct Record_cskip_no_state { - typedef ComputeSkipReason type_class; - }; - struct Record_cskip_bad_state { - typedef ComputeSkipReason type_class; - }; - struct Record_cskip_no_gas { - typedef ComputeSkipReason type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 2; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(2); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record_cskip_no_state& data) const; - bool unpack_cskip_no_state(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cskip_no_state& data) const; - bool cell_unpack_cskip_no_state(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cskip_no_state& data) const; - bool pack_cskip_no_state(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cskip_no_state& data) const; - bool cell_pack_cskip_no_state(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cskip_bad_state& data) const; - bool unpack_cskip_bad_state(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cskip_bad_state& data) const; - bool cell_unpack_cskip_bad_state(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cskip_bad_state& data) const; - bool pack_cskip_bad_state(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cskip_bad_state& data) const; - bool cell_pack_cskip_bad_state(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cskip_no_gas& data) const; - bool unpack_cskip_no_gas(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cskip_no_gas& data) const; - bool cell_unpack_cskip_no_gas(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cskip_no_gas& data) const; - bool pack_cskip_no_gas(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cskip_no_gas& data) const; - bool cell_pack_cskip_no_gas(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ComputeSkipReason"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(2, 7); - } -}; - -extern const ComputeSkipReason t_ComputeSkipReason; - -// -// headers for type `TrActionPhase` -// - -struct TrActionPhase final : TLB_Complex { - enum { tr_phase_action }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrActionPhase"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct TrActionPhase::Record { - typedef TrActionPhase type_class; - bool success; // success : Bool - bool valid; // valid : Bool - bool no_funds; // no_funds : Bool - char status_change; // status_change : AccStatusChange - Ref total_fwd_fees; // total_fwd_fees : Maybe Grams - Ref total_action_fees; // total_action_fees : Maybe Grams - int result_code; // result_code : int32 - Ref result_arg; // result_arg : Maybe int32 - int tot_actions; // tot_actions : uint16 - int spec_actions; // spec_actions : uint16 - int skipped_actions; // skipped_actions : uint16 - int msgs_created; // msgs_created : uint16 - td::BitArray<256> action_list_hash; // action_list_hash : bits256 - Ref tot_msg_size; // tot_msg_size : StorageUsedShort - Record() = default; - Record(bool _success, bool _valid, bool _no_funds, char _status_change, Ref _total_fwd_fees, Ref _total_action_fees, int _result_code, Ref _result_arg, int _tot_actions, int _spec_actions, int _skipped_actions, int _msgs_created, const td::BitArray<256>& _action_list_hash, Ref _tot_msg_size) : success(_success), valid(_valid), no_funds(_no_funds), status_change(_status_change), total_fwd_fees(std::move(_total_fwd_fees)), total_action_fees(std::move(_total_action_fees)), result_code(_result_code), result_arg(std::move(_result_arg)), tot_actions(_tot_actions), spec_actions(_spec_actions), skipped_actions(_skipped_actions), msgs_created(_msgs_created), action_list_hash(_action_list_hash), tot_msg_size(std::move(_tot_msg_size)) {} -}; - -extern const TrActionPhase t_TrActionPhase; - -// -// headers for type `TrBouncePhase` -// - -struct TrBouncePhase final : TLB_Complex { - enum { tr_phase_bounce_negfunds, tr_phase_bounce_nofunds, tr_phase_bounce_ok }; - static constexpr char cons_len[3] = { 2, 2, 1 }; - static constexpr unsigned char cons_tag[3] = { 0, 1, 1 }; - struct Record_tr_phase_bounce_negfunds { - typedef TrBouncePhase type_class; - }; - struct Record_tr_phase_bounce_nofunds { - typedef TrBouncePhase type_class; - Ref msg_size; // msg_size : StorageUsedShort - Ref req_fwd_fees; // req_fwd_fees : Grams - Record_tr_phase_bounce_nofunds() = default; - Record_tr_phase_bounce_nofunds(Ref _msg_size, Ref _req_fwd_fees) : msg_size(std::move(_msg_size)), req_fwd_fees(std::move(_req_fwd_fees)) {} - }; - struct Record_tr_phase_bounce_ok; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_tr_phase_bounce_negfunds& data) const; - bool unpack_tr_phase_bounce_negfunds(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_tr_phase_bounce_negfunds& data) const; - bool cell_unpack_tr_phase_bounce_negfunds(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_tr_phase_bounce_negfunds& data) const; - bool pack_tr_phase_bounce_negfunds(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_tr_phase_bounce_negfunds& data) const; - bool cell_pack_tr_phase_bounce_negfunds(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_tr_phase_bounce_nofunds& data) const; - bool unpack_tr_phase_bounce_nofunds(vm::CellSlice& cs, Ref& msg_size, Ref& req_fwd_fees) const; - bool cell_unpack(Ref cell_ref, Record_tr_phase_bounce_nofunds& data) const; - bool cell_unpack_tr_phase_bounce_nofunds(Ref cell_ref, Ref& msg_size, Ref& req_fwd_fees) const; - bool pack(vm::CellBuilder& cb, const Record_tr_phase_bounce_nofunds& data) const; - bool pack_tr_phase_bounce_nofunds(vm::CellBuilder& cb, Ref msg_size, Ref req_fwd_fees) const; - bool cell_pack(Ref& cell_ref, const Record_tr_phase_bounce_nofunds& data) const; - bool cell_pack_tr_phase_bounce_nofunds(Ref& cell_ref, Ref msg_size, Ref req_fwd_fees) const; - bool unpack(vm::CellSlice& cs, Record_tr_phase_bounce_ok& data) const; - bool unpack_tr_phase_bounce_ok(vm::CellSlice& cs, Ref& msg_size, Ref& msg_fees, Ref& fwd_fees) const; - bool cell_unpack(Ref cell_ref, Record_tr_phase_bounce_ok& data) const; - bool cell_unpack_tr_phase_bounce_ok(Ref cell_ref, Ref& msg_size, Ref& msg_fees, Ref& fwd_fees) const; - bool pack(vm::CellBuilder& cb, const Record_tr_phase_bounce_ok& data) const; - bool pack_tr_phase_bounce_ok(vm::CellBuilder& cb, Ref msg_size, Ref msg_fees, Ref fwd_fees) const; - bool cell_pack(Ref& cell_ref, const Record_tr_phase_bounce_ok& data) const; - bool cell_pack_tr_phase_bounce_ok(Ref& cell_ref, Ref msg_size, Ref msg_fees, Ref fwd_fees) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TrBouncePhase"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect_ext(2, 7); - } -}; - -struct TrBouncePhase::Record_tr_phase_bounce_ok { - typedef TrBouncePhase type_class; - Ref msg_size; // msg_size : StorageUsedShort - Ref msg_fees; // msg_fees : Grams - Ref fwd_fees; // fwd_fees : Grams - Record_tr_phase_bounce_ok() = default; - Record_tr_phase_bounce_ok(Ref _msg_size, Ref _msg_fees, Ref _fwd_fees) : msg_size(std::move(_msg_size)), msg_fees(std::move(_msg_fees)), fwd_fees(std::move(_fwd_fees)) {} -}; - -extern const TrBouncePhase t_TrBouncePhase; - -// -// headers for type `SplitMergeInfo` -// - -struct SplitMergeInfo final : TLB_Complex { - enum { split_merge_info }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 524; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(524); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(524); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SplitMergeInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct SplitMergeInfo::Record { - typedef SplitMergeInfo type_class; - int cur_shard_pfx_len; // cur_shard_pfx_len : ## 6 - int acc_split_depth; // acc_split_depth : ## 6 - td::BitArray<256> this_addr; // this_addr : bits256 - td::BitArray<256> sibling_addr; // sibling_addr : bits256 - Record() = default; - Record(int _cur_shard_pfx_len, int _acc_split_depth, const td::BitArray<256>& _this_addr, const td::BitArray<256>& _sibling_addr) : cur_shard_pfx_len(_cur_shard_pfx_len), acc_split_depth(_acc_split_depth), this_addr(_this_addr), sibling_addr(_sibling_addr) {} -}; - -extern const SplitMergeInfo t_SplitMergeInfo; - -// -// headers for type `TransactionDescr` -// - -struct TransactionDescr final : TLB_Complex { - enum { trans_ord, trans_storage, trans_tick_tock, trans_split_prepare, trans_split_install, trans_merge_prepare, trans_merge_install }; - static constexpr char cons_len[7] = { 4, 4, 3, 4, 4, 4, 4 }; - static constexpr unsigned char cons_tag[7] = { 0, 1, 1, 4, 5, 6, 7 }; - struct Record_trans_ord; - struct Record_trans_storage { - typedef TransactionDescr type_class; - Ref storage_ph; // storage_ph : TrStoragePhase - Record_trans_storage() = default; - Record_trans_storage(Ref _storage_ph) : storage_ph(std::move(_storage_ph)) {} - }; - struct Record_trans_tick_tock; - struct Record_trans_split_prepare; - struct Record_trans_split_install; - struct Record_trans_merge_prepare; - struct Record_trans_merge_install; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_trans_ord& data) const; - bool cell_unpack(Ref cell_ref, Record_trans_ord& data) const; - bool pack(vm::CellBuilder& cb, const Record_trans_ord& data) const; - bool cell_pack(Ref& cell_ref, const Record_trans_ord& data) const; - bool unpack(vm::CellSlice& cs, Record_trans_storage& data) const; - bool unpack_trans_storage(vm::CellSlice& cs, Ref& storage_ph) const; - bool cell_unpack(Ref cell_ref, Record_trans_storage& data) const; - bool cell_unpack_trans_storage(Ref cell_ref, Ref& storage_ph) const; - bool pack(vm::CellBuilder& cb, const Record_trans_storage& data) const; - bool pack_trans_storage(vm::CellBuilder& cb, Ref storage_ph) const; - bool cell_pack(Ref& cell_ref, const Record_trans_storage& data) const; - bool cell_pack_trans_storage(Ref& cell_ref, Ref storage_ph) const; - bool unpack(vm::CellSlice& cs, Record_trans_tick_tock& data) const; - bool cell_unpack(Ref cell_ref, Record_trans_tick_tock& data) const; - bool pack(vm::CellBuilder& cb, const Record_trans_tick_tock& data) const; - bool cell_pack(Ref& cell_ref, const Record_trans_tick_tock& data) const; - bool unpack(vm::CellSlice& cs, Record_trans_split_prepare& data) const; - bool cell_unpack(Ref cell_ref, Record_trans_split_prepare& data) const; - bool pack(vm::CellBuilder& cb, const Record_trans_split_prepare& data) const; - bool cell_pack(Ref& cell_ref, const Record_trans_split_prepare& data) const; - bool unpack(vm::CellSlice& cs, Record_trans_split_install& data) const; - bool unpack_trans_split_install(vm::CellSlice& cs, Ref& split_info, Ref& prepare_transaction, bool& installed) const; - bool cell_unpack(Ref cell_ref, Record_trans_split_install& data) const; - bool cell_unpack_trans_split_install(Ref cell_ref, Ref& split_info, Ref& prepare_transaction, bool& installed) const; - bool pack(vm::CellBuilder& cb, const Record_trans_split_install& data) const; - bool pack_trans_split_install(vm::CellBuilder& cb, Ref split_info, Ref prepare_transaction, bool installed) const; - bool cell_pack(Ref& cell_ref, const Record_trans_split_install& data) const; - bool cell_pack_trans_split_install(Ref& cell_ref, Ref split_info, Ref prepare_transaction, bool installed) const; - bool unpack(vm::CellSlice& cs, Record_trans_merge_prepare& data) const; - bool unpack_trans_merge_prepare(vm::CellSlice& cs, Ref& split_info, Ref& storage_ph, bool& aborted) const; - bool cell_unpack(Ref cell_ref, Record_trans_merge_prepare& data) const; - bool cell_unpack_trans_merge_prepare(Ref cell_ref, Ref& split_info, Ref& storage_ph, bool& aborted) const; - bool pack(vm::CellBuilder& cb, const Record_trans_merge_prepare& data) const; - bool pack_trans_merge_prepare(vm::CellBuilder& cb, Ref split_info, Ref storage_ph, bool aborted) const; - bool cell_pack(Ref& cell_ref, const Record_trans_merge_prepare& data) const; - bool cell_pack_trans_merge_prepare(Ref& cell_ref, Ref split_info, Ref storage_ph, bool aborted) const; - bool unpack(vm::CellSlice& cs, Record_trans_merge_install& data) const; - bool cell_unpack(Ref cell_ref, Record_trans_merge_install& data) const; - bool pack(vm::CellBuilder& cb, const Record_trans_merge_install& data) const; - bool cell_pack(Ref& cell_ref, const Record_trans_merge_install& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TransactionDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 0xf7); - } -}; - -struct TransactionDescr::Record_trans_ord { - typedef TransactionDescr type_class; - bool credit_first; // credit_first : Bool - Ref storage_ph; // storage_ph : Maybe TrStoragePhase - Ref credit_ph; // credit_ph : Maybe TrCreditPhase - Ref compute_ph; // compute_ph : TrComputePhase - Ref action; // action : Maybe ^TrActionPhase - bool aborted; // aborted : Bool - Ref bounce; // bounce : Maybe TrBouncePhase - bool destroyed; // destroyed : Bool - Record_trans_ord() = default; - Record_trans_ord(bool _credit_first, Ref _storage_ph, Ref _credit_ph, Ref _compute_ph, Ref _action, bool _aborted, Ref _bounce, bool _destroyed) : credit_first(_credit_first), storage_ph(std::move(_storage_ph)), credit_ph(std::move(_credit_ph)), compute_ph(std::move(_compute_ph)), action(std::move(_action)), aborted(_aborted), bounce(std::move(_bounce)), destroyed(_destroyed) {} -}; - -struct TransactionDescr::Record_trans_tick_tock { - typedef TransactionDescr type_class; - bool is_tock; // is_tock : Bool - Ref storage_ph; // storage_ph : TrStoragePhase - Ref compute_ph; // compute_ph : TrComputePhase - Ref action; // action : Maybe ^TrActionPhase - bool aborted; // aborted : Bool - bool destroyed; // destroyed : Bool - Record_trans_tick_tock() = default; - Record_trans_tick_tock(bool _is_tock, Ref _storage_ph, Ref _compute_ph, Ref _action, bool _aborted, bool _destroyed) : is_tock(_is_tock), storage_ph(std::move(_storage_ph)), compute_ph(std::move(_compute_ph)), action(std::move(_action)), aborted(_aborted), destroyed(_destroyed) {} -}; - -struct TransactionDescr::Record_trans_split_prepare { - typedef TransactionDescr type_class; - Ref split_info; // split_info : SplitMergeInfo - Ref storage_ph; // storage_ph : Maybe TrStoragePhase - Ref compute_ph; // compute_ph : TrComputePhase - Ref action; // action : Maybe ^TrActionPhase - bool aborted; // aborted : Bool - bool destroyed; // destroyed : Bool - Record_trans_split_prepare() = default; - Record_trans_split_prepare(Ref _split_info, Ref _storage_ph, Ref _compute_ph, Ref _action, bool _aborted, bool _destroyed) : split_info(std::move(_split_info)), storage_ph(std::move(_storage_ph)), compute_ph(std::move(_compute_ph)), action(std::move(_action)), aborted(_aborted), destroyed(_destroyed) {} -}; - -struct TransactionDescr::Record_trans_split_install { - typedef TransactionDescr type_class; - Ref split_info; // split_info : SplitMergeInfo - Ref prepare_transaction; // prepare_transaction : ^Transaction - bool installed; // installed : Bool - Record_trans_split_install() = default; - Record_trans_split_install(Ref _split_info, Ref _prepare_transaction, bool _installed) : split_info(std::move(_split_info)), prepare_transaction(std::move(_prepare_transaction)), installed(_installed) {} -}; - -struct TransactionDescr::Record_trans_merge_prepare { - typedef TransactionDescr type_class; - Ref split_info; // split_info : SplitMergeInfo - Ref storage_ph; // storage_ph : TrStoragePhase - bool aborted; // aborted : Bool - Record_trans_merge_prepare() = default; - Record_trans_merge_prepare(Ref _split_info, Ref _storage_ph, bool _aborted) : split_info(std::move(_split_info)), storage_ph(std::move(_storage_ph)), aborted(_aborted) {} -}; - -struct TransactionDescr::Record_trans_merge_install { - typedef TransactionDescr type_class; - Ref split_info; // split_info : SplitMergeInfo - Ref prepare_transaction; // prepare_transaction : ^Transaction - Ref storage_ph; // storage_ph : Maybe TrStoragePhase - Ref credit_ph; // credit_ph : Maybe TrCreditPhase - Ref compute_ph; // compute_ph : TrComputePhase - Ref action; // action : Maybe ^TrActionPhase - bool aborted; // aborted : Bool - bool destroyed; // destroyed : Bool - Record_trans_merge_install() = default; - Record_trans_merge_install(Ref _split_info, Ref _prepare_transaction, Ref _storage_ph, Ref _credit_ph, Ref _compute_ph, Ref _action, bool _aborted, bool _destroyed) : split_info(std::move(_split_info)), prepare_transaction(std::move(_prepare_transaction)), storage_ph(std::move(_storage_ph)), credit_ph(std::move(_credit_ph)), compute_ph(std::move(_compute_ph)), action(std::move(_action)), aborted(_aborted), destroyed(_destroyed) {} -}; - -extern const TransactionDescr t_TransactionDescr; - -// -// headers for type `SmartContractInfo` -// - -struct SmartContractInfo final : TLB_Complex { - enum { smc_info }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x76ef1ea }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SmartContractInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct SmartContractInfo::Record { - typedef SmartContractInfo type_class; - int actions; // actions : uint16 - int msgs_sent; // msgs_sent : uint16 - unsigned unixtime; // unixtime : uint32 - unsigned long long block_lt; // block_lt : uint64 - unsigned long long trans_lt; // trans_lt : uint64 - td::BitArray<256> rand_seed; // rand_seed : bits256 - Ref balance_remaining; // balance_remaining : CurrencyCollection - Ref myself; // myself : MsgAddressInt - Record() = default; - Record(int _actions, int _msgs_sent, unsigned _unixtime, unsigned long long _block_lt, unsigned long long _trans_lt, const td::BitArray<256>& _rand_seed, Ref _balance_remaining, Ref _myself) : actions(_actions), msgs_sent(_msgs_sent), unixtime(_unixtime), block_lt(_block_lt), trans_lt(_trans_lt), rand_seed(_rand_seed), balance_remaining(std::move(_balance_remaining)), myself(std::move(_myself)) {} -}; - -extern const SmartContractInfo t_SmartContractInfo; - -// -// headers for type `OutList` -// - -struct OutList final : TLB_Complex { - enum { out_list, out_list_empty }; - static constexpr int cons_len_exact = 0; - int m_; - OutList(int m) : m_(m) {} - struct Record_out_list_empty { - typedef OutList type_class; - }; - struct Record_out_list; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_out_list_empty& data) const; - bool unpack_out_list_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_out_list_empty& data) const; - bool cell_unpack_out_list_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_out_list_empty& data) const; - bool pack_out_list_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_out_list_empty& data) const; - bool cell_pack_out_list_empty(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_out_list& data) const; - bool unpack_out_list(vm::CellSlice& cs, int& n, Ref& prev, Ref& action) const; - bool cell_unpack(Ref cell_ref, Record_out_list& data) const; - bool cell_unpack_out_list(Ref cell_ref, int& n, Ref& prev, Ref& action) const; - bool pack(vm::CellBuilder& cb, const Record_out_list& data) const; - bool pack_out_list(vm::CellBuilder& cb, Ref prev, Ref action) const; - bool cell_pack(Ref& cell_ref, const Record_out_list& data) const; - bool cell_pack_out_list(Ref& cell_ref, Ref prev, Ref action) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(OutList " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct OutList::Record_out_list { - typedef OutList type_class; - int n; // n : # - Ref prev; // prev : ^(OutList n) - Ref action; // action : OutAction - Record_out_list() = default; - Record_out_list(Ref _prev, Ref _action) : n(-1), prev(std::move(_prev)), action(std::move(_action)) {} -}; - -// -// headers for type `LibRef` -// - -struct LibRef final : TLB_Complex { - enum { libref_hash, libref_ref }; - static constexpr int cons_len_exact = 1; - struct Record_libref_hash { - typedef LibRef type_class; - td::BitArray<256> lib_hash; // lib_hash : bits256 - Record_libref_hash() = default; - Record_libref_hash(const td::BitArray<256>& _lib_hash) : lib_hash(_lib_hash) {} - }; - struct Record_libref_ref { - typedef LibRef type_class; - Ref library; // library : ^Cell - Record_libref_ref() = default; - Record_libref_ref(Ref _library) : library(std::move(_library)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_libref_hash& data) const; - bool unpack_libref_hash(vm::CellSlice& cs, td::BitArray<256>& lib_hash) const; - bool cell_unpack(Ref cell_ref, Record_libref_hash& data) const; - bool cell_unpack_libref_hash(Ref cell_ref, td::BitArray<256>& lib_hash) const; - bool pack(vm::CellBuilder& cb, const Record_libref_hash& data) const; - bool pack_libref_hash(vm::CellBuilder& cb, td::BitArray<256> lib_hash) const; - bool cell_pack(Ref& cell_ref, const Record_libref_hash& data) const; - bool cell_pack_libref_hash(Ref& cell_ref, td::BitArray<256> lib_hash) const; - bool unpack(vm::CellSlice& cs, Record_libref_ref& data) const; - bool unpack_libref_ref(vm::CellSlice& cs, Ref& library) const; - bool cell_unpack(Ref cell_ref, Record_libref_ref& data) const; - bool cell_unpack_libref_ref(Ref cell_ref, Ref& library) const; - bool pack(vm::CellBuilder& cb, const Record_libref_ref& data) const; - bool pack_libref_ref(vm::CellBuilder& cb, Ref library) const; - bool cell_pack(Ref& cell_ref, const Record_libref_ref& data) const; - bool cell_pack_libref_ref(Ref& cell_ref, Ref library) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "LibRef"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const LibRef t_LibRef; - -// -// headers for type `OutAction` -// - -struct OutAction final : TLB_Complex { - enum { action_send_msg, action_change_library, action_reserve_currency, action_set_code }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[4] = { 0xec3c86d, 0x26fa1dd4, 0x36e6b809, 0xad4de08eU }; - struct Record_action_send_msg { - typedef OutAction type_class; - int mode; // mode : ## 8 - Ref out_msg; // out_msg : ^(MessageRelaxed Any) - Record_action_send_msg() = default; - Record_action_send_msg(int _mode, Ref _out_msg) : mode(_mode), out_msg(std::move(_out_msg)) {} - }; - struct Record_action_set_code { - typedef OutAction type_class; - Ref new_code; // new_code : ^Cell - Record_action_set_code() = default; - Record_action_set_code(Ref _new_code) : new_code(std::move(_new_code)) {} - }; - struct Record_action_reserve_currency { - typedef OutAction type_class; - int mode; // mode : ## 8 - Ref currency; // currency : CurrencyCollection - Record_action_reserve_currency() = default; - Record_action_reserve_currency(int _mode, Ref _currency) : mode(_mode), currency(std::move(_currency)) {} - }; - struct Record_action_change_library { - typedef OutAction type_class; - int mode; // mode : ## 7 - Ref libref; // libref : LibRef - Record_action_change_library() = default; - Record_action_change_library(int _mode, Ref _libref) : mode(_mode), libref(std::move(_libref)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_action_send_msg& data) const; - bool unpack_action_send_msg(vm::CellSlice& cs, int& mode, Ref& out_msg) const; - bool cell_unpack(Ref cell_ref, Record_action_send_msg& data) const; - bool cell_unpack_action_send_msg(Ref cell_ref, int& mode, Ref& out_msg) const; - bool pack(vm::CellBuilder& cb, const Record_action_send_msg& data) const; - bool pack_action_send_msg(vm::CellBuilder& cb, int mode, Ref out_msg) const; - bool cell_pack(Ref& cell_ref, const Record_action_send_msg& data) const; - bool cell_pack_action_send_msg(Ref& cell_ref, int mode, Ref out_msg) const; - bool unpack(vm::CellSlice& cs, Record_action_set_code& data) const; - bool unpack_action_set_code(vm::CellSlice& cs, Ref& new_code) const; - bool cell_unpack(Ref cell_ref, Record_action_set_code& data) const; - bool cell_unpack_action_set_code(Ref cell_ref, Ref& new_code) const; - bool pack(vm::CellBuilder& cb, const Record_action_set_code& data) const; - bool pack_action_set_code(vm::CellBuilder& cb, Ref new_code) const; - bool cell_pack(Ref& cell_ref, const Record_action_set_code& data) const; - bool cell_pack_action_set_code(Ref& cell_ref, Ref new_code) const; - bool unpack(vm::CellSlice& cs, Record_action_reserve_currency& data) const; - bool unpack_action_reserve_currency(vm::CellSlice& cs, int& mode, Ref& currency) const; - bool cell_unpack(Ref cell_ref, Record_action_reserve_currency& data) const; - bool cell_unpack_action_reserve_currency(Ref cell_ref, int& mode, Ref& currency) const; - bool pack(vm::CellBuilder& cb, const Record_action_reserve_currency& data) const; - bool pack_action_reserve_currency(vm::CellBuilder& cb, int mode, Ref currency) const; - bool cell_pack(Ref& cell_ref, const Record_action_reserve_currency& data) const; - bool cell_pack_action_reserve_currency(Ref& cell_ref, int mode, Ref currency) const; - bool unpack(vm::CellSlice& cs, Record_action_change_library& data) const; - bool unpack_action_change_library(vm::CellSlice& cs, int& mode, Ref& libref) const; - bool cell_unpack(Ref cell_ref, Record_action_change_library& data) const; - bool cell_unpack_action_change_library(Ref cell_ref, int& mode, Ref& libref) const; - bool pack(vm::CellBuilder& cb, const Record_action_change_library& data) const; - bool pack_action_change_library(vm::CellBuilder& cb, int mode, Ref libref) const; - bool cell_pack(Ref& cell_ref, const Record_action_change_library& data) const; - bool cell_pack_action_change_library(Ref& cell_ref, int mode, Ref libref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutAction"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 0x40d); - } -}; - -extern const OutAction t_OutAction; - -// -// headers for type `OutListNode` -// - -struct OutListNode final : TLB_Complex { - enum { out_list_node }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef OutListNode type_class; - Ref prev; // prev : ^Cell - Ref action; // action : OutAction - Record() = default; - Record(Ref _prev, Ref _action) : prev(std::move(_prev)), action(std::move(_action)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_out_list_node(vm::CellSlice& cs, Ref& prev, Ref& action) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_out_list_node(Ref cell_ref, Ref& prev, Ref& action) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_out_list_node(vm::CellBuilder& cb, Ref prev, Ref action) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_out_list_node(Ref& cell_ref, Ref prev, Ref action) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OutListNode"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const OutListNode t_OutListNode; - -// -// headers for type `ShardIdent` -// - -struct ShardIdent final : TLB_Complex { - enum { shard_ident }; - static constexpr int cons_len_exact = 2; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 104; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(104); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_shard_ident(vm::CellSlice& cs, int& shard_pfx_bits, int& workchain_id, unsigned long long& shard_prefix) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_shard_ident(Ref cell_ref, int& shard_pfx_bits, int& workchain_id, unsigned long long& shard_prefix) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_shard_ident(vm::CellBuilder& cb, int shard_pfx_bits, int workchain_id, unsigned long long shard_prefix) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_shard_ident(Ref& cell_ref, int shard_pfx_bits, int workchain_id, unsigned long long shard_prefix) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardIdent"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ShardIdent::Record { - typedef ShardIdent type_class; - int shard_pfx_bits; // shard_pfx_bits : #<= 60 - int workchain_id; // workchain_id : int32 - unsigned long long shard_prefix; // shard_prefix : uint64 - Record() = default; - Record(int _shard_pfx_bits, int _workchain_id, unsigned long long _shard_prefix) : shard_pfx_bits(_shard_pfx_bits), workchain_id(_workchain_id), shard_prefix(_shard_prefix) {} -}; - -extern const ShardIdent t_ShardIdent; - -// -// headers for type `ExtBlkRef` -// - -struct ExtBlkRef final : TLB_Complex { - enum { ext_blk_ref }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 608; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(608); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(608); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ExtBlkRef"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ExtBlkRef::Record { - typedef ExtBlkRef type_class; - unsigned long long end_lt; // end_lt : uint64 - unsigned seq_no; // seq_no : uint32 - td::BitArray<256> root_hash; // root_hash : bits256 - td::BitArray<256> file_hash; // file_hash : bits256 - Record() = default; - Record(unsigned long long _end_lt, unsigned _seq_no, const td::BitArray<256>& _root_hash, const td::BitArray<256>& _file_hash) : end_lt(_end_lt), seq_no(_seq_no), root_hash(_root_hash), file_hash(_file_hash) {} -}; - -extern const ExtBlkRef t_ExtBlkRef; - -// -// headers for type `BlockIdExt` -// - -struct BlockIdExt final : TLB_Complex { - enum { block_id_ext }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 648; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(648); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockIdExt"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockIdExt::Record { - typedef BlockIdExt type_class; - Ref shard_id; // shard_id : ShardIdent - unsigned seq_no; // seq_no : uint32 - td::BitArray<256> root_hash; // root_hash : bits256 - td::BitArray<256> file_hash; // file_hash : bits256 - Record() = default; - Record(Ref _shard_id, unsigned _seq_no, const td::BitArray<256>& _root_hash, const td::BitArray<256>& _file_hash) : shard_id(std::move(_shard_id)), seq_no(_seq_no), root_hash(_root_hash), file_hash(_file_hash) {} -}; - -extern const BlockIdExt t_BlockIdExt; - -// -// headers for type `BlkMasterInfo` -// - -struct BlkMasterInfo final : TLB_Complex { - enum { master_info }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef BlkMasterInfo type_class; - Ref master; // master : ExtBlkRef - Record() = default; - Record(Ref _master) : master(std::move(_master)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 608; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(608); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(608); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_master_info(vm::CellSlice& cs, Ref& master) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_master_info(Ref cell_ref, Ref& master) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_master_info(vm::CellBuilder& cb, Ref master) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_master_info(Ref& cell_ref, Ref master) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlkMasterInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const BlkMasterInfo t_BlkMasterInfo; - -// -// headers for auxiliary type `ShardStateUnsplit_aux` -// - -struct ShardStateUnsplit_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardStateUnsplit_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ShardStateUnsplit_aux::Record { - typedef ShardStateUnsplit_aux type_class; - unsigned long long overload_history; // overload_history : uint64 - unsigned long long underload_history; // underload_history : uint64 - Ref total_balance; // total_balance : CurrencyCollection - Ref total_validator_fees; // total_validator_fees : CurrencyCollection - Ref libraries; // libraries : HashmapE 256 LibDescr - Ref master_ref; // master_ref : Maybe BlkMasterInfo - Record() = default; - Record(unsigned long long _overload_history, unsigned long long _underload_history, Ref _total_balance, Ref _total_validator_fees, Ref _libraries, Ref _master_ref) : overload_history(_overload_history), underload_history(_underload_history), total_balance(std::move(_total_balance)), total_validator_fees(std::move(_total_validator_fees)), libraries(std::move(_libraries)), master_ref(std::move(_master_ref)) {} -}; - -extern const ShardStateUnsplit_aux t_ShardStateUnsplit_aux; - -// -// headers for type `ShardStateUnsplit` -// - -struct ShardStateUnsplit final : TLB_Complex { - enum { shard_state }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x9023afe2U }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardStateUnsplit"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ShardStateUnsplit::Record { - typedef ShardStateUnsplit type_class; - int global_id; // global_id : int32 - Ref shard_id; // shard_id : ShardIdent - unsigned seq_no; // seq_no : uint32 - int vert_seq_no; // vert_seq_no : # - unsigned gen_utime; // gen_utime : uint32 - unsigned long long gen_lt; // gen_lt : uint64 - unsigned min_ref_mc_seqno; // min_ref_mc_seqno : uint32 - Ref out_msg_queue_info; // out_msg_queue_info : ^OutMsgQueueInfo - bool before_split; // before_split : ## 1 - Ref accounts; // accounts : ^ShardAccounts - ShardStateUnsplit_aux::Record r1; // ^[$_ overload_history:uint64 underload_history:uint64 total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ] - Ref custom; // custom : Maybe ^McStateExtra - Record() = default; - Record(int _global_id, Ref _shard_id, unsigned _seq_no, int _vert_seq_no, unsigned _gen_utime, unsigned long long _gen_lt, unsigned _min_ref_mc_seqno, Ref _out_msg_queue_info, bool _before_split, Ref _accounts, const ShardStateUnsplit_aux::Record& _r1, Ref _custom) : global_id(_global_id), shard_id(std::move(_shard_id)), seq_no(_seq_no), vert_seq_no(_vert_seq_no), gen_utime(_gen_utime), gen_lt(_gen_lt), min_ref_mc_seqno(_min_ref_mc_seqno), out_msg_queue_info(std::move(_out_msg_queue_info)), before_split(_before_split), accounts(std::move(_accounts)), r1(_r1), custom(std::move(_custom)) {} -}; - -extern const ShardStateUnsplit t_ShardStateUnsplit; - -// -// headers for type `ShardState` -// - -struct ShardState final : TLB_Complex { - enum { split_state, cons1 }; - static constexpr char cons_len[2] = { 32, 0 }; - static constexpr unsigned cons_tag[2] = { 0x5f327da5, 0 }; - struct Record_cons1 { - typedef ShardState type_class; - Ref x; // ShardStateUnsplit - Record_cons1() = default; - Record_cons1(Ref _x) : x(std::move(_x)) {} - }; - struct Record_split_state { - typedef ShardState type_class; - Ref left; // left : ^ShardStateUnsplit - Ref right; // right : ^ShardStateUnsplit - Record_split_state() = default; - Record_split_state(Ref _left, Ref _right) : left(std::move(_left)), right(std::move(_right)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cons1& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons1& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons1& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons1& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_split_state& data) const; - bool unpack_split_state(vm::CellSlice& cs, Ref& left, Ref& right) const; - bool cell_unpack(Ref cell_ref, Record_split_state& data) const; - bool cell_unpack_split_state(Ref cell_ref, Ref& left, Ref& right) const; - bool pack(vm::CellBuilder& cb, const Record_split_state& data) const; - bool pack_split_state(vm::CellBuilder& cb, Ref left, Ref right) const; - bool cell_pack(Ref& cell_ref, const Record_split_state& data) const; - bool cell_pack_split_state(Ref& cell_ref, Ref left, Ref right) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardState"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const ShardState t_ShardState; - -// -// headers for type `LibDescr` -// - -struct LibDescr final : TLB_Complex { - enum { shared_lib_descr }; - static constexpr int cons_len_exact = 2; - struct Record { - typedef LibDescr type_class; - Ref lib; // lib : ^Cell - Ref publishers; // publishers : Hashmap 256 True - Record() = default; - Record(Ref _lib, Ref _publishers) : lib(std::move(_lib)), publishers(std::move(_publishers)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_shared_lib_descr(vm::CellSlice& cs, Ref& lib, Ref& publishers) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_shared_lib_descr(Ref cell_ref, Ref& lib, Ref& publishers) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_shared_lib_descr(vm::CellBuilder& cb, Ref lib, Ref publishers) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_shared_lib_descr(Ref& cell_ref, Ref lib, Ref publishers) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "LibDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const LibDescr t_LibDescr; - -// -// headers for type `BlockInfo` -// - -struct BlockInfo final : TLB_Complex { - enum { block_info }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x9bc7a987U }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockInfo::Record { - typedef BlockInfo type_class; - unsigned version; // version : uint32 - bool not_master; // not_master : ## 1 - bool after_merge; // after_merge : ## 1 - bool before_split; // before_split : ## 1 - bool after_split; // after_split : ## 1 - bool want_split; // want_split : Bool - bool want_merge; // want_merge : Bool - bool key_block; // key_block : Bool - bool vert_seqno_incr; // vert_seqno_incr : ## 1 - int flags; // flags : ## 8 - int seq_no; // seq_no : # - int vert_seq_no; // vert_seq_no : # - Ref shard; // shard : ShardIdent - unsigned gen_utime; // gen_utime : uint32 - unsigned long long start_lt; // start_lt : uint64 - unsigned long long end_lt; // end_lt : uint64 - unsigned gen_validator_list_hash_short; // gen_validator_list_hash_short : uint32 - unsigned gen_catchain_seqno; // gen_catchain_seqno : uint32 - unsigned min_ref_mc_seqno; // min_ref_mc_seqno : uint32 - unsigned prev_key_block_seqno; // prev_key_block_seqno : uint32 - Ref gen_software; // gen_software : flags.0?GlobalVersion - Ref master_ref; // master_ref : not_master?^BlkMasterInfo - Ref prev_ref; // prev_ref : ^(BlkPrevInfo after_merge) - Ref prev_vert_ref; // prev_vert_ref : vert_seqno_incr?^(BlkPrevInfo 0) - Record() = default; - Record(unsigned _version, bool _not_master, bool _after_merge, bool _before_split, bool _after_split, bool _want_split, bool _want_merge, bool _key_block, bool _vert_seqno_incr, int _flags, int _seq_no, int _vert_seq_no, Ref _shard, unsigned _gen_utime, unsigned long long _start_lt, unsigned long long _end_lt, unsigned _gen_validator_list_hash_short, unsigned _gen_catchain_seqno, unsigned _min_ref_mc_seqno, unsigned _prev_key_block_seqno, Ref _gen_software, Ref _master_ref, Ref _prev_ref, Ref _prev_vert_ref) : version(_version), not_master(_not_master), after_merge(_after_merge), before_split(_before_split), after_split(_after_split), want_split(_want_split), want_merge(_want_merge), key_block(_key_block), vert_seqno_incr(_vert_seqno_incr), flags(_flags), seq_no(_seq_no), vert_seq_no(_vert_seq_no), shard(std::move(_shard)), gen_utime(_gen_utime), start_lt(_start_lt), end_lt(_end_lt), gen_validator_list_hash_short(_gen_validator_list_hash_short), gen_catchain_seqno(_gen_catchain_seqno), min_ref_mc_seqno(_min_ref_mc_seqno), prev_key_block_seqno(_prev_key_block_seqno), gen_software(std::move(_gen_software)), master_ref(std::move(_master_ref)), prev_ref(std::move(_prev_ref)), prev_vert_ref(std::move(_prev_vert_ref)) {} -}; - -extern const BlockInfo t_BlockInfo; - -// -// headers for type `BlkPrevInfo` -// - -struct BlkPrevInfo final : TLB_Complex { - enum { prev_blk_info, prev_blks_info }; - static constexpr int cons_len_exact = 0; - int m_; - BlkPrevInfo(int m) : m_(m) {} - struct Record_prev_blk_info { - typedef BlkPrevInfo type_class; - Ref prev; // prev : ExtBlkRef - Record_prev_blk_info() = default; - Record_prev_blk_info(Ref _prev) : prev(std::move(_prev)) {} - }; - struct Record_prev_blks_info { - typedef BlkPrevInfo type_class; - Ref prev1; // prev1 : ^ExtBlkRef - Ref prev2; // prev2 : ^ExtBlkRef - Record_prev_blks_info() = default; - Record_prev_blks_info(Ref _prev1, Ref _prev2) : prev1(std::move(_prev1)), prev2(std::move(_prev2)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_prev_blk_info& data) const; - bool unpack_prev_blk_info(vm::CellSlice& cs, Ref& prev) const; - bool cell_unpack(Ref cell_ref, Record_prev_blk_info& data) const; - bool cell_unpack_prev_blk_info(Ref cell_ref, Ref& prev) const; - bool pack(vm::CellBuilder& cb, const Record_prev_blk_info& data) const; - bool pack_prev_blk_info(vm::CellBuilder& cb, Ref prev) const; - bool cell_pack(Ref& cell_ref, const Record_prev_blk_info& data) const; - bool cell_pack_prev_blk_info(Ref& cell_ref, Ref prev) const; - bool unpack(vm::CellSlice& cs, Record_prev_blks_info& data) const; - bool unpack_prev_blks_info(vm::CellSlice& cs, Ref& prev1, Ref& prev2) const; - bool cell_unpack(Ref cell_ref, Record_prev_blks_info& data) const; - bool cell_unpack_prev_blks_info(Ref cell_ref, Ref& prev1, Ref& prev2) const; - bool pack(vm::CellBuilder& cb, const Record_prev_blks_info& data) const; - bool pack_prev_blks_info(vm::CellBuilder& cb, Ref prev1, Ref prev2) const; - bool cell_pack(Ref& cell_ref, const Record_prev_blks_info& data) const; - bool cell_pack_prev_blks_info(Ref& cell_ref, Ref prev1, Ref prev2) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(BlkPrevInfo " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -// -// headers for type `Block` -// - -struct Block final : TLB_Complex { - enum { block }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x11ef55aa }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 0x40040; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x40040); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Block"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Block::Record { - typedef Block type_class; - int global_id; // global_id : int32 - Ref info; // info : ^BlockInfo - Ref value_flow; // value_flow : ^ValueFlow - Ref state_update; // state_update : ^(MERKLE_UPDATE ShardState) - Ref extra; // extra : ^BlockExtra - Record() = default; - Record(int _global_id, Ref _info, Ref _value_flow, Ref _state_update, Ref _extra) : global_id(_global_id), info(std::move(_info)), value_flow(std::move(_value_flow)), state_update(std::move(_state_update)), extra(std::move(_extra)) {} -}; - -extern const Block t_Block; - -// -// headers for type `BlockExtra` -// - -struct BlockExtra final : TLB_Complex { - enum { block_extra }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x4a33f6fd }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockExtra"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockExtra::Record { - typedef BlockExtra type_class; - Ref in_msg_descr; // in_msg_descr : ^InMsgDescr - Ref out_msg_descr; // out_msg_descr : ^OutMsgDescr - Ref account_blocks; // account_blocks : ^ShardAccountBlocks - td::BitArray<256> rand_seed; // rand_seed : bits256 - td::BitArray<256> created_by; // created_by : bits256 - Ref custom; // custom : Maybe ^McBlockExtra - Record() = default; - Record(Ref _in_msg_descr, Ref _out_msg_descr, Ref _account_blocks, const td::BitArray<256>& _rand_seed, const td::BitArray<256>& _created_by, Ref _custom) : in_msg_descr(std::move(_in_msg_descr)), out_msg_descr(std::move(_out_msg_descr)), account_blocks(std::move(_account_blocks)), rand_seed(_rand_seed), created_by(_created_by), custom(std::move(_custom)) {} -}; - -extern const BlockExtra t_BlockExtra; - -// -// headers for auxiliary type `ValueFlow_aux` -// - -struct ValueFlow_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValueFlow_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValueFlow_aux::Record { - typedef ValueFlow_aux type_class; - Ref from_prev_blk; // from_prev_blk : CurrencyCollection - Ref to_next_blk; // to_next_blk : CurrencyCollection - Ref imported; // imported : CurrencyCollection - Ref exported; // exported : CurrencyCollection - Record() = default; - Record(Ref _from_prev_blk, Ref _to_next_blk, Ref _imported, Ref _exported) : from_prev_blk(std::move(_from_prev_blk)), to_next_blk(std::move(_to_next_blk)), imported(std::move(_imported)), exported(std::move(_exported)) {} -}; - -extern const ValueFlow_aux t_ValueFlow_aux; - -// -// headers for auxiliary type `ValueFlow_aux1` -// - -struct ValueFlow_aux1 final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValueFlow_aux1"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValueFlow_aux1::Record { - typedef ValueFlow_aux1 type_class; - Ref fees_imported; // fees_imported : CurrencyCollection - Ref recovered; // recovered : CurrencyCollection - Ref created; // created : CurrencyCollection - Ref minted; // minted : CurrencyCollection - Record() = default; - Record(Ref _fees_imported, Ref _recovered, Ref _created, Ref _minted) : fees_imported(std::move(_fees_imported)), recovered(std::move(_recovered)), created(std::move(_created)), minted(std::move(_minted)) {} -}; - -extern const ValueFlow_aux1 t_ValueFlow_aux1; - -// -// headers for type `ValueFlow` -// - -struct ValueFlow final : TLB_Complex { - enum { value_flow }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0xb8e48dfbU }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValueFlow"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValueFlow::Record { - typedef ValueFlow type_class; - ValueFlow_aux::Record r1; // ^[$_ from_prev_blk:CurrencyCollection to_next_blk:CurrencyCollection imported:CurrencyCollection exported:CurrencyCollection ] - Ref fees_collected; // fees_collected : CurrencyCollection - ValueFlow_aux1::Record r2; // ^[$_ fees_imported:CurrencyCollection recovered:CurrencyCollection created:CurrencyCollection minted:CurrencyCollection ] - Record() = default; - Record(const ValueFlow_aux::Record& _r1, Ref _fees_collected, const ValueFlow_aux1::Record& _r2) : r1(_r1), fees_collected(std::move(_fees_collected)), r2(_r2) {} -}; - -extern const ValueFlow t_ValueFlow; - -// -// headers for type `BinTree` -// - -struct BinTree final : TLB_Complex { - enum { bt_leaf, bt_fork }; - static constexpr int cons_len_exact = 1; - const TLB &X_; - BinTree(const TLB& X) : X_(X) {} - struct Record_bt_leaf { - typedef BinTree type_class; - Ref leaf; // leaf : X - Record_bt_leaf() = default; - Record_bt_leaf(Ref _leaf) : leaf(std::move(_leaf)) {} - }; - struct Record_bt_fork { - typedef BinTree type_class; - Ref left; // left : ^(BinTree X) - Ref right; // right : ^(BinTree X) - Record_bt_fork() = default; - Record_bt_fork(Ref _left, Ref _right) : left(std::move(_left)), right(std::move(_right)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_bt_leaf& data) const; - bool unpack_bt_leaf(vm::CellSlice& cs, Ref& leaf) const; - bool cell_unpack(Ref cell_ref, Record_bt_leaf& data) const; - bool cell_unpack_bt_leaf(Ref cell_ref, Ref& leaf) const; - bool pack(vm::CellBuilder& cb, const Record_bt_leaf& data) const; - bool pack_bt_leaf(vm::CellBuilder& cb, Ref leaf) const; - bool cell_pack(Ref& cell_ref, const Record_bt_leaf& data) const; - bool cell_pack_bt_leaf(Ref& cell_ref, Ref leaf) const; - bool unpack(vm::CellSlice& cs, Record_bt_fork& data) const; - bool unpack_bt_fork(vm::CellSlice& cs, Ref& left, Ref& right) const; - bool cell_unpack(Ref cell_ref, Record_bt_fork& data) const; - bool cell_unpack_bt_fork(Ref cell_ref, Ref& left, Ref& right) const; - bool pack(vm::CellBuilder& cb, const Record_bt_fork& data) const; - bool pack_bt_fork(vm::CellBuilder& cb, Ref left, Ref right) const; - bool cell_pack(Ref& cell_ref, const Record_bt_fork& data) const; - bool cell_pack_bt_fork(Ref& cell_ref, Ref left, Ref right) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(BinTree " << X_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -// -// headers for type `FutureSplitMerge` -// - -struct FutureSplitMerge final : TLB_Complex { - enum { fsm_none, fsm_split, fsm_merge }; - static constexpr char cons_len[3] = { 1, 2, 2 }; - static constexpr unsigned char cons_tag[3] = { 0, 2, 3 }; - struct Record_fsm_none { - typedef FutureSplitMerge type_class; - }; - struct Record_fsm_split { - typedef FutureSplitMerge type_class; - unsigned split_utime; // split_utime : uint32 - unsigned interval; // interval : uint32 - Record_fsm_split() = default; - Record_fsm_split(unsigned _split_utime, unsigned _interval) : split_utime(_split_utime), interval(_interval) {} - }; - struct Record_fsm_merge { - typedef FutureSplitMerge type_class; - unsigned merge_utime; // merge_utime : uint32 - unsigned interval; // interval : uint32 - Record_fsm_merge() = default; - Record_fsm_merge(unsigned _merge_utime, unsigned _interval) : merge_utime(_merge_utime), interval(_interval) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_fsm_none& data) const; - bool unpack_fsm_none(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_fsm_none& data) const; - bool cell_unpack_fsm_none(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_fsm_none& data) const; - bool pack_fsm_none(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_fsm_none& data) const; - bool cell_pack_fsm_none(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_fsm_split& data) const; - bool unpack_fsm_split(vm::CellSlice& cs, unsigned& split_utime, unsigned& interval) const; - bool cell_unpack(Ref cell_ref, Record_fsm_split& data) const; - bool cell_unpack_fsm_split(Ref cell_ref, unsigned& split_utime, unsigned& interval) const; - bool pack(vm::CellBuilder& cb, const Record_fsm_split& data) const; - bool pack_fsm_split(vm::CellBuilder& cb, unsigned split_utime, unsigned interval) const; - bool cell_pack(Ref& cell_ref, const Record_fsm_split& data) const; - bool cell_pack_fsm_split(Ref& cell_ref, unsigned split_utime, unsigned interval) const; - bool unpack(vm::CellSlice& cs, Record_fsm_merge& data) const; - bool unpack_fsm_merge(vm::CellSlice& cs, unsigned& merge_utime, unsigned& interval) const; - bool cell_unpack(Ref cell_ref, Record_fsm_merge& data) const; - bool cell_unpack_fsm_merge(Ref cell_ref, unsigned& merge_utime, unsigned& interval) const; - bool pack(vm::CellBuilder& cb, const Record_fsm_merge& data) const; - bool pack_fsm_merge(vm::CellBuilder& cb, unsigned merge_utime, unsigned interval) const; - bool cell_pack(Ref& cell_ref, const Record_fsm_merge& data) const; - bool cell_pack_fsm_merge(Ref& cell_ref, unsigned merge_utime, unsigned interval) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "FutureSplitMerge"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect_ext(2, 13); - } -}; - -extern const FutureSplitMerge t_FutureSplitMerge; - -// -// headers for auxiliary type `ShardDescr_aux` -// - -struct ShardDescr_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardDescr_aux type_class; - Ref fees_collected; // fees_collected : CurrencyCollection - Ref funds_created; // funds_created : CurrencyCollection - Record() = default; - Record(Ref _fees_collected, Ref _funds_created) : fees_collected(std::move(_fees_collected)), funds_created(std::move(_funds_created)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& fees_collected, Ref& funds_created) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& fees_collected, Ref& funds_created) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref fees_collected, Ref funds_created) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref fees_collected, Ref funds_created) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardDescr_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardDescr_aux t_ShardDescr_aux; - -// -// headers for type `ShardDescr` -// - -struct ShardDescr final : TLB_Complex { - enum { shard_descr_new, shard_descr }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[2] = { 10, 11 }; - struct Record_shard_descr; - struct Record_shard_descr_new; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_shard_descr& data) const; - bool cell_unpack(Ref cell_ref, Record_shard_descr& data) const; - bool pack(vm::CellBuilder& cb, const Record_shard_descr& data) const; - bool cell_pack(Ref& cell_ref, const Record_shard_descr& data) const; - bool unpack(vm::CellSlice& cs, Record_shard_descr_new& data) const; - bool cell_unpack(Ref cell_ref, Record_shard_descr_new& data) const; - bool pack(vm::CellBuilder& cb, const Record_shard_descr_new& data) const; - bool cell_pack(Ref& cell_ref, const Record_shard_descr_new& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 0xc00); - } -}; - -struct ShardDescr::Record_shard_descr { - typedef ShardDescr type_class; - unsigned seq_no; // seq_no : uint32 - unsigned reg_mc_seqno; // reg_mc_seqno : uint32 - unsigned long long start_lt; // start_lt : uint64 - unsigned long long end_lt; // end_lt : uint64 - td::BitArray<256> root_hash; // root_hash : bits256 - td::BitArray<256> file_hash; // file_hash : bits256 - bool before_split; // before_split : Bool - bool before_merge; // before_merge : Bool - bool want_split; // want_split : Bool - bool want_merge; // want_merge : Bool - bool nx_cc_updated; // nx_cc_updated : Bool - int flags; // flags : ## 3 - unsigned next_catchain_seqno; // next_catchain_seqno : uint32 - unsigned long long next_validator_shard; // next_validator_shard : uint64 - unsigned min_ref_mc_seqno; // min_ref_mc_seqno : uint32 - unsigned gen_utime; // gen_utime : uint32 - Ref split_merge_at; // split_merge_at : FutureSplitMerge - Ref fees_collected; // fees_collected : CurrencyCollection - Ref funds_created; // funds_created : CurrencyCollection - Record_shard_descr() = default; - Record_shard_descr(unsigned _seq_no, unsigned _reg_mc_seqno, unsigned long long _start_lt, unsigned long long _end_lt, const td::BitArray<256>& _root_hash, const td::BitArray<256>& _file_hash, bool _before_split, bool _before_merge, bool _want_split, bool _want_merge, bool _nx_cc_updated, int _flags, unsigned _next_catchain_seqno, unsigned long long _next_validator_shard, unsigned _min_ref_mc_seqno, unsigned _gen_utime, Ref _split_merge_at, Ref _fees_collected, Ref _funds_created) : seq_no(_seq_no), reg_mc_seqno(_reg_mc_seqno), start_lt(_start_lt), end_lt(_end_lt), root_hash(_root_hash), file_hash(_file_hash), before_split(_before_split), before_merge(_before_merge), want_split(_want_split), want_merge(_want_merge), nx_cc_updated(_nx_cc_updated), flags(_flags), next_catchain_seqno(_next_catchain_seqno), next_validator_shard(_next_validator_shard), min_ref_mc_seqno(_min_ref_mc_seqno), gen_utime(_gen_utime), split_merge_at(std::move(_split_merge_at)), fees_collected(std::move(_fees_collected)), funds_created(std::move(_funds_created)) {} -}; - -struct ShardDescr::Record_shard_descr_new { - typedef ShardDescr type_class; - unsigned seq_no; // seq_no : uint32 - unsigned reg_mc_seqno; // reg_mc_seqno : uint32 - unsigned long long start_lt; // start_lt : uint64 - unsigned long long end_lt; // end_lt : uint64 - td::BitArray<256> root_hash; // root_hash : bits256 - td::BitArray<256> file_hash; // file_hash : bits256 - bool before_split; // before_split : Bool - bool before_merge; // before_merge : Bool - bool want_split; // want_split : Bool - bool want_merge; // want_merge : Bool - bool nx_cc_updated; // nx_cc_updated : Bool - int flags; // flags : ## 3 - unsigned next_catchain_seqno; // next_catchain_seqno : uint32 - unsigned long long next_validator_shard; // next_validator_shard : uint64 - unsigned min_ref_mc_seqno; // min_ref_mc_seqno : uint32 - unsigned gen_utime; // gen_utime : uint32 - Ref split_merge_at; // split_merge_at : FutureSplitMerge - ShardDescr_aux::Record r1; // ^[$_ fees_collected:CurrencyCollection funds_created:CurrencyCollection ] - Record_shard_descr_new() = default; - Record_shard_descr_new(unsigned _seq_no, unsigned _reg_mc_seqno, unsigned long long _start_lt, unsigned long long _end_lt, const td::BitArray<256>& _root_hash, const td::BitArray<256>& _file_hash, bool _before_split, bool _before_merge, bool _want_split, bool _want_merge, bool _nx_cc_updated, int _flags, unsigned _next_catchain_seqno, unsigned long long _next_validator_shard, unsigned _min_ref_mc_seqno, unsigned _gen_utime, Ref _split_merge_at, const ShardDescr_aux::Record& _r1) : seq_no(_seq_no), reg_mc_seqno(_reg_mc_seqno), start_lt(_start_lt), end_lt(_end_lt), root_hash(_root_hash), file_hash(_file_hash), before_split(_before_split), before_merge(_before_merge), want_split(_want_split), want_merge(_want_merge), nx_cc_updated(_nx_cc_updated), flags(_flags), next_catchain_seqno(_next_catchain_seqno), next_validator_shard(_next_validator_shard), min_ref_mc_seqno(_min_ref_mc_seqno), gen_utime(_gen_utime), split_merge_at(std::move(_split_merge_at)), r1(_r1) {} -}; - -extern const ShardDescr t_ShardDescr; - -// -// headers for type `ShardHashes` -// - -struct ShardHashes final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardHashes type_class; - Ref x; // HashmapE 32 ^(BinTree ShardDescr) - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardHashes"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardHashes t_ShardHashes; - -// -// headers for type `BinTreeAug` -// - -struct BinTreeAug final : TLB_Complex { - enum { bta_leaf, bta_fork }; - static constexpr int cons_len_exact = 1; - const TLB &X_, &Y_; - BinTreeAug(const TLB& X, const TLB& Y) : X_(X), Y_(Y) {} - struct Record_bta_leaf { - typedef BinTreeAug type_class; - Ref extra; // extra : Y - Ref leaf; // leaf : X - Record_bta_leaf() = default; - Record_bta_leaf(Ref _extra, Ref _leaf) : extra(std::move(_extra)), leaf(std::move(_leaf)) {} - }; - struct Record_bta_fork; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_bta_leaf& data) const; - bool unpack_bta_leaf(vm::CellSlice& cs, Ref& extra, Ref& leaf) const; - bool cell_unpack(Ref cell_ref, Record_bta_leaf& data) const; - bool cell_unpack_bta_leaf(Ref cell_ref, Ref& extra, Ref& leaf) const; - bool pack(vm::CellBuilder& cb, const Record_bta_leaf& data) const; - bool pack_bta_leaf(vm::CellBuilder& cb, Ref extra, Ref leaf) const; - bool cell_pack(Ref& cell_ref, const Record_bta_leaf& data) const; - bool cell_pack_bta_leaf(Ref& cell_ref, Ref extra, Ref leaf) const; - bool unpack(vm::CellSlice& cs, Record_bta_fork& data) const; - bool unpack_bta_fork(vm::CellSlice& cs, Ref& left, Ref& right, Ref& extra) const; - bool cell_unpack(Ref cell_ref, Record_bta_fork& data) const; - bool cell_unpack_bta_fork(Ref cell_ref, Ref& left, Ref& right, Ref& extra) const; - bool pack(vm::CellBuilder& cb, const Record_bta_fork& data) const; - bool pack_bta_fork(vm::CellBuilder& cb, Ref left, Ref right, Ref extra) const; - bool cell_pack(Ref& cell_ref, const Record_bta_fork& data) const; - bool cell_pack_bta_fork(Ref& cell_ref, Ref left, Ref right, Ref extra) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(BinTreeAug " << X_ << " " << Y_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct BinTreeAug::Record_bta_fork { - typedef BinTreeAug type_class; - Ref left; // left : ^(BinTreeAug X Y) - Ref right; // right : ^(BinTreeAug X Y) - Ref extra; // extra : Y - Record_bta_fork() = default; - Record_bta_fork(Ref _left, Ref _right, Ref _extra) : left(std::move(_left)), right(std::move(_right)), extra(std::move(_extra)) {} -}; - -// -// headers for type `ShardFeeCreated` -// - -struct ShardFeeCreated final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardFeeCreated type_class; - Ref fees; // fees : CurrencyCollection - Ref create; // create : CurrencyCollection - Record() = default; - Record(Ref _fees, Ref _create) : fees(std::move(_fees)), create(std::move(_create)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& fees, Ref& create) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& fees, Ref& create) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref fees, Ref create) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref fees, Ref create) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardFeeCreated"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardFeeCreated t_ShardFeeCreated; - -// -// headers for type `ShardFees` -// - -struct ShardFees final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ShardFees type_class; - Ref x; // HashmapAugE 96 ShardFeeCreated ShardFeeCreated - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ShardFees"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardFees t_ShardFees; - -// -// headers for type `ConfigParams` -// - -struct ConfigParams final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ConfigParams type_class; - td::BitArray<256> config_addr; // config_addr : bits256 - Ref config; // config : ^(Hashmap 32 ^Cell) - Record() = default; - Record(const td::BitArray<256>& _config_addr, Ref _config) : config_addr(_config_addr), config(std::move(_config)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x10100; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10100); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, td::BitArray<256>& config_addr, Ref& config) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, td::BitArray<256>& config_addr, Ref& config) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, td::BitArray<256> config_addr, Ref config) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, td::BitArray<256> config_addr, Ref config) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConfigParams"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ConfigParams t_ConfigParams; - -// -// headers for type `ValidatorInfo` -// - -struct ValidatorInfo final : TLB_Complex { - enum { validator_info }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 65; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(65); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(65); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_validator_info(vm::CellSlice& cs, unsigned& validator_list_hash_short, unsigned& catchain_seqno, bool& nx_cc_updated) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_validator_info(Ref cell_ref, unsigned& validator_list_hash_short, unsigned& catchain_seqno, bool& nx_cc_updated) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_validator_info(vm::CellBuilder& cb, unsigned validator_list_hash_short, unsigned catchain_seqno, bool nx_cc_updated) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_validator_info(Ref& cell_ref, unsigned validator_list_hash_short, unsigned catchain_seqno, bool nx_cc_updated) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValidatorInfo::Record { - typedef ValidatorInfo type_class; - unsigned validator_list_hash_short; // validator_list_hash_short : uint32 - unsigned catchain_seqno; // catchain_seqno : uint32 - bool nx_cc_updated; // nx_cc_updated : Bool - Record() = default; - Record(unsigned _validator_list_hash_short, unsigned _catchain_seqno, bool _nx_cc_updated) : validator_list_hash_short(_validator_list_hash_short), catchain_seqno(_catchain_seqno), nx_cc_updated(_nx_cc_updated) {} -}; - -extern const ValidatorInfo t_ValidatorInfo; - -// -// headers for type `ValidatorBaseInfo` -// - -struct ValidatorBaseInfo final : TLB_Complex { - enum { validator_base_info }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ValidatorBaseInfo type_class; - unsigned validator_list_hash_short; // validator_list_hash_short : uint32 - unsigned catchain_seqno; // catchain_seqno : uint32 - Record() = default; - Record(unsigned _validator_list_hash_short, unsigned _catchain_seqno) : validator_list_hash_short(_validator_list_hash_short), catchain_seqno(_catchain_seqno) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 64; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(64); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(64); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_validator_base_info(vm::CellSlice& cs, unsigned& validator_list_hash_short, unsigned& catchain_seqno) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_validator_base_info(Ref cell_ref, unsigned& validator_list_hash_short, unsigned& catchain_seqno) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_validator_base_info(vm::CellBuilder& cb, unsigned validator_list_hash_short, unsigned catchain_seqno) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_validator_base_info(Ref& cell_ref, unsigned validator_list_hash_short, unsigned catchain_seqno) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorBaseInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ValidatorBaseInfo t_ValidatorBaseInfo; - -// -// headers for type `KeyMaxLt` -// - -struct KeyMaxLt final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef KeyMaxLt type_class; - bool key; // key : Bool - unsigned long long max_end_lt; // max_end_lt : uint64 - Record() = default; - Record(bool _key, unsigned long long _max_end_lt) : key(_key), max_end_lt(_max_end_lt) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 65; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(65); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(65); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, bool& key, unsigned long long& max_end_lt) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, bool& key, unsigned long long& max_end_lt) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, bool key, unsigned long long max_end_lt) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, bool key, unsigned long long max_end_lt) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "KeyMaxLt"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const KeyMaxLt t_KeyMaxLt; - -// -// headers for type `KeyExtBlkRef` -// - -struct KeyExtBlkRef final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef KeyExtBlkRef type_class; - bool key; // key : Bool - Ref blk_ref; // blk_ref : ExtBlkRef - Record() = default; - Record(bool _key, Ref _blk_ref) : key(_key), blk_ref(std::move(_blk_ref)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 609; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(609); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(609); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, bool& key, Ref& blk_ref) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, bool& key, Ref& blk_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, bool key, Ref blk_ref) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, bool key, Ref blk_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "KeyExtBlkRef"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const KeyExtBlkRef t_KeyExtBlkRef; - -// -// headers for type `OldMcBlocksInfo` -// - -struct OldMcBlocksInfo final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef OldMcBlocksInfo type_class; - Ref x; // HashmapAugE 32 KeyExtBlkRef KeyMaxLt - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "OldMcBlocksInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const OldMcBlocksInfo t_OldMcBlocksInfo; - -// -// headers for type `Counters` -// - -struct Counters final : TLB_Complex { - enum { counters }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 224; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(224); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(224); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Counters"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Counters::Record { - typedef Counters type_class; - unsigned last_updated; // last_updated : uint32 - unsigned long long total; // total : uint64 - unsigned long long cnt2048; // cnt2048 : uint64 - unsigned long long cnt65536; // cnt65536 : uint64 - Record() = default; - Record(unsigned _last_updated, unsigned long long _total, unsigned long long _cnt2048, unsigned long long _cnt65536) : last_updated(_last_updated), total(_total), cnt2048(_cnt2048), cnt65536(_cnt65536) {} -}; - -extern const Counters t_Counters; - -// -// headers for type `CreatorStats` -// - -struct CreatorStats final : TLB_Complex { - enum { creator_info }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 4 }; - struct Record { - typedef CreatorStats type_class; - Ref mc_blocks; // mc_blocks : Counters - Ref shard_blocks; // shard_blocks : Counters - Record() = default; - Record(Ref _mc_blocks, Ref _shard_blocks) : mc_blocks(std::move(_mc_blocks)), shard_blocks(std::move(_shard_blocks)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 452; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(452); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_creator_info(vm::CellSlice& cs, Ref& mc_blocks, Ref& shard_blocks) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_creator_info(Ref cell_ref, Ref& mc_blocks, Ref& shard_blocks) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_creator_info(vm::CellBuilder& cb, Ref mc_blocks, Ref shard_blocks) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_creator_info(Ref& cell_ref, Ref mc_blocks, Ref shard_blocks) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CreatorStats"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const CreatorStats t_CreatorStats; - -// -// headers for type `BlockCreateStats` -// - -struct BlockCreateStats final : TLB_Complex { - enum { block_create_stats, block_create_stats_ext }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[2] = { 23, 0x34 }; - struct Record_block_create_stats { - typedef BlockCreateStats type_class; - Ref counters; // counters : HashmapE 256 CreatorStats - Record_block_create_stats() = default; - Record_block_create_stats(Ref _counters) : counters(std::move(_counters)) {} - }; - struct Record_block_create_stats_ext { - typedef BlockCreateStats type_class; - Ref counters; // counters : HashmapAugE 256 CreatorStats uint32 - Record_block_create_stats_ext() = default; - Record_block_create_stats_ext(Ref _counters) : counters(std::move(_counters)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_block_create_stats& data) const; - bool unpack_block_create_stats(vm::CellSlice& cs, Ref& counters) const; - bool cell_unpack(Ref cell_ref, Record_block_create_stats& data) const; - bool cell_unpack_block_create_stats(Ref cell_ref, Ref& counters) const; - bool pack(vm::CellBuilder& cb, const Record_block_create_stats& data) const; - bool pack_block_create_stats(vm::CellBuilder& cb, Ref counters) const; - bool cell_pack(Ref& cell_ref, const Record_block_create_stats& data) const; - bool cell_pack_block_create_stats(Ref& cell_ref, Ref counters) const; - bool unpack(vm::CellSlice& cs, Record_block_create_stats_ext& data) const; - bool unpack_block_create_stats_ext(vm::CellSlice& cs, Ref& counters) const; - bool cell_unpack(Ref cell_ref, Record_block_create_stats_ext& data) const; - bool cell_unpack_block_create_stats_ext(Ref cell_ref, Ref& counters) const; - bool pack(vm::CellBuilder& cb, const Record_block_create_stats_ext& data) const; - bool pack_block_create_stats_ext(vm::CellBuilder& cb, Ref counters) const; - bool cell_pack(Ref& cell_ref, const Record_block_create_stats_ext& data) const; - bool cell_pack_block_create_stats_ext(Ref& cell_ref, Ref counters) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockCreateStats"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(3, 3); - } -}; - -extern const BlockCreateStats t_BlockCreateStats; - -// -// headers for auxiliary type `McStateExtra_aux` -// - -struct McStateExtra_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "McStateExtra_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct McStateExtra_aux::Record { - typedef McStateExtra_aux type_class; - int flags; // flags : ## 16 - Ref validator_info; // validator_info : ValidatorInfo - Ref prev_blocks; // prev_blocks : OldMcBlocksInfo - bool after_key_block; // after_key_block : Bool - Ref last_key_block; // last_key_block : Maybe ExtBlkRef - Ref block_create_stats; // block_create_stats : flags.0?BlockCreateStats - Record() = default; - Record(int _flags, Ref _validator_info, Ref _prev_blocks, bool _after_key_block, Ref _last_key_block, Ref _block_create_stats) : flags(_flags), validator_info(std::move(_validator_info)), prev_blocks(std::move(_prev_blocks)), after_key_block(_after_key_block), last_key_block(std::move(_last_key_block)), block_create_stats(std::move(_block_create_stats)) {} -}; - -extern const McStateExtra_aux t_McStateExtra_aux; - -// -// headers for type `McStateExtra` -// - -struct McStateExtra final : TLB_Complex { - enum { masterchain_state_extra }; - static constexpr int cons_len_exact = 16; - static constexpr unsigned short cons_tag[1] = { 0xcc26 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "McStateExtra"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct McStateExtra::Record { - typedef McStateExtra type_class; - Ref shard_hashes; // shard_hashes : ShardHashes - Ref config; // config : ConfigParams - McStateExtra_aux::Record r1; // ^[$_ flags:(## 16) {<= flags 1} validator_info:ValidatorInfo prev_blocks:OldMcBlocksInfo after_key_block:Bool last_key_block:(Maybe ExtBlkRef) block_create_stats:flags.0?BlockCreateStats ] - Ref global_balance; // global_balance : CurrencyCollection - Record() = default; - Record(Ref _shard_hashes, Ref _config, const McStateExtra_aux::Record& _r1, Ref _global_balance) : shard_hashes(std::move(_shard_hashes)), config(std::move(_config)), r1(_r1), global_balance(std::move(_global_balance)) {} -}; - -extern const McStateExtra t_McStateExtra; - -// -// headers for type `SigPubKey` -// - -struct SigPubKey final : TLB_Complex { - enum { ed25519_pubkey }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x8e81278aU }; - struct Record { - typedef SigPubKey type_class; - td::BitArray<256> pubkey; // pubkey : bits256 - Record() = default; - Record(const td::BitArray<256>& _pubkey) : pubkey(_pubkey) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 288; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(288); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_ed25519_pubkey(vm::CellSlice& cs, td::BitArray<256>& pubkey) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_ed25519_pubkey(Ref cell_ref, td::BitArray<256>& pubkey) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_ed25519_pubkey(vm::CellBuilder& cb, td::BitArray<256> pubkey) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_ed25519_pubkey(Ref& cell_ref, td::BitArray<256> pubkey) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SigPubKey"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const SigPubKey t_SigPubKey; - -// -// headers for type `CryptoSignatureSimple` -// - -struct CryptoSignatureSimple final : TLB_Complex { - enum { ed25519_signature }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 5 }; - struct Record { - typedef CryptoSignatureSimple type_class; - td::BitArray<256> R; // R : bits256 - td::BitArray<256> s; // s : bits256 - Record() = default; - Record(const td::BitArray<256>& _R, const td::BitArray<256>& _s) : R(_R), s(_s) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 516; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(516); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_ed25519_signature(vm::CellSlice& cs, td::BitArray<256>& R, td::BitArray<256>& s) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_ed25519_signature(Ref cell_ref, td::BitArray<256>& R, td::BitArray<256>& s) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_ed25519_signature(vm::CellBuilder& cb, td::BitArray<256> R, td::BitArray<256> s) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_ed25519_signature(Ref& cell_ref, td::BitArray<256> R, td::BitArray<256> s) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CryptoSignatureSimple"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const CryptoSignatureSimple t_CryptoSignatureSimple; - -// -// headers for type `CryptoSignaturePair` -// - -struct CryptoSignaturePair final : TLB_Complex { - enum { sig_pair }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef CryptoSignaturePair type_class; - td::BitArray<256> node_id_short; // node_id_short : bits256 - Ref sign; // sign : CryptoSignature - Record() = default; - Record(const td::BitArray<256>& _node_id_short, Ref _sign) : node_id_short(_node_id_short), sign(std::move(_sign)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_sig_pair(vm::CellSlice& cs, td::BitArray<256>& node_id_short, Ref& sign) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_sig_pair(Ref cell_ref, td::BitArray<256>& node_id_short, Ref& sign) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_sig_pair(vm::CellBuilder& cb, td::BitArray<256> node_id_short, Ref sign) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_sig_pair(Ref& cell_ref, td::BitArray<256> node_id_short, Ref sign) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CryptoSignaturePair"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const CryptoSignaturePair t_CryptoSignaturePair; - -// -// headers for type `Certificate` -// - -struct Certificate final : TLB_Complex { - enum { certificate }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 4 }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 356; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(356); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_certificate(vm::CellSlice& cs, Ref& temp_key, unsigned& valid_since, unsigned& valid_until) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_certificate(Ref cell_ref, Ref& temp_key, unsigned& valid_since, unsigned& valid_until) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_certificate(vm::CellBuilder& cb, Ref temp_key, unsigned valid_since, unsigned valid_until) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_certificate(Ref& cell_ref, Ref temp_key, unsigned valid_since, unsigned valid_until) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Certificate"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct Certificate::Record { - typedef Certificate type_class; - Ref temp_key; // temp_key : SigPubKey - unsigned valid_since; // valid_since : uint32 - unsigned valid_until; // valid_until : uint32 - Record() = default; - Record(Ref _temp_key, unsigned _valid_since, unsigned _valid_until) : temp_key(std::move(_temp_key)), valid_since(_valid_since), valid_until(_valid_until) {} -}; - -extern const Certificate t_Certificate; - -// -// headers for type `CertificateEnv` -// - -struct CertificateEnv final : TLB_Complex { - enum { certificate_env }; - static constexpr int cons_len_exact = 28; - static constexpr unsigned cons_tag[1] = { 0xa419b7d }; - struct Record { - typedef CertificateEnv type_class; - Ref certificate; // certificate : Certificate - Record() = default; - Record(Ref _certificate) : certificate(std::move(_certificate)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 384; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(384); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_certificate_env(vm::CellSlice& cs, Ref& certificate) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_certificate_env(Ref cell_ref, Ref& certificate) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_certificate_env(vm::CellBuilder& cb, Ref certificate) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_certificate_env(Ref& cell_ref, Ref certificate) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CertificateEnv"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const CertificateEnv t_CertificateEnv; - -// -// headers for type `SignedCertificate` -// - -struct SignedCertificate final : TLB_Complex { - enum { signed_certificate }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef SignedCertificate type_class; - Ref certificate; // certificate : Certificate - Ref certificate_signature; // certificate_signature : CryptoSignature - Record() = default; - Record(Ref _certificate, Ref _certificate_signature) : certificate(std::move(_certificate)), certificate_signature(std::move(_certificate_signature)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_signed_certificate(vm::CellSlice& cs, Ref& certificate, Ref& certificate_signature) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_signed_certificate(Ref cell_ref, Ref& certificate, Ref& certificate_signature) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_signed_certificate(vm::CellBuilder& cb, Ref certificate, Ref certificate_signature) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_signed_certificate(Ref& cell_ref, Ref certificate, Ref certificate_signature) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SignedCertificate"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const SignedCertificate t_SignedCertificate; - -// -// headers for type `CryptoSignature` -// - -struct CryptoSignature final : TLB_Complex { - enum { cons1, chained_signature }; - static constexpr char cons_len[2] = { 0, 4 }; - static constexpr unsigned char cons_tag[2] = { 0, 15 }; - struct Record_cons1 { - typedef CryptoSignature type_class; - Ref x; // CryptoSignatureSimple - Record_cons1() = default; - Record_cons1(Ref _x) : x(std::move(_x)) {} - }; - struct Record_chained_signature { - typedef CryptoSignature type_class; - Ref signed_cert; // signed_cert : ^SignedCertificate - Ref temp_key_signature; // temp_key_signature : CryptoSignatureSimple - Record_chained_signature() = default; - Record_chained_signature(Ref _signed_cert, Ref _temp_key_signature) : signed_cert(std::move(_signed_cert)), temp_key_signature(std::move(_temp_key_signature)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cons1& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons1& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons1& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons1& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_chained_signature& data) const; - bool unpack_chained_signature(vm::CellSlice& cs, Ref& signed_cert, Ref& temp_key_signature) const; - bool cell_unpack(Ref cell_ref, Record_chained_signature& data) const; - bool cell_unpack_chained_signature(Ref cell_ref, Ref& signed_cert, Ref& temp_key_signature) const; - bool pack(vm::CellBuilder& cb, const Record_chained_signature& data) const; - bool pack_chained_signature(vm::CellBuilder& cb, Ref signed_cert, Ref temp_key_signature) const; - bool cell_pack(Ref& cell_ref, const Record_chained_signature& data) const; - bool cell_pack_chained_signature(Ref& cell_ref, Ref signed_cert, Ref temp_key_signature) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CryptoSignature"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const CryptoSignature t_CryptoSignature; - -// -// headers for auxiliary type `McBlockExtra_aux` -// - -struct McBlockExtra_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& prev_blk_signatures, Ref& recover_create_msg, Ref& mint_msg) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& prev_blk_signatures, Ref& recover_create_msg, Ref& mint_msg) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref prev_blk_signatures, Ref recover_create_msg, Ref mint_msg) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref prev_blk_signatures, Ref recover_create_msg, Ref mint_msg) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "McBlockExtra_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct McBlockExtra_aux::Record { - typedef McBlockExtra_aux type_class; - Ref prev_blk_signatures; // prev_blk_signatures : HashmapE 16 CryptoSignaturePair - Ref recover_create_msg; // recover_create_msg : Maybe ^InMsg - Ref mint_msg; // mint_msg : Maybe ^InMsg - Record() = default; - Record(Ref _prev_blk_signatures, Ref _recover_create_msg, Ref _mint_msg) : prev_blk_signatures(std::move(_prev_blk_signatures)), recover_create_msg(std::move(_recover_create_msg)), mint_msg(std::move(_mint_msg)) {} -}; - -extern const McBlockExtra_aux t_McBlockExtra_aux; - -// -// headers for type `McBlockExtra` -// - -struct McBlockExtra final : TLB_Complex { - enum { masterchain_block_extra }; - static constexpr int cons_len_exact = 16; - static constexpr unsigned short cons_tag[1] = { 0xcca5 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "McBlockExtra"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct McBlockExtra::Record { - typedef McBlockExtra type_class; - bool key_block; // key_block : ## 1 - Ref shard_hashes; // shard_hashes : ShardHashes - Ref shard_fees; // shard_fees : ShardFees - McBlockExtra_aux::Record r1; // ^[$_ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair) recover_create_msg:(Maybe ^InMsg) mint_msg:(Maybe ^InMsg) ] - Ref config; // config : key_block?ConfigParams - Record() = default; - Record(bool _key_block, Ref _shard_hashes, Ref _shard_fees, const McBlockExtra_aux::Record& _r1, Ref _config) : key_block(_key_block), shard_hashes(std::move(_shard_hashes)), shard_fees(std::move(_shard_fees)), r1(_r1), config(std::move(_config)) {} -}; - -extern const McBlockExtra t_McBlockExtra; - -// -// headers for type `ValidatorDescr` -// - -struct ValidatorDescr final : TLB_Complex { - enum { validator, validator_addr }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[2] = { 0x53, 0x73 }; - struct Record_validator { - typedef ValidatorDescr type_class; - Ref public_key; // public_key : SigPubKey - unsigned long long weight; // weight : uint64 - Record_validator() = default; - Record_validator(Ref _public_key, unsigned long long _weight) : public_key(std::move(_public_key)), weight(_weight) {} - }; - struct Record_validator_addr; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_validator& data) const; - bool unpack_validator(vm::CellSlice& cs, Ref& public_key, unsigned long long& weight) const; - bool cell_unpack(Ref cell_ref, Record_validator& data) const; - bool cell_unpack_validator(Ref cell_ref, Ref& public_key, unsigned long long& weight) const; - bool pack(vm::CellBuilder& cb, const Record_validator& data) const; - bool pack_validator(vm::CellBuilder& cb, Ref public_key, unsigned long long weight) const; - bool cell_pack(Ref& cell_ref, const Record_validator& data) const; - bool cell_pack_validator(Ref& cell_ref, Ref public_key, unsigned long long weight) const; - bool unpack(vm::CellSlice& cs, Record_validator_addr& data) const; - bool unpack_validator_addr(vm::CellSlice& cs, Ref& public_key, unsigned long long& weight, td::BitArray<256>& adnl_addr) const; - bool cell_unpack(Ref cell_ref, Record_validator_addr& data) const; - bool cell_unpack_validator_addr(Ref cell_ref, Ref& public_key, unsigned long long& weight, td::BitArray<256>& adnl_addr) const; - bool pack(vm::CellBuilder& cb, const Record_validator_addr& data) const; - bool pack_validator_addr(vm::CellBuilder& cb, Ref public_key, unsigned long long weight, td::BitArray<256> adnl_addr) const; - bool cell_pack(Ref& cell_ref, const Record_validator_addr& data) const; - bool cell_pack_validator_addr(Ref& cell_ref, Ref public_key, unsigned long long weight, td::BitArray<256> adnl_addr) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(3, 12); - } -}; - -struct ValidatorDescr::Record_validator_addr { - typedef ValidatorDescr type_class; - Ref public_key; // public_key : SigPubKey - unsigned long long weight; // weight : uint64 - td::BitArray<256> adnl_addr; // adnl_addr : bits256 - Record_validator_addr() = default; - Record_validator_addr(Ref _public_key, unsigned long long _weight, const td::BitArray<256>& _adnl_addr) : public_key(std::move(_public_key)), weight(_weight), adnl_addr(_adnl_addr) {} -}; - -extern const ValidatorDescr t_ValidatorDescr; - -// -// headers for type `ValidatorSet` -// - -struct ValidatorSet final : TLB_Complex { - enum { validators, validators_ext }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[2] = { 17, 18 }; - struct Record_validators; - struct Record_validators_ext; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_validators& data) const; - bool cell_unpack(Ref cell_ref, Record_validators& data) const; - bool pack(vm::CellBuilder& cb, const Record_validators& data) const; - bool cell_pack(Ref& cell_ref, const Record_validators& data) const; - bool unpack(vm::CellSlice& cs, Record_validators_ext& data) const; - bool cell_unpack(Ref cell_ref, Record_validators_ext& data) const; - bool pack(vm::CellBuilder& cb, const Record_validators_ext& data) const; - bool cell_pack(Ref& cell_ref, const Record_validators_ext& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorSet"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct ValidatorSet::Record_validators { - typedef ValidatorSet type_class; - unsigned utime_since; // utime_since : uint32 - unsigned utime_until; // utime_until : uint32 - int total; // total : ## 16 - int main; // main : ## 16 - Ref list; // list : Hashmap 16 ValidatorDescr - Record_validators() = default; - Record_validators(unsigned _utime_since, unsigned _utime_until, int _total, int _main, Ref _list) : utime_since(_utime_since), utime_until(_utime_until), total(_total), main(_main), list(std::move(_list)) {} -}; - -struct ValidatorSet::Record_validators_ext { - typedef ValidatorSet type_class; - unsigned utime_since; // utime_since : uint32 - unsigned utime_until; // utime_until : uint32 - int total; // total : ## 16 - int main; // main : ## 16 - unsigned long long total_weight; // total_weight : uint64 - Ref list; // list : HashmapE 16 ValidatorDescr - Record_validators_ext() = default; - Record_validators_ext(unsigned _utime_since, unsigned _utime_until, int _total, int _main, unsigned long long _total_weight, Ref _list) : utime_since(_utime_since), utime_until(_utime_until), total(_total), main(_main), total_weight(_total_weight), list(std::move(_list)) {} -}; - -extern const ValidatorSet t_ValidatorSet; - -// -// headers for type `GlobalVersion` -// - -struct GlobalVersion final : TLB_Complex { - enum { capabilities }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xc4 }; - struct Record { - typedef GlobalVersion type_class; - unsigned version; // version : uint32 - unsigned long long capabilities; // capabilities : uint64 - Record() = default; - Record(unsigned _version, unsigned long long _capabilities) : version(_version), capabilities(_capabilities) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 104; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(104); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_capabilities(vm::CellSlice& cs, unsigned& version, unsigned long long& capabilities) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_capabilities(Ref cell_ref, unsigned& version, unsigned long long& capabilities) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_capabilities(vm::CellBuilder& cb, unsigned version, unsigned long long capabilities) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_capabilities(Ref& cell_ref, unsigned version, unsigned long long capabilities) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "GlobalVersion"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const GlobalVersion t_GlobalVersion; - -// -// headers for type `ConfigProposalSetup` -// - -struct ConfigProposalSetup final : TLB_Complex { - enum { cfg_vote_cfg }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x36 }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 168; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(168); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConfigProposalSetup"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ConfigProposalSetup::Record { - typedef ConfigProposalSetup type_class; - int min_tot_rounds; // min_tot_rounds : uint8 - int max_tot_rounds; // max_tot_rounds : uint8 - int min_wins; // min_wins : uint8 - int max_losses; // max_losses : uint8 - unsigned min_store_sec; // min_store_sec : uint32 - unsigned max_store_sec; // max_store_sec : uint32 - unsigned bit_price; // bit_price : uint32 - unsigned cell_price; // cell_price : uint32 - Record() = default; - Record(int _min_tot_rounds, int _max_tot_rounds, int _min_wins, int _max_losses, unsigned _min_store_sec, unsigned _max_store_sec, unsigned _bit_price, unsigned _cell_price) : min_tot_rounds(_min_tot_rounds), max_tot_rounds(_max_tot_rounds), min_wins(_min_wins), max_losses(_max_losses), min_store_sec(_min_store_sec), max_store_sec(_max_store_sec), bit_price(_bit_price), cell_price(_cell_price) {} -}; - -extern const ConfigProposalSetup t_ConfigProposalSetup; - -// -// headers for type `ConfigVotingSetup` -// - -struct ConfigVotingSetup final : TLB_Complex { - enum { cfg_vote_setup }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x91 }; - struct Record { - typedef ConfigVotingSetup type_class; - Ref normal_params; // normal_params : ^ConfigProposalSetup - Ref critical_params; // critical_params : ^ConfigProposalSetup - Record() = default; - Record(Ref _normal_params, Ref _critical_params) : normal_params(std::move(_normal_params)), critical_params(std::move(_critical_params)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x20008; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x20008); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cfg_vote_setup(vm::CellSlice& cs, Ref& normal_params, Ref& critical_params) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cfg_vote_setup(Ref cell_ref, Ref& normal_params, Ref& critical_params) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cfg_vote_setup(vm::CellBuilder& cb, Ref normal_params, Ref critical_params) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cfg_vote_setup(Ref& cell_ref, Ref normal_params, Ref critical_params) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConfigVotingSetup"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ConfigVotingSetup t_ConfigVotingSetup; - -// -// headers for type `ConfigProposal` -// - -struct ConfigProposal final : TLB_Complex { - enum { cfg_proposal }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xf3 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cfg_proposal(vm::CellSlice& cs, int& param_id, Ref& param_value, Ref& if_hash_equal) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cfg_proposal(Ref cell_ref, int& param_id, Ref& param_value, Ref& if_hash_equal) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cfg_proposal(vm::CellBuilder& cb, int param_id, Ref param_value, Ref if_hash_equal) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cfg_proposal(Ref& cell_ref, int param_id, Ref param_value, Ref if_hash_equal) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConfigProposal"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ConfigProposal::Record { - typedef ConfigProposal type_class; - int param_id; // param_id : int32 - Ref param_value; // param_value : Maybe ^Cell - Ref if_hash_equal; // if_hash_equal : Maybe uint256 - Record() = default; - Record(int _param_id, Ref _param_value, Ref _if_hash_equal) : param_id(_param_id), param_value(std::move(_param_value)), if_hash_equal(std::move(_if_hash_equal)) {} -}; - -extern const ConfigProposal t_ConfigProposal; - -// -// headers for type `ConfigProposalStatus` -// - -struct ConfigProposalStatus final : TLB_Complex { - enum { cfg_proposal_status }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xce }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConfigProposalStatus"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ConfigProposalStatus::Record { - typedef ConfigProposalStatus type_class; - unsigned expires; // expires : uint32 - Ref proposal; // proposal : ^ConfigProposal - bool is_critical; // is_critical : Bool - Ref voters; // voters : HashmapE 16 True - long long remaining_weight; // remaining_weight : int64 - RefInt256 validator_set_id; // validator_set_id : uint256 - int rounds_remaining; // rounds_remaining : uint8 - int wins; // wins : uint8 - int losses; // losses : uint8 - Record() = default; - Record(unsigned _expires, Ref _proposal, bool _is_critical, Ref _voters, long long _remaining_weight, RefInt256 _validator_set_id, int _rounds_remaining, int _wins, int _losses) : expires(_expires), proposal(std::move(_proposal)), is_critical(_is_critical), voters(std::move(_voters)), remaining_weight(_remaining_weight), validator_set_id(std::move(_validator_set_id)), rounds_remaining(_rounds_remaining), wins(_wins), losses(_losses) {} -}; - -extern const ConfigProposalStatus t_ConfigProposalStatus; - -// -// headers for type `WorkchainFormat` -// - -struct WorkchainFormat final : TLB_Complex { - enum { wfmt_ext, wfmt_basic }; - static constexpr int cons_len_exact = 4; - int m_; - WorkchainFormat(int m) : m_(m) {} - struct Record_wfmt_basic { - typedef WorkchainFormat type_class; - int vm_version; // vm_version : int32 - unsigned long long vm_mode; // vm_mode : uint64 - Record_wfmt_basic() = default; - Record_wfmt_basic(int _vm_version, unsigned long long _vm_mode) : vm_version(_vm_version), vm_mode(_vm_mode) {} - }; - struct Record_wfmt_ext; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_wfmt_basic& data) const; - bool unpack_wfmt_basic(vm::CellSlice& cs, int& vm_version, unsigned long long& vm_mode) const; - bool cell_unpack(Ref cell_ref, Record_wfmt_basic& data) const; - bool cell_unpack_wfmt_basic(Ref cell_ref, int& vm_version, unsigned long long& vm_mode) const; - bool pack(vm::CellBuilder& cb, const Record_wfmt_basic& data) const; - bool pack_wfmt_basic(vm::CellBuilder& cb, int vm_version, unsigned long long vm_mode) const; - bool cell_pack(Ref& cell_ref, const Record_wfmt_basic& data) const; - bool cell_pack_wfmt_basic(Ref& cell_ref, int vm_version, unsigned long long vm_mode) const; - bool unpack(vm::CellSlice& cs, Record_wfmt_ext& data) const; - bool cell_unpack(Ref cell_ref, Record_wfmt_ext& data) const; - bool pack(vm::CellBuilder& cb, const Record_wfmt_ext& data) const; - bool cell_pack(Ref& cell_ref, const Record_wfmt_ext& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(WorkchainFormat " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 3); - } -}; - -struct WorkchainFormat::Record_wfmt_ext { - typedef WorkchainFormat type_class; - int min_addr_len; // min_addr_len : ## 12 - int max_addr_len; // max_addr_len : ## 12 - int addr_len_step; // addr_len_step : ## 12 - int workchain_type_id; // workchain_type_id : ## 32 - Record_wfmt_ext() = default; - Record_wfmt_ext(int _min_addr_len, int _max_addr_len, int _addr_len_step, int _workchain_type_id) : min_addr_len(_min_addr_len), max_addr_len(_max_addr_len), addr_len_step(_addr_len_step), workchain_type_id(_workchain_type_id) {} -}; - -// -// headers for type `WorkchainDescr` -// - -struct WorkchainDescr final : TLB_Complex { - enum { workchain }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xa6 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "WorkchainDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct WorkchainDescr::Record { - typedef WorkchainDescr type_class; - unsigned enabled_since; // enabled_since : uint32 - int actual_min_split; // actual_min_split : ## 8 - int min_split; // min_split : ## 8 - int max_split; // max_split : ## 8 - bool basic; // basic : ## 1 - bool active; // active : Bool - bool accept_msgs; // accept_msgs : Bool - int flags; // flags : ## 13 - td::BitArray<256> zerostate_root_hash; // zerostate_root_hash : bits256 - td::BitArray<256> zerostate_file_hash; // zerostate_file_hash : bits256 - unsigned version; // version : uint32 - Ref format; // format : WorkchainFormat basic - Record() = default; - Record(unsigned _enabled_since, int _actual_min_split, int _min_split, int _max_split, bool _basic, bool _active, bool _accept_msgs, int _flags, const td::BitArray<256>& _zerostate_root_hash, const td::BitArray<256>& _zerostate_file_hash, unsigned _version, Ref _format) : enabled_since(_enabled_since), actual_min_split(_actual_min_split), min_split(_min_split), max_split(_max_split), basic(_basic), active(_active), accept_msgs(_accept_msgs), flags(_flags), zerostate_root_hash(_zerostate_root_hash), zerostate_file_hash(_zerostate_file_hash), version(_version), format(std::move(_format)) {} -}; - -extern const WorkchainDescr t_WorkchainDescr; - -// -// headers for type `ComplaintPricing` -// - -struct ComplaintPricing final : TLB_Complex { - enum { complaint_prices }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 26 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_complaint_prices(vm::CellSlice& cs, Ref& deposit, Ref& bit_price, Ref& cell_price) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_complaint_prices(Ref cell_ref, Ref& deposit, Ref& bit_price, Ref& cell_price) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_complaint_prices(vm::CellBuilder& cb, Ref deposit, Ref bit_price, Ref cell_price) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_complaint_prices(Ref& cell_ref, Ref deposit, Ref bit_price, Ref cell_price) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ComplaintPricing"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ComplaintPricing::Record { - typedef ComplaintPricing type_class; - Ref deposit; // deposit : Grams - Ref bit_price; // bit_price : Grams - Ref cell_price; // cell_price : Grams - Record() = default; - Record(Ref _deposit, Ref _bit_price, Ref _cell_price) : deposit(std::move(_deposit)), bit_price(std::move(_bit_price)), cell_price(std::move(_cell_price)) {} -}; - -extern const ComplaintPricing t_ComplaintPricing; - -// -// headers for type `BlockCreateFees` -// - -struct BlockCreateFees final : TLB_Complex { - enum { block_grams_created }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x6b }; - struct Record { - typedef BlockCreateFees type_class; - Ref masterchain_block_fee; // masterchain_block_fee : Grams - Ref basechain_block_fee; // basechain_block_fee : Grams - Record() = default; - Record(Ref _masterchain_block_fee, Ref _basechain_block_fee) : masterchain_block_fee(std::move(_masterchain_block_fee)), basechain_block_fee(std::move(_basechain_block_fee)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_block_grams_created(vm::CellSlice& cs, Ref& masterchain_block_fee, Ref& basechain_block_fee) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_block_grams_created(Ref cell_ref, Ref& masterchain_block_fee, Ref& basechain_block_fee) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_block_grams_created(vm::CellBuilder& cb, Ref masterchain_block_fee, Ref basechain_block_fee) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_block_grams_created(Ref& cell_ref, Ref masterchain_block_fee, Ref basechain_block_fee) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockCreateFees"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const BlockCreateFees t_BlockCreateFees; - -// -// headers for type `StoragePrices` -// - -struct StoragePrices final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xcc }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 296; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(296); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "StoragePrices"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct StoragePrices::Record { - typedef StoragePrices type_class; - unsigned utime_since; // utime_since : uint32 - unsigned long long bit_price_ps; // bit_price_ps : uint64 - unsigned long long cell_price_ps; // cell_price_ps : uint64 - unsigned long long mc_bit_price_ps; // mc_bit_price_ps : uint64 - unsigned long long mc_cell_price_ps; // mc_cell_price_ps : uint64 - Record() = default; - Record(unsigned _utime_since, unsigned long long _bit_price_ps, unsigned long long _cell_price_ps, unsigned long long _mc_bit_price_ps, unsigned long long _mc_cell_price_ps) : utime_since(_utime_since), bit_price_ps(_bit_price_ps), cell_price_ps(_cell_price_ps), mc_bit_price_ps(_mc_bit_price_ps), mc_cell_price_ps(_mc_cell_price_ps) {} -}; - -extern const StoragePrices t_StoragePrices; - -// -// headers for type `GasLimitsPrices` -// - -struct GasLimitsPrices final : TLB_Complex { - enum { gas_flat_pfx, gas_prices, gas_prices_ext }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[3] = { 0xd1, 0xdd, 0xde }; - struct Record_gas_prices; - struct Record_gas_prices_ext; - struct Record_gas_flat_pfx; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_gas_prices& data) const; - bool cell_unpack(Ref cell_ref, Record_gas_prices& data) const; - bool pack(vm::CellBuilder& cb, const Record_gas_prices& data) const; - bool cell_pack(Ref& cell_ref, const Record_gas_prices& data) const; - bool unpack(vm::CellSlice& cs, Record_gas_prices_ext& data) const; - bool cell_unpack(Ref cell_ref, Record_gas_prices_ext& data) const; - bool pack(vm::CellBuilder& cb, const Record_gas_prices_ext& data) const; - bool cell_pack(Ref& cell_ref, const Record_gas_prices_ext& data) const; - bool unpack(vm::CellSlice& cs, Record_gas_flat_pfx& data) const; - bool unpack_gas_flat_pfx(vm::CellSlice& cs, unsigned long long& flat_gas_limit, unsigned long long& flat_gas_price, Ref& other) const; - bool cell_unpack(Ref cell_ref, Record_gas_flat_pfx& data) const; - bool cell_unpack_gas_flat_pfx(Ref cell_ref, unsigned long long& flat_gas_limit, unsigned long long& flat_gas_price, Ref& other) const; - bool pack(vm::CellBuilder& cb, const Record_gas_flat_pfx& data) const; - bool pack_gas_flat_pfx(vm::CellBuilder& cb, unsigned long long flat_gas_limit, unsigned long long flat_gas_price, Ref other) const; - bool cell_pack(Ref& cell_ref, const Record_gas_flat_pfx& data) const; - bool cell_pack_gas_flat_pfx(Ref& cell_ref, unsigned long long flat_gas_limit, unsigned long long flat_gas_price, Ref other) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "GasLimitsPrices"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct GasLimitsPrices::Record_gas_prices { - typedef GasLimitsPrices type_class; - unsigned long long gas_price; // gas_price : uint64 - unsigned long long gas_limit; // gas_limit : uint64 - unsigned long long gas_credit; // gas_credit : uint64 - unsigned long long block_gas_limit; // block_gas_limit : uint64 - unsigned long long freeze_due_limit; // freeze_due_limit : uint64 - unsigned long long delete_due_limit; // delete_due_limit : uint64 - Record_gas_prices() = default; - Record_gas_prices(unsigned long long _gas_price, unsigned long long _gas_limit, unsigned long long _gas_credit, unsigned long long _block_gas_limit, unsigned long long _freeze_due_limit, unsigned long long _delete_due_limit) : gas_price(_gas_price), gas_limit(_gas_limit), gas_credit(_gas_credit), block_gas_limit(_block_gas_limit), freeze_due_limit(_freeze_due_limit), delete_due_limit(_delete_due_limit) {} -}; - -struct GasLimitsPrices::Record_gas_prices_ext { - typedef GasLimitsPrices type_class; - unsigned long long gas_price; // gas_price : uint64 - unsigned long long gas_limit; // gas_limit : uint64 - unsigned long long special_gas_limit; // special_gas_limit : uint64 - unsigned long long gas_credit; // gas_credit : uint64 - unsigned long long block_gas_limit; // block_gas_limit : uint64 - unsigned long long freeze_due_limit; // freeze_due_limit : uint64 - unsigned long long delete_due_limit; // delete_due_limit : uint64 - Record_gas_prices_ext() = default; - Record_gas_prices_ext(unsigned long long _gas_price, unsigned long long _gas_limit, unsigned long long _special_gas_limit, unsigned long long _gas_credit, unsigned long long _block_gas_limit, unsigned long long _freeze_due_limit, unsigned long long _delete_due_limit) : gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_special_gas_limit), gas_credit(_gas_credit), block_gas_limit(_block_gas_limit), freeze_due_limit(_freeze_due_limit), delete_due_limit(_delete_due_limit) {} -}; - -struct GasLimitsPrices::Record_gas_flat_pfx { - typedef GasLimitsPrices type_class; - unsigned long long flat_gas_limit; // flat_gas_limit : uint64 - unsigned long long flat_gas_price; // flat_gas_price : uint64 - Ref other; // other : GasLimitsPrices - Record_gas_flat_pfx() = default; - Record_gas_flat_pfx(unsigned long long _flat_gas_limit, unsigned long long _flat_gas_price, Ref _other) : flat_gas_limit(_flat_gas_limit), flat_gas_price(_flat_gas_price), other(std::move(_other)) {} -}; - -extern const GasLimitsPrices t_GasLimitsPrices; - -// -// headers for type `ParamLimits` -// - -struct ParamLimits final : TLB_Complex { - enum { param_limits }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xc3 }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 104; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(104); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_param_limits(vm::CellSlice& cs, int& underload, int& soft_limit, int& hard_limit) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_param_limits(Ref cell_ref, int& underload, int& soft_limit, int& hard_limit) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_param_limits(vm::CellBuilder& cb, int underload, int soft_limit, int hard_limit) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_param_limits(Ref& cell_ref, int underload, int soft_limit, int hard_limit) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ParamLimits"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ParamLimits::Record { - typedef ParamLimits type_class; - int underload; // underload : # - int soft_limit; // soft_limit : # - int hard_limit; // hard_limit : # - Record() = default; - Record(int _underload, int _soft_limit, int _hard_limit) : underload(_underload), soft_limit(_soft_limit), hard_limit(_hard_limit) {} -}; - -extern const ParamLimits t_ParamLimits; - -// -// headers for type `BlockLimits` -// - -struct BlockLimits final : TLB_Complex { - enum { block_limits }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x5d }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 320; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(320); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_block_limits(vm::CellSlice& cs, Ref& bytes, Ref& gas, Ref& lt_delta) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_block_limits(Ref cell_ref, Ref& bytes, Ref& gas, Ref& lt_delta) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_block_limits(vm::CellBuilder& cb, Ref bytes, Ref gas, Ref lt_delta) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_block_limits(Ref& cell_ref, Ref bytes, Ref gas, Ref lt_delta) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockLimits"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockLimits::Record { - typedef BlockLimits type_class; - Ref bytes; // bytes : ParamLimits - Ref gas; // gas : ParamLimits - Ref lt_delta; // lt_delta : ParamLimits - Record() = default; - Record(Ref _bytes, Ref _gas, Ref _lt_delta) : bytes(std::move(_bytes)), gas(std::move(_gas)), lt_delta(std::move(_lt_delta)) {} -}; - -extern const BlockLimits t_BlockLimits; - -// -// headers for type `MsgForwardPrices` -// - -struct MsgForwardPrices final : TLB_Complex { - enum { msg_forward_prices }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xea }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 264; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(264); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "MsgForwardPrices"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct MsgForwardPrices::Record { - typedef MsgForwardPrices type_class; - unsigned long long lump_price; // lump_price : uint64 - unsigned long long bit_price; // bit_price : uint64 - unsigned long long cell_price; // cell_price : uint64 - unsigned ihr_price_factor; // ihr_price_factor : uint32 - int first_frac; // first_frac : uint16 - int next_frac; // next_frac : uint16 - Record() = default; - Record(unsigned long long _lump_price, unsigned long long _bit_price, unsigned long long _cell_price, unsigned _ihr_price_factor, int _first_frac, int _next_frac) : lump_price(_lump_price), bit_price(_bit_price), cell_price(_cell_price), ihr_price_factor(_ihr_price_factor), first_frac(_first_frac), next_frac(_next_frac) {} -}; - -extern const MsgForwardPrices t_MsgForwardPrices; - -// -// headers for type `CatchainConfig` -// - -struct CatchainConfig final : TLB_Complex { - enum { catchain_config, catchain_config_new }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[2] = { 0xc1, 0xc2 }; - struct Record_catchain_config; - struct Record_catchain_config_new; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_catchain_config& data) const; - bool cell_unpack(Ref cell_ref, Record_catchain_config& data) const; - bool pack(vm::CellBuilder& cb, const Record_catchain_config& data) const; - bool cell_pack(Ref& cell_ref, const Record_catchain_config& data) const; - bool unpack(vm::CellSlice& cs, Record_catchain_config_new& data) const; - bool cell_unpack(Ref cell_ref, Record_catchain_config_new& data) const; - bool pack(vm::CellBuilder& cb, const Record_catchain_config_new& data) const; - bool cell_pack(Ref& cell_ref, const Record_catchain_config_new& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "CatchainConfig"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct CatchainConfig::Record_catchain_config { - typedef CatchainConfig type_class; - unsigned mc_catchain_lifetime; // mc_catchain_lifetime : uint32 - unsigned shard_catchain_lifetime; // shard_catchain_lifetime : uint32 - unsigned shard_validators_lifetime; // shard_validators_lifetime : uint32 - unsigned shard_validators_num; // shard_validators_num : uint32 - Record_catchain_config() = default; - Record_catchain_config(unsigned _mc_catchain_lifetime, unsigned _shard_catchain_lifetime, unsigned _shard_validators_lifetime, unsigned _shard_validators_num) : mc_catchain_lifetime(_mc_catchain_lifetime), shard_catchain_lifetime(_shard_catchain_lifetime), shard_validators_lifetime(_shard_validators_lifetime), shard_validators_num(_shard_validators_num) {} -}; - -struct CatchainConfig::Record_catchain_config_new { - typedef CatchainConfig type_class; - int flags; // flags : ## 7 - bool shuffle_mc_validators; // shuffle_mc_validators : Bool - unsigned mc_catchain_lifetime; // mc_catchain_lifetime : uint32 - unsigned shard_catchain_lifetime; // shard_catchain_lifetime : uint32 - unsigned shard_validators_lifetime; // shard_validators_lifetime : uint32 - unsigned shard_validators_num; // shard_validators_num : uint32 - Record_catchain_config_new() = default; - Record_catchain_config_new(int _flags, bool _shuffle_mc_validators, unsigned _mc_catchain_lifetime, unsigned _shard_catchain_lifetime, unsigned _shard_validators_lifetime, unsigned _shard_validators_num) : flags(_flags), shuffle_mc_validators(_shuffle_mc_validators), mc_catchain_lifetime(_mc_catchain_lifetime), shard_catchain_lifetime(_shard_catchain_lifetime), shard_validators_lifetime(_shard_validators_lifetime), shard_validators_num(_shard_validators_num) {} -}; - -extern const CatchainConfig t_CatchainConfig; - -// -// headers for type `ConsensusConfig` -// - -struct ConsensusConfig final : TLB_Complex { - enum { consensus_config, consensus_config_new }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[2] = { 0xd6, 0xd7 }; - struct Record_consensus_config; - struct Record_consensus_config_new; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_consensus_config& data) const; - bool cell_unpack(Ref cell_ref, Record_consensus_config& data) const; - bool pack(vm::CellBuilder& cb, const Record_consensus_config& data) const; - bool cell_pack(Ref& cell_ref, const Record_consensus_config& data) const; - bool unpack(vm::CellSlice& cs, Record_consensus_config_new& data) const; - bool cell_unpack(Ref cell_ref, Record_consensus_config_new& data) const; - bool pack(vm::CellBuilder& cb, const Record_consensus_config_new& data) const; - bool cell_pack(Ref& cell_ref, const Record_consensus_config_new& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ConsensusConfig"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct ConsensusConfig::Record_consensus_config { - typedef ConsensusConfig type_class; - int round_candidates; // round_candidates : # - unsigned next_candidate_delay_ms; // next_candidate_delay_ms : uint32 - unsigned consensus_timeout_ms; // consensus_timeout_ms : uint32 - unsigned fast_attempts; // fast_attempts : uint32 - unsigned attempt_duration; // attempt_duration : uint32 - unsigned catchain_max_deps; // catchain_max_deps : uint32 - unsigned max_block_bytes; // max_block_bytes : uint32 - unsigned max_collated_bytes; // max_collated_bytes : uint32 - Record_consensus_config() = default; - Record_consensus_config(int _round_candidates, unsigned _next_candidate_delay_ms, unsigned _consensus_timeout_ms, unsigned _fast_attempts, unsigned _attempt_duration, unsigned _catchain_max_deps, unsigned _max_block_bytes, unsigned _max_collated_bytes) : round_candidates(_round_candidates), next_candidate_delay_ms(_next_candidate_delay_ms), consensus_timeout_ms(_consensus_timeout_ms), fast_attempts(_fast_attempts), attempt_duration(_attempt_duration), catchain_max_deps(_catchain_max_deps), max_block_bytes(_max_block_bytes), max_collated_bytes(_max_collated_bytes) {} -}; - -struct ConsensusConfig::Record_consensus_config_new { - typedef ConsensusConfig type_class; - int flags; // flags : ## 7 - bool new_catchain_ids; // new_catchain_ids : Bool - int round_candidates; // round_candidates : ## 8 - unsigned next_candidate_delay_ms; // next_candidate_delay_ms : uint32 - unsigned consensus_timeout_ms; // consensus_timeout_ms : uint32 - unsigned fast_attempts; // fast_attempts : uint32 - unsigned attempt_duration; // attempt_duration : uint32 - unsigned catchain_max_deps; // catchain_max_deps : uint32 - unsigned max_block_bytes; // max_block_bytes : uint32 - unsigned max_collated_bytes; // max_collated_bytes : uint32 - Record_consensus_config_new() = default; - Record_consensus_config_new(int _flags, bool _new_catchain_ids, int _round_candidates, unsigned _next_candidate_delay_ms, unsigned _consensus_timeout_ms, unsigned _fast_attempts, unsigned _attempt_duration, unsigned _catchain_max_deps, unsigned _max_block_bytes, unsigned _max_collated_bytes) : flags(_flags), new_catchain_ids(_new_catchain_ids), round_candidates(_round_candidates), next_candidate_delay_ms(_next_candidate_delay_ms), consensus_timeout_ms(_consensus_timeout_ms), fast_attempts(_fast_attempts), attempt_duration(_attempt_duration), catchain_max_deps(_catchain_max_deps), max_block_bytes(_max_block_bytes), max_collated_bytes(_max_collated_bytes) {} -}; - -extern const ConsensusConfig t_ConsensusConfig; - -// -// headers for type `ValidatorTempKey` -// - -struct ValidatorTempKey final : TLB_Complex { - enum { validator_temp_key }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 3 }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 612; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(612); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorTempKey"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValidatorTempKey::Record { - typedef ValidatorTempKey type_class; - td::BitArray<256> adnl_addr; // adnl_addr : bits256 - Ref temp_public_key; // temp_public_key : SigPubKey - int seqno; // seqno : # - unsigned valid_until; // valid_until : uint32 - Record() = default; - Record(const td::BitArray<256>& _adnl_addr, Ref _temp_public_key, int _seqno, unsigned _valid_until) : adnl_addr(_adnl_addr), temp_public_key(std::move(_temp_public_key)), seqno(_seqno), valid_until(_valid_until) {} -}; - -extern const ValidatorTempKey t_ValidatorTempKey; - -// -// headers for type `ValidatorSignedTempKey` -// - -struct ValidatorSignedTempKey final : TLB_Complex { - enum { signed_temp_key }; - static constexpr int cons_len_exact = 4; - static constexpr unsigned char cons_tag[1] = { 4 }; - struct Record { - typedef ValidatorSignedTempKey type_class; - Ref key; // key : ^ValidatorTempKey - Ref signature; // signature : CryptoSignature - Record() = default; - Record(Ref _key, Ref _signature) : key(std::move(_key)), signature(std::move(_signature)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_signed_temp_key(vm::CellSlice& cs, Ref& key, Ref& signature) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_signed_temp_key(Ref cell_ref, Ref& key, Ref& signature) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_signed_temp_key(vm::CellBuilder& cb, Ref key, Ref signature) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_signed_temp_key(Ref& cell_ref, Ref key, Ref signature) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorSignedTempKey"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ValidatorSignedTempKey t_ValidatorSignedTempKey; - -// -// headers for type `ConfigParam` -// - -struct ConfigParam final : TLB_Complex { - enum { cons32, cons33, cons34, cons35, cons36, cons37, cons13, config_mc_block_limits, config_block_limits, cons14, cons0, cons1, cons2, cons3, cons4, cons6, cons7, cons9, cons10, cons12, cons15, cons16, cons17, cons18, cons31, cons39, cons11, cons28, cons8, config_mc_gas_prices, config_gas_prices, cons29, config_mc_fwd_prices, config_fwd_prices }; - static constexpr int cons_len_exact = 0; - int m_; - ConfigParam(int m) : m_(m) {} - struct Record_cons0 { - typedef ConfigParam type_class; - td::BitArray<256> config_addr; // config_addr : bits256 - Record_cons0() = default; - Record_cons0(const td::BitArray<256>& _config_addr) : config_addr(_config_addr) {} - }; - struct Record_cons1 { - typedef ConfigParam type_class; - td::BitArray<256> elector_addr; // elector_addr : bits256 - Record_cons1() = default; - Record_cons1(const td::BitArray<256>& _elector_addr) : elector_addr(_elector_addr) {} - }; - struct Record_cons2 { - typedef ConfigParam type_class; - td::BitArray<256> minter_addr; // minter_addr : bits256 - Record_cons2() = default; - Record_cons2(const td::BitArray<256>& _minter_addr) : minter_addr(_minter_addr) {} - }; - struct Record_cons3 { - typedef ConfigParam type_class; - td::BitArray<256> fee_collector_addr; // fee_collector_addr : bits256 - Record_cons3() = default; - Record_cons3(const td::BitArray<256>& _fee_collector_addr) : fee_collector_addr(_fee_collector_addr) {} - }; - struct Record_cons4 { - typedef ConfigParam type_class; - td::BitArray<256> dns_root_addr; // dns_root_addr : bits256 - Record_cons4() = default; - Record_cons4(const td::BitArray<256>& _dns_root_addr) : dns_root_addr(_dns_root_addr) {} - }; - struct Record_cons6 { - typedef ConfigParam type_class; - Ref mint_new_price; // mint_new_price : Grams - Ref mint_add_price; // mint_add_price : Grams - Record_cons6() = default; - Record_cons6(Ref _mint_new_price, Ref _mint_add_price) : mint_new_price(std::move(_mint_new_price)), mint_add_price(std::move(_mint_add_price)) {} - }; - struct Record_cons7 { - typedef ConfigParam type_class; - Ref to_mint; // to_mint : ExtraCurrencyCollection - Record_cons7() = default; - Record_cons7(Ref _to_mint) : to_mint(std::move(_to_mint)) {} - }; - struct Record_cons8 { - typedef ConfigParam type_class; - Ref x; // GlobalVersion - Record_cons8() = default; - Record_cons8(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons9 { - typedef ConfigParam type_class; - Ref mandatory_params; // mandatory_params : Hashmap 32 True - Record_cons9() = default; - Record_cons9(Ref _mandatory_params) : mandatory_params(std::move(_mandatory_params)) {} - }; - struct Record_cons10 { - typedef ConfigParam type_class; - Ref critical_params; // critical_params : Hashmap 32 True - Record_cons10() = default; - Record_cons10(Ref _critical_params) : critical_params(std::move(_critical_params)) {} - }; - struct Record_cons11 { - typedef ConfigParam type_class; - Ref x; // ConfigVotingSetup - Record_cons11() = default; - Record_cons11(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons12 { - typedef ConfigParam type_class; - Ref workchains; // workchains : HashmapE 32 WorkchainDescr - Record_cons12() = default; - Record_cons12(Ref _workchains) : workchains(std::move(_workchains)) {} - }; - struct Record_cons13 { - typedef ConfigParam type_class; - Ref x; // ComplaintPricing - Record_cons13() = default; - Record_cons13(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons14 { - typedef ConfigParam type_class; - Ref x; // BlockCreateFees - Record_cons14() = default; - Record_cons14(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons15; - struct Record_cons16; - struct Record_cons17; - struct Record_cons18 { - typedef ConfigParam type_class; - Ref x; // Hashmap 32 StoragePrices - Record_cons18() = default; - Record_cons18(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_mc_gas_prices { - typedef ConfigParam type_class; - Ref x; // GasLimitsPrices - Record_config_mc_gas_prices() = default; - Record_config_mc_gas_prices(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_gas_prices { - typedef ConfigParam type_class; - Ref x; // GasLimitsPrices - Record_config_gas_prices() = default; - Record_config_gas_prices(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_mc_block_limits { - typedef ConfigParam type_class; - Ref x; // BlockLimits - Record_config_mc_block_limits() = default; - Record_config_mc_block_limits(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_block_limits { - typedef ConfigParam type_class; - Ref x; // BlockLimits - Record_config_block_limits() = default; - Record_config_block_limits(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_mc_fwd_prices { - typedef ConfigParam type_class; - Ref x; // MsgForwardPrices - Record_config_mc_fwd_prices() = default; - Record_config_mc_fwd_prices(Ref _x) : x(std::move(_x)) {} - }; - struct Record_config_fwd_prices { - typedef ConfigParam type_class; - Ref x; // MsgForwardPrices - Record_config_fwd_prices() = default; - Record_config_fwd_prices(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons28 { - typedef ConfigParam type_class; - Ref x; // CatchainConfig - Record_cons28() = default; - Record_cons28(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons29 { - typedef ConfigParam type_class; - Ref x; // ConsensusConfig - Record_cons29() = default; - Record_cons29(Ref _x) : x(std::move(_x)) {} - }; - struct Record_cons31 { - typedef ConfigParam type_class; - Ref fundamental_smc_addr; // fundamental_smc_addr : HashmapE 256 True - Record_cons31() = default; - Record_cons31(Ref _fundamental_smc_addr) : fundamental_smc_addr(std::move(_fundamental_smc_addr)) {} - }; - struct Record_cons32 { - typedef ConfigParam type_class; - Ref prev_validators; // prev_validators : ValidatorSet - Record_cons32() = default; - Record_cons32(Ref _prev_validators) : prev_validators(std::move(_prev_validators)) {} - }; - struct Record_cons33 { - typedef ConfigParam type_class; - Ref prev_temp_validators; // prev_temp_validators : ValidatorSet - Record_cons33() = default; - Record_cons33(Ref _prev_temp_validators) : prev_temp_validators(std::move(_prev_temp_validators)) {} - }; - struct Record_cons34 { - typedef ConfigParam type_class; - Ref cur_validators; // cur_validators : ValidatorSet - Record_cons34() = default; - Record_cons34(Ref _cur_validators) : cur_validators(std::move(_cur_validators)) {} - }; - struct Record_cons35 { - typedef ConfigParam type_class; - Ref cur_temp_validators; // cur_temp_validators : ValidatorSet - Record_cons35() = default; - Record_cons35(Ref _cur_temp_validators) : cur_temp_validators(std::move(_cur_temp_validators)) {} - }; - struct Record_cons36 { - typedef ConfigParam type_class; - Ref next_validators; // next_validators : ValidatorSet - Record_cons36() = default; - Record_cons36(Ref _next_validators) : next_validators(std::move(_next_validators)) {} - }; - struct Record_cons37 { - typedef ConfigParam type_class; - Ref next_temp_validators; // next_temp_validators : ValidatorSet - Record_cons37() = default; - Record_cons37(Ref _next_temp_validators) : next_temp_validators(std::move(_next_temp_validators)) {} - }; - struct Record_cons39 { - typedef ConfigParam type_class; - Ref x; // HashmapE 256 ValidatorSignedTempKey - Record_cons39() = default; - Record_cons39(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cons0& data) const; - bool unpack_cons0(vm::CellSlice& cs, td::BitArray<256>& config_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons0& data) const; - bool cell_unpack_cons0(Ref cell_ref, td::BitArray<256>& config_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons0& data) const; - bool pack_cons0(vm::CellBuilder& cb, td::BitArray<256> config_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons0& data) const; - bool cell_pack_cons0(Ref& cell_ref, td::BitArray<256> config_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons1& data) const; - bool unpack_cons1(vm::CellSlice& cs, td::BitArray<256>& elector_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons1& data) const; - bool cell_unpack_cons1(Ref cell_ref, td::BitArray<256>& elector_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons1& data) const; - bool pack_cons1(vm::CellBuilder& cb, td::BitArray<256> elector_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons1& data) const; - bool cell_pack_cons1(Ref& cell_ref, td::BitArray<256> elector_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons2& data) const; - bool unpack_cons2(vm::CellSlice& cs, td::BitArray<256>& minter_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons2& data) const; - bool cell_unpack_cons2(Ref cell_ref, td::BitArray<256>& minter_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons2& data) const; - bool pack_cons2(vm::CellBuilder& cb, td::BitArray<256> minter_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons2& data) const; - bool cell_pack_cons2(Ref& cell_ref, td::BitArray<256> minter_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons3& data) const; - bool unpack_cons3(vm::CellSlice& cs, td::BitArray<256>& fee_collector_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons3& data) const; - bool cell_unpack_cons3(Ref cell_ref, td::BitArray<256>& fee_collector_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons3& data) const; - bool pack_cons3(vm::CellBuilder& cb, td::BitArray<256> fee_collector_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons3& data) const; - bool cell_pack_cons3(Ref& cell_ref, td::BitArray<256> fee_collector_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons4& data) const; - bool unpack_cons4(vm::CellSlice& cs, td::BitArray<256>& dns_root_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons4& data) const; - bool cell_unpack_cons4(Ref cell_ref, td::BitArray<256>& dns_root_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons4& data) const; - bool pack_cons4(vm::CellBuilder& cb, td::BitArray<256> dns_root_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons4& data) const; - bool cell_pack_cons4(Ref& cell_ref, td::BitArray<256> dns_root_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons6& data) const; - bool unpack_cons6(vm::CellSlice& cs, Ref& mint_new_price, Ref& mint_add_price) const; - bool cell_unpack(Ref cell_ref, Record_cons6& data) const; - bool cell_unpack_cons6(Ref cell_ref, Ref& mint_new_price, Ref& mint_add_price) const; - bool pack(vm::CellBuilder& cb, const Record_cons6& data) const; - bool pack_cons6(vm::CellBuilder& cb, Ref mint_new_price, Ref mint_add_price) const; - bool cell_pack(Ref& cell_ref, const Record_cons6& data) const; - bool cell_pack_cons6(Ref& cell_ref, Ref mint_new_price, Ref mint_add_price) const; - bool unpack(vm::CellSlice& cs, Record_cons7& data) const; - bool unpack_cons7(vm::CellSlice& cs, Ref& to_mint) const; - bool cell_unpack(Ref cell_ref, Record_cons7& data) const; - bool cell_unpack_cons7(Ref cell_ref, Ref& to_mint) const; - bool pack(vm::CellBuilder& cb, const Record_cons7& data) const; - bool pack_cons7(vm::CellBuilder& cb, Ref to_mint) const; - bool cell_pack(Ref& cell_ref, const Record_cons7& data) const; - bool cell_pack_cons7(Ref& cell_ref, Ref to_mint) const; - bool unpack(vm::CellSlice& cs, Record_cons8& data) const; - bool unpack_cons8(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons8& data) const; - bool cell_unpack_cons8(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons8& data) const; - bool pack_cons8(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons8& data) const; - bool cell_pack_cons8(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons9& data) const; - bool unpack_cons9(vm::CellSlice& cs, Ref& mandatory_params) const; - bool cell_unpack(Ref cell_ref, Record_cons9& data) const; - bool cell_unpack_cons9(Ref cell_ref, Ref& mandatory_params) const; - bool pack(vm::CellBuilder& cb, const Record_cons9& data) const; - bool pack_cons9(vm::CellBuilder& cb, Ref mandatory_params) const; - bool cell_pack(Ref& cell_ref, const Record_cons9& data) const; - bool cell_pack_cons9(Ref& cell_ref, Ref mandatory_params) const; - bool unpack(vm::CellSlice& cs, Record_cons10& data) const; - bool unpack_cons10(vm::CellSlice& cs, Ref& critical_params) const; - bool cell_unpack(Ref cell_ref, Record_cons10& data) const; - bool cell_unpack_cons10(Ref cell_ref, Ref& critical_params) const; - bool pack(vm::CellBuilder& cb, const Record_cons10& data) const; - bool pack_cons10(vm::CellBuilder& cb, Ref critical_params) const; - bool cell_pack(Ref& cell_ref, const Record_cons10& data) const; - bool cell_pack_cons10(Ref& cell_ref, Ref critical_params) const; - bool unpack(vm::CellSlice& cs, Record_cons11& data) const; - bool unpack_cons11(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons11& data) const; - bool cell_unpack_cons11(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons11& data) const; - bool pack_cons11(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons11& data) const; - bool cell_pack_cons11(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons12& data) const; - bool unpack_cons12(vm::CellSlice& cs, Ref& workchains) const; - bool cell_unpack(Ref cell_ref, Record_cons12& data) const; - bool cell_unpack_cons12(Ref cell_ref, Ref& workchains) const; - bool pack(vm::CellBuilder& cb, const Record_cons12& data) const; - bool pack_cons12(vm::CellBuilder& cb, Ref workchains) const; - bool cell_pack(Ref& cell_ref, const Record_cons12& data) const; - bool cell_pack_cons12(Ref& cell_ref, Ref workchains) const; - bool unpack(vm::CellSlice& cs, Record_cons13& data) const; - bool unpack_cons13(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons13& data) const; - bool cell_unpack_cons13(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons13& data) const; - bool pack_cons13(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons13& data) const; - bool cell_pack_cons13(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons14& data) const; - bool unpack_cons14(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons14& data) const; - bool cell_unpack_cons14(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons14& data) const; - bool pack_cons14(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons14& data) const; - bool cell_pack_cons14(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons15& data) const; - bool cell_unpack(Ref cell_ref, Record_cons15& data) const; - bool pack(vm::CellBuilder& cb, const Record_cons15& data) const; - bool cell_pack(Ref& cell_ref, const Record_cons15& data) const; - bool unpack(vm::CellSlice& cs, Record_cons16& data) const; - bool unpack_cons16(vm::CellSlice& cs, int& max_validators, int& max_main_validators, int& min_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons16& data) const; - bool cell_unpack_cons16(Ref cell_ref, int& max_validators, int& max_main_validators, int& min_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons16& data) const; - bool pack_cons16(vm::CellBuilder& cb, int max_validators, int max_main_validators, int min_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons16& data) const; - bool cell_pack_cons16(Ref& cell_ref, int max_validators, int max_main_validators, int min_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons17& data) const; - bool cell_unpack(Ref cell_ref, Record_cons17& data) const; - bool pack(vm::CellBuilder& cb, const Record_cons17& data) const; - bool cell_pack(Ref& cell_ref, const Record_cons17& data) const; - bool unpack(vm::CellSlice& cs, Record_cons18& data) const; - bool unpack_cons18(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons18& data) const; - bool cell_unpack_cons18(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons18& data) const; - bool pack_cons18(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons18& data) const; - bool cell_pack_cons18(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_mc_gas_prices& data) const; - bool unpack_config_mc_gas_prices(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_mc_gas_prices& data) const; - bool cell_unpack_config_mc_gas_prices(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_mc_gas_prices& data) const; - bool pack_config_mc_gas_prices(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_mc_gas_prices& data) const; - bool cell_pack_config_mc_gas_prices(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_gas_prices& data) const; - bool unpack_config_gas_prices(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_gas_prices& data) const; - bool cell_unpack_config_gas_prices(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_gas_prices& data) const; - bool pack_config_gas_prices(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_gas_prices& data) const; - bool cell_pack_config_gas_prices(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_mc_block_limits& data) const; - bool unpack_config_mc_block_limits(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_mc_block_limits& data) const; - bool cell_unpack_config_mc_block_limits(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_mc_block_limits& data) const; - bool pack_config_mc_block_limits(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_mc_block_limits& data) const; - bool cell_pack_config_mc_block_limits(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_block_limits& data) const; - bool unpack_config_block_limits(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_block_limits& data) const; - bool cell_unpack_config_block_limits(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_block_limits& data) const; - bool pack_config_block_limits(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_block_limits& data) const; - bool cell_pack_config_block_limits(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_mc_fwd_prices& data) const; - bool unpack_config_mc_fwd_prices(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_mc_fwd_prices& data) const; - bool cell_unpack_config_mc_fwd_prices(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_mc_fwd_prices& data) const; - bool pack_config_mc_fwd_prices(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_mc_fwd_prices& data) const; - bool cell_pack_config_mc_fwd_prices(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_config_fwd_prices& data) const; - bool unpack_config_fwd_prices(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_config_fwd_prices& data) const; - bool cell_unpack_config_fwd_prices(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_config_fwd_prices& data) const; - bool pack_config_fwd_prices(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_config_fwd_prices& data) const; - bool cell_pack_config_fwd_prices(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons28& data) const; - bool unpack_cons28(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons28& data) const; - bool cell_unpack_cons28(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons28& data) const; - bool pack_cons28(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons28& data) const; - bool cell_pack_cons28(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons29& data) const; - bool unpack_cons29(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons29& data) const; - bool cell_unpack_cons29(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons29& data) const; - bool pack_cons29(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons29& data) const; - bool cell_pack_cons29(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_cons31& data) const; - bool unpack_cons31(vm::CellSlice& cs, Ref& fundamental_smc_addr) const; - bool cell_unpack(Ref cell_ref, Record_cons31& data) const; - bool cell_unpack_cons31(Ref cell_ref, Ref& fundamental_smc_addr) const; - bool pack(vm::CellBuilder& cb, const Record_cons31& data) const; - bool pack_cons31(vm::CellBuilder& cb, Ref fundamental_smc_addr) const; - bool cell_pack(Ref& cell_ref, const Record_cons31& data) const; - bool cell_pack_cons31(Ref& cell_ref, Ref fundamental_smc_addr) const; - bool unpack(vm::CellSlice& cs, Record_cons32& data) const; - bool unpack_cons32(vm::CellSlice& cs, Ref& prev_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons32& data) const; - bool cell_unpack_cons32(Ref cell_ref, Ref& prev_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons32& data) const; - bool pack_cons32(vm::CellBuilder& cb, Ref prev_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons32& data) const; - bool cell_pack_cons32(Ref& cell_ref, Ref prev_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons33& data) const; - bool unpack_cons33(vm::CellSlice& cs, Ref& prev_temp_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons33& data) const; - bool cell_unpack_cons33(Ref cell_ref, Ref& prev_temp_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons33& data) const; - bool pack_cons33(vm::CellBuilder& cb, Ref prev_temp_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons33& data) const; - bool cell_pack_cons33(Ref& cell_ref, Ref prev_temp_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons34& data) const; - bool unpack_cons34(vm::CellSlice& cs, Ref& cur_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons34& data) const; - bool cell_unpack_cons34(Ref cell_ref, Ref& cur_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons34& data) const; - bool pack_cons34(vm::CellBuilder& cb, Ref cur_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons34& data) const; - bool cell_pack_cons34(Ref& cell_ref, Ref cur_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons35& data) const; - bool unpack_cons35(vm::CellSlice& cs, Ref& cur_temp_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons35& data) const; - bool cell_unpack_cons35(Ref cell_ref, Ref& cur_temp_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons35& data) const; - bool pack_cons35(vm::CellBuilder& cb, Ref cur_temp_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons35& data) const; - bool cell_pack_cons35(Ref& cell_ref, Ref cur_temp_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons36& data) const; - bool unpack_cons36(vm::CellSlice& cs, Ref& next_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons36& data) const; - bool cell_unpack_cons36(Ref cell_ref, Ref& next_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons36& data) const; - bool pack_cons36(vm::CellBuilder& cb, Ref next_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons36& data) const; - bool cell_pack_cons36(Ref& cell_ref, Ref next_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons37& data) const; - bool unpack_cons37(vm::CellSlice& cs, Ref& next_temp_validators) const; - bool cell_unpack(Ref cell_ref, Record_cons37& data) const; - bool cell_unpack_cons37(Ref cell_ref, Ref& next_temp_validators) const; - bool pack(vm::CellBuilder& cb, const Record_cons37& data) const; - bool pack_cons37(vm::CellBuilder& cb, Ref next_temp_validators) const; - bool cell_pack(Ref& cell_ref, const Record_cons37& data) const; - bool cell_pack_cons37(Ref& cell_ref, Ref next_temp_validators) const; - bool unpack(vm::CellSlice& cs, Record_cons39& data) const; - bool unpack_cons39(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_cons39& data) const; - bool cell_unpack_cons39(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_cons39& data) const; - bool pack_cons39(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_cons39& data) const; - bool cell_pack_cons39(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(ConfigParam " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct ConfigParam::Record_cons15 { - typedef ConfigParam type_class; - unsigned validators_elected_for; // validators_elected_for : uint32 - unsigned elections_start_before; // elections_start_before : uint32 - unsigned elections_end_before; // elections_end_before : uint32 - unsigned stake_held_for; // stake_held_for : uint32 - Record_cons15() = default; - Record_cons15(unsigned _validators_elected_for, unsigned _elections_start_before, unsigned _elections_end_before, unsigned _stake_held_for) : validators_elected_for(_validators_elected_for), elections_start_before(_elections_start_before), elections_end_before(_elections_end_before), stake_held_for(_stake_held_for) {} -}; - -struct ConfigParam::Record_cons16 { - typedef ConfigParam type_class; - int max_validators; // max_validators : ## 16 - int max_main_validators; // max_main_validators : ## 16 - int min_validators; // min_validators : ## 16 - Record_cons16() = default; - Record_cons16(int _max_validators, int _max_main_validators, int _min_validators) : max_validators(_max_validators), max_main_validators(_max_main_validators), min_validators(_min_validators) {} -}; - -struct ConfigParam::Record_cons17 { - typedef ConfigParam type_class; - Ref min_stake; // min_stake : Grams - Ref max_stake; // max_stake : Grams - Ref min_total_stake; // min_total_stake : Grams - unsigned max_stake_factor; // max_stake_factor : uint32 - Record_cons17() = default; - Record_cons17(Ref _min_stake, Ref _max_stake, Ref _min_total_stake, unsigned _max_stake_factor) : min_stake(std::move(_min_stake)), max_stake(std::move(_max_stake)), min_total_stake(std::move(_min_total_stake)), max_stake_factor(_max_stake_factor) {} -}; - -// -// headers for type `BlockSignaturesPure` -// - -struct BlockSignaturesPure final : TLB_Complex { - enum { block_signatures_pure }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_block_signatures_pure(vm::CellSlice& cs, unsigned& sig_count, unsigned long long& sig_weight, Ref& signatures) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_block_signatures_pure(Ref cell_ref, unsigned& sig_count, unsigned long long& sig_weight, Ref& signatures) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_block_signatures_pure(vm::CellBuilder& cb, unsigned sig_count, unsigned long long sig_weight, Ref signatures) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_block_signatures_pure(Ref& cell_ref, unsigned sig_count, unsigned long long sig_weight, Ref signatures) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockSignaturesPure"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockSignaturesPure::Record { - typedef BlockSignaturesPure type_class; - unsigned sig_count; // sig_count : uint32 - unsigned long long sig_weight; // sig_weight : uint64 - Ref signatures; // signatures : HashmapE 16 CryptoSignaturePair - Record() = default; - Record(unsigned _sig_count, unsigned long long _sig_weight, Ref _signatures) : sig_count(_sig_count), sig_weight(_sig_weight), signatures(std::move(_signatures)) {} -}; - -extern const BlockSignaturesPure t_BlockSignaturesPure; - -// -// headers for type `BlockSignatures` -// - -struct BlockSignatures final : TLB_Complex { - enum { block_signatures }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 17 }; - struct Record { - typedef BlockSignatures type_class; - Ref validator_info; // validator_info : ValidatorBaseInfo - Ref pure_signatures; // pure_signatures : BlockSignaturesPure - Record() = default; - Record(Ref _validator_info, Ref _pure_signatures) : validator_info(std::move(_validator_info)), pure_signatures(std::move(_pure_signatures)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_block_signatures(vm::CellSlice& cs, Ref& validator_info, Ref& pure_signatures) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_block_signatures(Ref cell_ref, Ref& validator_info, Ref& pure_signatures) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_block_signatures(vm::CellBuilder& cb, Ref validator_info, Ref pure_signatures) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_block_signatures(Ref& cell_ref, Ref validator_info, Ref pure_signatures) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockSignatures"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const BlockSignatures t_BlockSignatures; - -// -// headers for type `BlockProof` -// - -struct BlockProof final : TLB_Complex { - enum { block_proof }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xc3 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_block_proof(vm::CellSlice& cs, Ref& proof_for, Ref& root, Ref& signatures) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_block_proof(Ref cell_ref, Ref& proof_for, Ref& root, Ref& signatures) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_block_proof(vm::CellBuilder& cb, Ref proof_for, Ref root, Ref signatures) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_block_proof(Ref& cell_ref, Ref proof_for, Ref root, Ref signatures) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "BlockProof"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct BlockProof::Record { - typedef BlockProof type_class; - Ref proof_for; // proof_for : BlockIdExt - Ref root; // root : ^Cell - Ref signatures; // signatures : Maybe ^BlockSignatures - Record() = default; - Record(Ref _proof_for, Ref _root, Ref _signatures) : proof_for(std::move(_proof_for)), root(std::move(_root)), signatures(std::move(_signatures)) {} -}; - -extern const BlockProof t_BlockProof; - -// -// headers for type `ProofChain` -// - -struct ProofChain final : TLB_Complex { - enum { chain_empty, chain_link }; - static constexpr int cons_len_exact = 0; - int m_; - ProofChain(int m) : m_(m) {} - struct Record_chain_empty { - typedef ProofChain type_class; - }; - struct Record_chain_link; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_chain_empty& data) const; - bool unpack_chain_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_chain_empty& data) const; - bool cell_unpack_chain_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_chain_empty& data) const; - bool pack_chain_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_chain_empty& data) const; - bool cell_pack_chain_empty(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_chain_link& data) const; - bool unpack_chain_link(vm::CellSlice& cs, int& n, Ref& root, Ref& prev) const; - bool cell_unpack(Ref cell_ref, Record_chain_link& data) const; - bool cell_unpack_chain_link(Ref cell_ref, int& n, Ref& root, Ref& prev) const; - bool pack(vm::CellBuilder& cb, const Record_chain_link& data) const; - bool pack_chain_link(vm::CellBuilder& cb, Ref root, Ref prev) const; - bool cell_pack(Ref& cell_ref, const Record_chain_link& data) const; - bool cell_pack_chain_link(Ref& cell_ref, Ref root, Ref prev) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(ProofChain " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct ProofChain::Record_chain_link { - typedef ProofChain type_class; - int n; // n : # - Ref root; // root : ^Cell - Ref prev; // prev : n?^(ProofChain n) - Record_chain_link() = default; - Record_chain_link(Ref _root, Ref _prev) : n(-1), root(std::move(_root)), prev(std::move(_prev)) {} -}; - -// -// headers for type `TopBlockDescr` -// - -struct TopBlockDescr final : TLB_Complex { - enum { top_block_descr }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xd5 }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TopBlockDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct TopBlockDescr::Record { - typedef TopBlockDescr type_class; - Ref proof_for; // proof_for : BlockIdExt - Ref signatures; // signatures : Maybe ^BlockSignatures - int len; // len : ## 8 - Ref chain; // chain : ProofChain len - Record() = default; - Record(Ref _proof_for, Ref _signatures, int _len, Ref _chain) : proof_for(std::move(_proof_for)), signatures(std::move(_signatures)), len(_len), chain(std::move(_chain)) {} -}; - -extern const TopBlockDescr t_TopBlockDescr; - -// -// headers for type `TopBlockDescrSet` -// - -struct TopBlockDescrSet final : TLB_Complex { - enum { top_block_descr_set }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x4ac789f3 }; - struct Record { - typedef TopBlockDescrSet type_class; - Ref collection; // collection : HashmapE 96 ^TopBlockDescr - Record() = default; - Record(Ref _collection) : collection(std::move(_collection)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_top_block_descr_set(vm::CellSlice& cs, Ref& collection) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_top_block_descr_set(Ref cell_ref, Ref& collection) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_top_block_descr_set(vm::CellBuilder& cb, Ref collection) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_top_block_descr_set(Ref& cell_ref, Ref collection) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "TopBlockDescrSet"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const TopBlockDescrSet t_TopBlockDescrSet; - -// -// headers for type `ProducerInfo` -// - -struct ProducerInfo final : TLB_Complex { - enum { prod_info }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x34 }; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 0x20288; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x20288); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ProducerInfo"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ProducerInfo::Record { - typedef ProducerInfo type_class; - unsigned utime; // utime : uint32 - Ref mc_blk_ref; // mc_blk_ref : ExtBlkRef - Ref state_proof; // state_proof : ^(MERKLE_PROOF Block) - Ref prod_proof; // prod_proof : ^(MERKLE_PROOF ShardState) - Record() = default; - Record(unsigned _utime, Ref _mc_blk_ref, Ref _state_proof, Ref _prod_proof) : utime(_utime), mc_blk_ref(std::move(_mc_blk_ref)), state_proof(std::move(_state_proof)), prod_proof(std::move(_prod_proof)) {} -}; - -extern const ProducerInfo t_ProducerInfo; - -// -// headers for type `ComplaintDescr` -// - -struct ComplaintDescr final : TLB_Complex { - enum { no_blk_gen, no_blk_gen_diff }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[2] = { 0x450e8bd9, 0xc737b0caU }; - struct Record_no_blk_gen { - typedef ComplaintDescr type_class; - unsigned from_utime; // from_utime : uint32 - Ref prod_info; // prod_info : ^ProducerInfo - Record_no_blk_gen() = default; - Record_no_blk_gen(unsigned _from_utime, Ref _prod_info) : from_utime(_from_utime), prod_info(std::move(_prod_info)) {} - }; - struct Record_no_blk_gen_diff { - typedef ComplaintDescr type_class; - Ref prod_info_old; // prod_info_old : ^ProducerInfo - Ref prod_info_new; // prod_info_new : ^ProducerInfo - Record_no_blk_gen_diff() = default; - Record_no_blk_gen_diff(Ref _prod_info_old, Ref _prod_info_new) : prod_info_old(std::move(_prod_info_old)), prod_info_new(std::move(_prod_info_new)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_no_blk_gen& data) const; - bool unpack_no_blk_gen(vm::CellSlice& cs, unsigned& from_utime, Ref& prod_info) const; - bool cell_unpack(Ref cell_ref, Record_no_blk_gen& data) const; - bool cell_unpack_no_blk_gen(Ref cell_ref, unsigned& from_utime, Ref& prod_info) const; - bool pack(vm::CellBuilder& cb, const Record_no_blk_gen& data) const; - bool pack_no_blk_gen(vm::CellBuilder& cb, unsigned from_utime, Ref prod_info) const; - bool cell_pack(Ref& cell_ref, const Record_no_blk_gen& data) const; - bool cell_pack_no_blk_gen(Ref& cell_ref, unsigned from_utime, Ref prod_info) const; - bool unpack(vm::CellSlice& cs, Record_no_blk_gen_diff& data) const; - bool unpack_no_blk_gen_diff(vm::CellSlice& cs, Ref& prod_info_old, Ref& prod_info_new) const; - bool cell_unpack(Ref cell_ref, Record_no_blk_gen_diff& data) const; - bool cell_unpack_no_blk_gen_diff(Ref cell_ref, Ref& prod_info_old, Ref& prod_info_new) const; - bool pack(vm::CellBuilder& cb, const Record_no_blk_gen_diff& data) const; - bool pack_no_blk_gen_diff(vm::CellBuilder& cb, Ref prod_info_old, Ref prod_info_new) const; - bool cell_pack(Ref& cell_ref, const Record_no_blk_gen_diff& data) const; - bool cell_pack_no_blk_gen_diff(Ref& cell_ref, Ref prod_info_old, Ref prod_info_new) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ComplaintDescr"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const ComplaintDescr t_ComplaintDescr; - -// -// headers for type `ValidatorComplaint` -// - -struct ValidatorComplaint final : TLB_Complex { - enum { validator_complaint }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0xbc }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorComplaint"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValidatorComplaint::Record { - typedef ValidatorComplaint type_class; - td::BitArray<256> validator_pubkey; // validator_pubkey : bits256 - Ref description; // description : ^ComplaintDescr - unsigned created_at; // created_at : uint32 - int severity; // severity : uint8 - RefInt256 reward_addr; // reward_addr : uint256 - Ref paid; // paid : Grams - Ref suggested_fine; // suggested_fine : Grams - unsigned suggested_fine_part; // suggested_fine_part : uint32 - Record() = default; - Record(const td::BitArray<256>& _validator_pubkey, Ref _description, unsigned _created_at, int _severity, RefInt256 _reward_addr, Ref _paid, Ref _suggested_fine, unsigned _suggested_fine_part) : validator_pubkey(_validator_pubkey), description(std::move(_description)), created_at(_created_at), severity(_severity), reward_addr(std::move(_reward_addr)), paid(std::move(_paid)), suggested_fine(std::move(_suggested_fine)), suggested_fine_part(_suggested_fine_part) {} -}; - -extern const ValidatorComplaint t_ValidatorComplaint; - -// -// headers for type `ValidatorComplaintStatus` -// - -struct ValidatorComplaintStatus final : TLB_Complex { - enum { complaint_status }; - static constexpr int cons_len_exact = 8; - static constexpr unsigned char cons_tag[1] = { 0x2d }; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ValidatorComplaintStatus"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ValidatorComplaintStatus::Record { - typedef ValidatorComplaintStatus type_class; - Ref complaint; // complaint : ^ValidatorComplaint - Ref voters; // voters : HashmapE 16 True - RefInt256 vset_id; // vset_id : uint256 - long long weight_remaining; // weight_remaining : int64 - Record() = default; - Record(Ref _complaint, Ref _voters, RefInt256 _vset_id, long long _weight_remaining) : complaint(std::move(_complaint)), voters(std::move(_voters)), vset_id(std::move(_vset_id)), weight_remaining(_weight_remaining) {} -}; - -extern const ValidatorComplaintStatus t_ValidatorComplaintStatus; - -// -// headers for type `VmCellSlice` -// - -struct VmCellSlice final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 0x1001a; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x1001a); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmCellSlice"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VmCellSlice::Record { - typedef VmCellSlice type_class; - Ref cell; // cell : ^Cell - int st_bits; // st_bits : ## 10 - int end_bits; // end_bits : ## 10 - int st_ref; // st_ref : #<= 4 - int end_ref; // end_ref : #<= 4 - Record() = default; - Record(Ref _cell, int _st_bits, int _end_bits, int _st_ref, int _end_ref) : cell(std::move(_cell)), st_bits(_st_bits), end_bits(_end_bits), st_ref(_st_ref), end_ref(_end_ref) {} -}; - -extern const VmCellSlice t_VmCellSlice; - -// -// headers for type `VmTupleRef` -// - -struct VmTupleRef final : TLB_Complex { - enum { vm_tupref_nil, vm_tupref_single, vm_tupref_any }; - static constexpr int cons_len_exact = 0; - int m_; - VmTupleRef(int m) : m_(m) {} - struct Record_vm_tupref_nil { - typedef VmTupleRef type_class; - }; - struct Record_vm_tupref_single { - typedef VmTupleRef type_class; - Ref entry; // entry : ^VmStackValue - Record_vm_tupref_single() = default; - Record_vm_tupref_single(Ref _entry) : entry(std::move(_entry)) {} - }; - struct Record_vm_tupref_any { - typedef VmTupleRef type_class; - int n; // n : # - Ref ref; // ref : ^(VmTuple (n + 2)) - Record_vm_tupref_any() = default; - Record_vm_tupref_any(Ref _ref) : n(-1), ref(std::move(_ref)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vm_tupref_nil& data) const; - bool unpack_vm_tupref_nil(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vm_tupref_nil& data) const; - bool cell_unpack_vm_tupref_nil(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_tupref_nil& data) const; - bool pack_vm_tupref_nil(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vm_tupref_nil& data) const; - bool cell_pack_vm_tupref_nil(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vm_tupref_single& data) const; - bool unpack_vm_tupref_single(vm::CellSlice& cs, Ref& entry) const; - bool cell_unpack(Ref cell_ref, Record_vm_tupref_single& data) const; - bool cell_unpack_vm_tupref_single(Ref cell_ref, Ref& entry) const; - bool pack(vm::CellBuilder& cb, const Record_vm_tupref_single& data) const; - bool pack_vm_tupref_single(vm::CellBuilder& cb, Ref entry) const; - bool cell_pack(Ref& cell_ref, const Record_vm_tupref_single& data) const; - bool cell_pack_vm_tupref_single(Ref& cell_ref, Ref entry) const; - bool unpack(vm::CellSlice& cs, Record_vm_tupref_any& data) const; - bool unpack_vm_tupref_any(vm::CellSlice& cs, int& n, Ref& ref) const; - bool cell_unpack(Ref cell_ref, Record_vm_tupref_any& data) const; - bool cell_unpack_vm_tupref_any(Ref cell_ref, int& n, Ref& ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_tupref_any& data) const; - bool pack_vm_tupref_any(vm::CellBuilder& cb, Ref ref) const; - bool cell_pack(Ref& cell_ref, const Record_vm_tupref_any& data) const; - bool cell_pack_vm_tupref_any(Ref& cell_ref, Ref ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VmTupleRef " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -// -// headers for type `VmTuple` -// - -struct VmTuple final : TLB_Complex { - enum { vm_tuple_nil, vm_tuple_tcons }; - static constexpr int cons_len_exact = 0; - int m_; - VmTuple(int m) : m_(m) {} - struct Record_vm_tuple_nil { - typedef VmTuple type_class; - }; - struct Record_vm_tuple_tcons; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vm_tuple_nil& data) const; - bool unpack_vm_tuple_nil(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vm_tuple_nil& data) const; - bool cell_unpack_vm_tuple_nil(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_tuple_nil& data) const; - bool pack_vm_tuple_nil(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vm_tuple_nil& data) const; - bool cell_pack_vm_tuple_nil(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vm_tuple_tcons& data) const; - bool unpack_vm_tuple_tcons(vm::CellSlice& cs, int& n, Ref& head, Ref& tail) const; - bool cell_unpack(Ref cell_ref, Record_vm_tuple_tcons& data) const; - bool cell_unpack_vm_tuple_tcons(Ref cell_ref, int& n, Ref& head, Ref& tail) const; - bool pack(vm::CellBuilder& cb, const Record_vm_tuple_tcons& data) const; - bool pack_vm_tuple_tcons(vm::CellBuilder& cb, Ref head, Ref tail) const; - bool cell_pack(Ref& cell_ref, const Record_vm_tuple_tcons& data) const; - bool cell_pack_vm_tuple_tcons(Ref& cell_ref, Ref head, Ref tail) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VmTuple " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct VmTuple::Record_vm_tuple_tcons { - typedef VmTuple type_class; - int n; // n : # - Ref head; // head : VmTupleRef n - Ref tail; // tail : ^VmStackValue - Record_vm_tuple_tcons() = default; - Record_vm_tuple_tcons(Ref _head, Ref _tail) : n(-1), head(std::move(_head)), tail(std::move(_tail)) {} -}; - -// -// headers for type `VmStackValue` -// - -struct VmStackValue final : TLB_Complex { - enum { vm_stk_null, vm_stk_tinyint, vm_stk_int, vm_stk_nan, vm_stk_cell, vm_stk_slice, vm_stk_builder, vm_stk_cont, vm_stk_tuple }; - static constexpr char cons_len[9] = { 8, 8, 15, 16, 8, 8, 8, 8, 8 }; - static constexpr unsigned short cons_tag[9] = { 0, 1, 0x100, 0x2ff, 3, 4, 5, 6, 7 }; - struct Record_vm_stk_null { - typedef VmStackValue type_class; - }; - struct Record_vm_stk_tinyint { - typedef VmStackValue type_class; - long long value; // value : int64 - Record_vm_stk_tinyint() = default; - Record_vm_stk_tinyint(long long _value) : value(_value) {} - }; - struct Record_vm_stk_int { - typedef VmStackValue type_class; - RefInt256 value; // value : int257 - Record_vm_stk_int() = default; - Record_vm_stk_int(RefInt256 _value) : value(std::move(_value)) {} - }; - struct Record_vm_stk_nan { - typedef VmStackValue type_class; - }; - struct Record_vm_stk_cell { - typedef VmStackValue type_class; - Ref cell; // cell : ^Cell - Record_vm_stk_cell() = default; - Record_vm_stk_cell(Ref _cell) : cell(std::move(_cell)) {} - }; - struct Record_vm_stk_slice { - typedef VmStackValue type_class; - Ref x; // VmCellSlice - Record_vm_stk_slice() = default; - Record_vm_stk_slice(Ref _x) : x(std::move(_x)) {} - }; - struct Record_vm_stk_builder { - typedef VmStackValue type_class; - Ref cell; // cell : ^Cell - Record_vm_stk_builder() = default; - Record_vm_stk_builder(Ref _cell) : cell(std::move(_cell)) {} - }; - struct Record_vm_stk_cont { - typedef VmStackValue type_class; - Ref cont; // cont : VmCont - Record_vm_stk_cont() = default; - Record_vm_stk_cont(Ref _cont) : cont(std::move(_cont)) {} - }; - struct Record_vm_stk_tuple { - typedef VmStackValue type_class; - int len; // len : ## 16 - Ref data; // data : VmTuple len - Record_vm_stk_tuple() = default; - Record_vm_stk_tuple(int _len, Ref _data) : len(_len), data(std::move(_data)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vm_stk_null& data) const; - bool unpack_vm_stk_null(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_null& data) const; - bool cell_unpack_vm_stk_null(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_null& data) const; - bool pack_vm_stk_null(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_null& data) const; - bool cell_pack_vm_stk_null(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_tinyint& data) const; - bool unpack_vm_stk_tinyint(vm::CellSlice& cs, long long& value) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_tinyint& data) const; - bool cell_unpack_vm_stk_tinyint(Ref cell_ref, long long& value) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_tinyint& data) const; - bool pack_vm_stk_tinyint(vm::CellBuilder& cb, long long value) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_tinyint& data) const; - bool cell_pack_vm_stk_tinyint(Ref& cell_ref, long long value) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_int& data) const; - bool unpack_vm_stk_int(vm::CellSlice& cs, RefInt256& value) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_int& data) const; - bool cell_unpack_vm_stk_int(Ref cell_ref, RefInt256& value) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_int& data) const; - bool pack_vm_stk_int(vm::CellBuilder& cb, RefInt256 value) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_int& data) const; - bool cell_pack_vm_stk_int(Ref& cell_ref, RefInt256 value) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_nan& data) const; - bool unpack_vm_stk_nan(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_nan& data) const; - bool cell_unpack_vm_stk_nan(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_nan& data) const; - bool pack_vm_stk_nan(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_nan& data) const; - bool cell_pack_vm_stk_nan(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_cell& data) const; - bool unpack_vm_stk_cell(vm::CellSlice& cs, Ref& cell) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_cell& data) const; - bool cell_unpack_vm_stk_cell(Ref cell_ref, Ref& cell) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_cell& data) const; - bool pack_vm_stk_cell(vm::CellBuilder& cb, Ref cell) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_cell& data) const; - bool cell_pack_vm_stk_cell(Ref& cell_ref, Ref cell) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_slice& data) const; - bool unpack_vm_stk_slice(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_slice& data) const; - bool cell_unpack_vm_stk_slice(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_slice& data) const; - bool pack_vm_stk_slice(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_slice& data) const; - bool cell_pack_vm_stk_slice(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_builder& data) const; - bool unpack_vm_stk_builder(vm::CellSlice& cs, Ref& cell) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_builder& data) const; - bool cell_unpack_vm_stk_builder(Ref cell_ref, Ref& cell) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_builder& data) const; - bool pack_vm_stk_builder(vm::CellBuilder& cb, Ref cell) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_builder& data) const; - bool cell_pack_vm_stk_builder(Ref& cell_ref, Ref cell) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_cont& data) const; - bool unpack_vm_stk_cont(vm::CellSlice& cs, Ref& cont) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_cont& data) const; - bool cell_unpack_vm_stk_cont(Ref cell_ref, Ref& cont) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_cont& data) const; - bool pack_vm_stk_cont(vm::CellBuilder& cb, Ref cont) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_cont& data) const; - bool cell_pack_vm_stk_cont(Ref& cell_ref, Ref cont) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_tuple& data) const; - bool unpack_vm_stk_tuple(vm::CellSlice& cs, int& len, Ref& data) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_tuple& data) const; - bool cell_unpack_vm_stk_tuple(Ref cell_ref, int& len, Ref& data) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_tuple& data) const; - bool pack_vm_stk_tuple(vm::CellBuilder& cb, int len, Ref data) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_tuple& data) const; - bool cell_pack_vm_stk_tuple(Ref& cell_ref, int len, Ref data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmStackValue"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -extern const VmStackValue t_VmStackValue; - -// -// headers for type `VmStack` -// - -struct VmStack final : TLB_Complex { - enum { vm_stack }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef VmStack type_class; - int depth; // depth : ## 24 - Ref stack; // stack : VmStackList depth - Record() = default; - Record(int _depth, Ref _stack) : depth(_depth), stack(std::move(_stack)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_vm_stack(vm::CellSlice& cs, int& depth, Ref& stack) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_vm_stack(Ref cell_ref, int& depth, Ref& stack) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_vm_stack(vm::CellBuilder& cb, int depth, Ref stack) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_vm_stack(Ref& cell_ref, int depth, Ref stack) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmStack"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const VmStack t_VmStack; - -// -// headers for type `VmStackList` -// - -struct VmStackList final : TLB_Complex { - enum { vm_stk_cons, vm_stk_nil }; - static constexpr int cons_len_exact = 0; - int m_; - VmStackList(int m) : m_(m) {} - struct Record_vm_stk_cons; - struct Record_vm_stk_nil { - typedef VmStackList type_class; - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vm_stk_cons& data) const; - bool unpack_vm_stk_cons(vm::CellSlice& cs, int& n, Ref& rest, Ref& tos) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_cons& data) const; - bool cell_unpack_vm_stk_cons(Ref cell_ref, int& n, Ref& rest, Ref& tos) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_cons& data) const; - bool pack_vm_stk_cons(vm::CellBuilder& cb, Ref rest, Ref tos) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_cons& data) const; - bool cell_pack_vm_stk_cons(Ref& cell_ref, Ref rest, Ref tos) const; - bool unpack(vm::CellSlice& cs, Record_vm_stk_nil& data) const; - bool unpack_vm_stk_nil(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vm_stk_nil& data) const; - bool cell_unpack_vm_stk_nil(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vm_stk_nil& data) const; - bool pack_vm_stk_nil(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vm_stk_nil& data) const; - bool cell_pack_vm_stk_nil(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VmStackList " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct VmStackList::Record_vm_stk_cons { - typedef VmStackList type_class; - int n; // n : # - Ref rest; // rest : ^(VmStackList n) - Ref tos; // tos : VmStackValue - Record_vm_stk_cons() = default; - Record_vm_stk_cons(Ref _rest, Ref _tos) : n(-1), rest(std::move(_rest)), tos(std::move(_tos)) {} -}; - -// -// headers for type `VmSaveList` -// - -struct VmSaveList final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef VmSaveList type_class; - Ref cregs; // cregs : HashmapE 4 VmStackValue - Record() = default; - Record(Ref _cregs) : cregs(std::move(_cregs)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& cregs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& cregs) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref cregs) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref cregs) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmSaveList"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const VmSaveList t_VmSaveList; - -// -// headers for auxiliary type `VmGasLimits_aux` -// - -struct VmGasLimits_aux final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 192; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(192); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(192); - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, long long& max_limit, long long& cur_limit, long long& credit) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, long long& max_limit, long long& cur_limit, long long& credit) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, long long max_limit, long long cur_limit, long long credit) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, long long max_limit, long long cur_limit, long long credit) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmGasLimits_aux"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VmGasLimits_aux::Record { - typedef VmGasLimits_aux type_class; - long long max_limit; // max_limit : int64 - long long cur_limit; // cur_limit : int64 - long long credit; // credit : int64 - Record() = default; - Record(long long _max_limit, long long _cur_limit, long long _credit) : max_limit(_max_limit), cur_limit(_cur_limit), credit(_credit) {} -}; - -extern const VmGasLimits_aux t_VmGasLimits_aux; - -// -// headers for type `VmGasLimits` -// - -struct VmGasLimits final : TLB_Complex { - enum { gas_limits }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef VmGasLimits type_class; - long long remaining; // remaining : int64 - VmGasLimits_aux::Record r1; // ^[$_ max_limit:int64 cur_limit:int64 credit:int64 ] - Record() = default; - Record(long long _remaining, const VmGasLimits_aux::Record& _r1) : remaining(_remaining), r1(_r1) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x10040; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10040); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmGasLimits"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const VmGasLimits t_VmGasLimits; - -// -// headers for type `VmLibraries` -// - -struct VmLibraries final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef VmLibraries type_class; - Ref libraries; // libraries : HashmapE 256 ^Cell - Record() = default; - Record(Ref _libraries) : libraries(std::move(_libraries)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& libraries) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& libraries) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref libraries) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref libraries) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmLibraries"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const VmLibraries t_VmLibraries; - -// -// headers for type `VmControlData` -// - -struct VmControlData final : TLB_Complex { - enum { vm_ctl_data }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmControlData"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct VmControlData::Record { - typedef VmControlData type_class; - Ref nargs; // nargs : Maybe uint13 - Ref stack; // stack : Maybe VmStack - Ref save; // save : VmSaveList - Ref cp; // cp : Maybe int16 - Record() = default; - Record(Ref _nargs, Ref _stack, Ref _save, Ref _cp) : nargs(std::move(_nargs)), stack(std::move(_stack)), save(std::move(_save)), cp(std::move(_cp)) {} -}; - -extern const VmControlData t_VmControlData; - -// -// headers for type `VmCont` -// - -struct VmCont final : TLB_Complex { - enum { vmc_std, vmc_envelope, vmc_quit, vmc_quit_exc, vmc_repeat, vmc_until, vmc_again, vmc_while_cond, vmc_while_body, vmc_pushint }; - static constexpr char cons_len[10] = { 2, 2, 4, 4, 5, 6, 6, 6, 6, 4 }; - static constexpr unsigned char cons_tag[10] = { 0, 1, 8, 9, 20, 0x30, 0x31, 0x32, 0x33, 15 }; - struct Record_vmc_std { - typedef VmCont type_class; - Ref cdata; // cdata : VmControlData - Ref code; // code : VmCellSlice - Record_vmc_std() = default; - Record_vmc_std(Ref _cdata, Ref _code) : cdata(std::move(_cdata)), code(std::move(_code)) {} - }; - struct Record_vmc_envelope { - typedef VmCont type_class; - Ref cdata; // cdata : VmControlData - Ref next; // next : ^VmCont - Record_vmc_envelope() = default; - Record_vmc_envelope(Ref _cdata, Ref _next) : cdata(std::move(_cdata)), next(std::move(_next)) {} - }; - struct Record_vmc_quit { - typedef VmCont type_class; - int exit_code; // exit_code : int32 - Record_vmc_quit() = default; - Record_vmc_quit(int _exit_code) : exit_code(_exit_code) {} - }; - struct Record_vmc_quit_exc { - typedef VmCont type_class; - }; - struct Record_vmc_repeat; - struct Record_vmc_until { - typedef VmCont type_class; - Ref body; // body : ^VmCont - Ref after; // after : ^VmCont - Record_vmc_until() = default; - Record_vmc_until(Ref _body, Ref _after) : body(std::move(_body)), after(std::move(_after)) {} - }; - struct Record_vmc_again { - typedef VmCont type_class; - Ref body; // body : ^VmCont - Record_vmc_again() = default; - Record_vmc_again(Ref _body) : body(std::move(_body)) {} - }; - struct Record_vmc_while_cond; - struct Record_vmc_while_body; - struct Record_vmc_pushint { - typedef VmCont type_class; - int value; // value : int32 - Ref next; // next : ^VmCont - Record_vmc_pushint() = default; - Record_vmc_pushint(int _value, Ref _next) : value(_value), next(std::move(_next)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_vmc_std& data) const; - bool unpack_vmc_std(vm::CellSlice& cs, Ref& cdata, Ref& code) const; - bool cell_unpack(Ref cell_ref, Record_vmc_std& data) const; - bool cell_unpack_vmc_std(Ref cell_ref, Ref& cdata, Ref& code) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_std& data) const; - bool pack_vmc_std(vm::CellBuilder& cb, Ref cdata, Ref code) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_std& data) const; - bool cell_pack_vmc_std(Ref& cell_ref, Ref cdata, Ref code) const; - bool unpack(vm::CellSlice& cs, Record_vmc_envelope& data) const; - bool unpack_vmc_envelope(vm::CellSlice& cs, Ref& cdata, Ref& next) const; - bool cell_unpack(Ref cell_ref, Record_vmc_envelope& data) const; - bool cell_unpack_vmc_envelope(Ref cell_ref, Ref& cdata, Ref& next) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_envelope& data) const; - bool pack_vmc_envelope(vm::CellBuilder& cb, Ref cdata, Ref next) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_envelope& data) const; - bool cell_pack_vmc_envelope(Ref& cell_ref, Ref cdata, Ref next) const; - bool unpack(vm::CellSlice& cs, Record_vmc_quit& data) const; - bool unpack_vmc_quit(vm::CellSlice& cs, int& exit_code) const; - bool cell_unpack(Ref cell_ref, Record_vmc_quit& data) const; - bool cell_unpack_vmc_quit(Ref cell_ref, int& exit_code) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_quit& data) const; - bool pack_vmc_quit(vm::CellBuilder& cb, int exit_code) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_quit& data) const; - bool cell_pack_vmc_quit(Ref& cell_ref, int exit_code) const; - bool unpack(vm::CellSlice& cs, Record_vmc_quit_exc& data) const; - bool unpack_vmc_quit_exc(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_vmc_quit_exc& data) const; - bool cell_unpack_vmc_quit_exc(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_quit_exc& data) const; - bool pack_vmc_quit_exc(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_quit_exc& data) const; - bool cell_pack_vmc_quit_exc(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_vmc_repeat& data) const; - bool unpack_vmc_repeat(vm::CellSlice& cs, long long& count, Ref& body, Ref& after) const; - bool cell_unpack(Ref cell_ref, Record_vmc_repeat& data) const; - bool cell_unpack_vmc_repeat(Ref cell_ref, long long& count, Ref& body, Ref& after) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_repeat& data) const; - bool pack_vmc_repeat(vm::CellBuilder& cb, long long count, Ref body, Ref after) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_repeat& data) const; - bool cell_pack_vmc_repeat(Ref& cell_ref, long long count, Ref body, Ref after) const; - bool unpack(vm::CellSlice& cs, Record_vmc_until& data) const; - bool unpack_vmc_until(vm::CellSlice& cs, Ref& body, Ref& after) const; - bool cell_unpack(Ref cell_ref, Record_vmc_until& data) const; - bool cell_unpack_vmc_until(Ref cell_ref, Ref& body, Ref& after) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_until& data) const; - bool pack_vmc_until(vm::CellBuilder& cb, Ref body, Ref after) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_until& data) const; - bool cell_pack_vmc_until(Ref& cell_ref, Ref body, Ref after) const; - bool unpack(vm::CellSlice& cs, Record_vmc_again& data) const; - bool unpack_vmc_again(vm::CellSlice& cs, Ref& body) const; - bool cell_unpack(Ref cell_ref, Record_vmc_again& data) const; - bool cell_unpack_vmc_again(Ref cell_ref, Ref& body) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_again& data) const; - bool pack_vmc_again(vm::CellBuilder& cb, Ref body) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_again& data) const; - bool cell_pack_vmc_again(Ref& cell_ref, Ref body) const; - bool unpack(vm::CellSlice& cs, Record_vmc_while_cond& data) const; - bool unpack_vmc_while_cond(vm::CellSlice& cs, Ref& cond, Ref& body, Ref& after) const; - bool cell_unpack(Ref cell_ref, Record_vmc_while_cond& data) const; - bool cell_unpack_vmc_while_cond(Ref cell_ref, Ref& cond, Ref& body, Ref& after) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_while_cond& data) const; - bool pack_vmc_while_cond(vm::CellBuilder& cb, Ref cond, Ref body, Ref after) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_while_cond& data) const; - bool cell_pack_vmc_while_cond(Ref& cell_ref, Ref cond, Ref body, Ref after) const; - bool unpack(vm::CellSlice& cs, Record_vmc_while_body& data) const; - bool unpack_vmc_while_body(vm::CellSlice& cs, Ref& cond, Ref& body, Ref& after) const; - bool cell_unpack(Ref cell_ref, Record_vmc_while_body& data) const; - bool cell_unpack_vmc_while_body(Ref cell_ref, Ref& cond, Ref& body, Ref& after) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_while_body& data) const; - bool pack_vmc_while_body(vm::CellBuilder& cb, Ref cond, Ref body, Ref after) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_while_body& data) const; - bool cell_pack_vmc_while_body(Ref& cell_ref, Ref cond, Ref body, Ref after) const; - bool unpack(vm::CellSlice& cs, Record_vmc_pushint& data) const; - bool unpack_vmc_pushint(vm::CellSlice& cs, int& value, Ref& next) const; - bool cell_unpack(Ref cell_ref, Record_vmc_pushint& data) const; - bool cell_unpack_vmc_pushint(Ref cell_ref, int& value, Ref& next) const; - bool pack(vm::CellBuilder& cb, const Record_vmc_pushint& data) const; - bool pack_vmc_pushint(vm::CellBuilder& cb, int value, Ref next) const; - bool cell_pack(Ref& cell_ref, const Record_vmc_pushint& data) const; - bool cell_pack_vmc_pushint(Ref& cell_ref, int value, Ref next) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "VmCont"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect_ext(6, 0x100f011100010001ULL); - } -}; - -struct VmCont::Record_vmc_repeat { - typedef VmCont type_class; - long long count; // count : uint63 - Ref body; // body : ^VmCont - Ref after; // after : ^VmCont - Record_vmc_repeat() = default; - Record_vmc_repeat(long long _count, Ref _body, Ref _after) : count(_count), body(std::move(_body)), after(std::move(_after)) {} -}; - -struct VmCont::Record_vmc_while_cond { - typedef VmCont type_class; - Ref cond; // cond : ^VmCont - Ref body; // body : ^VmCont - Ref after; // after : ^VmCont - Record_vmc_while_cond() = default; - Record_vmc_while_cond(Ref _cond, Ref _body, Ref _after) : cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)) {} -}; - -struct VmCont::Record_vmc_while_body { - typedef VmCont type_class; - Ref cond; // cond : ^VmCont - Ref body; // body : ^VmCont - Ref after; // after : ^VmCont - Record_vmc_while_body() = default; - Record_vmc_while_body(Ref _cond, Ref _body, Ref _after) : cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)) {} -}; - -extern const VmCont t_VmCont; - -// -// headers for type `DNS_RecordSet` -// - -struct DNS_RecordSet final : TLB_Complex { - enum { cons1 }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef DNS_RecordSet type_class; - Ref x; // HashmapE 16 ^DNSRecord - Record() = default; - Record(Ref _x) : x(std::move(_x)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_cons1(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_cons1(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_cons1(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_cons1(Ref& cell_ref, Ref x) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "DNS_RecordSet"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const DNS_RecordSet t_DNS_RecordSet; - -// -// headers for type `TextChunkRef` -// - -struct TextChunkRef final : TLB_Complex { - enum { chunk_ref, chunk_ref_empty }; - static constexpr int cons_len_exact = 0; - int m_; - TextChunkRef(int m) : m_(m) {} - struct Record_chunk_ref { - typedef TextChunkRef type_class; - int n; // n : # - Ref ref; // ref : ^(TextChunks (n + 1)) - Record_chunk_ref() = default; - Record_chunk_ref(Ref _ref) : n(-1), ref(std::move(_ref)) {} - }; - struct Record_chunk_ref_empty { - typedef TextChunkRef type_class; - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_chunk_ref& data) const; - bool unpack_chunk_ref(vm::CellSlice& cs, int& n, Ref& ref) const; - bool cell_unpack(Ref cell_ref, Record_chunk_ref& data) const; - bool cell_unpack_chunk_ref(Ref cell_ref, int& n, Ref& ref) const; - bool pack(vm::CellBuilder& cb, const Record_chunk_ref& data) const; - bool pack_chunk_ref(vm::CellBuilder& cb, Ref ref) const; - bool cell_pack(Ref& cell_ref, const Record_chunk_ref& data) const; - bool cell_pack_chunk_ref(Ref& cell_ref, Ref ref) const; - bool unpack(vm::CellSlice& cs, Record_chunk_ref_empty& data) const; - bool unpack_chunk_ref_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_chunk_ref_empty& data) const; - bool cell_unpack_chunk_ref_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_chunk_ref_empty& data) const; - bool pack_chunk_ref_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_chunk_ref_empty& data) const; - bool cell_pack_chunk_ref_empty(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(TextChunkRef " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -// -// headers for type `TextChunks` -// - -struct TextChunks final : TLB_Complex { - enum { text_chunk, text_chunk_empty }; - static constexpr int cons_len_exact = 0; - int m_; - TextChunks(int m) : m_(m) {} - struct Record_text_chunk; - struct Record_text_chunk_empty { - typedef TextChunks type_class; - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_text_chunk& data) const; - bool cell_unpack(Ref cell_ref, Record_text_chunk& data) const; - bool pack(vm::CellBuilder& cb, const Record_text_chunk& data) const; - bool cell_pack(Ref& cell_ref, const Record_text_chunk& data) const; - bool unpack(vm::CellSlice& cs, Record_text_chunk_empty& data) const; - bool unpack_text_chunk_empty(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_text_chunk_empty& data) const; - bool cell_unpack_text_chunk_empty(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_text_chunk_empty& data) const; - bool pack_text_chunk_empty(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_text_chunk_empty& data) const; - bool cell_pack_text_chunk_empty(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(TextChunks " << m_ << ")"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct TextChunks::Record_text_chunk { - typedef TextChunks type_class; - int n; // n : # - int len; // len : ## 8 - Ref data; // data : bits (8 * len) - Ref next; // next : TextChunkRef n - Record_text_chunk() = default; - Record_text_chunk(int _len, Ref _data, Ref _next) : n(-1), len(_len), data(std::move(_data)), next(std::move(_next)) {} -}; - -// -// headers for type `Text` -// - -struct Text final : TLB_Complex { - enum { text }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef Text type_class; - int chunks; // chunks : ## 8 - Ref rest; // rest : TextChunks chunks - Record() = default; - Record(int _chunks, Ref _rest) : chunks(_chunks), rest(std::move(_rest)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_text(vm::CellSlice& cs, int& chunks, Ref& rest) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_text(Ref cell_ref, int& chunks, Ref& rest) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_text(vm::CellBuilder& cb, int chunks, Ref rest) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_text(Ref& cell_ref, int chunks, Ref rest) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Text"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Text t_Text; - -// -// headers for type `ProtoList` -// - -struct ProtoList final : TLB_Complex { - enum { proto_list_nil, proto_list_next }; - static constexpr int cons_len_exact = 1; - struct Record_proto_list_nil { - typedef ProtoList type_class; - }; - struct Record_proto_list_next { - typedef ProtoList type_class; - char head; // head : Protocol - Ref tail; // tail : ProtoList - Record_proto_list_next() = default; - Record_proto_list_next(char _head, Ref _tail) : head(_head), tail(std::move(_tail)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_proto_list_nil& data) const; - bool unpack_proto_list_nil(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_proto_list_nil& data) const; - bool cell_unpack_proto_list_nil(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_proto_list_nil& data) const; - bool pack_proto_list_nil(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_proto_list_nil& data) const; - bool cell_pack_proto_list_nil(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_proto_list_next& data) const; - bool unpack_proto_list_next(vm::CellSlice& cs, char& head, Ref& tail) const; - bool cell_unpack(Ref cell_ref, Record_proto_list_next& data) const; - bool cell_unpack_proto_list_next(Ref cell_ref, char& head, Ref& tail) const; - bool pack(vm::CellBuilder& cb, const Record_proto_list_next& data) const; - bool pack_proto_list_next(vm::CellBuilder& cb, char head, Ref tail) const; - bool cell_pack(Ref& cell_ref, const Record_proto_list_next& data) const; - bool cell_pack_proto_list_next(Ref& cell_ref, char head, Ref tail) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ProtoList"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const ProtoList t_ProtoList; - -// -// headers for type `Protocol` -// - -struct Protocol final : TLB_Complex { - enum { proto_http }; - static constexpr int cons_len_exact = 16; - static constexpr unsigned short cons_tag[1] = { 0x4854 }; - struct Record { - typedef Protocol type_class; - }; - int get_size(const vm::CellSlice& cs) const override { - return 16; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(16); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_enum_to(vm::CellSlice& cs, char& value) const; - bool store_enum_from(vm::CellBuilder& cb, int value) const; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_proto_http(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_proto_http(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_proto_http(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_proto_http(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "Protocol"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const Protocol t_Protocol; - -// -// headers for type `DNSRecord` -// - -struct DNSRecord final : TLB_Complex { - enum { dns_text, dns_smc_address, dns_adnl_address, dns_next_resolver }; - static constexpr int cons_len_exact = 16; - static constexpr unsigned short cons_tag[4] = { 0x1eda, 0x9fd3, 0xad01, 0xba93 }; - struct Record_dns_text { - typedef DNSRecord type_class; - Ref x; // Text - Record_dns_text() = default; - Record_dns_text(Ref _x) : x(std::move(_x)) {} - }; - struct Record_dns_next_resolver { - typedef DNSRecord type_class; - Ref resolver; // resolver : MsgAddressInt - Record_dns_next_resolver() = default; - Record_dns_next_resolver(Ref _resolver) : resolver(std::move(_resolver)) {} - }; - struct Record_dns_adnl_address; - struct Record_dns_smc_address; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_dns_text& data) const; - bool unpack_dns_text(vm::CellSlice& cs, Ref& x) const; - bool cell_unpack(Ref cell_ref, Record_dns_text& data) const; - bool cell_unpack_dns_text(Ref cell_ref, Ref& x) const; - bool pack(vm::CellBuilder& cb, const Record_dns_text& data) const; - bool pack_dns_text(vm::CellBuilder& cb, Ref x) const; - bool cell_pack(Ref& cell_ref, const Record_dns_text& data) const; - bool cell_pack_dns_text(Ref& cell_ref, Ref x) const; - bool unpack(vm::CellSlice& cs, Record_dns_next_resolver& data) const; - bool unpack_dns_next_resolver(vm::CellSlice& cs, Ref& resolver) const; - bool cell_unpack(Ref cell_ref, Record_dns_next_resolver& data) const; - bool cell_unpack_dns_next_resolver(Ref cell_ref, Ref& resolver) const; - bool pack(vm::CellBuilder& cb, const Record_dns_next_resolver& data) const; - bool pack_dns_next_resolver(vm::CellBuilder& cb, Ref resolver) const; - bool cell_pack(Ref& cell_ref, const Record_dns_next_resolver& data) const; - bool cell_pack_dns_next_resolver(Ref& cell_ref, Ref resolver) const; - bool unpack(vm::CellSlice& cs, Record_dns_adnl_address& data) const; - bool unpack_dns_adnl_address(vm::CellSlice& cs, td::BitArray<256>& adnl_addr, int& flags, Ref& proto_list) const; - bool cell_unpack(Ref cell_ref, Record_dns_adnl_address& data) const; - bool cell_unpack_dns_adnl_address(Ref cell_ref, td::BitArray<256>& adnl_addr, int& flags, Ref& proto_list) const; - bool pack(vm::CellBuilder& cb, const Record_dns_adnl_address& data) const; - bool pack_dns_adnl_address(vm::CellBuilder& cb, td::BitArray<256> adnl_addr, int flags, Ref proto_list) const; - bool cell_pack(Ref& cell_ref, const Record_dns_adnl_address& data) const; - bool cell_pack_dns_adnl_address(Ref& cell_ref, td::BitArray<256> adnl_addr, int flags, Ref proto_list) const; - bool unpack(vm::CellSlice& cs, Record_dns_smc_address& data) const; - bool unpack_dns_smc_address(vm::CellSlice& cs, Ref& smc_addr, int& flags, Ref& cap_list) const; - bool cell_unpack(Ref cell_ref, Record_dns_smc_address& data) const; - bool cell_unpack_dns_smc_address(Ref cell_ref, Ref& smc_addr, int& flags, Ref& cap_list) const; - bool pack(vm::CellBuilder& cb, const Record_dns_smc_address& data) const; - bool pack_dns_smc_address(vm::CellBuilder& cb, Ref smc_addr, int flags, Ref cap_list) const; - bool cell_pack(Ref& cell_ref, const Record_dns_smc_address& data) const; - bool cell_pack_dns_smc_address(Ref& cell_ref, Ref smc_addr, int flags, Ref cap_list) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "DNSRecord"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 0xe02); - } -}; - -struct DNSRecord::Record_dns_adnl_address { - typedef DNSRecord type_class; - td::BitArray<256> adnl_addr; // adnl_addr : bits256 - int flags; // flags : ## 8 - Ref proto_list; // proto_list : flags.0?ProtoList - Record_dns_adnl_address() = default; - Record_dns_adnl_address(const td::BitArray<256>& _adnl_addr, int _flags, Ref _proto_list) : adnl_addr(_adnl_addr), flags(_flags), proto_list(std::move(_proto_list)) {} -}; - -struct DNSRecord::Record_dns_smc_address { - typedef DNSRecord type_class; - Ref smc_addr; // smc_addr : MsgAddressInt - int flags; // flags : ## 8 - Ref cap_list; // cap_list : flags.0?SmcCapList - Record_dns_smc_address() = default; - Record_dns_smc_address(Ref _smc_addr, int _flags, Ref _cap_list) : smc_addr(std::move(_smc_addr)), flags(_flags), cap_list(std::move(_cap_list)) {} -}; - -extern const DNSRecord t_DNSRecord; - -// -// headers for type `SmcCapList` -// - -struct SmcCapList final : TLB_Complex { - enum { cap_list_nil, cap_list_next }; - static constexpr int cons_len_exact = 1; - struct Record_cap_list_nil { - typedef SmcCapList type_class; - }; - struct Record_cap_list_next { - typedef SmcCapList type_class; - Ref head; // head : SmcCapability - Ref tail; // tail : SmcCapList - Record_cap_list_next() = default; - Record_cap_list_next(Ref _head, Ref _tail) : head(std::move(_head)), tail(std::move(_tail)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cap_list_nil& data) const; - bool unpack_cap_list_nil(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cap_list_nil& data) const; - bool cell_unpack_cap_list_nil(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cap_list_nil& data) const; - bool pack_cap_list_nil(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cap_list_nil& data) const; - bool cell_pack_cap_list_nil(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cap_list_next& data) const; - bool unpack_cap_list_next(vm::CellSlice& cs, Ref& head, Ref& tail) const; - bool cell_unpack(Ref cell_ref, Record_cap_list_next& data) const; - bool cell_unpack_cap_list_next(Ref cell_ref, Ref& head, Ref& tail) const; - bool pack(vm::CellBuilder& cb, const Record_cap_list_next& data) const; - bool pack_cap_list_next(vm::CellBuilder& cb, Ref head, Ref tail) const; - bool cell_pack(Ref& cell_ref, const Record_cap_list_next& data) const; - bool cell_pack_cap_list_next(Ref& cell_ref, Ref head, Ref tail) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SmcCapList"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const SmcCapList t_SmcCapList; - -// -// headers for type `SmcCapability` -// - -struct SmcCapability final : TLB_Complex { - enum { cap_is_wallet, cap_method_seqno, cap_method_pubkey, cap_name }; - static constexpr char cons_len[4] = { 16, 16, 16, 8 }; - static constexpr unsigned short cons_tag[4] = { 0x2177, 0x5371, 0x71f4, 0xff }; - struct Record_cap_method_seqno { - typedef SmcCapability type_class; - }; - struct Record_cap_method_pubkey { - typedef SmcCapability type_class; - }; - struct Record_cap_is_wallet { - typedef SmcCapability type_class; - }; - struct Record_cap_name { - typedef SmcCapability type_class; - Ref name; // name : Text - Record_cap_name() = default; - Record_cap_name(Ref _name) : name(std::move(_name)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_cap_method_seqno& data) const; - bool unpack_cap_method_seqno(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cap_method_seqno& data) const; - bool cell_unpack_cap_method_seqno(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cap_method_seqno& data) const; - bool pack_cap_method_seqno(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cap_method_seqno& data) const; - bool cell_pack_cap_method_seqno(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cap_method_pubkey& data) const; - bool unpack_cap_method_pubkey(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cap_method_pubkey& data) const; - bool cell_unpack_cap_method_pubkey(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cap_method_pubkey& data) const; - bool pack_cap_method_pubkey(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cap_method_pubkey& data) const; - bool cell_pack_cap_method_pubkey(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cap_is_wallet& data) const; - bool unpack_cap_is_wallet(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_cap_is_wallet& data) const; - bool cell_unpack_cap_is_wallet(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_cap_is_wallet& data) const; - bool pack_cap_is_wallet(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_cap_is_wallet& data) const; - bool cell_pack_cap_is_wallet(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_cap_name& data) const; - bool unpack_cap_name(vm::CellSlice& cs, Ref& name) const; - bool cell_unpack(Ref cell_ref, Record_cap_name& data) const; - bool cell_unpack_cap_name(Ref cell_ref, Ref& name) const; - bool pack(vm::CellBuilder& cb, const Record_cap_name& data) const; - bool pack_cap_name(vm::CellBuilder& cb, Ref name) const; - bool cell_pack(Ref& cell_ref, const Record_cap_name& data) const; - bool cell_pack_cap_name(Ref& cell_ref, Ref name) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "SmcCapability"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(3, 0x8e); - } -}; - -extern const SmcCapability t_SmcCapability; - -// -// headers for type `ChanConfig` -// - -struct ChanConfig final : TLB_Complex { - enum { chan_config }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanConfig"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ChanConfig::Record { - typedef ChanConfig type_class; - unsigned init_timeout; // init_timeout : uint32 - unsigned close_timeout; // close_timeout : uint32 - td::BitArray<256> a_key; // a_key : bits256 - td::BitArray<256> b_key; // b_key : bits256 - Ref a_addr; // a_addr : ^MsgAddressInt - Ref b_addr; // b_addr : ^MsgAddressInt - unsigned long long channel_id; // channel_id : uint64 - Ref min_A_extra; // min_A_extra : Grams - Record() = default; - Record(unsigned _init_timeout, unsigned _close_timeout, const td::BitArray<256>& _a_key, const td::BitArray<256>& _b_key, Ref _a_addr, Ref _b_addr, unsigned long long _channel_id, Ref _min_A_extra) : init_timeout(_init_timeout), close_timeout(_close_timeout), a_key(_a_key), b_key(_b_key), a_addr(std::move(_a_addr)), b_addr(std::move(_b_addr)), channel_id(_channel_id), min_A_extra(std::move(_min_A_extra)) {} -}; - -extern const ChanConfig t_ChanConfig; - -// -// headers for type `ChanState` -// - -struct ChanState final : TLB_Complex { - enum { chan_state_init, chan_state_close, chan_state_payout }; - static constexpr int cons_len_exact = 3; - struct Record_chan_state_init; - struct Record_chan_state_close; - struct Record_chan_state_payout { - typedef ChanState type_class; - Ref A; // A : Grams - Ref B; // B : Grams - Record_chan_state_payout() = default; - Record_chan_state_payout(Ref _A, Ref _B) : A(std::move(_A)), B(std::move(_B)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_chan_state_init& data) const; - bool cell_unpack(Ref cell_ref, Record_chan_state_init& data) const; - bool pack(vm::CellBuilder& cb, const Record_chan_state_init& data) const; - bool cell_pack(Ref& cell_ref, const Record_chan_state_init& data) const; - bool unpack(vm::CellSlice& cs, Record_chan_state_close& data) const; - bool cell_unpack(Ref cell_ref, Record_chan_state_close& data) const; - bool pack(vm::CellBuilder& cb, const Record_chan_state_close& data) const; - bool cell_pack(Ref& cell_ref, const Record_chan_state_close& data) const; - bool unpack(vm::CellSlice& cs, Record_chan_state_payout& data) const; - bool unpack_chan_state_payout(vm::CellSlice& cs, Ref& A, Ref& B) const; - bool cell_unpack(Ref cell_ref, Record_chan_state_payout& data) const; - bool cell_unpack_chan_state_payout(Ref cell_ref, Ref& A, Ref& B) const; - bool pack(vm::CellBuilder& cb, const Record_chan_state_payout& data) const; - bool pack_chan_state_payout(vm::CellBuilder& cb, Ref A, Ref B) const; - bool cell_pack(Ref& cell_ref, const Record_chan_state_payout& data) const; - bool cell_pack_chan_state_payout(Ref& cell_ref, Ref A, Ref B) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanState"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(3, 7); - } -}; - -struct ChanState::Record_chan_state_init { - typedef ChanState type_class; - bool signed_A; // signed_A : Bool - bool signed_B; // signed_B : Bool - Ref min_A; // min_A : Grams - Ref min_B; // min_B : Grams - unsigned expire_at; // expire_at : uint32 - Ref A; // A : Grams - Ref B; // B : Grams - Record_chan_state_init() = default; - Record_chan_state_init(bool _signed_A, bool _signed_B, Ref _min_A, Ref _min_B, unsigned _expire_at, Ref _A, Ref _B) : signed_A(_signed_A), signed_B(_signed_B), min_A(std::move(_min_A)), min_B(std::move(_min_B)), expire_at(_expire_at), A(std::move(_A)), B(std::move(_B)) {} -}; - -struct ChanState::Record_chan_state_close { - typedef ChanState type_class; - bool signed_A; // signed_A : Bool - bool signed_B; // signed_B : Bool - Ref promise_A; // promise_A : Grams - Ref promise_B; // promise_B : Grams - unsigned expire_at; // expire_at : uint32 - Ref A; // A : Grams - Ref B; // B : Grams - Record_chan_state_close() = default; - Record_chan_state_close(bool _signed_A, bool _signed_B, Ref _promise_A, Ref _promise_B, unsigned _expire_at, Ref _A, Ref _B) : signed_A(_signed_A), signed_B(_signed_B), promise_A(std::move(_promise_A)), promise_B(std::move(_promise_B)), expire_at(_expire_at), A(std::move(_A)), B(std::move(_B)) {} -}; - -extern const ChanState t_ChanState; - -// -// headers for type `ChanPromise` -// - -struct ChanPromise final : TLB_Complex { - enum { chan_promise }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_chan_promise(vm::CellSlice& cs, unsigned long long& channel_id, Ref& promise_A, Ref& promise_B) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_chan_promise(Ref cell_ref, unsigned long long& channel_id, Ref& promise_A, Ref& promise_B) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_chan_promise(vm::CellBuilder& cb, unsigned long long channel_id, Ref promise_A, Ref promise_B) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_chan_promise(Ref& cell_ref, unsigned long long channel_id, Ref promise_A, Ref promise_B) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanPromise"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ChanPromise::Record { - typedef ChanPromise type_class; - unsigned long long channel_id; // channel_id : uint64 - Ref promise_A; // promise_A : Grams - Ref promise_B; // promise_B : Grams - Record() = default; - Record(unsigned long long _channel_id, Ref _promise_A, Ref _promise_B) : channel_id(_channel_id), promise_A(std::move(_promise_A)), promise_B(std::move(_promise_B)) {} -}; - -extern const ChanPromise t_ChanPromise; - -// -// headers for type `ChanSignedPromise` -// - -struct ChanSignedPromise final : TLB_Complex { - enum { chan_signed_promise }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ChanSignedPromise type_class; - Ref sig; // sig : Maybe ^bits512 - Ref promise; // promise : ChanPromise - Record() = default; - Record(Ref _sig, Ref _promise) : sig(std::move(_sig)), promise(std::move(_promise)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_chan_signed_promise(vm::CellSlice& cs, Ref& sig, Ref& promise) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_chan_signed_promise(Ref cell_ref, Ref& sig, Ref& promise) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_chan_signed_promise(vm::CellBuilder& cb, Ref sig, Ref promise) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_chan_signed_promise(Ref& cell_ref, Ref sig, Ref promise) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanSignedPromise"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ChanSignedPromise t_ChanSignedPromise; - -// -// headers for type `ChanMsg` -// - -struct ChanMsg final : TLB_Complex { - enum { chan_msg_init, chan_msg_payout, chan_msg_timeout, chan_msg_close }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[4] = { 0x27317822, 0x37fe7810, 0x43278a28, 0xf28ae183U }; - struct Record_chan_msg_init; - struct Record_chan_msg_close; - struct Record_chan_msg_timeout { - typedef ChanMsg type_class; - }; - struct Record_chan_msg_payout { - typedef ChanMsg type_class; - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record_chan_msg_init& data) const; - bool cell_unpack(Ref cell_ref, Record_chan_msg_init& data) const; - bool pack(vm::CellBuilder& cb, const Record_chan_msg_init& data) const; - bool cell_pack(Ref& cell_ref, const Record_chan_msg_init& data) const; - bool unpack(vm::CellSlice& cs, Record_chan_msg_close& data) const; - bool unpack_chan_msg_close(vm::CellSlice& cs, Ref& extra_A, Ref& extra_B, Ref& promise) const; - bool cell_unpack(Ref cell_ref, Record_chan_msg_close& data) const; - bool cell_unpack_chan_msg_close(Ref cell_ref, Ref& extra_A, Ref& extra_B, Ref& promise) const; - bool pack(vm::CellBuilder& cb, const Record_chan_msg_close& data) const; - bool pack_chan_msg_close(vm::CellBuilder& cb, Ref extra_A, Ref extra_B, Ref promise) const; - bool cell_pack(Ref& cell_ref, const Record_chan_msg_close& data) const; - bool cell_pack_chan_msg_close(Ref& cell_ref, Ref extra_A, Ref extra_B, Ref promise) const; - bool unpack(vm::CellSlice& cs, Record_chan_msg_timeout& data) const; - bool unpack_chan_msg_timeout(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_chan_msg_timeout& data) const; - bool cell_unpack_chan_msg_timeout(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_chan_msg_timeout& data) const; - bool pack_chan_msg_timeout(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_chan_msg_timeout& data) const; - bool cell_pack_chan_msg_timeout(Ref& cell_ref) const; - bool unpack(vm::CellSlice& cs, Record_chan_msg_payout& data) const; - bool unpack_chan_msg_payout(vm::CellSlice& cs) const; - bool cell_unpack(Ref cell_ref, Record_chan_msg_payout& data) const; - bool cell_unpack_chan_msg_payout(Ref cell_ref) const; - bool pack(vm::CellBuilder& cb, const Record_chan_msg_payout& data) const; - bool pack_chan_msg_payout(vm::CellBuilder& cb) const; - bool cell_pack(Ref& cell_ref, const Record_chan_msg_payout& data) const; - bool cell_pack_chan_msg_payout(Ref& cell_ref) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanMsg"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.bselect(4, 0x801c); - } -}; - -struct ChanMsg::Record_chan_msg_init { - typedef ChanMsg type_class; - Ref inc_A; // inc_A : Grams - Ref inc_B; // inc_B : Grams - Ref min_A; // min_A : Grams - Ref min_B; // min_B : Grams - unsigned long long channel_id; // channel_id : uint64 - Record_chan_msg_init() = default; - Record_chan_msg_init(Ref _inc_A, Ref _inc_B, Ref _min_A, Ref _min_B, unsigned long long _channel_id) : inc_A(std::move(_inc_A)), inc_B(std::move(_inc_B)), min_A(std::move(_min_A)), min_B(std::move(_min_B)), channel_id(_channel_id) {} -}; - -struct ChanMsg::Record_chan_msg_close { - typedef ChanMsg type_class; - Ref extra_A; // extra_A : Grams - Ref extra_B; // extra_B : Grams - Ref promise; // promise : ChanSignedPromise - Record_chan_msg_close() = default; - Record_chan_msg_close(Ref _extra_A, Ref _extra_B, Ref _promise) : extra_A(std::move(_extra_A)), extra_B(std::move(_extra_B)), promise(std::move(_promise)) {} -}; - -extern const ChanMsg t_ChanMsg; - -// -// headers for type `ChanSignedMsg` -// - -struct ChanSignedMsg final : TLB_Complex { - enum { chan_signed_msg }; - static constexpr int cons_len_exact = 0; - struct Record; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_chan_signed_msg(vm::CellSlice& cs, Ref& sig_A, Ref& sig_B, Ref& msg) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_chan_signed_msg(Ref cell_ref, Ref& sig_A, Ref& sig_B, Ref& msg) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_chan_signed_msg(vm::CellBuilder& cb, Ref sig_A, Ref sig_B, Ref msg) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_chan_signed_msg(Ref& cell_ref, Ref sig_A, Ref sig_B, Ref msg) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanSignedMsg"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -struct ChanSignedMsg::Record { - typedef ChanSignedMsg type_class; - Ref sig_A; // sig_A : Maybe ^bits512 - Ref sig_B; // sig_B : Maybe ^bits512 - Ref msg; // msg : ChanMsg - Record() = default; - Record(Ref _sig_A, Ref _sig_B, Ref _msg) : sig_A(std::move(_sig_A)), sig_B(std::move(_sig_B)), msg(std::move(_msg)) {} -}; - -extern const ChanSignedMsg t_ChanSignedMsg; - -// -// headers for type `ChanOp` -// - -struct ChanOp final : TLB_Complex { - enum { chan_op_cmd }; - static constexpr int cons_len_exact = 32; - static constexpr unsigned cons_tag[1] = { 0x912838d1U }; - struct Record { - typedef ChanOp type_class; - Ref msg; // msg : ChanSignedMsg - Record() = default; - Record(Ref _msg) : msg(std::move(_msg)) {} - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_chan_op_cmd(vm::CellSlice& cs, Ref& msg) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_chan_op_cmd(Ref cell_ref, Ref& msg) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_chan_op_cmd(vm::CellBuilder& cb, Ref msg) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_chan_op_cmd(Ref& cell_ref, Ref msg) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanOp"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ChanOp t_ChanOp; - -// -// headers for type `ChanData` -// - -struct ChanData final : TLB_Complex { - enum { chan_data }; - static constexpr int cons_len_exact = 0; - struct Record { - typedef ChanData type_class; - Ref config; // config : ^ChanConfig - Ref state; // state : ^ChanState - Record() = default; - Record(Ref _config, Ref _state) : config(std::move(_config)), state(std::move(_state)) {} - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x20000; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x20000); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack_chan_data(vm::CellSlice& cs, Ref& config, Ref& state) const; - bool cell_unpack(Ref cell_ref, Record& data) const; - bool cell_unpack_chan_data(Ref cell_ref, Ref& config, Ref& state) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool pack_chan_data(vm::CellBuilder& cb, Ref config, Ref state) const; - bool cell_pack(Ref& cell_ref, const Record& data) const; - bool cell_pack_chan_data(Ref& cell_ref, Ref config, Ref state) const; - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "ChanData"; - } - int check_tag(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ChanData t_ChanData; - -// declarations of constant types used - -// ## 1 -extern const NatWidth t_natwidth_1; -// ## 9 -extern const NatWidth t_natwidth_9; -// #<= 30 -extern const NatLeq t_natleq_30; -// Maybe Anycast -extern const Maybe t_Maybe_Anycast; -// int8 -extern const Int t_int8; -// bits256 -extern const Bits t_bits256; -// int32 -extern const Int t_int32; -// VarUInteger 16 -extern const VarUInteger t_VarUInteger_16; -// VarUInteger 32 -extern const VarUInteger t_VarUInteger_32; -// HashmapE 32 (VarUInteger 32) -extern const HashmapE t_HashmapE_32_VarUInteger_32; -// uint64 -extern const UInt t_uint64; -// uint32 -extern const UInt t_uint32; -// ## 5 -extern const NatWidth t_natwidth_5; -// Maybe (## 5) -extern const Maybe t_Maybe_natwidth_5; -// Maybe TickTock -extern const Maybe t_Maybe_TickTock; -// Maybe ^Cell -extern const Maybe t_Maybe_Ref_Cell; -// HashmapE 256 SimpleLib -extern const HashmapE t_HashmapE_256_SimpleLib; -// ^StateInit -extern const RefT t_Ref_StateInit; -// Either StateInit ^StateInit -extern const Either t_Either_StateInit_Ref_StateInit; -// Maybe (Either StateInit ^StateInit) -extern const Maybe t_Maybe_Either_StateInit_Ref_StateInit; -// Message Any -extern const Message t_Message_Any; -// #<= 96 -extern const NatLeq t_natleq_96; -// ^(Message Any) -extern const RefT t_Ref_Message_Any; -// ^Transaction -extern const RefT t_Ref_Transaction; -// ^MsgEnvelope -extern const RefT t_Ref_MsgEnvelope; -// HashmapAugE 256 InMsg ImportFees -extern const HashmapAugE t_HashmapAugE_256_InMsg_ImportFees; -// ^InMsg -extern const RefT t_Ref_InMsg; -// uint63 -extern const UInt t_uint63; -// HashmapAugE 256 OutMsg CurrencyCollection -extern const HashmapAugE t_HashmapAugE_256_OutMsg_CurrencyCollection; -// HashmapAugE 352 EnqueuedMsg uint64 -extern const HashmapAugE t_HashmapAugE_352_EnqueuedMsg_uint64; -// HashmapE 96 ProcessedUpto -extern const HashmapE t_HashmapE_96_ProcessedUpto; -// HashmapE 320 IhrPendingSince -extern const HashmapE t_HashmapE_320_IhrPendingSince; -// VarUInteger 7 -extern const VarUInteger t_VarUInteger_7; -// Maybe Grams -extern const Maybe t_Maybe_Grams; -// ^Account -extern const RefT t_Ref_Account; -// HashmapAugE 256 ShardAccount DepthBalanceInfo -extern const HashmapAugE t_HashmapAugE_256_ShardAccount_DepthBalanceInfo; -// uint15 -extern const UInt t_uint15; -// Maybe ^(Message Any) -extern const Maybe t_Maybe_Ref_Message_Any; -// HashmapE 15 ^(Message Any) -extern const HashmapE t_HashmapE_15_Ref_Message_Any; -// ^[$_ in_msg:(Maybe ^(Message Any)) out_msgs:(HashmapE 15 ^(Message Any)) ] -extern const RefT t_Ref_TYPE_1614; -// HASH_UPDATE Account -extern const HASH_UPDATE t_HASH_UPDATE_Account; -// ^(HASH_UPDATE Account) -extern const RefT t_Ref_HASH_UPDATE_Account; -// ^TransactionDescr -extern const RefT t_Ref_TransactionDescr; -// uint16 -extern const UInt t_uint16; -// HashmapAug 64 ^Transaction CurrencyCollection -extern const HashmapAug t_HashmapAug_64_Ref_Transaction_CurrencyCollection; -// HashmapAugE 256 AccountBlock CurrencyCollection -extern const HashmapAugE t_HashmapAugE_256_AccountBlock_CurrencyCollection; -// VarUInteger 3 -extern const VarUInteger t_VarUInteger_3; -// Maybe (VarUInteger 3) -extern const Maybe t_Maybe_VarUInteger_3; -// Maybe int32 -extern const Maybe t_Maybe_int32; -// ^[$_ gas_used:(VarUInteger 7) gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3)) mode:int8 exit_code:int32 exit_arg:(Maybe int32) vm_steps:uint32 vm_init_state_hash:bits256 vm_final_state_hash:bits256 ] -extern const RefT t_Ref_TYPE_1626; -// Maybe TrStoragePhase -extern const Maybe t_Maybe_TrStoragePhase; -// Maybe TrCreditPhase -extern const Maybe t_Maybe_TrCreditPhase; -// ^TrActionPhase -extern const RefT t_Ref_TrActionPhase; -// Maybe ^TrActionPhase -extern const Maybe t_Maybe_Ref_TrActionPhase; -// Maybe TrBouncePhase -extern const Maybe t_Maybe_TrBouncePhase; -// ## 6 -extern const NatWidth t_natwidth_6; -// ## 8 -extern const NatWidth t_natwidth_8; -// MessageRelaxed Any -extern const MessageRelaxed t_MessageRelaxed_Any; -// ^(MessageRelaxed Any) -extern const RefT t_Ref_MessageRelaxed_Any; -// ## 7 -extern const NatWidth t_natwidth_7; -// #<= 60 -extern const NatLeq t_natleq_60; -// ^OutMsgQueueInfo -extern const RefT t_Ref_OutMsgQueueInfo; -// ^ShardAccounts -extern const RefT t_Ref_ShardAccounts; -// HashmapE 256 LibDescr -extern const HashmapE t_HashmapE_256_LibDescr; -// Maybe BlkMasterInfo -extern const Maybe t_Maybe_BlkMasterInfo; -// ^[$_ overload_history:uint64 underload_history:uint64 total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ] -extern const RefT t_Ref_TYPE_1640; -// ^McStateExtra -extern const RefT t_Ref_McStateExtra; -// Maybe ^McStateExtra -extern const Maybe t_Maybe_Ref_McStateExtra; -// ^ShardStateUnsplit -extern const RefT t_Ref_ShardStateUnsplit; -// Hashmap 256 True -extern const Hashmap t_Hashmap_256_True; -// ^BlkMasterInfo -extern const RefT t_Ref_BlkMasterInfo; -// BlkPrevInfo 0 -extern const BlkPrevInfo t_BlkPrevInfo_0; -// ^(BlkPrevInfo 0) -extern const RefT t_Ref_BlkPrevInfo_0; -// ^ExtBlkRef -extern const RefT t_Ref_ExtBlkRef; -// ^BlockInfo -extern const RefT t_Ref_BlockInfo; -// ^ValueFlow -extern const RefT t_Ref_ValueFlow; -// MERKLE_UPDATE ShardState -extern const MERKLE_UPDATE t_MERKLE_UPDATE_ShardState; -// ^(MERKLE_UPDATE ShardState) -extern const RefT t_Ref_MERKLE_UPDATE_ShardState; -// ^BlockExtra -extern const RefT t_Ref_BlockExtra; -// ^InMsgDescr -extern const RefT t_Ref_InMsgDescr; -// ^OutMsgDescr -extern const RefT t_Ref_OutMsgDescr; -// ^ShardAccountBlocks -extern const RefT t_Ref_ShardAccountBlocks; -// ^McBlockExtra -extern const RefT t_Ref_McBlockExtra; -// Maybe ^McBlockExtra -extern const Maybe t_Maybe_Ref_McBlockExtra; -// ^[$_ from_prev_blk:CurrencyCollection to_next_blk:CurrencyCollection imported:CurrencyCollection exported:CurrencyCollection ] -extern const RefT t_Ref_TYPE_1651; -// ^[$_ fees_imported:CurrencyCollection recovered:CurrencyCollection created:CurrencyCollection minted:CurrencyCollection ] -extern const RefT t_Ref_TYPE_1652; -// ## 3 -extern const NatWidth t_natwidth_3; -// ^[$_ fees_collected:CurrencyCollection funds_created:CurrencyCollection ] -extern const RefT t_Ref_TYPE_1656; -// BinTree ShardDescr -extern const BinTree t_BinTree_ShardDescr; -// ^(BinTree ShardDescr) -extern const RefT t_Ref_BinTree_ShardDescr; -// HashmapE 32 ^(BinTree ShardDescr) -extern const HashmapE t_HashmapE_32_Ref_BinTree_ShardDescr; -// HashmapAugE 96 ShardFeeCreated ShardFeeCreated -extern const HashmapAugE t_HashmapAugE_96_ShardFeeCreated_ShardFeeCreated; -// Hashmap 32 ^Cell -extern const Hashmap t_Hashmap_32_Ref_Cell; -// ^(Hashmap 32 ^Cell) -extern const RefT t_Ref_Hashmap_32_Ref_Cell; -// HashmapAugE 32 KeyExtBlkRef KeyMaxLt -extern const HashmapAugE t_HashmapAugE_32_KeyExtBlkRef_KeyMaxLt; -// HashmapE 256 CreatorStats -extern const HashmapE t_HashmapE_256_CreatorStats; -// HashmapAugE 256 CreatorStats uint32 -extern const HashmapAugE t_HashmapAugE_256_CreatorStats_uint32; -// ## 16 -extern const NatWidth t_natwidth_16; -// Maybe ExtBlkRef -extern const Maybe t_Maybe_ExtBlkRef; -// ^[$_ flags:(## 16) {<= flags 1} validator_info:ValidatorInfo prev_blocks:OldMcBlocksInfo after_key_block:Bool last_key_block:(Maybe ExtBlkRef) block_create_stats:flags.0?BlockCreateStats ] -extern const RefT t_Ref_TYPE_1670; -// ^SignedCertificate -extern const RefT t_Ref_SignedCertificate; -// HashmapE 16 CryptoSignaturePair -extern const HashmapE t_HashmapE_16_CryptoSignaturePair; -// Maybe ^InMsg -extern const Maybe t_Maybe_Ref_InMsg; -// ^[$_ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair) recover_create_msg:(Maybe ^InMsg) mint_msg:(Maybe ^InMsg) ] -extern const RefT t_Ref_TYPE_1678; -// Hashmap 16 ValidatorDescr -extern const Hashmap t_Hashmap_16_ValidatorDescr; -// HashmapE 16 ValidatorDescr -extern const HashmapE t_HashmapE_16_ValidatorDescr; -// Hashmap 32 True -extern const Hashmap t_Hashmap_32_True; -// uint8 -extern const UInt t_uint8; -// ^ConfigProposalSetup -extern const RefT t_Ref_ConfigProposalSetup; -// uint256 -extern const UInt t_uint256; -// Maybe uint256 -extern const Maybe t_Maybe_uint256; -// ^ConfigProposal -extern const RefT t_Ref_ConfigProposal; -// HashmapE 16 True -extern const HashmapE t_HashmapE_16_True; -// int64 -extern const Int t_int64; -// ## 12 -extern const NatWidth t_natwidth_12; -// ## 32 -extern const NatWidth t_natwidth_32; -// ## 13 -extern const NatWidth t_natwidth_13; -// HashmapE 32 WorkchainDescr -extern const HashmapE t_HashmapE_32_WorkchainDescr; -// Hashmap 32 StoragePrices -extern const Hashmap t_Hashmap_32_StoragePrices; -// HashmapE 256 True -extern const HashmapE t_HashmapE_256_True; -// ^ValidatorTempKey -extern const RefT t_Ref_ValidatorTempKey; -// HashmapE 256 ValidatorSignedTempKey -extern const HashmapE t_HashmapE_256_ValidatorSignedTempKey; -// ^BlockSignatures -extern const RefT t_Ref_BlockSignatures; -// Maybe ^BlockSignatures -extern const Maybe t_Maybe_Ref_BlockSignatures; -// ^TopBlockDescr -extern const RefT t_Ref_TopBlockDescr; -// HashmapE 96 ^TopBlockDescr -extern const HashmapE t_HashmapE_96_Ref_TopBlockDescr; -// MERKLE_PROOF Block -extern const MERKLE_PROOF t_MERKLE_PROOF_Block; -// ^(MERKLE_PROOF Block) -extern const RefT t_Ref_MERKLE_PROOF_Block; -// MERKLE_PROOF ShardState -extern const MERKLE_PROOF t_MERKLE_PROOF_ShardState; -// ^(MERKLE_PROOF ShardState) -extern const RefT t_Ref_MERKLE_PROOF_ShardState; -// ^ProducerInfo -extern const RefT t_Ref_ProducerInfo; -// ^ComplaintDescr -extern const RefT t_Ref_ComplaintDescr; -// ^ValidatorComplaint -extern const RefT t_Ref_ValidatorComplaint; -// int257 -extern const Int t_int257; -// ## 10 -extern const NatWidth t_natwidth_10; -// #<= 4 -extern const NatLeq t_natleq_4; -// ^VmStackValue -extern const RefT t_Ref_VmStackValue; -// ## 24 -extern const NatWidth t_natwidth_24; -// HashmapE 4 VmStackValue -extern const HashmapE t_HashmapE_4_VmStackValue; -// ^[$_ max_limit:int64 cur_limit:int64 credit:int64 ] -extern const RefT t_Ref_TYPE_1717; -// HashmapE 256 ^Cell -extern const HashmapE t_HashmapE_256_Ref_Cell; -// uint13 -extern const UInt t_uint13; -// Maybe uint13 -extern const Maybe t_Maybe_uint13; -// Maybe VmStack -extern const Maybe t_Maybe_VmStack; -// int16 -extern const Int t_int16; -// Maybe int16 -extern const Maybe t_Maybe_int16; -// ^VmCont -extern const RefT t_Ref_VmCont; -// ^DNSRecord -extern const RefT t_Ref_DNSRecord; -// HashmapE 16 ^DNSRecord -extern const HashmapE t_HashmapE_16_Ref_DNSRecord; -// ^MsgAddressInt -extern const RefT t_Ref_MsgAddressInt; -// bits512 -extern const Bits t_bits512; -// ^bits512 -extern const RefT t_Ref_bits512; -// Maybe ^bits512 -extern const Maybe t_Maybe_Ref_bits512; -// ^ChanConfig -extern const RefT t_Ref_ChanConfig; -// ^ChanState -extern const RefT t_Ref_ChanState; - -// declaration of type name registration function -extern bool register_simple_types(std::function func); - -} // namespace gen - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-binlog.h b/submodules/ton/tonlib-src/crypto/block/block-binlog.h deleted file mode 100644 index 904f4c73..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-binlog.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/int_types.h" -#include "ton/ton-types.h" - -#include - -namespace block { - -namespace log { - -#pragma pack(push, 4) - -struct Start { - static constexpr unsigned tag = 0x0442446b; - static constexpr unsigned log_type = 0x290100; - unsigned tag_field; - unsigned type_field; - unsigned created_at; - unsigned char zerostate_root_hash[32]; - Start(const RootHash& hash, unsigned _now = 0) - : tag_field(tag), type_field(log_type), created_at(_now ? _now : (unsigned)std::time(nullptr)) { - td::as(zerostate_root_hash) = hash; - } -}; - -struct SetZeroState { - static constexpr unsigned tag = 0x63ab3cd9; - unsigned tag_field; - unsigned flags; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - SetZeroState(const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, unsigned _flags = 0) - : tag_field(tag), flags(_flags), file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - } -}; - -struct NewBlock { - static constexpr unsigned tag = 0x19f4bc63; - unsigned tag_field; - unsigned flags; // lower 8 bits = authority - int workchain; - unsigned seqno; - unsigned long long shard; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - unsigned char last_bytes[8]; - NewBlock(const ton::BlockId& block, const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, - unsigned _flags) - : tag_field(tag) - , flags(_flags) - , workchain(block.workchain) - , seqno(block.seqno) - , shard(block.shard) - , file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - td::as(last_bytes) = 0; - } -}; - -struct NewState { - static constexpr unsigned tag = 0x4190a21f; - unsigned tag_field; - unsigned flags; // lower 8 bits = authority - int workchain; - unsigned seqno; - unsigned long long shard; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - unsigned char last_bytes[8]; - NewState(const ton::BlockId& state, const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, - unsigned _flags) - : tag_field(tag) - , flags(_flags) - , workchain(state.workchain) - , seqno(state.seqno) - , shard(state.shard) - , file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - td::as(last_bytes) = 0; - } -}; - -#pragma pack(pop) - -} // namespace log -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-db-impl.h b/submodules/ton/tonlib-src/crypto/block/block-db-impl.h deleted file mode 100644 index 07869ca9..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-db-impl.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include "vm/cells.h" -#include "block/Binlog.h" -#include "block/block-db.h" -#include "block/block-binlog.h" - -namespace block { -using td::Ref; - -/* - * - * BLOCK DATABASE - * - */ - -class BlockDbImpl; - -class BlockBinlogCallback : public BinlogCallback { - BlockDbImpl& db; - td::Status init_new_binlog(BinlogBuffer& bb) override; - int replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, unsigned long long log_pos) override; - int replay(const block::log::Start& lev, unsigned long long log_pos) const; - int replay(const block::log::SetZeroState& lev, unsigned long long log_pos) const; - int replay(const block::log::NewBlock& lev, unsigned long long log_pos) const; - int replay(const block::log::NewState& lev, unsigned long long log_pos) const; - template - inline int try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos); - - public: - BlockBinlogCallback(BlockDbImpl& _db) : db(_db) { - } -}; - -template -inline int BlockBinlogCallback::try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos) { - if (len < sizeof(T)) { - return 0x80000000 + sizeof(T); - } else { - int res = replay(*reinterpret_cast(ptr), log_pos); - return res >= 0 ? sizeof(T) : res; - } -} - -class BlockDbImpl final : public BlockDb { - int status; - bool allow_uninit; - bool created; - int depth; - std::unique_ptr zstate; - std::string base_dir; - std::string binlog_name; - BinlogBuffer bb; - ton::Bits256 zstate_rhash, zstate_fhash; - unsigned created_at; - std::map file_cache; - std::map> block_info; - std::map> state_info; - // - td::Result do_init(); - - public: - enum FMode { - chk_none = 0, - chk_if_exists = 1, - fail_if_exists = 2, - overwrite = 4, - chk_size_only = 16, - chk_file_hash = 32 - }; - static constexpr const char* default_binlog_name = "blockdb"; - static constexpr const char* default_binlog_suffix = ".bin"; - static constexpr int default_depth = 4; - BlockDbImpl(td::Result& _res, std::string _base_dir, std::unique_ptr _zstate = nullptr, - bool _allow_uninit = false, int _depth = 4, std::string _binlog_name = ""); - ~BlockDbImpl(); - bool ok() const { - return status >= 0; - } - bool initialized() const { - return status != 0; - } - bool init_ok() const { - return status > 0; - } - - protected: - friend class BlockBinlogCallback; - td::Ref zerostate; - td::Status init_from_zstate(); - td::Status update_block_info(Ref blk_info); - td::Status update_state_info(Ref state); - - private: - std::string compute_db_filename(const FileHash& file_hash) const; - std::string compute_db_tmp_filename(const FileHash& file_hash, int i, bool makedirs) const; - td::Status save_db_file(const FileHash& file_hash, const td::BufferSlice& data, int fmode = 0); - td::Status load_data(FileInfo& file_info, bool force = false); - // actor BlockDb implementation - void get_top_block_id(ton::ShardIdFull shard, int authority, td::Promise promise) override; - void get_top_block_state_id(ton::ShardIdFull shard, int authority, td::Promise promise) override; - void get_block_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) override; - void get_state_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) override; - void get_out_queue_info_by_id(ton::BlockId blk_id, td::Promise> promise) override; - void get_object_by_file_hash(FileHash file_hash, bool need_data, bool force_file_load, - td::Promise> promise) override; - void get_object_by_root_hash(RootHash root_hash, bool need_data, bool force_file_load, - td::Promise> promise) override; - void save_new_block(ton::BlockIdExt blk_id, td::BufferSlice data, int authority, - td::Promise promise) override; - void save_new_state(ton::BlockIdExt state_id, td::BufferSlice data, int authority, - td::Promise promise) override; - bool file_cache_insert(const FileHash& file_hash, const td::BufferSlice& data, int mode = 0); -}; - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-db.cpp b/submodules/ton/tonlib-src/crypto/block/block-db.cpp deleted file mode 100644 index 2be1f580..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-db.cpp +++ /dev/null @@ -1,835 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "block-db.h" -#include "block-db-impl.h" -#include "block-binlog.h" -#include "td/utils/common.h" -#include "td/utils/crypto.h" -#include "td/utils/format.h" -#include "td/utils/misc.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/path.h" -#include "td/utils/filesystem.h" -#include "vm/cellslice.h" -#include "vm/boc.h" -#include "vm/db/StaticBagOfCellsDb.h" - -#include - -namespace block { - -//static constexpr std::string default_binlog_name = "blockdb"; -//static constexpr std::string default_binlog_suffix = ".bin"; - -bool parse_hash_string(std::string arg, RootHash& res) { - if (arg.size() != 64) { - res.set_zero(); - return false; - } - int f = 1; - unsigned char* ptr = res.data(); - for (char c : arg) { - f <<= 4; - if (c >= '0' && c <= '9') { - f += c - '0'; - } else { - c |= 0x20; - if (c >= 'a' && c <= 'f') { - f += c - ('a' - 10); - } else { - res.set_zero(); - return false; - } - } - if (f >= 0x100) { - *ptr++ = (unsigned char)f; - f = 1; - } - } - return true; -} - -td::Result load_binary_file(std::string filename, td::int64 max_size) { - //TODO: use td::read_file - auto res = [&]() -> td::Result { - TRY_RESULT(fd, td::FileFd::open(filename, td::FileFd::Read)); - TRY_RESULT(stat, fd.stat()); - if (!stat.is_reg_) { - return td::Status::Error("file is not regular"); - } - td::int64 size = stat.size_; - if (!size) { - return td::Status::Error("file is empty"); - } - if ((max_size && size > max_size) || static_cast(size) > std::numeric_limits::max()) { - return td::Status::Error("file is too long"); - } - td::BufferSlice res(td::narrow_cast(size)); - TRY_RESULT(r, fd.read(res.as_slice())); - if (r != static_cast(size)) { - return td::Status::Error(PSLICE() << "read " << r << " bytes out of " << size); - } - return std::move(res); - }(); - LOG_IF(ERROR, res.is_error()) << "error reading file `" << filename << "` : " << res.error(); - return res; -} - -td::Status save_binary_file(std::string filename, const td::BufferSlice& data, unsigned long long max_size) { - //TODO: use td::write_file - auto status = [&]() { - if (max_size && data.size() > max_size) { - return td::Status::Error("contents too long"); - } - auto size = data.size(); - TRY_RESULT(to_file, td::FileFd::open(filename, td::FileFd::CreateNew | td::FileFd::Write)); - TRY_RESULT(written, to_file.write(data)); - if (written != static_cast(size)) { - return td::Status::Error(PSLICE() << "written " << written << " bytes instead of " << size); - } - to_file.close(); - return td::Status::OK(); - }(); - LOG_IF(ERROR, status.is_error()) << "error writing new file `" << filename << "` : " << status; - return status; -} - -FileHash compute_file_hash(const td::BufferSlice& data) { - ton::Bits256 data_hash; - td::sha256(data, td::MutableSlice{data_hash.data(), 32}); - return data_hash; -} - -FileHash compute_file_hash(td::Slice data) { - ton::Bits256 data_hash; - td::sha256(data, td::MutableSlice{data_hash.data(), 32}); - return data_hash; -} - -/* - * - * ZEROSTATE CONFIGURATION - * - */ - -td::Status ZerostateInfo::base_check() { - if (!has_data()) { - return td::Status::OK(); - } - auto data_hash = compute_file_hash(data); - if (!has_file_hash()) { - file_hash = data_hash; - } else if (file_hash != data_hash) { - return td::Status::Error("zerostate file hash mismatch"); - } - vm::BagOfCells boc; - auto res = boc.deserialize(data); - if (!res.is_ok() || boc.get_root_count() != 1) { - return td::Status::Error("zerostate is not a valid bag of cells"); // not a valid bag-of-Cells - } - data_hash = boc.get_root_cell()->get_hash().bits(); - if (!has_root_hash()) { - root_hash = data_hash; - } else if (root_hash != data_hash) { - return td::Status::Error("zerostate root hash mismatch"); - } - return td::Status::OK(); -} - -/* - * - * BLOCK DATABASE - * - */ - -std::string compute_db_filename(std::string base_dir, const FileHash& file_hash, int depth) { - static const char hex_digits[] = "0123456789ABCDEF"; - assert(depth >= 0 && depth <= 8); - std::string res = std::move(base_dir); - res.reserve(res.size() + 32 + depth * 3 + 4); - for (int i = 0; i < depth; i++) { - unsigned u = file_hash.data()[i]; - res.push_back(hex_digits[u >> 4]); - res.push_back(hex_digits[u & 15]); - res.push_back('/'); - } - for (int i = 0; i < 32; i++) { - unsigned u = file_hash.data()[i]; - res.push_back(hex_digits[u >> 4]); - res.push_back(hex_digits[u & 15]); - } - res += ".boc"; - return res; -} - -std::string BlockDbImpl::compute_db_filename(const FileHash& file_hash) const { - return block::compute_db_filename(base_dir, file_hash, depth); -} - -std::string compute_db_tmp_filename(std::string base_dir, const FileHash& file_hash, int i, bool makedirs, int depth) { - static const char hex_digits[] = "0123456789ABCDEF"; - assert(depth >= 0 && depth <= 8); - std::string res = std::move(base_dir); - res.reserve(res.size() + 32 + depth * 3 + 4); - for (int j = 0; j < depth; j++) { - unsigned u = file_hash.data()[j]; - res.push_back(hex_digits[u >> 4]); - res.push_back(hex_digits[u & 15]); - res.push_back('/'); - if (makedirs) { - td::mkdir(res, 0755).ignore(); - } - } - for (int j = 0; j < 32; j++) { - unsigned u = file_hash.data()[j]; - res.push_back(hex_digits[u >> 4]); - res.push_back(hex_digits[u & 15]); - } - res += ".tmp"; - if (i > 0) { - if (i < 10) { - res.push_back((char)('0' + i)); - } else { - res.push_back((char)('0' + i / 10)); - res.push_back((char)('0' + i % 10)); - } - } - return res; -} - -std::string BlockDbImpl::compute_db_tmp_filename(const FileHash& file_hash, int i, bool makedirs) const { - return block::compute_db_tmp_filename(base_dir, file_hash, i, makedirs, depth); -} - -bool BlockDbImpl::file_cache_insert(const FileHash& file_hash, const td::BufferSlice& data, int mode) { - auto it = file_cache.find(file_hash); - if (it != file_cache.end()) { - // found - return true; - } - auto res = file_cache.emplace(file_hash, data.clone()); - return res.second; -} - -td::Status BlockDbImpl::save_db_file(const FileHash& file_hash, const td::BufferSlice& data, int fmode) { - if (fmode & FMode::chk_file_hash && file_hash != compute_file_hash(data)) { - return td::Status::Error("file hash passed for creation of a new file does not match contents"); - } - std::string filename = compute_db_filename(file_hash); - bool overwrite = false; - auto r_stat = td::stat(filename); - if (r_stat.is_ok()) { - auto stat = r_stat.move_as_ok(); - // file exists - if (fmode & FMode::fail_if_exists) { - return td::Status::Error(PSLICE() << "file " << filename << " cannot be created, it already exists"); - } - if (!(fmode & (FMode::chk_if_exists | FMode::overwrite))) { - file_cache_insert(file_hash, data); - return td::Status::OK(); - } - if (fmode & FMode::chk_if_exists) { - if (stat.size_ != (long long)data.size()) { - LOG(ERROR) << "file " << filename << " already exists with wrong content"; - if (!(fmode & FMode::overwrite)) { - return td::Status::Error(PSLICE() << "file " << filename << " already exists with wrong content"); - } - } else if (fmode & FMode::chk_size_only) { - file_cache_insert(file_hash, data); - return td::Status::OK(); - } else { - auto res = load_binary_file(filename); - if (res.is_error()) { - return res.move_as_error(); - } - auto old_contents = res.move_as_ok(); - if (old_contents.size() != data.size() || old_contents.as_slice() != data.as_slice()) { - LOG(ERROR) << "file " << filename << " already exists with wrong content"; - if (!(fmode & FMode::overwrite)) { - return td::Status::Error(PSLICE() << "file " << filename << " already exists with wrong content"); - } - } else { - file_cache_insert(file_hash, data); - return td::Status::OK(); - } - } - } - overwrite = true; - } - std::string tmp_filename; - for (int i = 0; i < 10; i++) { - tmp_filename = compute_db_tmp_filename(file_hash, i, true); - auto res = save_binary_file(tmp_filename, data); - if (res.is_ok()) { - break; - } - if (i == 9) { - return res; - } - } - auto rename_status = td::rename(tmp_filename, filename); - if (rename_status.is_error()) { - td::unlink(tmp_filename).ignore(); - LOG(ERROR) << rename_status; - return rename_status; - } - if (overwrite) { - LOG(DEBUG) << "database file `" << filename << "` overwritten, " << data.size() << " bytes"; - } else { - LOG(DEBUG) << "new database file `" << filename << "` created, " << data.size() << " bytes"; - } - file_cache_insert(file_hash, data); - return td::Status::OK(); -} - -td::Result> BlockDb::create_block_db(std::string base_dir, - std::unique_ptr zstate, - bool allow_uninit, int depth, - std::string binlog_name) { - using td::actor::ActorId; - using td::actor::ActorOwn; - td::Result res; - ActorOwn actor = - td::actor::create_actor(td::actor::ActorOptions().with_name("BlockDB"), res, base_dir, - std::move(zstate), allow_uninit, depth, binlog_name); - if (res.is_error()) { - return std::move(res).move_as_error(); - } else { - return std::move(actor); - } -} - -BlockDbImpl::BlockDbImpl(td::Result& _res, std::string _base_dir, std::unique_ptr _zstate, - bool _allow_uninit, int _depth, std::string _binlog_name) - : status(0) - , allow_uninit(_allow_uninit) - , created(false) - , depth(_depth) - , zstate(std::move(_zstate)) - , base_dir(_base_dir) - , binlog_name(_binlog_name) - , bb(std::unique_ptr(new BlockBinlogCallback(*this))) - , created_at(0) { - auto res = do_init(); - status = (res.is_ok() && res.ok() > 0 ? res.ok() : -1); - if (res.is_error()) { - _res = std::move(res); - } else { - _res = res.move_as_ok(); - } -} - -td::Result BlockDbImpl::do_init() { - if (base_dir.empty()) { - return td::Status::Error("block database cannot have empty base directory"); - } - if (depth < 0 || depth >= 8) { - return td::Status::Error("block database directory tree depth must be in range 0..8"); - } - if (base_dir.back() != '/') { - base_dir.push_back('/'); - } - if (binlog_name.empty()) { - binlog_name = default_binlog_name; - } - bool f = true; - for (char c : binlog_name) { - if (c == '.') { - f = false; - } else if (c == '/') { - f = true; - } - } - if (f) { - binlog_name += default_binlog_suffix; - } - if (binlog_name.at(0) != '/') { - binlog_name = base_dir + binlog_name; - } - if (zstate) { - if (!zstate->has_data() && zstate->has_filename()) { - auto data = load_binary_file(zstate->filename, 1 << 20); - if (data.is_error()) { - return data.move_as_error(); - } - zstate->data = data.move_as_ok(); - } - auto res = zstate->base_check(); - if (res.is_error()) { - return res; - } - } - try { - auto res = bb.set_binlog(binlog_name, allow_uninit ? 3 : 1); - if (res.is_error()) { - return res; - } - } catch (BinlogBuffer::BinlogError& err) { - return td::Status::Error(-2, std::string{"error while initializing block database binlog: "} + err.msg); - } catch (BinlogBuffer::InterpretError& err) { - return td::Status::Error(-3, std::string{"error while interpreting block database binlog: "} + err.msg); - } - return created; -} - -BlockDbImpl::~BlockDbImpl() { -} - -td::Status BlockDbImpl::init_from_zstate() { - if (!zstate) { - return td::Status::Error("no zero state provided, cannot initialize from scratch"); - } - if (!zstate->has_data()) { - if (zstate->has_filename() || zstate->has_file_hash()) { - if (!zstate->has_filename()) { - zstate->filename = compute_db_filename(zstate->file_hash); - } - auto res = load_binary_file(zstate->filename, 1 << 20); - if (res.is_error()) { - return res.move_as_error(); - } - zstate->data = res.move_as_ok(); - } else { - return td::Status::Error("cannot load zero state for block DB creation"); - } - } - auto res = zstate->base_check(); - if (res.is_error()) { - return res; - } - assert(zstate->has_file_hash() && zstate->has_root_hash()); - res = save_db_file(zstate->file_hash, zstate->data, FMode::chk_if_exists | FMode::chk_file_hash); - if (res.is_error()) { - return res; - } - return res; -} - -td::Status BlockBinlogCallback::init_new_binlog(BinlogBuffer& bb) { - auto res = db.init_from_zstate(); - if (res.is_error()) { - return res; - } - auto lev = bb.alloc(db.zstate->root_hash); - assert(!lev.get_log_pos()); - auto lev2 = bb.alloc(db.zstate->root_hash, db.zstate->file_hash, db.zstate->data.size()); - lev.commit(); - lev2.commit(); // TODO: introduce multi-commit bb.commit(lev, lev2) - bb.flush(3); - db.created = true; - return td::Status::OK(); -} - -#define REPLAY_CASE(__T) \ - case __T::tag: \ - return try_interpret<__T>(ptr, len, log_pos); - -int BlockBinlogCallback::replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, - unsigned long long log_pos) { - assert(len >= 4); - LOG(DEBUG) << "replay_log_event(" << len << ", " << log_pos << ", " << *ptr << ")"; - switch (*ptr) { - REPLAY_CASE(log::Start); - REPLAY_CASE(log::SetZeroState); - REPLAY_CASE(log::NewBlock); - REPLAY_CASE(log::NewState); - } - std::ostringstream ss; - ss << "unknown binlog event 0x" << std::hex << *ptr << std::dec; - LOG(ERROR) << ss.str() << " at position " << log_pos; - throw BinlogBuffer::InterpretError{ss.str()}; -} - -#undef REPLAY_CASE - -int BlockBinlogCallback::replay(const log::Start& lev, unsigned long long log_pos) const { - LOG(DEBUG) << "in replay(Start{" << lev.tag_field << ", " << lev.type_field << ", " << lev.created_at << "})"; - if (lev.type_field != lev.log_type) { - throw BinlogBuffer::InterpretError{(PSLICE() << "unsupported binlog type " << lev.type_field).str()}; - } - if (log_pos) { - throw BinlogBuffer::InterpretError{"LEV_START can only be the very first record in a binlog"}; - } - db.zstate_rhash = lev.zerostate_root_hash; - db.created_at = lev.created_at; - if (db.zstate) { - if (!db.zstate->has_root_hash()) { - db.zstate->root_hash = db.zstate_rhash; - } else if (db.zstate->root_hash != db.zstate_rhash) { - throw BinlogBuffer::InterpretError{PSTRING() << "zerostate hash mismatch: in binlog " << db.zstate_rhash.to_hex() - << ", required " << db.zstate->root_hash.to_hex()}; - } - } - return 0; // ok -} - -int BlockBinlogCallback::replay(const log::SetZeroState& lev, unsigned long long log_pos) const { - LOG(DEBUG) << "in replay(SetZeroState)"; - // LOG(DEBUG) << "db.zstate_rhash = " << db.zstate_rhash.to_hex(); - if (db.zstate_rhash != td::ConstBitPtr{lev.root_hash}) { - throw BinlogBuffer::InterpretError{std::string{"SetZeroState: zerostate root hash mismatch: in binlog "} + - ton::Bits256{lev.root_hash}.to_hex() + ", required " + db.zstate_rhash.to_hex()}; - } - db.zerostate = td::Ref{true, - FileType::state, - ton::BlockId{ton::masterchainId, 1ULL << 63, 0}, - 0, - td::as(lev.file_hash), - td::as(lev.root_hash), - lev.file_size}; - return 0; // ok -} - -int BlockBinlogCallback::replay(const log::NewBlock& lev, unsigned long long log_pos) const { - LOG(DEBUG) << "in replay(NewBlock)"; - if (!lev.seqno || lev.workchain == ton::workchainInvalid) { - return -1; - } - ton::BlockId blkid{lev.workchain, lev.shard, lev.seqno}; - auto blk_info = td::Ref{true, - FileType::block, - blkid, - lev.flags & 0xff, - td::as(lev.file_hash), - td::as(lev.root_hash), - lev.file_size}; - auto res = db.update_block_info(blk_info); - if (res.is_error()) { - LOG(ERROR) << "cannot update block information in the local DB: " << res.to_string(); - return -1; - } else { - return 0; // ok - } -} - -int BlockBinlogCallback::replay(const log::NewState& lev, unsigned long long log_pos) const { - LOG(DEBUG) << "in replay(NewState)"; - if (!lev.seqno || lev.workchain == ton::workchainInvalid) { - return -1; - } - ton::BlockId id{lev.workchain, lev.shard, lev.seqno}; - auto state_info = td::Ref{true, - FileType::state, - id, - lev.flags & 0xff, - td::as(lev.file_hash), - td::as(lev.root_hash), - lev.file_size}; - auto res = db.update_state_info(state_info); - if (res.is_error()) { - LOG(ERROR) << "cannot update shardchain state information in the local DB: " << res.to_string(); - return -1; - } else { - return 0; // ok - } -} - -td::Status BlockDbImpl::update_block_info(Ref blk_info) { - auto it = block_info.find(blk_info->blk.id); - if (it != block_info.end()) { - // already exists - if (it->second->blk.file_hash != blk_info->blk.file_hash || it->second->blk.root_hash != blk_info->blk.root_hash) { - return td::Status::Error(-666, std::string{"fatal error in block DB: block "} + blk_info->blk.id.to_str() + - " has two records with different file or root hashes"); - } else { - return td::Status::OK(); - } - } else { - auto id = blk_info->blk.id; - auto res = block_info.emplace(std::move(id), std::move(blk_info)); - if (res.second) { - return td::Status::OK(); - } else { - return td::Status::Error(-666, "cannot insert block information into DB"); - } - } -} - -td::Status BlockDbImpl::update_state_info(Ref state) { - auto it = state_info.find(state->blk.id); - if (it != state_info.end()) { - // already exists - if (it->second->blk.root_hash != state->blk.root_hash) { - return td::Status::Error(-666, std::string{"fatal error in block DB: state for block "} + state->blk.id.to_str() + - " has two records with different root hashes"); - } else { - return td::Status::OK(); - } - } else { - auto id = state->blk.id; - auto res = state_info.emplace(std::move(id), std::move(state)); - if (res.second) { - return td::Status::OK(); - } else { - return td::Status::Error(-666, "cannot insert state information into DB"); - } - } -} - -void BlockDbImpl::get_top_block_id(ton::ShardIdFull shard, int authority, td::Promise promise) { - LOG(DEBUG) << "in BlockDb::get_top_block_id()"; - auto it = block_info.upper_bound(ton::BlockId{shard, std::numeric_limits::max()}); - if (it != block_info.begin() && ton::ShardIdFull{(--it)->first} == shard) { - promise(it->second->blk); - return; - } - if (shard.is_masterchain()) { - promise(ton::BlockIdExt{ton::BlockId{ton::masterchainId, 1ULL << 63, 0}}); - return; - } - promise(td::Status::Error(-666)); -} - -void BlockDbImpl::get_top_block_state_id(ton::ShardIdFull shard, int authority, td::Promise promise) { - LOG(DEBUG) << "in BlockDb::get_top_block_state_id()"; - auto it = state_info.upper_bound(ton::BlockId{shard, std::numeric_limits::max()}); - if (it != state_info.begin() && ton::ShardIdFull{(--it)->first} == shard) { - promise(it->second->blk); - return; - } - if (shard.is_masterchain() && zerostate.not_null()) { - promise(zerostate->blk); - return; - } - promise(td::Status::Error(-666, "no state for given workchain found in database")); -} - -void BlockDbImpl::get_block_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) { - LOG(DEBUG) << "in BlockDb::get_block_by_id({" << blk_id.workchain << ", " << blk_id.shard << ", " << blk_id.seqno - << "}, " << need_data << ")"; - auto it = block_info.find(blk_id); - if (it != block_info.end()) { - if (need_data && it->second->data.is_null()) { - LOG(DEBUG) << "loading data for block " << blk_id.to_str(); - auto res = load_data(it->second.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - promise(it->second); - } - promise(td::Status::Error(-666, "block not found in database")); -} - -void BlockDbImpl::get_state_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) { - LOG(DEBUG) << "in BlockDb::get_state_by_id({" << blk_id.workchain << ", " << blk_id.shard << ", " << blk_id.seqno - << "}, " << need_data << ")"; - auto it = state_info.find(blk_id); - if (it != state_info.end()) { - if (need_data && it->second->data.is_null()) { - LOG(DEBUG) << "loading data for state " << blk_id.to_str(); - auto res = load_data(it->second.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - promise(it->second); - } - if (zerostate.not_null() && blk_id == zerostate->blk.id) { - LOG(DEBUG) << "get_state_by_id(): zerostate requested"; - if (need_data && zerostate->data.is_null()) { - LOG(DEBUG) << "loading data for zerostate"; - auto res = load_data(zerostate.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - promise(zerostate); - return; - } - promise(td::Status::Error(-666, "requested state not found in database")); -} - -void BlockDbImpl::get_out_queue_info_by_id(ton::BlockId blk_id, td::Promise> promise) { - LOG(DEBUG) << "in BlockDb::get_out_queue_info_by_id({" << blk_id.workchain << ", " << blk_id.shard << ", " - << blk_id.seqno << ")"; - auto it = state_info.find(blk_id); - if (it == state_info.end()) { - promise(td::Status::Error( - -666, std::string{"cannot obtain output queue info for block "} + blk_id.to_str() + " : cannot load state")); - } - if (it->second->data.is_null()) { - LOG(DEBUG) << "loading data for state " << blk_id.to_str(); - auto res = load_data(it->second.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - auto it2 = block_info.find(blk_id); - if (it2 == block_info.end()) { - promise(td::Status::Error(-666, std::string{"cannot obtain output queue info for block "} + blk_id.to_str() + - " : cannot load block description")); - } - vm::StaticBagOfCellsDbLazy::Options options; - auto res = vm::StaticBagOfCellsDbLazy::create(it->second->data.clone(), options); - if (res.is_error()) { - td::Status err = res.move_as_error(); - LOG(ERROR) << "cannot deserialize state for block " << blk_id.to_str() << " : " << err.to_string(); - promise(std::move(err)); - return; - } - auto static_boc = res.move_as_ok(); - auto rc = static_boc->get_root_count(); - if (rc.is_error()) { - promise(rc.move_as_error()); - return; - } - if (rc.move_as_ok() != 1) { - promise(td::Status::Error(-668, std::string{"state for block "} + blk_id.to_str() + " is invalid")); - return; - } - auto res3 = static_boc->get_root_cell(0); - if (res3.is_error()) { - promise(res3.move_as_error()); - return; - } - auto state_root = res3.move_as_ok(); - if (it->second->blk.root_hash != state_root->get_hash().bits()) { - promise(td::Status::Error( - -668, std::string{"state for block "} + blk_id.to_str() + " is invalid : state root hash mismatch")); - } - vm::CellSlice cs = vm::load_cell_slice(state_root); - if (!cs.have(64, 1) || cs.prefetch_ulong(32) != 0x9023afde) { - promise(td::Status::Error(-668, std::string{"state for block "} + blk_id.to_str() + " is invalid")); - } - auto out_queue_info = cs.prefetch_ref(); - promise(Ref{true, blk_id, it2->second->blk.root_hash.cbits(), state_root->get_hash().bits(), - std::move(out_queue_info)}); -} - -void BlockDbImpl::get_object_by_file_hash(FileHash file_hash, bool need_data, bool force_file_load, - td::Promise> promise) { - if (zerostate.not_null() && zerostate->blk.file_hash == file_hash) { - if (need_data && zerostate->data.is_null()) { - auto res = load_data(zerostate.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - promise(zerostate); - return; - } - promise(td::Status::Error(-666)); -} - -void BlockDbImpl::get_object_by_root_hash(RootHash root_hash, bool need_data, bool force_file_load, - td::Promise> promise) { - if (zerostate.not_null() && zerostate->blk.root_hash == root_hash) { - if (need_data && zerostate->data.is_null()) { - auto res = load_data(zerostate.write()); - if (res.is_error()) { - promise(std::move(res)); - return; - } - } - promise(zerostate); - return; - } - promise(td::Status::Error(-666)); -} - -void BlockDbImpl::save_new_block(ton::BlockIdExt id, td::BufferSlice data, int authority, - td::Promise promise) { - // TODO: add verification that data is a BoC with correct root hash, and that it is a Block corresponding to blk_id - // ... - // TODO: check whether we already have a block with blk_id - // ... - auto save_res = save_db_file(id.file_hash, data, FMode::chk_if_exists | FMode::overwrite | FMode::chk_file_hash); - if (save_res.is_error()) { - promise(std::move(save_res)); - } - auto sz = data.size(); - auto lev = bb.alloc(id.id, id.root_hash, id.file_hash, data.size(), authority & 0xff); - if (sz <= 8) { - std::memcpy(lev->last_bytes, data.data(), sz); - } else { - std::memcpy(lev->last_bytes, data.data() + sz - 8, 8); - } - lev.commit(); - bb.flush(); - promise(td::Unit{}); -} - -void BlockDbImpl::save_new_state(ton::BlockIdExt id, td::BufferSlice data, int authority, - td::Promise promise) { - // TODO: add verification that data is a BoC with correct root hash, and that it is a Block corresponding to blk_id - // ... - // TODO: check whether we already have a block with blk_id - // ... - auto save_res = save_db_file(id.file_hash, data, FMode::chk_if_exists | FMode::overwrite | FMode::chk_file_hash); - if (save_res.is_error()) { - promise(std::move(save_res)); - } - auto sz = data.size(); - auto lev = bb.alloc(id.id, id.root_hash, id.file_hash, data.size(), authority & 0xff); - if (sz <= 8) { - std::memcpy(lev->last_bytes, data.data(), sz); - } else { - std::memcpy(lev->last_bytes, data.data() + sz - 8, 8); - } - lev.commit(); - bb.flush(); - promise(td::Unit{}); -} - -td::Status BlockDbImpl::load_data(FileInfo& file_info, bool force) { - if (!file_info.data.is_null() && !force) { - return td::Status::OK(); - } - if (file_info.blk.file_hash.is_zero()) { - return td::Status::Error("cannot load a block file without knowing its file hash"); - } - auto it = file_cache.find(file_info.blk.file_hash); - if (it != file_cache.end() && !force) { - file_info.data = it->second.clone(); - return td::Status::OK(); - } - std::string filename = compute_db_filename(file_info.blk.file_hash); - auto res = load_binary_file(filename); - if (res.is_error()) { - return res.move_as_error(); - } - file_info.data = res.move_as_ok(); - file_cache_insert(file_info.blk.file_hash, file_info.data); - return td::Status::OK(); -} - -FileInfo FileInfo::clone() const { - return FileInfo{*this}; -} - -FileInfo::FileInfo(const FileInfo& other) - : td::CntObject() - , blk(other.blk) - , type(other.type) - , status(other.status) - , file_size(other.file_size) - , data(other.data.clone()) { -} - -FileInfo* FileInfo::make_copy() const { - return new FileInfo(*this); -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-db.h b/submodules/ton/tonlib-src/crypto/block/block-db.h deleted file mode 100644 index cd9498fb..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-db.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/int_types.h" -#include "td/utils/buffer.h" -#include "td/actor/actor.h" -#include "ton/ton-types.h" -#include "crypto/common/refcnt.hpp" -#include "crypto/vm/cells.h" - -namespace block { - -using FileHash = ton::Bits256; -using RootHash = ton::Bits256; -using td::Ref; - -struct ZerostateInfo { - td::BufferSlice data; - std::string filename; - FileHash file_hash; - RootHash root_hash; - ZerostateInfo() { - file_hash.set_zero(); - root_hash.set_zero(); - } - ZerostateInfo(RootHash hash, std::string _filename) : filename(_filename), root_hash(std::move(hash)) { - file_hash.set_zero(); - } - ZerostateInfo(std::string _filename) : filename(_filename) { - file_hash.set_zero(); - root_hash.set_zero(); - } - ZerostateInfo(RootHash hash, FileHash fhash) : file_hash(std::move(fhash)), root_hash(std::move(hash)) { - } - bool has_file_hash() const { - return !file_hash.is_zero(); - } - bool has_root_hash() const { - return !root_hash.is_zero(); - } - bool has_filename() const { - return !filename.empty(); - } - bool has_data() const { - return !data.empty(); - } - td::Status base_check(); -}; - -enum class FileType { - unknown = 0, - unknown_boc = 1, - block = 2, - block_candidate = 3, - collated_data = 4, - block_signatures = 5, - state = 6, - out_queue = 7 -}; - -struct FileInfo : public td::CntObject { - ton::BlockIdExt blk; - FileType type; - int status; - long long file_size; - td::BufferSlice data; - FileInfo() : type(FileType::unknown), status(0), file_size(-1) { - blk.file_hash.set_zero(); - blk.root_hash.set_zero(); - } - FileInfo(FileType _type, const ton::BlockId& _id, int _status, const FileHash& _fhash, long long _fsize = -1) - : blk(_id, _fhash), type(_type), status(_status), file_size(_fsize) { - blk.root_hash.set_zero(); - } - FileInfo(FileType _type, const ton::BlockId& _id, int _status, const FileHash& _fhash, const RootHash& _rhash, - long long _fsize = -1) - : blk(_id, _rhash, _fhash), type(_type), status(_status), file_size(_fsize) { - } - FileInfo(FileType _type, const ton::BlockId& _id, int _status, const FileHash& _fhash, const RootHash& _rhash, - td::BufferSlice _data) - : blk(_id, _rhash, _fhash), type(_type), status(_status), file_size(_data.size()), data(std::move(_data)) { - } - FileInfo(FileInfo&& other) = default; - FileInfo clone() const; - FileInfo* make_copy() const override; - - private: - FileInfo(const FileInfo& other); -}; - -struct OutputQueueInfoDescr : public td::CntObject { - ton::BlockId id; - RootHash block_hash; - RootHash state_hash; - RootHash output_queue_info_hash; - td::Ref queue_info; - OutputQueueInfoDescr(ton::BlockId _id, const RootHash& _bhash, const RootHash& _shash, Ref _qinfo) - : id(_id) - , block_hash(_bhash) - , state_hash(_shash) - , output_queue_info_hash(_qinfo->get_hash().bits()) - , queue_info(std::move(_qinfo)) { - } - OutputQueueInfoDescr(ton::BlockId _id, td::ConstBitPtr _bhash, td::ConstBitPtr _shash, Ref _qinfo) - : id(_id) - , block_hash(_bhash) - , state_hash(_shash) - , output_queue_info_hash(_qinfo->get_hash().bits()) - , queue_info(std::move(_qinfo)) { - } -}; - -class BlockDb : public td::actor::Actor { - public: - BlockDb() = default; - virtual ~BlockDb() = default; - static td::Result> create_block_db(std::string _base_dir, - std::unique_ptr _zstate = nullptr, - bool _allow_uninit = false, int _depth = 4, - std::string _binlog_name = ""); - // authority: 0 = standard (inclusion in mc block), 1 = validator (by 2/3 validator signatures) - virtual void get_top_block_id(ton::ShardIdFull shard, int authority, td::Promise promise) = 0; - virtual void get_top_block_state_id(ton::ShardIdFull shard, int authority, td::Promise promise) = 0; - virtual void get_block_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) = 0; - virtual void get_state_by_id(ton::BlockId blk_id, bool need_data, td::Promise> promise) = 0; - virtual void get_out_queue_info_by_id(ton::BlockId blk_id, td::Promise> promise) = 0; - virtual void get_object_by_file_hash(FileHash file_hash, bool need_data, bool force_file_load, - td::Promise> promise) = 0; - virtual void get_object_by_root_hash(RootHash root_hash, bool need_data, bool force_file_load, - td::Promise> promise) = 0; - virtual void save_new_block(ton::BlockIdExt blk_id, td::BufferSlice data, int authority, - td::Promise promise) = 0; - virtual void save_new_state(ton::BlockIdExt state_id, td::BufferSlice data, int authority, - td::Promise promise) = 0; -}; - -bool parse_hash_string(std::string arg, RootHash& res); - -FileHash compute_file_hash(const td::BufferSlice& data); -FileHash compute_file_hash(td::Slice data); -td::Result load_binary_file(std::string filename, td::int64 max_size = 0); -td::Status save_binary_file(std::string filename, const td::BufferSlice& data, unsigned long long max_size = 0); - -std::string compute_db_filename(std::string base_dir, const FileHash& file_hash, int depth = 4); -std::string compute_db_tmp_filename(std::string base_dir, const FileHash& file_hash, int i = 0, bool makedirs = true, - int depth = 4); - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-parse.cpp b/submodules/ton/tonlib-src/crypto/block/block-parse.cpp deleted file mode 100644 index c62854d4..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-parse.cpp +++ /dev/null @@ -1,2296 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/bits.h" -#include "block/block-parse.h" -#include "block/block-auto.h" -#include "ton/ton-shard.h" -#include "common/util.h" -#include "td/utils/crypto.h" - -namespace block { -using namespace std::literals::string_literals; - -using CombineError = vm::CombineError; - -namespace { -bool debug(const char* str) TD_UNUSED; -bool debug(const char* str) { - std::cerr << str; - return true; -} - -bool debug(int x) TD_UNUSED; -bool debug(int x) { - if (x < 100) { - std::cerr << '[' << (char)(64 + x) << ']'; - } else { - std::cerr << '[' << (char)(64 + x / 100) << x % 100 << ']'; - } - return true; -} -} // namespace - -#define DBG_START int dbg = 0; -#define DBG debug(++dbg)&& -#define DEB_START DBG_START -#define DEB DBG - -namespace tlb { - -using namespace ::tlb; - -int MsgAddressExt::get_size(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case addr_none: // 00, addr_none - return 2; - case addr_ext: // 01, addr_extern - if (cs.have(2 + 9)) { - int len = cs.prefetch_long(2 + 9) & 0x1ff; - return 2 + 9 + len; - } - } - return -1; -} - -const MsgAddressExt t_MsgAddressExt; - -const Anycast t_Anycast; - -bool Maybe_Anycast::skip_get_depth(vm::CellSlice& cs, int& depth) const { - depth = 0; - bool have; - return cs.fetch_bool_to(have) && (!have || t_Anycast.skip_get_depth(cs, depth)); -} - -const Maybe_Anycast t_Maybe_Anycast; - -bool MsgAddressInt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - if (!cs.have(3)) { - return false; - } - switch (get_tag(cs)) { - case addr_std: - return cs.advance(2) && t_Maybe_Anycast.skip(cs) && cs.advance(8 + 256); - case addr_var: - if (cs.advance(2) && t_Maybe_Anycast.skip(cs) && cs.have(9 + 32)) { - int addr_len = (int)cs.fetch_ulong(9); - int workchain_id = (int)cs.fetch_long(32); - return cs.advance(addr_len) && (workchain_id < -0x80 || workchain_id > 0x7f || addr_len != 256) && - (workchain_id != 0 && workchain_id != -1); - } - } - return false; -} - -bool MsgAddressInt::skip_get_depth(vm::CellSlice& cs, int& depth) const { - if (!cs.have(3)) { - return false; - } - switch (get_tag(cs)) { - case addr_std: - return cs.advance(2) && t_Maybe_Anycast.skip_get_depth(cs, depth) && cs.advance(8 + 256); - case addr_var: - if (cs.advance(2) && t_Maybe_Anycast.skip_get_depth(cs, depth) && cs.have(9 + 32)) { - int addr_len = (int)cs.fetch_ulong(9); - return cs.advance(32 + addr_len); - } - } - return false; -} - -ton::AccountIdPrefixFull MsgAddressInt::get_prefix(vm::CellSlice&& cs) { - if (!cs.have(3 + 8 + 64)) { - return {}; - } - ton::WorkchainId workchain; - unsigned long long prefix; - int t = (int)cs.prefetch_ulong(2 + 1 + 5); - switch (t >> 5) { - case 4: { // addr_std$10, anycast=nothing$0 - if (cs.advance(3) && cs.fetch_int_to(8, workchain) && cs.fetch_uint_to(64, prefix)) { - return {workchain, prefix}; - } - break; - } - case 5: { // addr_std$10, anycast=just$1 (Anycast) - t &= 31; // depth:(## 5) - unsigned long long rewrite; - if (cs.advance(8) && cs.fetch_uint_to(t, rewrite) // rewrite_pfx:(bits depth) - && cs.fetch_int_to(8, workchain) // workchain_id:int8 - && cs.fetch_uint_to(64, prefix)) { // address:bits256 - rewrite <<= 64 - t; - return {workchain, (prefix & (std::numeric_limits::max() >> t)) | rewrite}; - } - break; - } - case 6: { // addr_var$11, anycast=nothing$0 - int len; - if (cs.advance(3) && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && len >= 64 // { len >= 64 } - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_uint_to(64, prefix)) { // address:(bits addr_len) - return {workchain, prefix}; - } - break; - } - case 7: { // addr_var$11, anycast=just$1 (Anycast) - t &= 31; // depth:(## 5) - int len; - unsigned long long rewrite; - if (cs.advance(8) && cs.fetch_uint_to(t, rewrite) // rewrite_pfx:(bits depth) - && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && len >= 64 // { len >= 64 } - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_uint_to(64, prefix)) { // address:bits256 - rewrite <<= 64 - t; - return {workchain, (prefix & (std::numeric_limits::max() >> t)) | rewrite}; - } - break; - } - } - return {}; -} - -ton::AccountIdPrefixFull MsgAddressInt::get_prefix(const vm::CellSlice& cs) { - return get_prefix(vm::CellSlice{cs}); -} - -ton::AccountIdPrefixFull MsgAddressInt::get_prefix(Ref cs_ref) { - if (cs_ref->is_unique()) { - return get_prefix(std::move(cs_ref.unique_write())); - } else { - return get_prefix(vm::CellSlice{*cs_ref}); - } -} - -bool MsgAddressInt::extract_std_address(Ref cs_ref, ton::WorkchainId& workchain, - ton::StdSmcAddress& addr, bool rewrite) const { - if (cs_ref.is_null()) { - return false; - } else if (cs_ref->is_unique()) { - return extract_std_address(cs_ref.unique_write(), workchain, addr, rewrite); - } else { - vm::CellSlice cs{*cs_ref}; - return extract_std_address(cs, workchain, addr, rewrite); - } -} - -bool MsgAddressInt::extract_std_address(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::StdSmcAddress& addr, - bool do_rewrite) const { - if (!cs.have(3 + 8 + 64)) { - return {}; - } - int t = (int)cs.prefetch_ulong(2 + 1 + 5); - switch (t >> 5) { - case 4: { // addr_std$10, anycast=nothing$0 - return cs.advance(3) && cs.fetch_int_to(8, workchain) && cs.fetch_bits_to(addr); - } - case 5: { // addr_std$10, anycast=just$1 (Anycast) - t &= 31; // depth:(## 5) - unsigned long long rewrite; - if (cs.advance(8) && cs.fetch_uint_to(t, rewrite) // rewrite_pfx:(bits depth) - && cs.fetch_int_to(8, workchain) // workchain_id:int8 - && cs.fetch_bits_to(addr)) { // address:bits256 - if (do_rewrite) { - addr.bits().store_uint(rewrite, t); - } - return true; - } - break; - } - case 6: { // addr_var$11, anycast=nothing$0 - int len; - return cs.advance(3) && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && len == 256 // only 256-bit addresses are standard - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_bits_to(addr); // address:(bits addr_len) - } - case 7: { // addr_var$11, anycast=just$1 (Anycast) - t &= 31; // depth:(## 5) - int len; - unsigned long long rewrite; - if (cs.advance(8) && cs.fetch_uint_to(t, rewrite) // rewrite_pfx:(bits depth) - && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && len == 256 // only 256-bit addresses are standard - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_bits_to(addr)) { // address:bits256 - if (do_rewrite) { - addr.bits().store_uint(rewrite, t); - } - return true; - } - break; - } - } - return false; -} - -bool MsgAddressInt::extract_std_address(Ref cs_ref, block::StdAddress& addr, bool rewrite) const { - return extract_std_address(std::move(cs_ref), addr.workchain, addr.addr, rewrite); -} - -bool MsgAddressInt::extract_std_address(vm::CellSlice& cs, block::StdAddress& addr, bool rewrite) const { - return extract_std_address(cs, addr.workchain, addr.addr, rewrite); -} - -bool MsgAddressInt::store_std_address(vm::CellBuilder& cb, ton::WorkchainId workchain, - const ton::StdSmcAddress& addr) const { - if (workchain >= -128 && workchain < 128) { - return cb.store_long_bool(4, 3) // addr_std$10 anycast:(Maybe Anycast) - && cb.store_long_bool(workchain, 8) // workchain_id:int8 - && cb.store_bits_bool(addr); // address:bits256 = MsgAddressInt; - } else { - return cb.store_long_bool(0xd00, 12) // addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) - && cb.store_long_bool(workchain, 32) // workchain_id:int32 - && cb.store_bits_bool(addr); // address:(bits addr_len) = MsgAddressInt; - } -} - -Ref MsgAddressInt::pack_std_address(ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const { - vm::CellBuilder cb; - if (store_std_address(cb, workchain, addr)) { - return vm::load_cell_slice_ref(cb.finalize()); - } else { - return {}; - } -} - -bool MsgAddressInt::store_std_address(vm::CellBuilder& cb, const block::StdAddress& addr) const { - return store_std_address(cb, addr.workchain, addr.addr); -} - -Ref MsgAddressInt::pack_std_address(const block::StdAddress& addr) const { - return pack_std_address(addr.workchain, addr.addr); -} - -const MsgAddressInt t_MsgAddressInt; - -bool MsgAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case addr_none: - case addr_ext: - return t_MsgAddressExt.validate_skip(ops, cs, weak); - case addr_std: - case addr_var: - return t_MsgAddressInt.validate_skip(ops, cs, weak); - } - return false; -} - -const MsgAddress t_MsgAddress; - -bool VarUInteger::skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return len >= 0 && len < n && cs.advance(len * 8); -} - -bool VarUInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len = (int)cs.fetch_ulong(ln); - return len >= 0 && len < n && (!len || cs.prefetch_ulong(8)) && cs.advance(len * 8); -} - -td::RefInt256 VarUInteger::as_integer_skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return (len >= 0 && len < n && (!len || cs.prefetch_ulong(8))) ? cs.fetch_int256(len * 8, false) : td::RefInt256{}; -} - -unsigned long long VarUInteger::as_uint(const vm::CellSlice& cs) const { - int len = (int)cs.prefetch_ulong(ln); - return len >= 0 && len <= 8 && cs.have(ln + len * 8) ? td::bitstring::bits_load_ulong(cs.data_bits() + ln, len * 8) - : std::numeric_limits::max(); -} - -bool VarUInteger::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - int k = value.bit_size(false); - return k <= (n - 1) * 8 && cb.store_long_bool((k + 7) >> 3, ln) && cb.store_int256_bool(value, (k + 7) & -8, false); -} - -unsigned VarUInteger::precompute_integer_size(const td::BigInt256& value) const { - int k = value.bit_size(false); - return k <= (n - 1) * 8 ? ln + ((k + 7) & -8) : 0xfff; -} - -unsigned VarUInteger::precompute_integer_size(td::RefInt256 value) const { - if (value.is_null()) { - return 0xfff; - } - int k = value->bit_size(false); - return k <= (n - 1) * 8 ? ln + ((k + 7) & -8) : 0xfff; -} - -const VarUInteger t_VarUInteger_3{3}, t_VarUInteger_7{7}, t_VarUInteger_16{16}, t_VarUInteger_32{32}; - -bool VarUIntegerPos::skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return len > 0 && len < n && cs.advance(len * 8); -} - -bool VarUIntegerPos::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len = (int)cs.fetch_ulong(ln); - return len > 0 && len < n && cs.prefetch_ulong(8) && cs.advance(len * 8); -} - -td::RefInt256 VarUIntegerPos::as_integer_skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return (len > 0 && len < n && cs.prefetch_ulong(8)) ? cs.fetch_int256(len * 8, false) : td::RefInt256{}; -} - -unsigned long long VarUIntegerPos::as_uint(const vm::CellSlice& cs) const { - int len = (int)cs.prefetch_ulong(ln); - return len > 0 && len <= 8 && cs.have(ln + len * 8) && cs.prefetch_ulong(8) - ? td::bitstring::bits_load_ulong(cs.data_bits() + ln, len * 8) - : std::numeric_limits::max(); -} - -bool VarUIntegerPos::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - int k = value.bit_size(false); - return k <= (n - 1) * 8 && value.sgn() >= (int)store_pos_only && cb.store_long_bool((k + 7) >> 3, ln) && - cb.store_int256_bool(value, (k + 7) & -8, false); -} - -const VarUIntegerPos t_VarUIntegerPos_16{16}, t_VarUIntegerPos_32{32}, t_VarUIntegerPosRelaxed_32{32, true}; - -static inline bool redundant_int(const vm::CellSlice& cs) { - int t = (int)cs.prefetch_long(9); - return t == 0 || t == -1; -} - -bool VarInteger::skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return len >= 0 && len < n && cs.advance(len * 8); -} - -bool VarInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len = (int)cs.fetch_ulong(ln); - return len >= 0 && len < n && (!len || !redundant_int(cs)) && cs.advance(len * 8); -} - -td::RefInt256 VarInteger::as_integer_skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return (len >= 0 && len < n && (!len || !redundant_int(cs))) ? cs.fetch_int256(len * 8, true) : td::RefInt256{}; -} - -long long VarInteger::as_int(const vm::CellSlice& cs) const { - int len = (int)cs.prefetch_ulong(ln); - return len >= 0 && len <= 8 && cs.have(ln + len * 8) ? td::bitstring::bits_load_long(cs.data_bits() + ln, len * 8) - : (1ULL << 63); -} - -bool VarInteger::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - int k = value.bit_size(true); - return k <= (n - 1) * 8 && cb.store_long_bool((k + 7) >> 3, ln) && cb.store_int256_bool(value, (k + 7) & -8, true); -} - -bool VarIntegerNz::skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return len > 0 && len < n && cs.advance(len * 8); -} - -bool VarIntegerNz::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int len = (int)cs.fetch_ulong(ln); - return len > 0 && len < n && !redundant_int(cs) && cs.advance(len * 8); -} - -td::RefInt256 VarIntegerNz::as_integer_skip(vm::CellSlice& cs) const { - int len = (int)cs.fetch_ulong(ln); - return (len > 0 && len < n && !redundant_int(cs)) ? cs.fetch_int256(len * 8, true) : td::RefInt256{}; -} - -long long VarIntegerNz::as_int(const vm::CellSlice& cs) const { - int len = (int)cs.prefetch_ulong(ln); - return len > 0 && len <= 8 && cs.have(ln + len * 8) && !redundant_int(cs) - ? td::bitstring::bits_load_long(cs.data_bits() + ln, len * 8) - : (1ULL << 63); -} - -bool VarIntegerNz::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - int k = value.bit_size(true); - return k <= (n - 1) * 8 && value.sgn() != 0 && cb.store_long_bool((k + 7) >> 3, ln) && - cb.store_int256_bool(value, (k + 7) & -8, true); -} - -bool Grams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_16.validate_skip(ops, cs, weak); -} - -td::RefInt256 Grams::as_integer_skip(vm::CellSlice& cs) const { - return t_VarUInteger_16.as_integer_skip(cs); -} - -bool Grams::null_value(vm::CellBuilder& cb) const { - return t_VarUInteger_16.null_value(cb); -} - -bool Grams::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - return t_VarUInteger_16.store_integer_value(cb, value); -} - -unsigned Grams::precompute_size(const td::BigInt256& value) const { - return t_VarUInteger_16.precompute_integer_size(value); -} - -unsigned Grams::precompute_size(td::RefInt256 value) const { - return t_VarUInteger_16.precompute_integer_size(std::move(value)); -} - -const Grams t_Grams; - -const Unary t_Unary; - -bool HmLabel::validate_skip(vm::CellSlice& cs, bool weak, int& n) const { - switch (get_tag(cs)) { - case hml_short: - return cs.advance(1) && (n = cs.count_leading(1)) <= m && cs.advance(2 * n + 1); - case hml_long: - return cs.advance(2) && cs.fetch_uint_leq(m, n) && cs.advance(n); - case hml_same: - return cs.advance(3) && cs.fetch_uint_leq(m, n); - } - return false; -} - -int HmLabel::get_tag(const vm::CellSlice& cs) const { - int tag = (int)cs.prefetch_ulong(2); - return tag != 1 ? tag : hml_short; -} - -int HashmapNode::get_size(const vm::CellSlice& cs) const { - assert(n >= 0); - return n ? 0x20000 : value_type.get_size(cs); -} - -bool HashmapNode::skip(vm::CellSlice& cs) const { - assert(n >= 0); - return n ? cs.advance_refs(2) : value_type.skip(cs); -} - -bool HashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - assert(n >= 0); - if (!n) { - // hmn_leaf - return value_type.validate_skip(ops, cs, weak); - } else { - // hmn_fork - Hashmap branch_type{n - 1, value_type}; - return branch_type.validate_ref(ops, cs.fetch_ref(), weak) && branch_type.validate_ref(ops, cs.fetch_ref(), weak); - } -} - -bool Hashmap::skip(vm::CellSlice& cs) const { - int l; - return HmLabel{n}.skip(cs, l) && HashmapNode{n - l, value_type}.skip(cs); -} - -bool Hashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l; - return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(ops, cs, weak); -} - -int HashmapE::get_size(const vm::CellSlice& cs) const { - int tag = get_tag(cs); - return (tag >= 0 ? (tag > 0 ? 0x10001 : 1) : -1); -} - -bool HashmapE::validate(int* ops, const vm::CellSlice& cs, bool weak) const { - int tag = get_tag(cs); - return tag <= 0 ? !tag : root_type.validate_ref(ops, cs.prefetch_ref(), weak); -} - -bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - int n = root_type.n; - vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n}; - const TLB& vt = root_type.value_type; - vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref cs1_ref, - Ref cs2_ref) -> bool { - if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) { - throw CombineError{}; - } - return true; - }; - return dict1.combine_with(dict2, combine) && std::move(dict1).append_dict_to_bool(cb); -} - -bool HashmapE::add_values_ref(Ref& res, Ref arg1, Ref arg2) const { - int n = root_type.n; - vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n}; - const TLB& vt = root_type.value_type; - vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref cs1_ref, - Ref cs2_ref) -> bool { - if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) { - throw CombineError{}; - } - return true; - }; - if (dict1.combine_with(dict2, combine)) { - dict2.reset(); - res = std::move(dict1).extract_root_cell(); - return true; - } else { - res = Ref{}; - return false; - } -} - -int HashmapE::sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - int n = root_type.n; - vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n}; - const TLB& vt = root_type.value_type; - vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref cs1_ref, - Ref cs2_ref) -> bool { - int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write()); - if (r < 0) { - throw CombineError{}; - } - return r; - }; - if (!dict1.combine_with(dict2, combine, 1)) { - return -1; - } - dict2.reset(); - bool not_empty = !dict1.is_empty(); - return std::move(dict1).append_dict_to_bool(cb) ? not_empty : -1; -} - -int HashmapE::sub_values_ref(Ref& res, Ref arg1, Ref arg2) const { - int n = root_type.n; - vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n}; - const TLB& vt = root_type.value_type; - vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref cs1_ref, - Ref cs2_ref) -> bool { - int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write()); - if (r < 0) { - throw CombineError{}; - } - return r; - }; - if (dict1.combine_with(dict2, combine, 1)) { - dict2.reset(); - res = std::move(dict1).extract_root_cell(); - return res.not_null(); - } else { - res = Ref{}; - return -1; - } -} - -bool HashmapE::store_ref(vm::CellBuilder& cb, Ref arg) const { - if (arg.is_null()) { - return cb.store_long_bool(0, 1); - } else { - return cb.store_long_bool(1, 1) && cb.store_ref_bool(std::move(arg)); - } -} - -const ExtraCurrencyCollection t_ExtraCurrencyCollection; - -bool CurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) && t_ExtraCurrencyCollection.validate_skip(ops, cs, weak); -} - -bool CurrencyCollection::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) && t_ExtraCurrencyCollection.skip(cs); -} - -td::RefInt256 CurrencyCollection::as_integer_skip(vm::CellSlice& cs) const { - auto res = t_Grams.as_integer_skip(cs); - if (res.not_null() && t_ExtraCurrencyCollection.skip(cs)) { - return res; - } else { - return {}; - } -} - -bool CurrencyCollection::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - return t_Grams.add_values(cb, cs1, cs2) && t_ExtraCurrencyCollection.add_values(cb, cs1, cs2); -} - -bool CurrencyCollection::unpack_special(vm::CellSlice& cs, td::RefInt256& balance, Ref& extra, - bool inexact) const { - balance = t_Grams.as_integer_skip(cs); - if (cs.fetch_ulong(1) == 1) { - return balance.not_null() && cs.fetch_ref_to(extra) && (inexact || cs.empty_ext()); - } else { - extra.clear(); - return balance.not_null() && (inexact || cs.empty_ext()); - } -} - -bool CurrencyCollection::unpack_special(vm::CellSlice& cs, block::CurrencyCollection& value, bool inexact) const { - return unpack_special(cs, value.grams, value.extra, inexact); -} - -bool CurrencyCollection::pack_special(vm::CellBuilder& cb, td::RefInt256 balance, Ref extra) const { - return t_Grams.store_integer_ref(cb, std::move(balance)) && t_ExtraCurrencyCollection.store_ref(cb, std::move(extra)); -} - -bool CurrencyCollection::pack_special(vm::CellBuilder& cb, const block::CurrencyCollection& value) const { - return value.is_valid() && pack_special(cb, value.grams, value.extra); -} - -bool CurrencyCollection::pack_special(vm::CellBuilder& cb, block::CurrencyCollection&& value) const { - return value.is_valid() && pack_special(cb, std::move(value.grams), std::move(value.extra)); -} - -bool CurrencyCollection::unpack(vm::CellSlice& cs, block::CurrencyCollection& res) const { - return unpack_special(cs, res.grams, res.extra); -} - -bool CurrencyCollection::pack(vm::CellBuilder& cb, const block::CurrencyCollection& res) const { - return res.is_valid() && pack_special(cb, res.grams, res.extra); -} - -const CurrencyCollection t_CurrencyCollection; - -bool CommonMsgInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int tag = get_tag(cs); - switch (tag) { - case int_msg_info: - return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - && t_MsgAddressInt.validate_skip(ops, cs, weak) // src - && t_MsgAddressInt.validate_skip(ops, cs, weak) // dest - && t_CurrencyCollection.validate_skip(ops, cs, weak) // value - && t_Grams.validate_skip(ops, cs, weak) // ihr_fee - && t_Grams.validate_skip(ops, cs, weak) // fwd_fee - && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32 - case ext_in_msg_info: - return cs.advance(2) && t_MsgAddressExt.validate_skip(ops, cs, weak) // src - && t_MsgAddressInt.validate_skip(ops, cs, weak) // dest - && t_Grams.validate_skip(ops, cs, weak); // import_fee - case ext_out_msg_info: - return cs.advance(2) && t_MsgAddressInt.validate_skip(ops, cs, weak) // src - && t_MsgAddressExt.validate_skip(ops, cs, weak) // dest - && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32 - } - return false; -} - -bool CommonMsgInfo::unpack(vm::CellSlice& cs, CommonMsgInfo::Record_int_msg_info& data) const { - return get_tag(cs) == int_msg_info && cs.advance(1) && cs.fetch_bool_to(data.ihr_disabled) && - cs.fetch_bool_to(data.bounce) && cs.fetch_bool_to(data.bounced) && t_MsgAddressInt.fetch_to(cs, data.src) && - t_MsgAddressInt.fetch_to(cs, data.dest) && t_CurrencyCollection.fetch_to(cs, data.value) && - t_Grams.fetch_to(cs, data.ihr_fee) && t_Grams.fetch_to(cs, data.fwd_fee) && - cs.fetch_uint_to(64, data.created_lt) && cs.fetch_uint_to(32, data.created_at); -} - -bool CommonMsgInfo::skip(vm::CellSlice& cs) const { - int tag = get_tag(cs); - switch (tag) { - case int_msg_info: - return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - && t_MsgAddressInt.skip(cs) // src - && t_MsgAddressInt.skip(cs) // dest - && t_CurrencyCollection.skip(cs) // value - && t_Grams.skip(cs) // ihr_fee - && t_Grams.skip(cs) // fwd_fee - && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32 - case ext_in_msg_info: - return cs.advance(2) && t_MsgAddressExt.skip(cs) // src - && t_MsgAddressInt.skip(cs) // dest - && t_Grams.skip(cs); // import_fee - case ext_out_msg_info: - return cs.advance(2) && t_MsgAddressInt.skip(cs) // src - && t_MsgAddressExt.skip(cs) // dest - && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32 - } - return false; -} - -bool CommonMsgInfo::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const { - switch (get_tag(cs)) { - case int_msg_info: - return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - && t_MsgAddressInt.skip(cs) // src - && t_MsgAddressInt.skip(cs) // dest - && t_CurrencyCollection.skip(cs) // value - && t_Grams.skip(cs) // ihr_fee - && t_Grams.skip(cs) // fwd_fee - && cs.fetch_ulong_bool(64, created_lt) // created_lt:uint64 - && cs.advance(32); // created_at:uint32 - case ext_in_msg_info: - return false; - case ext_out_msg_info: - return cs.advance(2) && t_MsgAddressInt.skip(cs) // src - && t_MsgAddressExt.skip(cs) // dest - && cs.fetch_ulong_bool(64, created_lt) // created_lt:uint64 - && cs.advance(32); // created_at:uint32 - } - return false; -} - -const CommonMsgInfo t_CommonMsgInfo; -const TickTock t_TickTock; -const RefAnything t_RefCell; - -bool StateInit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return Maybe{5}.validate_skip(ops, cs, weak) // split_depth:(Maybe (## 5)) - && Maybe{}.validate_skip(ops, cs, weak) // special:(Maybe TickTock) - && Maybe{}.validate_skip(ops, cs, weak) // code:(Maybe ^Cell) - && Maybe{}.validate_skip(ops, cs, weak) // data:(Maybe ^Cell) - && Maybe{}.validate_skip(ops, cs, weak); // library:(Maybe ^Cell) -} - -bool StateInit::get_ticktock(vm::CellSlice& cs, int& ticktock) const { - bool have_tt; - ticktock = 0; - return Maybe{5}.validate_skip_upto(1, cs) && cs.fetch_bool_to(have_tt) && - (!have_tt || cs.fetch_uint_to(2, ticktock)); -} - -const StateInit t_StateInit; - -bool Message::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - static const Maybe>> init_type; - static const Either body_type; - return t_CommonMsgInfo.validate_skip(ops, cs, weak) // info:CommonMsgInfo - && init_type.validate_skip(ops, cs, weak) // init:(Maybe (Either StateInit ^StateInit)) - && body_type.validate_skip(ops, cs, weak); // body:(Either X ^X) -} - -bool Message::extract_info(vm::CellSlice& cs) const { - return t_CommonMsgInfo.extract(cs); -} - -bool Message::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const { - return t_CommonMsgInfo.get_created_lt(cs, created_lt); -} - -bool Message::is_internal(Ref ref) const { - return is_internal(load_cell_slice(std::move(ref))); -} - -const Message t_Message; -const RefTo t_Ref_Message; - -bool IntermediateAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case interm_addr_regular: - return cs.advance(1) && cs.fetch_ulong(7) <= 96U; - case interm_addr_simple: - return cs.advance(2 + 8 + 64); - case interm_addr_ext: - if (cs.have(2 + 32 + 64)) { - cs.advance(2); - int workchain_id = (int)cs.fetch_long(32); - return (workchain_id < -128 || workchain_id >= 128) && cs.advance(64); - } - // no break - } - return false; -} - -bool IntermediateAddress::skip(vm::CellSlice& cs) const { - return cs.advance(get_size(cs)); -} - -int IntermediateAddress::get_size(const vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case interm_addr_regular: - return 1 + 7; - case interm_addr_simple: - return 2 + 8 + 64; - case interm_addr_ext: - return 2 + 32 + 64; - } - return -1; -} - -const IntermediateAddress t_IntermediateAddress; - -bool MsgEnvelope::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 4 // msg_envelope#4 - && t_IntermediateAddress.validate_skip(ops, cs, weak) // cur_addr:IntermediateAddress - && t_IntermediateAddress.validate_skip(ops, cs, weak) // next_addr:IntermediateAddress - && t_Grams.validate_skip(ops, cs, weak) // fwd_fee_remaining:Grams - && t_Ref_Message.validate_skip(ops, cs, weak); // msg:^Message -} - -bool MsgEnvelope::skip(vm::CellSlice& cs) const { - return cs.advance(4) // msg_envelope#4 - && t_IntermediateAddress.skip(cs) // cur_addr:IntermediateAddress - && t_IntermediateAddress.skip(cs) // next_addr:IntermediateAddress - && t_Grams.skip(cs) // fwd_fee_remaining:Grams - && t_Ref_Message.skip(cs); // msg:^Message -} - -bool MsgEnvelope::extract_fwd_fees_remaining(vm::CellSlice& cs) const { - return t_IntermediateAddress.skip(cs) && t_IntermediateAddress.skip(cs) && t_Grams.extract(cs); -} - -bool MsgEnvelope::unpack(vm::CellSlice& cs, MsgEnvelope::Record& data) const { - return cs.fetch_ulong(4) == 4 // msg_envelope#4 - && t_IntermediateAddress.fetch_to(cs, data.cur_addr) // cur_addr:IntermediateAddress - && t_IntermediateAddress.fetch_to(cs, data.next_addr) // next_addr:IntermediateAddress - && t_Grams.fetch_to(cs, data.fwd_fee_remaining) // fwd_fee_remaining:Grams - && cs.fetch_ref_to(data.msg); // msg:^Message -} - -bool MsgEnvelope::unpack(vm::CellSlice& cs, MsgEnvelope::Record_std& data) const { - return cs.fetch_ulong(4) == 4 // msg_envelope#4 - && t_IntermediateAddress.fetch_regular(cs, data.cur_addr) // cur_addr:IntermediateAddress - && t_IntermediateAddress.fetch_regular(cs, data.next_addr) // next_addr:IntermediateAddress - && t_Grams.as_integer_skip_to(cs, data.fwd_fee_remaining) // fwd_fee_remaining:Grams - && cs.fetch_ref_to(data.msg); // msg:^Message -} - -bool MsgEnvelope::unpack_std(vm::CellSlice& cs, int& cur_a, int& nhop_a, Ref& msg) const { - return cs.fetch_ulong(4) == 4 // msg_envelope#4 - && t_IntermediateAddress.fetch_regular(cs, cur_a) // cur_addr:IntermediateAddress - && t_IntermediateAddress.fetch_regular(cs, nhop_a) // next_addr:IntermediateAddress - && cs.fetch_ref_to(msg); -} - -bool MsgEnvelope::get_created_lt(const vm::CellSlice& cs, unsigned long long& created_lt) const { - if (!cs.size_refs()) { - return false; - } - auto msg_cs = load_cell_slice(cs.prefetch_ref()); - return t_Message.get_created_lt(msg_cs, created_lt); -} - -const MsgEnvelope t_MsgEnvelope; -const RefTo t_Ref_MsgEnvelope; - -bool StorageUsed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7) - && t_VarUInteger_7.validate_skip(ops, cs, weak) // bits:(VarUInteger 7) - && t_VarUInteger_7.validate_skip(ops, cs, weak); // public_cells:(VarUInteger 7) -} - -bool StorageUsed::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) // cells:(VarUInteger 7) - && t_VarUInteger_7.skip(cs) // bits:(VarUInteger 7) - && t_VarUInteger_7.skip(cs); // public_cells:(VarUInteger 7) -} - -const StorageUsed t_StorageUsed; - -bool StorageUsedShort::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7) - && t_VarUInteger_7.validate_skip(ops, cs, weak); // bits:(VarUInteger 7) -} - -bool StorageUsedShort::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) // cells:(VarUInteger 7) - && t_VarUInteger_7.skip(cs); // bits:(VarUInteger 7) -} - -const StorageUsedShort t_StorageUsedShort; - -const Maybe t_Maybe_Grams; - -bool StorageInfo::skip(vm::CellSlice& cs) const { - return t_StorageUsed.skip(cs) // used:StorageUsed - && cs.advance(32) // last_paid:uint32 - && t_Maybe_Grams.skip(cs); // due_payment:(Maybe Grams) -} - -bool StorageInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_StorageUsed.validate_skip(ops, cs, weak) // used:StorageUsed - && cs.advance(32) // last_paid:uint32 - && t_Maybe_Grams.validate_skip(ops, cs, weak); // due_payment:(Maybe Grams) -} - -const StorageInfo t_StorageInfo; - -bool AccountState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case account_uninit: - return cs.advance(2); - case account_frozen: - return cs.advance(2 + 256); - case account_active: - return cs.advance(1) && t_StateInit.validate_skip(ops, cs, weak); - } - return false; -} - -bool AccountState::get_ticktock(vm::CellSlice& cs, int& ticktock) const { - if (get_tag(cs) != account_active) { - ticktock = 0; - return true; - } - return cs.advance(1) && t_StateInit.get_ticktock(cs, ticktock); -} - -const AccountState t_AccountState; - -bool AccountStorage::skip(vm::CellSlice& cs) const { - return cs.advance(64) && t_CurrencyCollection.skip(cs) && t_AccountState.skip(cs); -} - -bool AccountStorage::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const { - return cs.advance(64) && t_CurrencyCollection.skip_copy(cb, cs) && t_AccountState.skip(cs); -} - -bool AccountStorage::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) && t_CurrencyCollection.validate_skip(ops, cs, weak) && - t_AccountState.validate_skip(ops, cs, weak); -} - -const AccountStorage t_AccountStorage; - -bool Account::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_none: - return cs.advance(1); - case account: - return cs.advance(1) // account$1 - && t_MsgAddressInt.skip(cs) // addr:MsgAddressInt - && t_StorageInfo.skip(cs) // storage_stat:StorageInfo - && t_AccountStorage.skip(cs); // storage:AccountStorage - } - return false; -} - -bool Account::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case account_none: - return allow_empty && cs.advance(1); - case account: - return cs.advance(1) // account$1 - && t_MsgAddressInt.validate_skip(ops, cs, weak) // addr:MsgAddressInt - && t_StorageInfo.validate_skip(ops, cs, weak) // storage_stat:StorageInfo - && t_AccountStorage.validate_skip(ops, cs, weak); // storage:AccountStorage - } - return false; -} - -bool Account::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case account_none: - return allow_empty && cs.advance(1) && t_CurrencyCollection.null_value(cb); - case account: - return cs.advance(1) // account$1 - && t_MsgAddressInt.skip(cs) // addr:MsgAddressInt - && t_StorageInfo.skip(cs) // storage_stat:StorageInfo - && t_AccountStorage.skip_copy_balance(cb, cs); // storage:AccountStorage - } - return false; -} - -bool Account::skip_copy_depth_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const { - int depth; - switch (get_tag(cs)) { - case account_none: - return allow_empty && cs.advance(1) && t_DepthBalanceInfo.null_value(cb); - case account: - return cs.advance(1) // account$1 - && t_MsgAddressInt.skip_get_depth(cs, depth) // addr:MsgAddressInt - && cb.store_uint_leq(30, depth) // -> store split_depth:(#<= 30) - && t_StorageInfo.skip(cs) // storage_stat:StorageInfo - && t_AccountStorage.skip_copy_balance(cb, cs); // storage:AccountStorage - } - return false; -} - -const Account t_Account, t_AccountE{true}; -const RefTo t_Ref_Account; - -bool ShardAccount::extract_account_state(Ref cs_ref, Ref& acc_state) { - if (cs_ref.is_null()) { - vm::CellBuilder cb; - return cb.store_bool_bool(false) && cb.finalize_to(acc_state); - } else { - return cs_ref->prefetch_ref_to(acc_state); - } -} - -bool ShardAccount::Record::reset() { - last_trans_hash.set_zero(); - last_trans_lt = 0; - is_zero = valid = true; - vm::CellBuilder cb; - return (cb.store_bool_bool(false) && cb.finalize_to(account)) || invalidate(); -} - -bool ShardAccount::Record::unpack(vm::CellSlice& cs) { - is_zero = false; - valid = true; - return (cs.fetch_ref_to(account) && cs.fetch_bits_to(last_trans_hash) && cs.fetch_uint_to(64, last_trans_lt)) || - invalidate(); -} - -bool ShardAccount::Record::unpack(Ref cs_ref) { - if (cs_ref.not_null()) { - return unpack(cs_ref.write()) && (cs_ref->empty_ext() || invalidate()); - } else { - return reset(); - } -} - -const ShardAccount t_ShardAccount; - -const AccountStatus t_AccountStatus; - -bool HashmapAugNode::skip(vm::CellSlice& cs) const { - if (n < 0) { - return false; - } else if (!n) { - // ahmn_leaf - return aug.extra_type.skip(cs) && aug.value_type.skip(cs); - } else { - // ahmn_fork - return cs.advance_refs(2) && aug.extra_type.skip(cs); - } -} - -bool HashmapAugNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - if (n < 0) { - return false; - } - if (!n) { - // ahmn_leaf - vm::CellSlice cs_extra{cs}; - if (!aug.extra_type.validate_skip(ops, cs, weak)) { - return false; - } - cs_extra.cut_tail(cs); - vm::CellSlice cs_value{cs}; - if (!aug.value_type.validate_skip(ops, cs, weak)) { - return false; - } - cs_value.cut_tail(cs); - return aug.check_leaf(cs_extra, cs_value); - } - // ahmn_fork - if (!cs.have_refs(2)) { - return false; - } - HashmapAug branch_type{n - 1, aug}; - if (!branch_type.validate_ref(ops, cs.prefetch_ref(0), weak) || - !branch_type.validate_ref(ops, cs.prefetch_ref(1), weak)) { - return false; - } - auto cs_left = load_cell_slice(cs.fetch_ref()); - auto cs_right = load_cell_slice(cs.fetch_ref()); - vm::CellSlice cs_extra{cs}; - if (!aug.extra_type.validate_skip(ops, cs, weak)) { - return false; - } - cs_extra.cut_tail(cs); - return branch_type.extract_extra(cs_left) && branch_type.extract_extra(cs_right) && - aug.check_fork(cs_extra, cs_left, cs_right); -} - -bool HashmapAug::skip(vm::CellSlice& cs) const { - int l; - return HmLabel{n}.skip(cs, l) && HashmapAugNode{n - l, aug}.skip(cs); -} - -bool HashmapAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int l; - return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(ops, cs, weak); -} - -bool HashmapAug::extract_extra(vm::CellSlice& cs) const { - int l; - return HmLabel{n}.skip(cs, l) && (l == n || cs.advance_refs(2)) && aug.extra_type.extract(cs); -} - -bool HashmapAugE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - Ref extra; - switch (get_tag(cs)) { - case ahme_empty: - return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() && - root_type.aug.check_empty(extra.unique_write()); - case ahme_root: - if (cs.advance(1) && root_type.validate_ref(ops, cs.prefetch_ref(), weak)) { - bool special; - auto cs_root = load_cell_slice_special(cs.fetch_ref(), special); - if (special) { - return weak; - } - return (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() && - root_type.extract_extra(cs_root) && extra->contents_equal(cs_root); - } - break; - } - return false; -} - -bool HashmapAugE::skip(vm::CellSlice& cs) const { - int tag = (int)cs.fetch_ulong(1); - return tag >= 0 && cs.advance_refs(tag) && root_type.aug.extra_type.skip(cs); -} - -bool HashmapAugE::extract_extra(vm::CellSlice& cs) const { - int tag = (int)cs.fetch_ulong(1); - return tag >= 0 && cs.advance_refs(tag) && root_type.aug.extra_type.extract(cs); -} - -bool DepthBalanceInfo::skip(vm::CellSlice& cs) const { - return cs.advance(5) && - t_CurrencyCollection.skip( - cs); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection = DepthBalanceInfo; -} - -bool DepthBalanceInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(5) <= 30 && - t_CurrencyCollection.validate_skip(ops, cs, - weak); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection -} - -bool DepthBalanceInfo::null_value(vm::CellBuilder& cb) const { - return cb.store_zeroes_bool(5) && t_CurrencyCollection.null_value(cb); -} - -bool DepthBalanceInfo::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - unsigned d1, d2; - return cs1.fetch_uint_leq(30, d1) && cs2.fetch_uint_leq(30, d2) && cb.store_uint_leq(30, std::max(d1, d2)) && - t_CurrencyCollection.add_values(cb, cs1, cs2); -} - -const DepthBalanceInfo t_DepthBalanceInfo; - -bool Aug_ShardAccounts::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - if (cs.have_refs()) { - auto cs2 = load_cell_slice(cs.prefetch_ref()); - return t_Account.skip_copy_depth_balance(cb, cs2); - } else { - return false; - } -} - -const Aug_ShardAccounts aug_ShardAccounts; - -const ShardAccounts t_ShardAccounts; - -const AccStatusChange t_AccStatusChange; - -bool TrStoragePhase::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) // storage_fees_collected:Grams - && t_Maybe_Grams.skip(cs) // storage_fees_due:Grams - && t_AccStatusChange.skip(cs); // status_change:AccStatusChange -} - -bool TrStoragePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) // storage_fees_collected:Grams - && t_Maybe_Grams.validate_skip(ops, cs, weak) // storage_fees_due:Grams - && t_AccStatusChange.validate_skip(ops, cs, weak); // status_change:AccStatusChange -} - -bool TrStoragePhase::get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const { - return t_Grams.as_integer_skip_to(cs, storage_fees); // storage_fees_collected:Grams -} - -bool TrStoragePhase::maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const { - auto z = cs.fetch_ulong(1); - if (!z) { - storage_fees = td::make_refint(0); - return true; - } else { - return z == 1 && get_storage_fees(cs, storage_fees); - } -} - -const TrStoragePhase t_TrStoragePhase; - -bool TrCreditPhase::skip(vm::CellSlice& cs) const { - return t_Maybe_Grams.skip(cs) // due_fees_collected:(Maybe Grams) - && t_CurrencyCollection.skip(cs); // credit:CurrencyCollection -} - -bool TrCreditPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Maybe_Grams.validate_skip(ops, cs, weak) // due_fees_collected:(Maybe Grams) - && t_CurrencyCollection.validate_skip(ops, cs, weak); // credit:CurrencyCollection -} - -const TrCreditPhase t_TrCreditPhase; - -bool TrComputeInternal1::skip(vm::CellSlice& cs) const { - return t_VarUInteger_7.skip(cs) // gas_used:(VarUInteger 7) - && t_VarUInteger_7.skip(cs) // gas_limit:(VarUInteger 7) - && Maybe{3}.skip(cs) // gas_credit:(Maybe (VarUInteger 3)) - && cs.advance(8 + 32) // mode:int8 exit_code:int32 - && Maybe{32}.skip(cs) // exit_arg:(Maybe int32) - && cs.advance(32 + 256 + 256); // vm_steps:uint32 - // vm_init_state_hash:uint256 - // vm_final_state_hash:uint256 -} - -bool TrComputeInternal1::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_used:(VarUInteger 7) - && t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_limit:(VarUInteger 7) - && Maybe{3}.validate_skip(ops, cs, weak) // gas_credit:(Maybe (VarUInteger 3)) - && cs.advance(8 + 32) // mode:int8 exit_code:int32 - && Maybe{32}.validate_skip(ops, cs, weak) // exit_arg:(Maybe int32) - && cs.advance(32 + 256 + 256); // vm_steps:uint32 - // vm_init_state_hash:uint256 - // vm_final_state_hash:uint256 -} - -const TrComputeInternal1 t_TrComputeInternal1; -const RefTo t_Ref_TrComputeInternal1; -const ComputeSkipReason t_ComputeSkipReason; - -bool TrComputePhase::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.advance(1) && t_ComputeSkipReason.skip(cs); - case tr_phase_compute_vm: - return cs.advance(1 + 3) // tr_phase_compute_vm$1 success:Bool msg_state_used:Bool account_activated:Bool - && t_Grams.skip(cs) // gas_fees:Grams - && t_Ref_TrComputeInternal1.skip(cs); // ^[ gas_used:(..) .. ] - } - return false; -} - -bool TrComputePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case tr_phase_compute_skipped: - return cs.advance(1) && t_ComputeSkipReason.validate_skip(ops, cs, weak); - case tr_phase_compute_vm: - return cs.advance(1 + 3) // tr_phase_compute_vm$1 success:Bool msg_state_used:Bool account_activated:Bool - && t_Grams.validate_skip(ops, cs, weak) // gas_fees:Grams - && t_Ref_TrComputeInternal1.validate_skip(ops, cs, weak); // ^[ gas_used:(..) .. ] - } - return false; -} - -const TrComputePhase t_TrComputePhase; - -bool TrActionPhase::skip(vm::CellSlice& cs) const { - return cs.advance(3) // success:Bool valid:Bool no_funds:Bool - && t_AccStatusChange.skip(cs) // status_change:AccStatusChange - && t_Maybe_Grams.skip(cs) // total_fwd_fees:(Maybe Grams) - && t_Maybe_Grams.skip(cs) // total_action_fees:(Maybe Grams) - && cs.advance(32) // result_code:int32 - && Maybe{32}.skip(cs) // result_arg:(Maybe int32) - && cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16 - // skipped_actions:uint16 msgs_created:uint16 - // action_list_hash:uint256 - && t_StorageUsedShort.skip(cs); // tot_msg_size:StorageUsedShort -} - -bool TrActionPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(3) // success:Bool valid:Bool no_funds:Bool - && t_AccStatusChange.validate_skip(ops, cs, weak) // status_change:AccStatusChange - && t_Maybe_Grams.validate_skip(ops, cs, weak) // total_fwd_fees:(Maybe Grams) - && t_Maybe_Grams.validate_skip(ops, cs, weak) // total_action_fees:(Maybe Grams) - && cs.advance(32) // result_code:int32 - && Maybe{32}.validate_skip(ops, cs, weak) // result_arg:(Maybe int32) - && cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16 - // skipped_actions:uint16 msgs_created:uint16 - // action_list_hash:uint256 - && t_StorageUsedShort.validate_skip(ops, cs, weak); // tot_msg_size:StorageUsed -} - -const TrActionPhase t_TrActionPhase; - -bool TrBouncePhase::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.advance(2); // tr_phase_bounce_negfunds$00 - case tr_phase_bounce_nofunds: - return cs.advance(2) // tr_phase_bounce_nofunds$01 - && t_StorageUsedShort.skip(cs) // msg_size:StorageUsedShort - && t_Grams.skip(cs); // req_fwd_fees:Grams - case tr_phase_bounce_ok: - return cs.advance(1) // tr_phase_bounce_ok$1 - && t_StorageUsedShort.skip(cs) // msg_size:StorageUsedShort - && t_Grams.skip(cs) // msg_fees:Grams - && t_Grams.skip(cs); // fwd_fees:Grams - } - return false; -} - -bool TrBouncePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case tr_phase_bounce_negfunds: - return cs.advance(2); // tr_phase_bounce_negfunds$00 - case tr_phase_bounce_nofunds: - return cs.advance(2) // tr_phase_bounce_nofunds$01 - && t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort - && t_Grams.validate_skip(ops, cs, weak); // req_fwd_fees:Grams - case tr_phase_bounce_ok: - return cs.advance(1) // tr_phase_bounce_ok$1 - && t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort - && t_Grams.validate_skip(ops, cs, weak) // msg_fees:Grams - && t_Grams.validate_skip(ops, cs, weak); // fwd_fees:Grams - } - return false; -} - -int TrBouncePhase::get_tag(const vm::CellSlice& cs) const { - if (cs.size() == 1) { - return (int)cs.prefetch_ulong(1) == 1 ? tr_phase_bounce_ok : -1; - } - int v = (int)cs.prefetch_ulong(2); - return v == 3 ? tr_phase_bounce_ok : v; -}; - -const TrBouncePhase t_TrBouncePhase; - -bool SplitMergeInfo::skip(vm::CellSlice& cs) const { - // cur_shard_pfx_len:(## 6) acc_split_depth:(##6) this_addr:uint256 sibling_addr:uint256 - return cs.advance(6 + 6 + 256 + 256); -} - -bool SplitMergeInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - if (!cs.have(6 + 6 + 256 + 256)) { - return false; - } - int cur_pfx_len = (int)cs.fetch_ulong(6); - int split_depth = (int)cs.fetch_ulong(6); - unsigned char this_addr[32], sibling_addr[32]; - if (!cs.fetch_bytes(this_addr, 32) || !cs.fetch_bytes(sibling_addr, 32)) { - return false; - } - // cur_pfx_len < split_depth, addresses match except in bit cur_pfx_len - if (cur_pfx_len >= split_depth) { - return false; - } - sibling_addr[cur_pfx_len >> 3] ^= (unsigned char)(0x80 >> (cur_pfx_len & 7)); - return !std::memcmp(this_addr, sibling_addr, 32); -} - -const SplitMergeInfo t_SplitMergeInfo; - -bool TransactionDescr::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(4 + 1) // trans_ord$0000 storage_first:Bool - && Maybe{}.skip(cs) // storage_ph:(Maybe TrStoragePhase) - && Maybe{}.skip(cs) // credit_ph:(Maybe TrCreditPhase) - && t_TrComputePhase.skip(cs) // compute_ph:TrComputePhase - && Maybe>{}.skip(cs) // action:(Maybe ^TrActionPhase) - && cs.advance(1) // aborted:Bool - && Maybe{}.skip(cs) // bounce:(Maybe TrBouncePhase) - && cs.advance(1); // destroyed:Bool - case trans_storage: - return cs.advance(4) // trans_storage$0001 - && t_TrStoragePhase.skip(cs); // storage_ph:TrStoragePhase - case trans_tick_tock: - return cs.advance(4) // trans_tick_tock$001 is_tock:Bool - && t_TrStoragePhase.skip(cs) // storage_ph:TrStoragePhase - && t_TrComputePhase.skip(cs) // compute_ph:TrComputePhase - && Maybe>{}.skip(cs) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - case trans_split_prepare: - return cs.advance(4) // trans_split_prepare$0100 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && Maybe{}.skip(cs) // storage_ph:(Maybe TrStoragePhase) - && t_TrComputePhase.skip(cs) // compute_ph:TrComputePhase - && Maybe>{}.skip(cs) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - case trans_split_install: - return cs.advance(4) // trans_split_install$0101 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && t_Ref_Transaction.skip(cs) // prepare_transaction:^Transaction - && cs.advance(1); // installed:Bool - case trans_merge_prepare: - return cs.advance(4) // trans_merge_prepare$0110 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && t_TrStoragePhase.skip(cs) // storage_ph:TrStoragePhase - && cs.advance(1); // aborted:Bool - case trans_merge_install: - return cs.advance(4) // trans_merge_install$0111 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && t_Ref_Transaction.skip(cs) // prepare_transaction:^Transaction - && Maybe{}.skip(cs) // storage_ph:(Maybe TrStoragePhase) - && Maybe{}.skip(cs) // credit_ph:(Maybe TrCreditPhase) - && Maybe{}.skip(cs) // compute_ph:TrComputePhase - && Maybe>{}.skip(cs) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - } - return false; -} - -bool TransactionDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(4 + 1) // trans_ord$0000 credit_first:Bool - && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase) - && Maybe{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase) - && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase - && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase) - && cs.advance(1) // aborted:Bool - && Maybe{}.validate_skip(ops, cs, weak) // bounce:(Maybe TrBouncePhase) - && cs.advance(1); // destroyed:Bool - case trans_storage: - return cs.advance(4) // trans_storage$0001 - && t_TrStoragePhase.validate_skip(ops, cs, weak); // storage_ph:TrStoragePhase - case trans_tick_tock: - return cs.advance(4) // trans_tick_tock$001 is_tock:Bool - && t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase - && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase - && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - case trans_split_prepare: - return cs.advance(4) // trans_split_prepare$0100 - && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo - && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase) - && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase - && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - case trans_split_install: - return cs.advance(4) // trans_split_install$0101 - && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo - && t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction - && cs.advance(1); // installed:Bool - case trans_merge_prepare: - return cs.advance(4) // trans_merge_prepare$0110 - && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo - && t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase - && cs.advance(1); // aborted:Bool - case trans_merge_install: - return cs.advance(4) // trans_merge_install$0111 - && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo - && t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction - && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase) - && Maybe{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase) - && Maybe{}.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase - && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase) - && cs.advance(2); // aborted:Bool destroyed:Bool - } - return false; -} - -int TransactionDescr::get_tag(const vm::CellSlice& cs) const { - int t = (int)cs.prefetch_ulong(4); - return (t >= 0 && t <= 7) ? (t == 3 ? 2 : t) : -1; -} - -bool TransactionDescr::skip_to_storage_phase(vm::CellSlice& cs, bool& found) const { - found = false; - switch (get_tag(cs)) { - case trans_ord: - return cs.advance(4 + 1) // trans_ord$0000 storage_first:Bool - && cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase) - case trans_storage: - return cs.advance(4) // trans_storage$0001 - && (found = true); // storage_ph:TrStoragePhase - case trans_tick_tock: - return cs.advance(4) // trans_tick_tock$001 is_tock:Bool - && (found = true); // storage_ph:TrStoragePhase - case trans_split_prepare: - return cs.advance(4) // trans_split_prepare$0100 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase) - case trans_split_install: - return true; - case trans_merge_prepare: - return cs.advance(4) // trans_merge_prepare$0110 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && (found = true); // storage_ph:TrStoragePhase - case trans_merge_install: - return cs.advance(4) // trans_merge_install$0111 - && t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo - && t_Ref_Transaction.skip(cs) // prepare_transaction:^Transaction - && cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase) - } - return false; -} - -bool TransactionDescr::get_storage_fees(Ref cell, td::RefInt256& storage_fees) const { - if (cell.is_null()) { - return false; - } - auto cs = vm::load_cell_slice(std::move(cell)); - bool found; - if (!skip_to_storage_phase(cs, found)) { - return false; - } else if (found) { - return t_TrStoragePhase.get_storage_fees(cs, storage_fees); - } else { - storage_fees = td::make_refint(0); - return true; - } -} - -const TransactionDescr t_TransactionDescr; - -bool Transaction_aux::skip(vm::CellSlice& cs) const { - return Maybe>{}.skip(cs) // in_msg:(Maybe ^Message) - && HashmapE{15, t_Ref_Message}.skip(cs); // out_msgs:(HashmapE 15 ^Message) -} - -bool Transaction_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return Maybe>{}.validate_skip(ops, cs, weak) // in_msg:(Maybe ^Message) - && HashmapE{15, t_Ref_Message}.validate_skip(ops, cs, weak); // out_msgs:(HashmapE 15 ^Message) -} - -const Transaction_aux t_Transaction_aux; - -bool Transaction::skip(vm::CellSlice& cs) const { - return cs.advance( - 4 + 256 + 64 + 256 + 64 + 32 + - 15) // transaction$0111 account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15 - && t_AccountStatus.skip(cs) // orig_status:AccountStatus - && t_AccountStatus.skip(cs) // end_status:AccountStatus - && cs.advance_refs(1) // ^[ in_msg:(Maybe ^Message) out_msgs:(HashmapE 15 ^Message) ] - && t_CurrencyCollection.skip(cs) // total_fees:CurrencyCollection - && cs.advance_refs(1) // state_update:^(MERKLE_UPDATE Account) - && RefTo{}.skip(cs); // description:^TransactionDescr -} - -bool Transaction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 7 // transaction$0111 - && - cs.advance( - 256 + 64 + 256 + 64 + 32 + - 15) // account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15 - && t_AccountStatus.validate_skip(ops, cs, weak) // orig_status:AccountStatus - && t_AccountStatus.validate_skip(ops, cs, weak) // end_status:AccountStatus - && RefTo{}.validate_skip(ops, cs, weak) // ^[ in_msg:... out_msgs:... ] - && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_fees:CurrencyCollection - && t_Ref_HashUpdate.validate_skip(ops, cs, weak) // state_update:^(HASH_UPDATE Account) - && RefTo{}.validate_skip(ops, cs, weak); // description:^TransactionDescr -} - -bool Transaction::get_storage_fees(Ref cell, td::RefInt256& storage_fees) const { - Ref tdescr; - return get_descr(std::move(cell), tdescr) && t_TransactionDescr.get_storage_fees(std::move(tdescr), storage_fees); -} - -bool Transaction::get_descr(Ref cell, Ref& tdescr) const { - if (cell.is_null()) { - return false; - } else { - auto cs = vm::load_cell_slice(std::move(cell)); - return cs.is_valid() && get_descr(cs, tdescr) && cs.empty_ext(); - } -} - -bool Transaction::get_descr(vm::CellSlice& cs, Ref& tdescr) const { - return cs.advance( - 4 + 256 + 64 + 256 + 64 + 32 + - 15) // transaction$0111 account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15 - && t_AccountStatus.skip(cs) // orig_status:AccountStatus - && t_AccountStatus.skip(cs) // end_status:AccountStatus - && cs.advance_refs(1) // ^[ in_msg:(Maybe ^Message) out_msgs:(HashmapE 15 ^Message) ] - && t_CurrencyCollection.skip(cs) // total_fees:CurrencyCollection - && cs.advance_refs(1) // state_update:^(MERKLE_UPDATE Account) - && cs.fetch_ref_to(tdescr); // description:^TransactionDescr -} - -bool Transaction::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const { - return cs.is_valid() && cs.fetch_ulong(4) == 7 // transaction$0111 - && - cs.advance( - 256 + 64 + 256 + 64 + 32 + - 15) // account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15 - && t_AccountStatus.skip(cs) // orig_status:AccountStatus - && t_AccountStatus.skip(cs) // end_status:AccountStatus - && cs.advance_refs(1) // ^[ in_msg:... out_msg:... ] - && total_fees.fetch(cs); // total_fees:CurrencyCollection -} - -const Transaction t_Transaction; -const RefTo t_Ref_Transaction; - -// leaf evaluation for (HashmapAug 64 ^Transaction CurrencyCollection) -bool Aug_AccountTransactions::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - auto cell_ref = cs.prefetch_ref(); - block::CurrencyCollection total_fees; - return cell_ref.not_null() && t_Transaction.get_total_fees(vm::load_cell_slice(std::move(cell_ref)), total_fees) && - total_fees.store(cb); -} - -const Aug_AccountTransactions aug_AccountTransactions; -const HashmapAug t_AccountTransactions{64, aug_AccountTransactions}; - -const HashUpdate t_HashUpdate; -const RefTo t_Ref_HashUpdate; - -bool AccountBlock::skip(vm::CellSlice& cs) const { - return cs.advance(4 + 256) // acc_trans#5 account_addr:bits256 - && t_AccountTransactions.skip(cs) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection) - && cs.advance_refs(1); // state_update:^(HASH_UPDATE Account) -} - -bool AccountBlock::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.fetch_ulong(4) == 5 // acc_trans#5 - && cs.advance(256) // account_addr:bits256 - && t_AccountTransactions.validate_skip(ops, cs, - weak) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection) - && t_Ref_HashUpdate.validate_skip(ops, cs, weak); // state_update:^(HASH_UPDATE Account) -} - -bool AccountBlock::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const { - return cs.advance(4 + 256) // acc_trans#5 account_addr:bits256 - && t_AccountTransactions.extract_extra(cs) // transactions:(HashmapAug 64 ^Transaction Grams) - && total_fees.fetch(cs); -} - -const AccountBlock t_AccountBlock; - -bool Aug_ShardAccountBlocks::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - block::CurrencyCollection total_fees; - return t_AccountBlock.get_total_fees(std::move(cs), total_fees) && total_fees.store(cb); -} - -const Aug_ShardAccountBlocks aug_ShardAccountBlocks; -const HashmapAugE t_ShardAccountBlocks{256, - aug_ShardAccountBlocks}; // (HashmapAugE 256 AccountBlock CurrencyCollection) - -bool ImportFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_Grams.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ImportFees::skip(vm::CellSlice& cs) const { - return t_Grams.skip(cs) && t_CurrencyCollection.skip(cs); -} - -bool ImportFees::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - return t_Grams.add_values(cb, cs1, cs2) && t_CurrencyCollection.add_values(cb, cs1, cs2); -} - -const ImportFees t_ImportFees; - -bool InMsg::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.advance(3) // msg_import_ext$000 - && t_Ref_Message.skip(cs) // msg:^Message - && t_Ref_Transaction.skip(cs); // transaction:^Transaction - case msg_import_ihr: - return cs.advance(3) // msg_import_ihr$010 - && t_Ref_Message.skip(cs) // msg:^Message - && t_Ref_Transaction.skip(cs) // transaction:^Transaction - && t_Grams.skip(cs) // ihr_fee:Grams - && t_RefCell.skip(cs); // proof_created:^Cell - case msg_import_imm: - return cs.advance(3) // msg_import_imm$011 - && t_Ref_MsgEnvelope.skip(cs) // in_msg:^MsgEnvelope - && t_Ref_Transaction.skip(cs) // transaction:^Transaction - && t_Grams.skip(cs); // fwd_fee:Grams - case msg_import_fin: - return cs.advance(3) // msg_import_fin$100 - && t_Ref_MsgEnvelope.skip(cs) // in_msg:^MsgEnvelope - && t_Ref_Transaction.skip(cs) // transaction:^Transaction - && t_Grams.skip(cs); // fwd_fee:Grams - case msg_import_tr: - return cs.advance(3) // msg_import_tr$101 - && t_Ref_MsgEnvelope.skip(cs) // in_msg:^MsgEnvelope - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && t_Grams.skip(cs); // transit_fee:Grams - case msg_discard_fin: - return cs.advance(3) // msg_discard_fin$110 - && t_Ref_MsgEnvelope.skip(cs) // in_msg:^MsgEnvelope - && cs.advance(64) // transaction_id:uint64 - && t_Grams.skip(cs); // fwd_fee:Grams - case msg_discard_tr: - return cs.advance(3) // msg_discard_tr$111 - && t_Ref_MsgEnvelope.skip(cs) // in_msg:^MsgEnvelope - && cs.advance(64) // transaction_id:uint64 - && t_Grams.skip(cs) // fwd_fee:Grams - && t_RefCell.skip(cs); // proof_delivered:^Cell - } - return false; -} - -bool InMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case msg_import_ext: - return cs.advance(3) // msg_import_ext$000 - && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message - && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction - case msg_import_ihr: - return cs.advance(3) // msg_import_ihr$010 - && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message - && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction - && t_Grams.validate_skip(ops, cs, weak) // ihr_fee:Grams - && t_RefCell.validate_skip(ops, cs, weak); // proof_created:^Cell - case msg_import_imm: - return cs.advance(3) // msg_import_imm$011 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope - && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction - && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams - case msg_import_fin: - return cs.advance(3) // msg_import_fin$100 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope - && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction - && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams - case msg_import_tr: - return cs.advance(3) // msg_import_tr$101 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && t_Grams.validate_skip(ops, cs, weak); // transit_fee:Grams - case msg_discard_fin: - return cs.advance(3) // msg_discard_fin$110 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope - && cs.advance(64) // transaction_id:uint64 - && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams - case msg_discard_tr: - return cs.advance(3) // msg_discard_tr$111 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope - && cs.advance(64) // transaction_id:uint64 - && t_Grams.validate_skip(ops, cs, weak) // fwd_fee:Grams - && t_RefCell.validate_skip(ops, cs, weak); // proof_delivered:^Cell - } - return false; -} - -bool InMsg::get_import_fees(vm::CellBuilder& cb, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_import_ext: // inbound external message - return t_ImportFees.null_value(cb); // external messages have no value and no import fees - case msg_import_ihr: // IHR-forwarded internal message to its final destination - if (cs.advance(3) && cs.size_refs() >= 3) { - auto msg_cs = load_cell_slice(cs.fetch_ref()); - CommonMsgInfo::Record_int_msg_info msg_info; - td::RefInt256 ihr_fee; - vm::CellBuilder aux; - // sort of Prolog-style in C++ - return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) && - cs.fetch_ref().not_null() && (ihr_fee = t_Grams.as_integer_skip(cs)).not_null() && - cs.fetch_ref().not_null() && !cmp(ihr_fee, t_Grams.as_integer(*msg_info.ihr_fee)) && - cb.append_cellslice_bool(msg_info.ihr_fee) // fees_collected := ihr_fee - && aux.append_cellslice_bool(msg_info.ihr_fee) && t_ExtraCurrencyCollection.null_value(aux) && - t_CurrencyCollection.add_values(cb, aux.as_cellslice_ref().write(), - msg_info.value.write()); // value_imported := ihr_fee + value - } - return false; - case msg_import_imm: // internal message re-imported from this very block - if (cs.advance(3) && cs.size_refs() >= 2) { - return cs.fetch_ref().not_null() && cs.fetch_ref().not_null() && - cb.append_cellslice_bool(t_Grams.fetch(cs)) // fees_collected := fwd_fees - && t_CurrencyCollection.null_value(cb); // value_imported := 0 - } - return false; - case msg_import_fin: // internal message delivered to its final destination in this block - if (cs.advance(3) && cs.size_refs() >= 2) { - auto msg_env_cs = load_cell_slice(cs.fetch_ref()); - MsgEnvelope::Record in_msg; - td::RefInt256 fwd_fee, fwd_fee_remaining, value_grams, ihr_fee; - if (!(t_MsgEnvelope.unpack(msg_env_cs, in_msg) && cs.fetch_ref().not_null() && - t_Grams.as_integer_skip_to(cs, fwd_fee) && - (fwd_fee_remaining = t_Grams.as_integer(in_msg.fwd_fee_remaining)).not_null() && - !(cmp(fwd_fee, fwd_fee_remaining)))) { - return false; - } - auto msg_cs = load_cell_slice(std::move(in_msg.msg)); - CommonMsgInfo::Record_int_msg_info msg_info; - return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) && - cb.append_cellslice_bool(in_msg.fwd_fee_remaining) // fees_collected := fwd_fee_remaining - && t_Grams.as_integer_skip_to(msg_info.value.write(), value_grams) && - (ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() && - t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) && - cb.append_cellslice_bool( - msg_info.value.write()); // value_imported = msg.value + msg.ihr_fee + fwd_fee_remaining - } - return false; - case msg_import_tr: // transit internal message - if (cs.advance(3) && cs.size_refs() >= 2) { - auto msg_env_cs = load_cell_slice(cs.fetch_ref()); - MsgEnvelope::Record in_msg; - td::RefInt256 transit_fee, fwd_fee_remaining, value_grams, ihr_fee; - if (!(t_MsgEnvelope.unpack(msg_env_cs, in_msg) && cs.fetch_ref().not_null() && - t_Grams.as_integer_skip_to(cs, transit_fee) && - (fwd_fee_remaining = t_Grams.as_integer(in_msg.fwd_fee_remaining)).not_null() && - cmp(transit_fee, fwd_fee_remaining) <= 0)) { - return false; - } - auto msg_cs = load_cell_slice(in_msg.msg); - CommonMsgInfo::Record_int_msg_info msg_info; - return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) && - t_Grams.store_integer_ref(cb, std::move(transit_fee)) // fees_collected := transit_fees - && t_Grams.as_integer_skip_to(msg_info.value.write(), value_grams) && - (ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() && - t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) && - cb.append_cellslice_bool( - msg_info.value.write()); // value_imported = msg.value + msg.ihr_fee + fwd_fee_remaining - } - return false; - case msg_discard_fin: // internal message discarded at its final destination because of previous IHR delivery - if (cs.advance(3) && cs.size_refs() >= 1) { - Ref fwd_fee; - return cs.fetch_ref().not_null() && cs.advance(64) && (fwd_fee = t_Grams.fetch(cs)).not_null() && - cb.append_cellslice_bool(fwd_fee) // fees_collected := fwd_fee - && cb.append_cellslice_bool(std::move(fwd_fee)) && - t_ExtraCurrencyCollection.null_value(cb); // value_imported := fwd_fee - } - return false; - case msg_discard_tr: // internal message discarded at an intermediate destination - if (cs.advance(3) && cs.size_refs() >= 2) { - Ref fwd_fee; - return cs.fetch_ref().not_null() && cs.advance(64) && (fwd_fee = t_Grams.fetch(cs)).not_null() && - cs.fetch_ref().not_null() && cb.append_cellslice_bool(fwd_fee) // fees_collected := fwd_fee - && cb.append_cellslice_bool(std::move(fwd_fee)) && - t_ExtraCurrencyCollection.null_value(cb); // value_imported := fwd_fee - } - return false; - } - return false; -} - -const InMsg t_InMsg; - -const Aug_InMsgDescr aug_InMsgDescr; -const InMsgDescr t_InMsgDescr; - -bool OutMsg::skip(vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.advance(3) // msg_export_ext$000 - && t_Ref_Message.skip(cs) // msg:^Message - && t_Ref_Transaction.skip(cs); // transaction:^Transaction - case msg_export_imm: - return cs.advance(3) // msg_export_imm$010 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && t_Ref_Transaction.skip(cs) // transaction:^Transaction - && RefTo{}.skip(cs); // reimport:^InMsg - case msg_export_new: - return cs.advance(3) // msg_export_new$001 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && t_Ref_Transaction.skip(cs); // transaction:^Transaction - case msg_export_tr: - return cs.advance(3) // msg_export_tr$011 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && RefTo{}.skip(cs); // imported:^InMsg - case msg_export_deq_imm: - return cs.advance(3) // msg_export_deq_imm$100 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && RefTo{}.skip(cs); // reimport:^InMsg - case msg_export_deq: - return cs.advance(4) // msg_export_deq$1100 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && cs.advance(63); // import_block_lt:uint63 - case msg_export_deq_short: - return cs.advance( - 4 + 256 + 32 + 64 + - 64); // msg_export_deq_short$1101 msg_env_hash:bits256 next_workchain:int32 next_addr_pfx:uint64 import_block_lt:uint64 - case msg_export_tr_req: - return cs.advance(3) // msg_export_tr_req$111 - && t_Ref_MsgEnvelope.skip(cs) // out_msg:^MsgEnvelope - && RefTo{}.skip(cs); // imported:^InMsg - } - return false; -} - -bool OutMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - switch (get_tag(cs)) { - case msg_export_ext: - return cs.advance(3) // msg_export_ext$000 - && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message - && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction - case msg_export_imm: - return cs.advance(3) // msg_export_imm$010 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction - && RefTo{}.validate_skip(ops, cs, weak); // reimport:^InMsg - case msg_export_new: - return cs.advance(3) // msg_export_new$001 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction - case msg_export_tr: - return cs.advance(3) // msg_export_tr$011 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && RefTo{}.validate_skip(ops, cs, weak); // imported:^InMsg - case msg_export_deq_imm: - return cs.advance(3) // msg_export_deq_imm$100 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && RefTo{}.validate_skip(ops, cs, weak); // reimport:^InMsg - case msg_export_deq: - return cs.advance(4) // msg_export_deq$1100 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && cs.advance(63); // import_block_lt:uint63 - case msg_export_deq_short: - return cs.advance( - 4 + 256 + 32 + 64 + - 64); // msg_export_deq_short$1101 msg_env_hash:bits256 next_workchain:int32 next_addr_pfx:uint64 import_block_lt:uint64 - case msg_export_tr_req: - return cs.advance(3) // msg_export_tr_req$111 - && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope - && RefTo{}.validate_skip(ops, cs, weak); // imported:^InMsg - } - return false; -} - -bool OutMsg::get_export_value(vm::CellBuilder& cb, vm::CellSlice& cs) const { - switch (get_tag(cs)) { - case msg_export_ext: // external outbound message carries no value - if (cs.have(3, 2)) { - return t_CurrencyCollection.null_value(cb); - } - return false; - case msg_export_imm: // outbound internal message delivered in this very block, no value exported - return cs.have(3, 3) && t_CurrencyCollection.null_value(cb); - case msg_export_deq_imm: // dequeuing record for outbound message delivered in this very block, no value exported - return cs.have(3, 2) && t_CurrencyCollection.null_value(cb); - case msg_export_deq: // dequeueing record for outbound message, no exported value - return cs.have(4 + 63, 1) && t_CurrencyCollection.null_value(cb); - case msg_export_deq_short: // dequeueing record for outbound message, no exported value - return cs.have(4 + 256 + 32 + 64 + 64) && t_CurrencyCollection.null_value(cb); - case msg_export_new: // newly-generated outbound internal message, queued - case msg_export_tr: // transit internal message, queued - case msg_export_tr_req: // transit internal message, re-queued from this shardchain - if (cs.advance(3) && cs.size_refs() >= 2) { - auto msg_env_cs = load_cell_slice(cs.fetch_ref()); - MsgEnvelope::Record out_msg; - if (!(cs.fetch_ref().not_null() && t_MsgEnvelope.unpack(msg_env_cs, out_msg))) { - return false; - } - auto msg_cs = load_cell_slice(std::move(out_msg.msg)); - CommonMsgInfo::Record_int_msg_info msg_info; - td::RefInt256 value_grams, ihr_fee, fwd_fee_remaining; - return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) && - (value_grams = t_Grams.as_integer_skip(msg_info.value.write())).not_null() && - (ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() && - (fwd_fee_remaining = t_Grams.as_integer(out_msg.fwd_fee_remaining)).not_null() && - t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) && - cb.append_cellslice_bool(std::move(msg_info.value)); - // exported value = msg.value + msg.ihr_fee + fwd_fee_remaining - } - return false; - } - return false; -} - -bool OutMsg::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const { - switch (get_tag(cs)) { - case msg_export_ext: - if (cs.have(3, 1)) { - auto msg_cs = load_cell_slice(cs.prefetch_ref()); - return t_Message.get_created_lt(msg_cs, created_lt); - } else { - return false; - } - case msg_export_imm: - case msg_export_new: - case msg_export_tr: - case msg_export_deq: - case msg_export_deq_short: - case msg_export_deq_imm: - case msg_export_tr_req: - if (cs.have(3, 1)) { - auto out_msg_cs = load_cell_slice(cs.prefetch_ref()); - return t_MsgEnvelope.get_created_lt(out_msg_cs, created_lt); - } else { - return false; - } - } - return false; -} - -const OutMsg t_OutMsg; - -const Aug_OutMsgDescr aug_OutMsgDescr; -const OutMsgDescr t_OutMsgDescr; - -bool EnqueuedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak); -} - -const EnqueuedMsg t_EnqueuedMsg; - -bool Aug_OutMsgQueue::eval_fork(vm::CellBuilder& cb, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const { - unsigned long long x, y; - return left_cs.fetch_ulong_bool(64, x) && right_cs.fetch_ulong_bool(64, y) && - cb.store_ulong_rchk_bool(std::min(x, y), 64); -} - -bool Aug_OutMsgQueue::eval_empty(vm::CellBuilder& cb) const { - return cb.store_long_bool(0, 64); -} - -bool Aug_OutMsgQueue::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - Ref msg_env; - unsigned long long created_lt; - return cs.fetch_ref_to(msg_env) && t_MsgEnvelope.get_created_lt(load_cell_slice(std::move(msg_env)), created_lt) && - cb.store_ulong_rchk_bool(created_lt, 64); -} - -const Aug_OutMsgQueue aug_OutMsgQueue; -const OutMsgQueue t_OutMsgQueue; - -const ProcessedUpto t_ProcessedUpto; -const HashmapE t_ProcessedInfo{96, t_ProcessedUpto}; -const HashmapE t_IhrPendingInfo{256, t_uint128}; - -// _ out_queue:OutMsgQueue proc_info:ProcessedInfo = OutMsgQueueInfo; -bool OutMsgQueueInfo::skip(vm::CellSlice& cs) const { - return t_OutMsgQueue.skip(cs) && t_ProcessedInfo.skip(cs) && t_IhrPendingInfo.skip(cs); -} - -bool OutMsgQueueInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_OutMsgQueue.validate_skip(ops, cs, weak) && t_ProcessedInfo.validate_skip(ops, cs, weak) && - t_IhrPendingInfo.validate_skip(ops, cs, weak); -} - -const OutMsgQueueInfo t_OutMsgQueueInfo; -const RefTo t_Ref_OutMsgQueueInfo; - -bool ExtBlkRef::unpack(vm::CellSlice& cs, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - block::gen::ExtBlkRef::Record data; - if (!tlb::unpack(cs, data)) { - blkid.invalidate(); - return false; - } - blkid.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, data.seq_no}; - blkid.root_hash = data.root_hash; - blkid.file_hash = data.file_hash; - if (end_lt) { - *end_lt = data.end_lt; - } - return true; -} - -bool ExtBlkRef::unpack(Ref cs_ref, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - block::gen::ExtBlkRef::Record data; - if (!tlb::csr_unpack_safe(std::move(cs_ref), data)) { - blkid.invalidate(); - return false; - } - blkid.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, data.seq_no}; - blkid.root_hash = data.root_hash; - blkid.file_hash = data.file_hash; - if (end_lt) { - *end_lt = data.end_lt; - } - return true; -} - -bool ExtBlkRef::store(vm::CellBuilder& cb, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const { - return cb.store_long_bool(end_lt, 64) // ext_blk_ref$_ end_lt:uint64 - && cb.store_long_bool(blkid.seqno(), 32) // seq_no:uint32 - && cb.store_bits_bool(blkid.root_hash) // root_hash:bits256 - && cb.store_bits_bool(blkid.file_hash); // file_hash:bits256 = ExtBlkRef; -} - -Ref ExtBlkRef::pack_cell(const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const { - vm::CellBuilder cb; - return store(cb, blkid, end_lt) ? cb.finalize() : Ref{}; -} - -bool ExtBlkRef::pack_to(Ref& cell, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const { - vm::CellBuilder cb; - return store(cb, blkid, end_lt) && cb.finalize_to(cell); -} - -const ExtBlkRef t_ExtBlkRef; -const BlkMasterInfo t_BlkMasterInfo; - -bool ShardIdent::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int shard_pfx_len, workchain_id; - unsigned long long shard_pfx; - if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, shard_pfx_len) && cs.fetch_int_to(32, workchain_id) && - workchain_id != ton::workchainInvalid && cs.fetch_uint_to(64, shard_pfx)) { - auto pow2 = (1ULL << (63 - shard_pfx_len)); - if (!(shard_pfx & (pow2 - 1))) { - return true; - } - } - return false; -} - -bool ShardIdent::Record::check() const { - return workchain_id != ton::workchainInvalid && !(shard_prefix & ((1ULL << (63 - shard_pfx_bits)) - 1)); -} - -bool ShardIdent::unpack(vm::CellSlice& cs, ShardIdent::Record& data) const { - if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, data.shard_pfx_bits) && cs.fetch_int_to(32, data.workchain_id) && - cs.fetch_uint_to(64, data.shard_prefix) && data.check()) { - return true; - } else { - data.invalidate(); - return false; - } -} - -bool ShardIdent::pack(vm::CellBuilder& cb, const Record& data) const { - return data.check() && cb.store_ulong_rchk_bool(0, 2) && cb.store_ulong_rchk_bool(data.shard_pfx_bits, 6) && - cb.store_long_rchk_bool(data.workchain_id, 32) && cb.store_ulong_rchk_bool(data.shard_prefix, 64); -} - -bool ShardIdent::unpack(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::ShardId& shard) const { - int bits; - unsigned long long pow2; - auto assign = [](auto& a, auto b) { return a = b; }; - auto assign_or = [](auto& a, auto b) { return a |= b; }; - return cs.fetch_ulong(2) == 0 // shard_ident$00 - && cs.fetch_uint_leq(60, bits) // shard_pfx_bits:(#<= 60) - && assign(pow2, (1ULL << (63 - bits))) // (power) - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_uint_to(64, shard) // shard_prefix:uint64 - && workchain != ton::workchainInvalid && !(shard & (2 * pow2 - 1)) && assign_or(shard, pow2); -} - -bool ShardIdent::unpack(vm::CellSlice& cs, ton::ShardIdFull& data) const { - return unpack(cs, data.workchain, data.shard); -} - -bool ShardIdent::pack(vm::CellBuilder& cb, ton::WorkchainId workchain, ton::ShardId shard) const { - int bits = ton::shard_prefix_length(shard); - return workchain != ton::workchainInvalid // check workchain - && shard // check shard - && cb.store_long_bool(0, 2) // shard_ident$00 - && cb.store_uint_leq(60, bits) // shard_pfx_bits:(#<= 60) - && cb.store_long_bool(workchain, 32) // workchain_id:int32 - && cb.store_long_bool(shard & (shard - 1), 64); // shard_prefix:uint64 -} - -bool ShardIdent::pack(vm::CellBuilder& cb, ton::ShardIdFull data) const { - return pack(cb, data.workchain, data.shard); -} - -const ShardIdent t_ShardIdent; - -bool BlockIdExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_ShardIdent.validate_skip(ops, cs, weak) && cs.advance(32 + 256 * 2); -} - -bool BlockIdExt::unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const { - return t_ShardIdent.unpack(cs, data.id.workchain, data.id.shard) // block_id_ext$_ shard_id:ShardIdent - && cs.fetch_uint_to(32, data.id.seqno) // seq_no:uint32 - && cs.fetch_bits_to(data.root_hash) // root_hash:bits256 - && cs.fetch_bits_to(data.file_hash); // file_hash:bits256 -} - -bool BlockIdExt::pack(vm::CellBuilder& cb, const ton::BlockIdExt& data) const { - return t_ShardIdent.pack(cb, data.id.workchain, data.id.shard) // block_id_ext$_ shard_id:ShardIdent - && cb.store_long_bool(data.id.seqno, 32) // seq_no:uint32 - && cb.store_bits_bool(data.root_hash) // root_hash:bits256 - && cb.store_bits_bool(data.file_hash); // file_hash:bits256 -} - -const BlockIdExt t_BlockIdExt; - -bool ShardState::skip(vm::CellSlice& cs) const { - return get_tag(cs) == shard_state && cs.advance(64) // shard_state#9023afe2 blockchain_id:int32 - && t_ShardIdent.skip(cs) // shard_id:ShardIdent - && cs.advance(32 + 32 + 32 + 64 + - 32) // seq_no:int32 vert_seq_no:# gen_utime:uint32 gen_lt:uint64 min_ref_mc_seqno:uint32 - && t_Ref_OutMsgQueueInfo.skip(cs) // out_msg_queue_info:^OutMsgQueueInfo - && cs.advance(1) // before_split:Bool - && cs.advance_refs(1) // accounts:^ShardAccounts - && - cs.advance_refs( - 1) // ^[ total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ] - && Maybe>{}.skip(cs); // custom:(Maybe ^McStateExtra) -} - -bool ShardState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int seq_no; - return get_tag(cs) == shard_state && cs.advance(64) // shard_state#9023afe2 blockchain_id:int32 - && t_ShardIdent.validate_skip(ops, cs, weak) // shard_id:ShardIdent - && cs.fetch_int_to(32, seq_no) // seq_no:int32 - && seq_no >= -1 // { seq_no >= -1 } - && cs.advance(32 + 32 + 64 + 32) // vert_seq_no:# gen_utime:uint32 gen_lt:uint64 min_ref_mc_seqno:uint32 - && t_Ref_OutMsgQueueInfo.validate_skip(ops, cs, weak) // out_msg_queue_info:^OutMsgQueueInfo - && cs.advance(1) // before_split:Bool - && t_ShardAccounts.validate_skip_ref(ops, cs, weak) // accounts:^ShardAccounts - && - t_ShardState_aux.validate_skip_ref( - ops, cs, - weak) // ^[ total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ] - && Maybe>{}.validate_skip(ops, cs, weak); // custom:(Maybe ^McStateExtra) -} - -const ShardState t_ShardState; - -bool ShardState_aux::skip(vm::CellSlice& cs) const { - return cs.advance(128) // overload_history:uint64 underload_history:uint64 - && t_CurrencyCollection.skip(cs) // total_balance:CurrencyCollection - && t_CurrencyCollection.skip(cs) // total_validator_fees:CurrencyCollection - && HashmapE{256, t_LibDescr}.skip(cs) // libraries:(HashmapE 256 LibDescr) - && Maybe{}.skip(cs); // master_ref:(Maybe BlkMasterInfo) -} - -bool ShardState_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return cs.advance(128) // overload_history:uint64 underload_history:uint64 - && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_balance:CurrencyCollection - && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_validator_fees:CurrencyCollection - && HashmapE{256, t_LibDescr}.validate_skip(ops, cs, weak) // libraries:(HashmapE 256 LibDescr) - && Maybe{}.validate_skip(ops, cs, weak); // master_ref:(Maybe BlkMasterInfo) -} - -const ShardState_aux t_ShardState_aux; - -bool LibDescr::skip(vm::CellSlice& cs) const { - return cs.advance(2) // shared_lib_descr$00 - && cs.fetch_ref().not_null() // lib:^Cell - && Hashmap{256, t_True}.skip(cs); // publishers:(Hashmap 256 False) -} - -bool LibDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return get_tag(cs) == shared_lib_descr && cs.advance(2) // shared_lib_descr$00 - && cs.fetch_ref().not_null() // lib:^Cell - && Hashmap{256, t_True}.validate_skip(ops, cs, weak); // publishers:(Hashmap 256 False) -} - -const LibDescr t_LibDescr; - -bool BlkPrevInfo::skip(vm::CellSlice& cs) const { - return t_ExtBlkRef.skip(cs) // prev_blk_info$_ {merged:#} prev:ExtBlkRef - && (!merged || t_ExtBlkRef.skip(cs)); // prev_alt:merged?ExtBlkRef -} - -bool BlkPrevInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_ExtBlkRef.validate_skip(ops, cs, weak) // prev_blk_info$_ {merged:#} prev:ExtBlkRef - && (!merged || t_ExtBlkRef.validate_skip(ops, cs, weak)); // prev_alt:merged?ExtBlkRef -} - -const BlkPrevInfo t_BlkPrevInfo_0{0}; - -bool McStateExtra::skip(vm::CellSlice& cs) const { - return block::gen::t_McStateExtra.skip(cs); -} - -bool McStateExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return block::gen::t_McStateExtra.validate_skip(ops, cs, weak); // ?? -} - -const McStateExtra t_McStateExtra; - -const KeyExtBlkRef t_KeyExtBlkRef; - -bool KeyMaxLt::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - bool key1, key2; - unsigned long long lt1, lt2; - return cs1.fetch_bool_to(key1) && cs1.fetch_ulong_bool(64, lt1) // cs1 => _ key:Bool max_end_lt:uint64 = KeyMaxLt; - && cs2.fetch_bool_to(key2) && cs2.fetch_ulong_bool(64, lt2) // cs2 => _ key:Bool max_end_lt:uint64 = KeyMaxLt; - && cb.store_bool_bool(key1 | key2) && cb.store_long_bool(std::max(lt1, lt2), 64); -} - -const KeyMaxLt t_KeyMaxLt; - -bool Aug_OldMcBlocksInfo::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - return cs.have(65) && cb.append_bitslice(cs.prefetch_bits(65)); // copy first 1+64 bits -}; - -const Aug_OldMcBlocksInfo aug_OldMcBlocksInfo; - -bool ShardFeeCreated::skip(vm::CellSlice& cs) const { - return t_CurrencyCollection.skip(cs) && t_CurrencyCollection.skip(cs); -} - -bool ShardFeeCreated::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - return t_CurrencyCollection.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak); -} - -bool ShardFeeCreated::null_value(vm::CellBuilder& cb) const { - return t_CurrencyCollection.null_value(cb) && t_CurrencyCollection.null_value(cb); -} - -bool ShardFeeCreated::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - return t_CurrencyCollection.add_values(cb, cs1, cs2) && t_CurrencyCollection.add_values(cb, cs1, cs2); -} - -const ShardFeeCreated t_ShardFeeCreated; - -bool Aug_ShardFees::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const { - return cb.append_cellslice_bool(cs) && t_ShardFeeCreated.skip(cs) && cs.empty_ext(); -}; - -const Aug_ShardFees aug_ShardFees; - -} // namespace tlb -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block-parse.h b/submodules/ton/tonlib-src/crypto/block/block-parse.h deleted file mode 100644 index 1c490383..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block-parse.h +++ /dev/null @@ -1,1113 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/dict.h" -#include "vm/boc.h" -#include "block/block.h" -#include -#include "tl/tlblib.hpp" -#include "td/utils/bits.h" -#include "td/utils/StringBuilder.h" -#include "ton/ton-types.h" - -namespace block { - -using td::Ref; - -namespace tlb { -using namespace ::tlb; - -struct Anycast final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return cs.have(5) ? 5 + (int)cs.prefetch_ulong(5) : -1; - } - bool skip_get_depth(vm::CellSlice& cs, int& depth) const { - return cs.fetch_uint_leq(30, depth) && cs.advance(depth); - } -}; - -extern const Anycast t_Anycast; - -struct Maybe_Anycast final : public Maybe { - bool skip_get_depth(vm::CellSlice& cs, int& depth) const; -}; - -extern const Maybe_Anycast t_Maybe_Anycast; - -struct VarUInteger final : TLB_Complex { - int n, ln; - VarUInteger(int _n) : n(_n) { - ln = 32 - td::count_leading_zeroes32(n - 1); - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - unsigned long long as_uint(const vm::CellSlice& cs) const override; - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(ln); - } - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override; - unsigned precompute_integer_size(const td::BigInt256& value) const; - unsigned precompute_integer_size(td::RefInt256 value) const; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarUInteger " << n << ")"; - } -}; - -extern const VarUInteger t_VarUInteger_3, t_VarUInteger_7, t_VarUInteger_16, t_VarUInteger_32; - -struct VarUIntegerPos final : TLB_Complex { - int n, ln; - bool store_pos_only; - VarUIntegerPos(int _n, bool relaxed = false) : n(_n), store_pos_only(!relaxed) { - ln = 32 - td::count_leading_zeroes32(n - 1); - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - unsigned long long as_uint(const vm::CellSlice& cs) const override; - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarUIntegerPos " << n << ")"; - } -}; - -extern const VarUIntegerPos t_VarUIntegerPos_16, t_VarUIntegerPos_32, t_VarUIntegerPosRelaxed_32; - -struct VarInteger final : TLB_Complex { - int n, ln; - VarInteger(int _n) : n(_n) { - ln = 32 - td::count_leading_zeroes32(n - 1); - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - long long as_int(const vm::CellSlice& cs) const override; - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(ln); - } - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarInteger " << n << ")"; - } -}; - -struct VarIntegerNz final : TLB_Complex { - int n, ln; - VarIntegerNz(int _n) : n(_n) { - ln = 32 - td::count_leading_zeroes32(n - 1); - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - long long as_int(const vm::CellSlice& cs) const override; - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override; - std::ostream& print_type(std::ostream& os) const override { - return os << "(VarIntegerNz " << n << ")"; - } -}; - -struct Unary final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return cs.count_leading(1) + 1; - } - bool validate_skip(vm::CellSlice& cs, bool weak, int& n) const { - return cs.advance((n = cs.count_leading(1)) + 1); - } - bool skip(vm::CellSlice& cs, int& n) const { - return validate_skip(cs, false, n); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return skip(cs); - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(get_size(cs)); - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return cs.have(get_size(cs)); - } -}; - -extern const Unary t_Unary; - -struct HmLabel final : TLB_Complex { - enum { hml_short = 0, hml_long = 2, hml_same = 3 }; - int m; // max size - HmLabel(int _m) : m(_m) { - } - bool validate_skip(vm::CellSlice& cs, bool weak, int& n) const; - bool skip(vm::CellSlice& cs, int& n) const { - return validate_skip(cs, false, n); - } - bool skip(vm::CellSlice& cs) const override { - int n; - return skip(cs, n); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - int n; - return validate_skip(cs, weak, n); - } - int get_tag(const vm::CellSlice& cs) const override; -}; - -struct Hashmap final : TLB_Complex { - const TLB& value_type; - int n; - Hashmap(int _n, const TLB& _val_type) : value_type(_val_type), n(_n) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -struct HashmapNode final : TLB_Complex { - enum { hmn_leaf = 0, hmn_fork = 1 }; - const TLB& value_type; - int n; - HashmapNode(int _n, const TLB& _val_type) : value_type(_val_type), n(_n) { - } - int get_size(const vm::CellSlice& cs) const override; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return n > 0 ? hmn_fork : n; - } -}; - -struct HashmapE final : TLB { - enum { hme_empty = 0, hme_root = 1 }; - Hashmap root_type; - HashmapE(int _n, const TLB& _val_type) : root_type(_n, _val_type) { - } - int get_size(const vm::CellSlice& cs) const override; - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(1); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; - int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; - bool add_values_ref(Ref& res, Ref arg1, Ref arg2) const; - int sub_values_ref(Ref& res, Ref arg1, Ref arg2) const; - bool store_ref(vm::CellBuilder& cb, Ref arg) const; -}; - -struct AugmentationCheckData : vm::dict::AugmentationData { - const TLB& value_type; - const TLB& extra_type; - AugmentationCheckData(const TLB& val_type, const TLB& ex_type) : value_type(val_type), extra_type(ex_type) { - } - bool skip_extra(vm::CellSlice& cs) const override { - return extra_type.skip(cs); - } - bool eval_fork(vm::CellBuilder& cb, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const override { - return extra_type.add_values(cb, left_cs, right_cs); - } - bool eval_empty(vm::CellBuilder& cb) const override { - return extra_type.null_value(cb); - } -}; - -struct HashmapAug final : TLB_Complex { - const AugmentationCheckData& aug; - int n; - HashmapAug(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool extract_extra(vm::CellSlice& cs) const; -}; - -struct HashmapAugNode final : TLB_Complex { - enum { ahmn_leaf = 0, ahmn_fork = 1 }; - const AugmentationCheckData& aug; - int n; - HashmapAugNode(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return n > 0 ? ahmn_fork : n; - } -}; - -struct HashmapAugE final : TLB_Complex { - enum { ahme_empty = 0, ahme_root = 1 }; - HashmapAug root_type; - HashmapAugE(int _n, const AugmentationCheckData& _aug) : root_type(_n, std::move(_aug)) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool extract_extra(vm::CellSlice& cs) const; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -struct Grams final : TLB_Complex { - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - bool null_value(vm::CellBuilder& cb) const override; - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override; - unsigned precompute_size(const td::BigInt256& value) const; - unsigned precompute_size(td::RefInt256 value) const; -}; - -extern const Grams t_Grams; - -struct MsgAddressInt final : TLB_Complex { - enum { addr_std = 2, addr_var = 3 }; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } - static ton::AccountIdPrefixFull get_prefix(vm::CellSlice&& cs); - static ton::AccountIdPrefixFull get_prefix(const vm::CellSlice& cs); - static ton::AccountIdPrefixFull get_prefix(Ref cs_ref); - static bool get_prefix_to(vm::CellSlice&& cs, ton::AccountIdPrefixFull& pfx) { - return (pfx = get_prefix(std::move(cs))).is_valid(); - } - static bool get_prefix_to(const vm::CellSlice& cs, ton::AccountIdPrefixFull& pfx) { - return (pfx = get_prefix(cs)).is_valid(); - } - static bool get_prefix_to(Ref cs_ref, ton::AccountIdPrefixFull& pfx) { - return cs_ref.not_null() && (pfx = get_prefix(std::move(cs_ref))).is_valid(); - } - bool skip_get_depth(vm::CellSlice& cs, int& depth) const; - bool extract_std_address(Ref cs_ref, ton::WorkchainId& workchain, ton::StdSmcAddress& addr, - bool rewrite = true) const; - bool extract_std_address(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::StdSmcAddress& addr, - bool rewrite = true) const; - bool extract_std_address(Ref cs_ref, block::StdAddress& addr, bool rewrite = true) const; - bool extract_std_address(vm::CellSlice& cs, block::StdAddress& addr, bool rewrite = true) const; - bool store_std_address(vm::CellBuilder& cb, ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const; - Ref pack_std_address(ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const; - - bool store_std_address(vm::CellBuilder& cb, const block::StdAddress& addr) const; - Ref pack_std_address(const block::StdAddress& addr) const; -}; - -extern const MsgAddressInt t_MsgAddressInt; - -struct MsgAddressExt final : TLB { - enum { addr_none = 0, addr_ext = 1 }; - int get_size(const vm::CellSlice& cs) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } -}; - -extern const MsgAddressExt t_MsgAddressExt; - -struct MsgAddress final : TLB_Complex { - enum { addr_none = 0, addr_ext = 1, addr_std = 2, addr_var = 3 }; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } -}; - -extern const MsgAddress t_MsgAddress; - -struct ExtraCurrencyCollection final : TLB { - HashmapE dict_type, dict_type2; - ExtraCurrencyCollection() : dict_type(32, t_VarUIntegerPos_32), dict_type2(32, t_VarUIntegerPosRelaxed_32) { - } - int get_size(const vm::CellSlice& cs) const override { - return dict_type.get_size(cs); - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak) const override { - return dict_type.validate(ops, cs, weak); - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(1); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override { - return dict_type.add_values(cb, cs1, cs2); - } - int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override { - return dict_type2.sub_values(cb, cs1, cs2); - } - bool add_values_ref(Ref& res, Ref arg1, Ref arg2) const { - return dict_type.add_values_ref(res, std::move(arg1), std::move(arg2)); - } - int sub_values_ref(Ref& res, Ref arg1, Ref arg2) const { - return dict_type2.sub_values_ref(res, std::move(arg1), std::move(arg2)); - } - bool store_ref(vm::CellBuilder& cb, Ref arg) const { - return dict_type.store_ref(cb, std::move(arg)); - } - unsigned precompute_size(Ref arg) const { - return arg.is_null() ? 1 : 0x10001; - } -}; - -extern const ExtraCurrencyCollection t_ExtraCurrencyCollection; - -struct CurrencyCollection final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override; - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_bits_same_bool(1 + 4, false); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; - bool unpack_special(vm::CellSlice& cs, td::RefInt256& balance, Ref& extra, bool inexact = false) const; - bool unpack_special(vm::CellSlice& cs, block::CurrencyCollection& value, bool inexact = false) const; - bool pack_special(vm::CellBuilder& cb, td::RefInt256 balance, Ref extra) const; - bool pack_special(vm::CellBuilder& cb, const block::CurrencyCollection& value) const; - bool pack_special(vm::CellBuilder& cb, block::CurrencyCollection&& value) const; - bool unpack(vm::CellSlice& cs, block::CurrencyCollection& res) const; - bool pack(vm::CellBuilder& cb, const block::CurrencyCollection& res) const; - unsigned precompute_size(td::RefInt256 balance, Ref extra) const { - return t_Grams.precompute_size(std::move(balance)) + t_ExtraCurrencyCollection.precompute_size(std::move(extra)); - } -}; - -extern const CurrencyCollection t_CurrencyCollection; - -struct CommonMsgInfo final : TLB_Complex { - enum { int_msg_info = 0, ext_in_msg_info = 2, ext_out_msg_info = 3 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - int v = (int)cs.prefetch_ulong(2); - return v == 1 ? int_msg_info : v; - } - struct Record_int_msg_info; - bool unpack(vm::CellSlice& cs, Record_int_msg_info& data) const; - bool get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const; - bool is_internal(const vm::CellSlice& cs) const { - return get_tag(cs) == int_msg_info; - } -}; - -struct CommonMsgInfo::Record_int_msg_info { - bool ihr_disabled, bounce, bounced; - Ref src, dest, value, ihr_fee, fwd_fee; - unsigned long long created_lt; - unsigned created_at; -}; - -extern const CommonMsgInfo t_CommonMsgInfo; - -struct TickTock final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return 2; - } -}; - -extern const TickTock t_TickTock; - -struct StateInit final : TLB_Complex { - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool get_ticktock(vm::CellSlice& cs, int& ticktock) const; -}; - -extern const StateInit t_StateInit; - -struct Message final : TLB_Complex { - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool extract_info(vm::CellSlice& cs) const; - bool get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const; - bool is_internal(const vm::CellSlice& cs) const { - return t_CommonMsgInfo.is_internal(cs); - } - bool is_internal(Ref ref) const; -}; - -extern const Message t_Message; -extern const RefTo t_Ref_Message; - -struct IntermediateAddress final : TLB_Complex { - enum { interm_addr_regular = 0, interm_addr_simple = 2, interm_addr_ext = 3 }; - int get_size(const vm::CellSlice& cs) const override; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool fetch_regular(vm::CellSlice& cs, int& use_dst_bits) const { - return cs.fetch_uint_to(8, use_dst_bits) && use_dst_bits <= 96; - } - int get_tag(const vm::CellSlice& cs) const override { - int v = (int)cs.prefetch_ulong(2); - return v == 1 ? interm_addr_regular : v; - } -}; - -extern const IntermediateAddress t_IntermediateAddress; - -struct MsgEnvelope final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool extract_fwd_fees_remaining(vm::CellSlice& cs) const; - struct Record { - typedef MsgEnvelope type_class; - Ref cur_addr, next_addr, fwd_fee_remaining; - Ref msg; - }; - struct Record_std { - typedef MsgEnvelope type_class; - int cur_addr, next_addr; - td::RefInt256 fwd_fee_remaining; - Ref msg; - }; - bool unpack(vm::CellSlice& cs, Record& data) const; - bool unpack(vm::CellSlice& cs, Record_std& data) const; - bool unpack_std(vm::CellSlice& cs, int& cur_a, int& nhop_a, Ref& msg) const; - bool get_created_lt(const vm::CellSlice& cs, unsigned long long& created_lt) const; -}; - -extern const MsgEnvelope t_MsgEnvelope; -extern const RefTo t_Ref_MsgEnvelope; - -struct StorageUsed final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const StorageUsed t_StorageUsed; - -struct StorageUsedShort final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const StorageUsedShort t_StorageUsedShort; - -struct StorageInfo final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const StorageInfo t_StorageInfo; - -struct AccountState final : TLB_Complex { - enum { account_uninit = 0, account_frozen = 1, account_active = 2 }; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - int t = (int)cs.prefetch_ulong(2); - return t == 3 ? account_active : t; - } - bool get_ticktock(vm::CellSlice& cs, int& ticktock) const; -}; - -extern const AccountState t_AccountState; - -struct AccountStorage final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const; -}; - -extern const AccountStorage t_AccountStorage; - -struct Account final : TLB_Complex { - enum { account_none = 0, account = 1 }; - bool allow_empty; - Account(bool _allow_empty = false) : allow_empty(_allow_empty) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - // Ref get_balance(const vm::CellSlice& cs) const; - bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const; - bool skip_copy_depth_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const Account t_Account, t_AccountE; -extern const RefTo t_Ref_Account; - -struct AccountStatus final : TLB { - enum { acc_state_uninit, acc_state_frozen, acc_state_active, acc_state_nonexist }; - int get_size(const vm::CellSlice& cs) const override { - return 2; - } - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } -}; - -extern const AccountStatus t_AccountStatus; - -struct ShardAccount final : TLB_Complex { - struct Record { - using Type = ShardAccount; - Ref account; - ton::LogicalTime last_trans_lt; - ton::Bits256 last_trans_hash; - bool valid{false}; - bool is_zero{false}; - bool reset(); - bool unpack(vm::CellSlice& cs); - bool unpack(Ref cs_ref); - bool invalidate() { - return valid = false; - } - }; - int get_size(const vm::CellSlice& cs) const override { - return 0x10140; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x140, 1); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.advance(0x140) && t_Ref_Account.validate_skip(ops, cs, weak); - } - static bool unpack(vm::CellSlice& cs, Record& info) { - return info.unpack(cs); - } - static bool unpack(Ref cs_ref, Record& info) { - return info.unpack(std::move(cs_ref)); - } - static bool extract_account_state(Ref cs_ref, Ref& acc_state); -}; - -extern const ShardAccount t_ShardAccount; - -struct DepthBalanceInfo final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool null_value(vm::CellBuilder& cb) const override; - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; -}; - -extern const DepthBalanceInfo t_DepthBalanceInfo; - -struct Aug_ShardAccounts final : AugmentationCheckData { - Aug_ShardAccounts() : AugmentationCheckData(t_ShardAccount, t_DepthBalanceInfo) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_ShardAccounts aug_ShardAccounts; - -struct ShardAccounts final : TLB_Complex { - HashmapAugE dict_type; - ShardAccounts() : dict_type(256, aug_ShardAccounts){}; - bool skip(vm::CellSlice& cs) const override { - return dict_type.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return dict_type.validate_skip(ops, cs, weak); - } -}; - -extern const ShardAccounts t_ShardAccounts; - -struct AccStatusChange final : TLB { - enum { acst_unchanged = 0, acst_frozen = 2, acst_deleted = 3 }; - int get_size(const vm::CellSlice& cs) const override { - return cs.prefetch_ulong(1) ? 2 : 1; - } - int get_tag(const vm::CellSlice& cs) const override { - if (cs.size() == 1) { - return (int)cs.prefetch_ulong(1) ? -1 : acst_unchanged; - } - int v = (int)cs.prefetch_ulong(2); - return v == 1 ? acst_unchanged : v; - } -}; - -extern const AccStatusChange t_AccStatusChange; - -struct TrStoragePhase final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const; - bool maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const; -}; - -extern const TrStoragePhase t_TrStoragePhase; - -struct TrCreditPhase final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const TrCreditPhase t_TrCreditPhase; - -struct TrComputeInternal1 final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -struct ComputeSkipReason final : TLB { - enum { cskip_no_state = 0, cskip_bad_state = 1, cskip_no_gas = 2 }; - int get_size(const vm::CellSlice& cs) const override { - return 2; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return get_tag(cs) >= 0 && cs.advance(2); - } - int get_tag(const vm::CellSlice& cs) const override { - int t = (int)cs.prefetch_ulong(2); - return t < 3 ? t : -1; - } -}; - -extern const ComputeSkipReason t_ComputeSkipReason; - -struct TrComputePhase final : TLB_Complex { - enum { tr_phase_compute_skipped = 0, tr_phase_compute_vm = 1 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } -}; - -extern const TrComputePhase t_TrComputePhase; - -struct TrActionPhase final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const TrActionPhase t_TrActionPhase; - -struct TrBouncePhase final : TLB_Complex { - enum { tr_phase_bounce_negfunds = 0, tr_phase_bounce_nofunds = 1, tr_phase_bounce_ok = 2 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override; -}; - -extern const TrBouncePhase t_TrBouncePhase; - -struct SplitMergeInfo final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const SplitMergeInfo t_SplitMergeInfo; - -struct TransactionDescr final : TLB_Complex { - enum { - trans_ord = 0, - trans_storage = 1, - trans_tick_tock = 2, - trans_split_prepare = 4, - trans_split_install = 5, - trans_merge_prepare = 6, - trans_merge_install = 7 - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override; - bool skip_to_storage_phase(vm::CellSlice& cs, bool& found) const; - bool get_storage_fees(Ref cell, td::RefInt256& storage_fees) const; -}; - -extern const TransactionDescr t_TransactionDescr; - -struct Transaction_aux final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const Transaction_aux t_Transaction_aux; - -struct Transaction final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const; - bool get_descr(Ref cell, Ref& tdescr) const; - bool get_descr(vm::CellSlice& cs, Ref& tdescr) const; - bool get_storage_fees(Ref cell, td::RefInt256& storage_fees) const; -}; - -extern const Transaction t_Transaction; -extern const RefTo t_Ref_Transaction; - -struct Aug_AccountTransactions final : AugmentationCheckData { - Aug_AccountTransactions() : AugmentationCheckData(t_Ref_Transaction, t_CurrencyCollection) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_AccountTransactions aug_AccountTransactions; -extern const HashmapAug t_AccountTransactions; // (HashmapAug 64 ^Transaction CurrencyCollection) - -struct HashUpdate final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override { - return cs.advance(8 + 256 * 2); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.fetch_ulong(8) == 0x72 && cs.advance(256 * 2); - } -}; - -extern const HashUpdate t_HashUpdate; -extern const RefTo t_Ref_HashUpdate; - -struct AccountBlock final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const; -}; - -extern const AccountBlock t_AccountBlock; - -struct Aug_ShardAccountBlocks final : AugmentationCheckData { - Aug_ShardAccountBlocks() : AugmentationCheckData(t_AccountBlock, t_CurrencyCollection) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_ShardAccountBlocks aug_ShardAccountBlocks; -extern const HashmapAugE t_ShardAccountBlocks; // (HashmapAugE 256 AccountBlock CurrencyCollection) - -struct ImportFees final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_bits_same_bool(4 + 4 + 1, false); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; -}; - -extern const ImportFees t_ImportFees; - -struct InMsg final : TLB_Complex { - enum { - msg_import_ext = 0, - msg_import_ihr = 2, - msg_import_imm = 3, - msg_import_fin = 4, - msg_import_tr = 5, - msg_discard_fin = 6, - msg_discard_tr = 7 - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(3); - } - bool get_import_fees(vm::CellBuilder& cb, vm::CellSlice& cs) const; -}; - -extern const InMsg t_InMsg; - -struct OutMsg final : TLB_Complex { - enum { - msg_export_ext = 0, - msg_export_new = 1, - msg_export_imm = 2, - msg_export_tr = 3, - msg_export_deq_imm = 4, - msg_export_deq = 12, - msg_export_deq_short = 13, - msg_export_tr_req = 7 - }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - int t = (int)cs.prefetch_ulong(3); - return t != 6 ? t : (int)cs.prefetch_ulong(4); - } - bool get_export_value(vm::CellBuilder& cb, vm::CellSlice& cs) const; - bool get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const; -}; - -extern const OutMsg t_OutMsg; - -// next: InMsgDescr, OutMsgDescr, OutMsgQueue, and their augmentations - -struct Aug_InMsgDescr final : AugmentationCheckData { - Aug_InMsgDescr() : AugmentationCheckData(t_InMsg, t_ImportFees) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override { - return t_InMsg.get_import_fees(cb, cs); - } -}; - -extern const Aug_InMsgDescr aug_InMsgDescr; - -struct InMsgDescr final : TLB_Complex { - HashmapAugE dict_type; - InMsgDescr() : dict_type(256, aug_InMsgDescr){}; - bool skip(vm::CellSlice& cs) const override { - return dict_type.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return dict_type.validate_skip(ops, cs, weak); - } -}; - -extern const InMsgDescr t_InMsgDescr; - -struct Aug_OutMsgDescr final : AugmentationCheckData { - Aug_OutMsgDescr() : AugmentationCheckData(t_OutMsg, t_CurrencyCollection) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override { - return t_OutMsg.get_export_value(cb, cs); - } -}; - -extern const Aug_OutMsgDescr aug_OutMsgDescr; - -struct OutMsgDescr final : TLB_Complex { - HashmapAugE dict_type; - OutMsgDescr() : dict_type(256, aug_OutMsgDescr){}; - bool skip(vm::CellSlice& cs) const override { - return dict_type.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return dict_type.validate_skip(ops, cs, weak); - } -}; - -extern const OutMsgDescr t_OutMsgDescr; - -struct EnqueuedMsg final : TLB_Complex { - int get_size(const vm::CellSlice& cs) const override { - return 0x10040; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance_ext(0x10040); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, EnqueuedMsgDescr& descr) const { - return descr.unpack(cs); - } -}; - -extern const EnqueuedMsg t_EnqueuedMsg; - -struct Aug_OutMsgQueue final : AugmentationCheckData { - Aug_OutMsgQueue() : AugmentationCheckData(t_EnqueuedMsg, t_uint64) { - } - bool eval_fork(vm::CellBuilder& cb, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const override; - bool eval_empty(vm::CellBuilder& cb) const override; - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_OutMsgQueue aug_OutMsgQueue; - -struct OutMsgQueue final : TLB_Complex { - HashmapAugE dict_type; - OutMsgQueue() : dict_type(32 + 64 + 256, aug_OutMsgQueue){}; - bool skip(vm::CellSlice& cs) const override { - return dict_type.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return dict_type.validate_skip(ops, cs, weak); - } -}; - -extern const OutMsgQueue t_OutMsgQueue; - -struct ProcessedUpto final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return 64 + 256; - } -}; - -extern const ProcessedUpto t_ProcessedUpto; -extern const HashmapE t_ProcessedInfo; -extern const HashmapE t_IhrPendingInfo; - -struct OutMsgQueueInfo final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const OutMsgQueueInfo t_OutMsgQueueInfo; -extern const RefTo t_Ref_OutMsgQueueInfo; - -struct ExtBlkRef final : TLB { - enum { fixed_size = 64 + 32 + 256 * 2 }; - int get_size(const vm::CellSlice& cs) const override { - return fixed_size; - } - bool unpack(vm::CellSlice& cs, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - bool unpack(Ref cs_ref, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - bool store(vm::CellBuilder& cb, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const; - Ref pack_cell(const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const; - bool pack_to(Ref& cell, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const; -}; - -extern const ExtBlkRef t_ExtBlkRef; - -struct BlkMasterInfo final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return t_ExtBlkRef.get_size(cs); - } -}; - -extern const BlkMasterInfo t_BlkMasterInfo; - -struct ShardIdent final : TLB_Complex { - struct Record; - int get_size(const vm::CellSlice& cs) const override { - return 2 + 6 + 32 + 64; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(get_size(cs)); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } - bool unpack(vm::CellSlice& cs, Record& data) const; - bool pack(vm::CellBuilder& cb, const Record& data) const; - bool unpack(vm::CellSlice& cs, ton::ShardIdFull& data) const; - bool pack(vm::CellBuilder& cb, ton::ShardIdFull data) const; - bool unpack(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::ShardId& shard) const; - bool pack(vm::CellBuilder& cb, ton::WorkchainId workchain, ton::ShardId shard) const; -}; - -struct ShardIdent::Record { - int shard_pfx_bits; - int workchain_id; - unsigned long long shard_prefix; - Record() : shard_pfx_bits(-1) { - } - Record(int _pfxlen, int _wcid, unsigned long long _pfx) - : shard_pfx_bits(_pfxlen), workchain_id(_wcid), shard_prefix(_pfx) { - } - bool check() const; - bool is_valid() const { - return shard_pfx_bits >= 0; - } - void invalidate() { - shard_pfx_bits = -1; - } -}; - -extern const ShardIdent t_ShardIdent; - -struct BlockIdExt final : TLB_Complex { - int get_size(const vm::CellSlice& cs) const override { - return 2 + 6 + 32 + 64 + 32 + 256 * 2; - } - bool skip(vm::CellSlice& cs) const override { - return cs.advance(get_size(cs)); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const; - bool pack(vm::CellBuilder& cb, const ton::BlockIdExt& data) const; -}; - -extern const BlockIdExt t_BlockIdExt; - -struct ShardState final : TLB_Complex { - enum { shard_state = (int)0x9023afe2, split_state = 0x5f327da5 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(32) == shard_state ? shard_state : -1; - } -}; - -extern const ShardState t_ShardState; - -struct ShardState_aux final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } -}; - -extern const ShardState_aux t_ShardState_aux; - -struct LibDescr final : TLB_Complex { - enum { shared_lib_descr = 0 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(2); - } -}; - -extern const LibDescr t_LibDescr; - -struct BlkPrevInfo final : TLB_Complex { - bool merged; - BlkPrevInfo(bool _merged) : merged(_merged) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const BlkPrevInfo t_BlkPrevInfo_0; - -struct McStateExtra final : TLB_Complex { - enum { masterchain_state_extra = 0xcc26 }; - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; -}; - -extern const McStateExtra t_McStateExtra; - -struct KeyExtBlkRef final : TLB { - enum { fixed_size = 1 + ExtBlkRef::fixed_size }; - int get_size(const vm::CellSlice& cs) const override { - return fixed_size; - } -}; - -extern const KeyExtBlkRef t_KeyExtBlkRef; - -struct KeyMaxLt final : TLB { - enum { fixed_size = 1 + 64 }; - int get_size(const vm::CellSlice& cs) const override { - return fixed_size; - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_bits_same_bool(fixed_size, false); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; -}; - -extern const KeyMaxLt t_KeyMaxLt; - -struct Aug_OldMcBlocksInfo final : AugmentationCheckData { - Aug_OldMcBlocksInfo() : AugmentationCheckData(t_KeyExtBlkRef, t_KeyMaxLt) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_OldMcBlocksInfo aug_OldMcBlocksInfo; - -struct ShardFeeCreated final : TLB_Complex { - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - bool null_value(vm::CellBuilder& cb) const override; - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override; -}; - -extern const ShardFeeCreated t_ShardFeeCreated; - -struct Aug_ShardFees final : AugmentationCheckData { - Aug_ShardFees() : AugmentationCheckData(t_ShardFeeCreated, t_ShardFeeCreated) { - } - bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const override; -}; - -extern const Aug_ShardFees aug_ShardFees; - -} // namespace tlb -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block.cpp b/submodules/ton/tonlib-src/crypto/block/block.cpp deleted file mode 100644 index 9e2caef5..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block.cpp +++ /dev/null @@ -1,2280 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/bits.h" -#include "block/block.h" -#include "block/block-auto.h" -#include "block/block-parse.h" -#include "block/mc-config.h" -#include "ton/ton-shard.h" -#include "common/bigexp.h" -#include "common/util.h" -#include "td/utils/crypto.h" -#include "td/utils/tl_storers.h" -#include "td/utils/misc.h" -#include "td/utils/Random.h" - -namespace block { -using namespace std::literals::string_literals; - -td::Result PublicKey::from_bytes(td::Slice key) { - if (key.size() != 32) { - return td::Status::Error("Ed25519 public key must be exactly 32 bytes long"); - } - PublicKey res; - res.key = key.str(); - return res; -} - -td::Result PublicKey::parse(td::Slice key) { - if (key.size() != 48) { - return td::Status::Error("Serialized Ed25519 public key must be exactly 48 characters long"); - } - td::uint8 buf[36]; - if (!buff_base64_decode(td::MutableSlice(buf, 36), key, true)) { - return td::Status::Error("Public key is not serialized in base64 encoding"); - } - - td::uint16 hash = static_cast((static_cast(buf[34]) << 8) + buf[35]); - if (hash != td::crc16(td::Slice(buf, 34))) { - return td::Status::Error("Public key has incorrect crc16 hash"); - } - - if (buf[0] != 0x3e) { - return td::Status::Error("Not a public key"); - } - if (buf[1] != 0xe6) { - return td::Status::Error("Not an ed25519 public key"); - } - - return from_bytes(td::Slice(buf + 2, 32)); -} - -std::string PublicKey::serialize(bool base64_url) { - CHECK(key.size() == 32); - std::string buf(36, 0); - td::MutableSlice bytes(buf); - - bytes[0] = static_cast(0x3e); - bytes[1] = static_cast(0xe6); - bytes.substr(2).copy_from(key); - auto hash = td::crc16(bytes.substr(0, 34)); - bytes[34] = static_cast(hash >> 8); - bytes[35] = static_cast(hash & 255); - - std::string res(48, 0); - buff_base64_encode(res, bytes, base64_url); - return res; -} - -bool pack_std_smc_addr_to(char result[48], bool base64_url, ton::WorkchainId wc, const ton::StdSmcAddress& addr, - bool bounceable, bool testnet) { - if (wc < -128 || wc >= 128) { - return false; - } - unsigned char buffer[36]; - buffer[0] = (unsigned char)(0x51 - bounceable * 0x40 + testnet * 0x80); - buffer[1] = (unsigned char)wc; - std::memcpy(buffer + 2, addr.data(), 32); - unsigned crc = td::crc16(td::Slice{buffer, 34}); - buffer[34] = (unsigned char)(crc >> 8); - buffer[35] = (unsigned char)(crc & 0xff); - CHECK(buff_base64_encode(td::MutableSlice{result, 48}, td::Slice{buffer, 36}, base64_url) == 48); - return true; -} - -std::string pack_std_smc_addr(bool base64_url, ton::WorkchainId wc, const ton::StdSmcAddress& addr, bool bounceable, - bool testnet) { - char result[48]; - if (pack_std_smc_addr_to(result, base64_url, wc, addr, bounceable, testnet)) { - return std::string{result, 48}; - } else { - return ""; - } -} - -bool unpack_std_smc_addr(const char packed[48], ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet) { - unsigned char buffer[36]; - wc = ton::workchainInvalid; - if (!buff_base64_decode(td::MutableSlice{buffer, 36}, td::Slice{packed, 48}, true)) { - return false; - } - unsigned crc = td::crc16(td::Slice{buffer, 34}); - if (buffer[34] != (unsigned char)(crc >> 8) || buffer[35] != (unsigned char)(crc & 0xff)) { - return false; - } - if ((buffer[0] & 0x3f) != 0x11) { - return false; - } - testnet = (buffer[0] & 0x80); - bounceable = !(buffer[0] & 0x40); - wc = (td::int8)buffer[1]; - std::memcpy(addr.data(), buffer + 2, 32); - return true; -} - -bool unpack_std_smc_addr(td::Slice packed, ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet) { - return packed.size() == 48 && unpack_std_smc_addr(packed.data(), wc, addr, bounceable, testnet); -} - -bool unpack_std_smc_addr(std::string packed, ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet) { - return packed.size() == 48 && unpack_std_smc_addr(packed.data(), wc, addr, bounceable, testnet); -} - -StdAddress::StdAddress(std::string serialized) { - rdeserialize(std::move(serialized)); -} - -StdAddress::StdAddress(td::Slice from) { - rdeserialize(std::move(from)); -} - -std::string StdAddress::rserialize(bool base64_url) const { - char buffer[48]; - return rserialize_to(buffer, base64_url) ? std::string{buffer, 48} : ""; -} - -bool StdAddress::rserialize_to(td::MutableSlice to, bool base64_url) const { - return to.size() == 48 && rserialize_to(to.data(), base64_url); -} - -bool StdAddress::rserialize_to(char to[48], bool base64_url) const { - return pack_std_smc_addr_to(to, base64_url, workchain, addr, bounceable, testnet); -} - -bool StdAddress::rdeserialize(td::Slice from) { - return from.size() == 48 && unpack_std_smc_addr(from.data(), workchain, addr, bounceable, testnet); -} - -bool StdAddress::rdeserialize(std::string from) { - return from.size() == 48 && unpack_std_smc_addr(from.data(), workchain, addr, bounceable, testnet); -} - -bool StdAddress::rdeserialize(const char from[48]) { - return unpack_std_smc_addr(from, workchain, addr, bounceable, testnet); -} - -bool StdAddress::operator==(const StdAddress& other) const { - return workchain == other.workchain && addr == other.addr && bounceable == other.bounceable && - testnet == other.testnet; -} - -int parse_hex_digit(int c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - c |= 0x20; - if (c >= 'a' && c <= 'z') { - return c - 'a' + 10; - } - return -1; -} - -bool StdAddress::parse_addr(td::Slice acc_string) { - if (rdeserialize(acc_string)) { - return true; - } - testnet = false; - bounceable = true; - auto pos = acc_string.find(':'); - if (pos != std::string::npos) { - if (pos > 10) { - return invalidate(); - } - auto tmp = acc_string.substr(0, pos); - auto r_wc = td::to_integer_safe(tmp); - if (r_wc.is_error()) { - return invalidate(); - } - workchain = r_wc.move_as_ok(); - if (workchain == ton::workchainInvalid) { - return invalidate(); - } - ++pos; - } else { - pos = 0; - } - // LOG(DEBUG) << "parsing " << acc_string << " address"; - if (acc_string.size() != pos + 64) { - return invalidate(); - } - for (unsigned i = 0; i < 64; i++) { - int x = parse_hex_digit(acc_string[pos + i]), m = 15; - if (x < 0) { - return invalidate(); - } - if (!(i & 1)) { - x <<= 4; - m <<= 4; - } - addr.data()[i >> 1] = (unsigned char)((addr.data()[i >> 1] & ~m) | x); - } - return true; -} - -bool parse_std_account_addr(td::Slice acc_string, ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool* bounceable, - bool* testnet_only) { - StdAddress a; - if (!a.parse_addr(acc_string)) { - return false; - } - wc = a.workchain; - addr = a.addr; - if (testnet_only) { - *testnet_only = a.testnet; - } - if (bounceable) { - *bounceable = a.bounceable; - } - return true; -} - -td::Result StdAddress::parse(td::Slice acc_string) { - StdAddress res; - if (res.parse_addr(acc_string)) { - return res; - } - return td::Status::Error("Failed to parse account address"); -} - -void ShardId::init() { - if (!shard_pfx) { - shard_pfx = (1ULL << 63); - shard_pfx_len = 0; - } else { - shard_pfx_len = 63 - td::count_trailing_zeroes_non_zero64(shard_pfx); - } -} - -ShardId::ShardId(ton::WorkchainId wc_id, unsigned long long sh_pfx) : workchain_id(wc_id), shard_pfx(sh_pfx) { - init(); -} - -ShardId::ShardId(ton::ShardIdFull ton_shard_id) : workchain_id(ton_shard_id.workchain), shard_pfx(ton_shard_id.shard) { - init(); -} - -ShardId::ShardId(ton::BlockId ton_block_id) : workchain_id(ton_block_id.workchain), shard_pfx(ton_block_id.shard) { - init(); -} - -ShardId::ShardId(const ton::BlockIdExt& ton_block_id) - : workchain_id(ton_block_id.id.workchain), shard_pfx(ton_block_id.id.shard) { - init(); -} - -ShardId::ShardId(ton::WorkchainId wc_id, unsigned long long sh_pfx, int sh_pfx_len) - : workchain_id(wc_id), shard_pfx_len(sh_pfx_len) { - if (sh_pfx_len < 0) { - shard_pfx_len = 0; - shard_pfx = (1ULL << 63); - } else if (sh_pfx_len > 63) { - shard_pfx_len = 63; - shard_pfx = sh_pfx | 1; - } else { - unsigned long long pow = 1ULL << (63 - sh_pfx_len); - shard_pfx = (sh_pfx | pow) & (pow - 1); - } -} - -std::ostream& operator<<(std::ostream& os, const ShardId& shard_id) { - shard_id.show(os); - return os; -} - -void ShardId::show(std::ostream& os) const { - if (workchain_id == ton::workchainInvalid) { - os << '?'; - return; - } - os << workchain_id << ':' << shard_pfx_len << ','; - unsigned long long t = shard_pfx; - int cnt = 0; - while ((t & ((1ULL << 63) - 1)) != 0) { - static const char hex_digit[] = "0123456789ABCDEF"; - os << (char)hex_digit[t >> 60]; - t <<= 4; - ++cnt; - } - if (!t || !cnt) { - os << '_'; - } -} - -std::string ShardId::to_str() const { - std::ostringstream os; - show(os); - return os.str(); -} - -bool ShardId::serialize(vm::CellBuilder& cb) const { - if (workchain_id == ton::workchainInvalid || cb.remaining_bits() < 104) { - return false; - } - return cb.store_long_bool(0, 2) && cb.store_ulong_rchk_bool(shard_pfx_len, 6) && - cb.store_long_bool(workchain_id, 32) && cb.store_long_bool(shard_pfx & (shard_pfx - 1)); -} - -bool ShardId::deserialize(vm::CellSlice& cs) { - if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, shard_pfx_len) && cs.fetch_int_to(32, workchain_id) && - workchain_id != ton::workchainInvalid && cs.fetch_uint_to(64, shard_pfx)) { - auto pow2 = (1ULL << (63 - shard_pfx_len)); - if (!(shard_pfx & (pow2 - 1))) { - shard_pfx |= pow2; - return true; - } - } - - invalidate(); - return false; -} - -MsgProcessedUptoCollection::MsgProcessedUptoCollection(ton::ShardIdFull _owner, Ref cs_ref) - : owner(_owner) { - vm::Dictionary dict{std::move(cs_ref), 96}; - valid = dict.check_for_each([&](Ref value, td::ConstBitPtr key, int n) -> bool { - if (value->size_ext() != 64 + 256) { - return false; - } - list.emplace_back(); - MsgProcessedUpto& z = list.back(); - z.shard = key.get_uint(64); - z.mc_seqno = (unsigned)((key + 64).get_uint(32)); - z.last_inmsg_lt = value.write().fetch_ulong(64); - // std::cerr << "ProcessedUpto shard " << std::hex << z.shard << std::dec << std::endl; - return value.write().fetch_bits_to(z.last_inmsg_hash) && z.shard && ton::shard_contains(owner.shard, z.shard); - }); -} - -std::unique_ptr MsgProcessedUptoCollection::unpack(ton::ShardIdFull _owner, - Ref cs_ref) { - auto v = std::make_unique(_owner, std::move(cs_ref)); - return v && v->valid ? std::move(v) : std::unique_ptr{}; -} - -bool MsgProcessedUpto::contains(const MsgProcessedUpto& other) const& { - return ton::shard_is_ancestor(shard, other.shard) && mc_seqno >= other.mc_seqno && - (last_inmsg_lt > other.last_inmsg_lt || - (last_inmsg_lt == other.last_inmsg_lt && !(last_inmsg_hash < other.last_inmsg_hash))); -} - -bool MsgProcessedUpto::contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash, - ton::BlockSeqno other_mc_seqno) const& { - return ton::shard_is_ancestor(shard, other_shard) && mc_seqno >= other_mc_seqno && - (last_inmsg_lt > other_lt || (last_inmsg_lt == other_lt && !(last_inmsg_hash < other_hash))); -} - -bool MsgProcessedUptoCollection::insert(ton::BlockSeqno mc_seqno, ton::LogicalTime last_proc_lt, - td::ConstBitPtr last_proc_hash) { - if (!last_proc_lt) { - return false; - } - for (const auto& z : list) { - if (z.contains(owner.shard, last_proc_lt, last_proc_hash, mc_seqno)) { - return true; - } - } - list.emplace_back(owner.shard, mc_seqno, last_proc_lt, last_proc_hash); - return true; -} - -bool MsgProcessedUptoCollection::insert_infty(ton::BlockSeqno mc_seqno, ton::LogicalTime last_proc_lt) { - return insert(mc_seqno, last_proc_lt, td::Bits256::ones().bits()); -} - -bool MsgProcessedUptoCollection::is_reduced() const { - if (!valid) { - return false; - } - for (auto it = list.begin(); it < list.end(); ++it) { - for (auto it2 = it + 1; it2 < list.end(); ++it2) { - if (it->contains(*it2) || it2->contains(*it)) { - return false; - } - } - } - return true; -} - -bool MsgProcessedUptoCollection::contains(const MsgProcessedUpto& p_upto) const { - for (const auto& z : list) { - if (z.contains(p_upto)) { - return true; - } - } - return false; -} - -bool MsgProcessedUptoCollection::contains(const MsgProcessedUptoCollection& other) const { - for (const auto& w : other.list) { - if (!contains(w)) { - return false; - } - } - return true; -} - -const MsgProcessedUpto* MsgProcessedUptoCollection::is_simple_update_of(const MsgProcessedUptoCollection& other, - bool& ok) const { - ok = false; - if (!contains(other)) { - LOG(DEBUG) << "does not cointain the previous value"; - return nullptr; - } - if (other.contains(*this)) { - LOG(DEBUG) << "coincides with the previous value"; - ok = true; - return nullptr; - } - const MsgProcessedUpto* found = nullptr; - for (const auto& z : list) { - if (!other.contains(z)) { - if (found) { - LOG(DEBUG) << "has more than two new entries"; - return found; // ok = false: update is not simple - } - found = &z; - } - } - ok = true; - return found; -} - -ton::BlockSeqno MsgProcessedUptoCollection::min_mc_seqno() const { - ton::BlockSeqno min_mc_seqno = ~0U; - for (const auto& z : list) { - min_mc_seqno = std::min(min_mc_seqno, z.mc_seqno); - } - return min_mc_seqno; -} - -bool MsgProcessedUptoCollection::compactify() { - std::sort(list.begin(), list.end()); - std::size_t i, j, k = 0, m = 0, n = list.size(); - std::vector mark(n, false); - assert(mark.size() == n); - for (i = 0; i < n; i++) { - for (j = 0; j < n; j++) { - if (j != i && !mark[j] && list[j].contains(list[i])) { - mark[i] = true; - ++m; - break; - } - } - } - if (m) { - for (i = 0; i < n; i++) { - if (!mark[i]) { - list[k++] = list[i]; - } - } - list.resize(k); - } - return true; -} - -bool MsgProcessedUptoCollection::pack(vm::CellBuilder& cb) { - if (!compactify()) { - return false; - } - vm::Dictionary dict{96}; - for (const auto& z : list) { - td::BitArray<96> key; - vm::CellBuilder cb2; - key.bits().store_uint(z.shard, 64); - (key.bits() + 64).store_uint(z.mc_seqno, 32); - if (!(cb2.store_long_bool(z.last_inmsg_lt) && cb2.store_bits_bool(z.last_inmsg_hash) && - dict.set_builder(key, cb2, vm::Dictionary::SetMode::Add))) { - return false; - } - } - return std::move(dict).append_dict_to_bool(cb); -} - -bool MsgProcessedUptoCollection::split(ton::ShardIdFull new_owner) { - if (!ton::shard_is_ancestor(owner, new_owner)) { - return false; - } - if (owner == new_owner) { - return true; - } - std::size_t n = list.size(), i, j = 0; - for (i = 0; i < n; i++) { - if (ton::shard_intersects(list[i].shard, new_owner.shard)) { - list[i].shard = ton::shard_intersection(list[i].shard, new_owner.shard); - if (j < i) { - list[j] = std::move(list[i]); - } - j++; - } - } - list.resize(j); - owner = new_owner; - return compactify(); -} - -bool MsgProcessedUptoCollection::combine_with(const MsgProcessedUptoCollection& other) { - if (!(other.owner == owner || ton::shard_is_sibling(other.owner, owner))) { - return false; - } - list.insert(list.end(), other.list.begin(), other.list.end()); - if (owner != other.owner) { - owner = ton::shard_parent(owner); - } - return compactify(); -} - -bool MsgProcessedUpto::already_processed(const EnqueuedMsgDescr& msg) const { - // LOG(DEBUG) << "compare msg (" << msg.lt_ << "," << msg.hash_.to_hex() << ") against record's (" << last_inmsg_lt - // << "," << last_inmsg_hash.to_hex() << ")"; - if (msg.lt_ > last_inmsg_lt) { - return false; - } - if (!ton::shard_contains(shard, msg.next_prefix_.account_id_prefix)) { - return false; - } - if (msg.lt_ == last_inmsg_lt && last_inmsg_hash < msg.hash_) { - return false; - } - if (msg.same_workchain() && ton::shard_contains(shard, msg.cur_prefix_.account_id_prefix)) { - // this branch is needed only for messages generated in the same shard - // (such messages could have been processed without a reference from the masterchain) - // ? enable this branch only if an extra boolean parameter is set ? - return true; - } - auto shard_end_lt = compute_shard_end_lt(msg.cur_prefix_); - // LOG(DEBUG) << "enqueued_lt = " << msg.enqueued_lt_ << " , shard_end_lt = " << shard_end_lt; - return msg.enqueued_lt_ < shard_end_lt; -} - -bool MsgProcessedUptoCollection::already_processed(const EnqueuedMsgDescr& msg) const { - // LOG(DEBUG) << "checking message with cur_addr=" << msg.cur_prefix_.to_str() - // << " next_addr=" << msg.next_prefix_.to_str() << " against ProcessedUpto of neighbor " << owner.to_str(); - if (!ton::shard_contains(owner, msg.next_prefix_)) { - return false; - } - for (const auto& rec : list) { - if (rec.already_processed(msg)) { - return true; - } - } - return false; -} - -bool MsgProcessedUptoCollection::can_check_processed() const { - for (const auto& entry : list) { - if (!entry.can_check_processed()) { - return false; - } - } - return true; -} - -bool MsgProcessedUptoCollection::for_each_mcseqno(std::function func) const { - for (const auto& entry : list) { - if (!func(entry.mc_seqno)) { - return false; - } - } - return true; -} - -std::ostream& MsgProcessedUpto::print(std::ostream& os) const { - return os << "[" << ton::shard_to_str(shard) << "," << mc_seqno << "," << last_inmsg_lt << "," - << last_inmsg_hash.to_hex() << "]"; -} - -std::ostream& MsgProcessedUptoCollection::print(std::ostream& os) const { - os << "MsgProcessedUptoCollection of " << owner.to_str() << " = {"; - int i = 0; - for (const auto& entry : list) { - if (i++) { - os << ", "; - } - os << entry; - } - os << "}"; - return os; -} - -std::string MsgProcessedUpto::to_str() const { - std::ostringstream os; - print(os); - return os.str(); -} - -std::string MsgProcessedUptoCollection::to_str() const { - std::ostringstream os; - print(os); - return os.str(); -} - -// unpacks some fields from EnqueuedMsg -bool EnqueuedMsgDescr::unpack(vm::CellSlice& cs) { - block::gen::EnqueuedMsg::Record enq; - block::tlb::MsgEnvelope::Record_std env; - block::gen::CommonMsgInfo::Record_int_msg_info info; - if (!(tlb::unpack(cs, enq) && tlb::unpack_cell(enq.out_msg, env) && tlb::unpack_cell_inexact(env.msg, info))) { - return invalidate(); - } - src_prefix_ = block::tlb::t_MsgAddressInt.get_prefix(std::move(info.src)); - dest_prefix_ = block::tlb::t_MsgAddressInt.get_prefix(std::move(info.dest)); - if (!(src_prefix_.is_valid() && dest_prefix_.is_valid())) { - return invalidate(); - } - cur_prefix_ = interpolate_addr(src_prefix_, dest_prefix_, env.cur_addr); - next_prefix_ = interpolate_addr(src_prefix_, dest_prefix_, env.next_addr); - lt_ = info.created_lt; - enqueued_lt_ = enq.enqueued_lt; - hash_ = env.msg->get_hash().bits(); - msg_ = std::move(env.msg); - msg_env_ = std::move(enq.out_msg); - return true; -} - -bool EnqueuedMsgDescr::check_key(td::ConstBitPtr key) const { - return key.get_int(32) == next_prefix_.workchain && (key + 32).get_uint(64) == next_prefix_.account_id_prefix && - hash_ == key + 96; -} - -bool ParamLimits::deserialize(vm::CellSlice& cs) { - return cs.fetch_ulong(8) == 0xc3 // param_limits#c3 - && cs.fetch_uint_to(32, limits_[0]) // underload:uint32 - && cs.fetch_uint_to(32, limits_[1]) // soft_limit:uint32 - && cs.fetch_uint_to(32, limits_[3]) // hard_limit:uint32 - && limits_[0] <= limits_[1] // { underload <= soft_limit } - && limits_[1] <= limits_[3] // { soft_limit <= hard_limit } = ParamLimits; - && compute_medium_limit(); -} - -bool BlockLimits::deserialize(vm::CellSlice& cs) { - return cs.fetch_ulong(8) == 0x5d // block_limits#5d - && bytes.deserialize(cs) // bytes:ParamLimits - && gas.deserialize(cs) // gas:ParamLimits - && lt_delta.deserialize(cs); // lt_delta:ParamLimits -} - -int ParamLimits::classify(td::uint64 value) const { - int a = -1, b = limits_cnt; - while (b - a > 1) { - int c = (a + b) >> 1; - if (value >= limits_[c]) { - a = c; - } else { - b = c; - } - } - return a + 1; -} - -bool ParamLimits::fits(unsigned cls, td::uint64 value) const { - return cls >= limits_cnt || value < limits_[cls]; -} - -int BlockLimits::classify_size(td::uint64 size) const { - return bytes.classify(size); -} - -int BlockLimits::classify_gas(td::uint64 gas_value) const { - return gas.classify(gas_value); -} - -int BlockLimits::classify_lt(ton::LogicalTime lt) const { - return lt_delta.classify(lt - start_lt); -} - -int BlockLimits::classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const { - return std::max(std::max(classify_size(size), classify_gas(gas)), classify_lt(lt)); -} - -bool BlockLimits::fits(unsigned cls, td::uint64 size, td::uint64 gas_value, ton::LogicalTime lt) const { - return bytes.fits(cls, size) && gas.fits(cls, gas_value) && lt_delta.fits(cls, lt - start_lt); -} - -td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::Stat* extra) const { - auto sum = st_stat.get_total_stat(); - if (extra) { - sum += *extra; - } - return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + accounts * 200 + - transactions * 200 + (extra ? 200 : 0); -} - -int BlockLimitStatus::classify() const { - return limits.classify(estimate_block_size(), gas_used, cur_lt); -} - -bool BlockLimitStatus::fits(unsigned cls) const { - return cls >= ParamLimits::limits_cnt || - (limits.gas.fits(cls, gas_used) && limits.lt_delta.fits(cls, cur_lt - limits.start_lt) && - limits.bytes.fits(cls, estimate_block_size())); -} - -bool BlockLimitStatus::would_fit(unsigned cls, ton::LogicalTime end_lt, td::uint64 more_gas, - const vm::NewCellStorageStat::Stat* extra) const { - return cls >= ParamLimits::limits_cnt || (limits.gas.fits(cls, gas_used + more_gas) && - limits.lt_delta.fits(cls, std::max(cur_lt, end_lt) - limits.start_lt) && - limits.bytes.fits(cls, estimate_block_size(extra))); -} - -// SETS: account_dict, shard_libraries_, mc_state_extra -// total_balance{,_extra}, total_validator_fees -// SETS: out_msg_queue, processed_upto_, ihr_pending (via unpack_out_msg_queue_info) -// SETS: utime_, lt_ -td::Status ShardState::unpack_state(ton::BlockIdExt blkid, Ref prev_state_root) { - if (!blkid.is_valid()) { - return td::Status::Error(-666, "invalid block id supplied to ShardState::unpack"); - } - if (prev_state_root.is_null()) { - return td::Status::Error(-666, "the root cell supplied for the shardchain state "s + blkid.to_str() + " is null"); - } - block::gen::ShardStateUnsplit::Record state; - if (!tlb::unpack_cell(prev_state_root, state)) { - return td::Status::Error(-666, "cannot unpack header of shardchain state "s + blkid.to_str()); - } - if ((unsigned)state.seq_no != blkid.seqno()) { - return td::Status::Error( - -666, PSTRING() << "shardchain state for " << blkid.to_str() << " has incorrect seqno " << state.seq_no); - } - auto shard1 = ton::ShardIdFull(block::ShardId{state.shard_id}); - if (shard1 != blkid.shard_full()) { - return td::Status::Error(-666, "shardchain state for "s + blkid.to_str() + - " corresponds to incorrect workchain or shard " + shard1.to_str()); - } - id_ = blkid; - root_ = std::move(prev_state_root); - vert_seqno_ = state.vert_seq_no; - before_split_ = state.before_split; - account_dict_ = std::make_unique( - vm::load_cell_slice(std::move(state.accounts)).prefetch_ref(), 256, block::tlb::aug_ShardAccounts); - // check that all keys in account_dict have correct prefixes - td::BitArray<64> acc_pfx{(long long)shard1.shard}; - int acc_pfx_len = shard_prefix_length(shard1); - if (!account_dict_->has_common_prefix(acc_pfx.bits(), acc_pfx_len)) { - return td::Status::Error(-666, "account dictionary of previous state of "s + id_.to_str() + " does not have " + - acc_pfx.bits().to_hex(acc_pfx_len) + " as common key prefix"); - } - // get overload / underload history - overload_history_ = state.r1.overload_history; - underload_history_ = state.r1.underload_history; - // get shard libraries - shard_libraries_ = std::make_unique(state.r1.libraries->prefetch_ref(), 256); - if (!shard_libraries_->is_empty() && !shard1.is_masterchain()) { - return td::Status::Error(-666, - "shardchain state "s + id_.to_str() + - " has a non-trivial shard libraries collection, but it is not in the masterchain"); - } - mc_state_extra_ = state.custom->prefetch_ref(); - vm::CellSlice cs{*state.r1.master_ref}; // master_ref:(Maybe BlkMasterInfo) - if ((int)cs.fetch_ulong(1) == 1) { - if (!(block::tlb::t_ExtBlkRef.unpack(cs, mc_blk_ref_, &mc_blk_lt_) && cs.empty_ext())) { - return td::Status::Error(-666, "cannot unpack master_ref in shardchain state of "s + id_.to_str()); - } - mc_blk_seqno_ = mc_blk_ref_.seqno(); - } else { - mc_blk_seqno_ = 0; - mc_blk_lt_ = 0; - mc_blk_ref_.invalidate(); - } - min_ref_mc_seqno_ = state.min_ref_mc_seqno; - global_id_ = state.global_id; - utime_ = state.gen_utime; - lt_ = state.gen_lt; - if (!total_balance_.validate_unpack(state.r1.total_balance)) { - return td::Status::Error( - -666, "cannot unpack total_balance:CurrencyCollection from previous ShardState of "s + id_.to_str()); - } - auto accounts_extra = account_dict_->get_root_extra(); - CurrencyCollection old_total_balance; - if (!(accounts_extra.write().advance(5) && old_total_balance.fetch(accounts_extra.write()))) { - return td::Status::Error( - -666, - "cannot extract total account balance from ShardAccounts contained in previous ShardState of "s + id_.to_str()); - } - if (old_total_balance != total_balance_) { - return td::Status::Error(-666, "invalid previous ShardState for "s + id_.to_str() + ": declared total balance " + - total_balance_.to_str() + " differs from " + old_total_balance.to_str() + - " obtained by summing over all Accounts"); - } - if (!(total_validator_fees_.validate_unpack(state.r1.total_validator_fees) && !total_validator_fees_.has_extra())) { - return td::Status::Error( - -666, "cannot unpack total_validator_fees:CurrencyCollection from previous ShardState of "s + id_.to_str()); - } - if (is_masterchain()) { - if (mc_state_extra_.is_null()) { - return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain McStateExtra"); - } - block::gen::McStateExtra::Record extra; - if (!tlb::unpack_cell(mc_state_extra_, extra)) { - return td::Status::Error(-666, "cannot unpack McStateExtra in ShardState of "s + id_.to_str()); - } - if (!global_balance_.validate_unpack(extra.global_balance)) { - return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid global_balance"); - } - if (extra.r1.flags & 1) { - if (extra.r1.block_create_stats->prefetch_ulong(8) == 0x17) { - block_create_stats_ = std::make_unique(extra.r1.block_create_stats->prefetch_ref(), 256); - } else { - return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid BlockCreateStats"); - } - } else { - block_create_stats_ = std::make_unique(256); - } - } - return unpack_out_msg_queue_info(std::move(state.out_msg_queue_info)); -} - -// SETS: out_msg_queue, processed_upto_, ihr_pending -td::Status ShardState::unpack_out_msg_queue_info(Ref out_msg_queue_info) { - block::gen::OutMsgQueueInfo::Record qinfo; - if (!tlb::unpack_cell(std::move(out_msg_queue_info), qinfo)) { - return td::Status::Error(-666, "cannot unpack OutMsgQueueInfo in the state of "s + id_.to_str()); - } - out_msg_queue_ = - std::make_unique(std::move(qinfo.out_queue), 352, block::tlb::aug_OutMsgQueue); - if (verbosity >= 3 * 1) { - LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str(); - block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info); - } - if (!block::gen::t_ProcessedInfo.validate_csr(1024, qinfo.proc_info)) { - return td::Status::Error( - -666, "ProcessedInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks"); - } - if (!block::gen::t_IhrPendingInfo.validate_csr(1024, qinfo.ihr_pending)) { - return td::Status::Error( - -666, "IhrPendingInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks"); - } - processed_upto_ = block::MsgProcessedUptoCollection::unpack(ton::ShardIdFull(id_), std::move(qinfo.proc_info)); - ihr_pending_ = std::make_unique(std::move(qinfo.ihr_pending), 320); - auto shard1 = id_.shard_full(); - td::BitArray<64> pfx{(long long)shard1.shard}; - int pfx_len = shard_prefix_length(shard1); - if (!ihr_pending_->has_common_prefix(pfx.bits(), pfx_len)) { - return td::Status::Error(-666, "IhrPendingInfo in the state of "s + id_.to_str() + " does not have " + - pfx.bits().to_hex(pfx_len) + " as common key prefix"); - } - return td::Status::OK(); -} - -// UPDATES: prev_state_utime_, prev_state_lt_ -bool ShardState::update_prev_utime_lt(ton::UnixTime& prev_utime, ton::LogicalTime& prev_lt) const { - prev_utime = std::max(prev_utime, utime_); - prev_lt = std::max(prev_lt, lt_); - return true; -} - -td::Status ShardState::check_before_split(bool req_before_split) const { - CHECK(id_.is_valid()); - if (before_split_ != req_before_split) { - return td::Status::Error(PSTRING() << "previous state for " << id_.to_str() << " has before_split=" << before_split_ - << ", but we have after_split=" << req_before_split); - } - return td::Status::OK(); -} - -td::Status ShardState::check_global_id(int req_global_id) const { - if (global_id_ != req_global_id) { - return td::Status::Error(-666, PSTRING() << "global blockchain id mismatch in shard state of " << id_.to_str() - << ": expected " << req_global_id << ", found " << global_id_); - } - return td::Status::OK(); -} - -td::Status ShardState::check_mc_blk_seqno(ton::BlockSeqno last_mc_block_seqno) const { - if (mc_blk_seqno_ > last_mc_block_seqno) { - return td::Status::Error( - -666, PSTRING() << "previous block refers to masterchain block with seqno " << mc_blk_seqno_ - << " larger than the latest known masterchain block seqno " << last_mc_block_seqno); - } - return td::Status::OK(); -} - -td::Status ShardState::unpack_state_ext(ton::BlockIdExt id, Ref state_root, int global_id, - ton::BlockSeqno prev_mc_block_seqno, bool after_split, bool clear_history, - std::function for_each_mcseqno_func) { - TRY_STATUS(unpack_state(id, std::move(state_root))); - TRY_STATUS(check_global_id(global_id)); - TRY_STATUS(check_mc_blk_seqno(prev_mc_block_seqno)); - TRY_STATUS(check_before_split(after_split)); - clear_load_history_if(clear_history); - if (!for_each_mcseqno(std::move(for_each_mcseqno_func))) { - return td::Status::Error( - -666, "cannot perform necessary actions for each mc_seqno mentioned in ProcessedUpto of "s + id_.to_str()); - } - return td::Status::OK(); -} - -td::Status ShardState::merge_with(ShardState& sib) { - // 1. check that the two states are valid and belong to sibling shards - if (!is_valid() || !sib.is_valid()) { - return td::Status::Error(-666, "cannot merge invalid or uninitialized states"); - } - if (!ton::shard_is_sibling(id_.shard_full(), sib.id_.shard_full())) { - return td::Status::Error(-666, "cannot merge non-sibling states of "s + id_.to_str() + " and " + sib.id_.to_str()); - } - ton::ShardIdFull shard = ton::shard_parent(id_.shard_full()); - // 2. compute total_balance and total_validator_fees - total_balance_ += std::move(sib.total_balance_); - if (!total_balance_.is_valid()) { - return td::Status::Error(-667, "cannot add total_balance_extra of the two states being merged"); - } - total_validator_fees_ += std::move(sib.total_validator_fees_); - // 3. merge account_dict with sibling_account_dict - LOG(DEBUG) << "merging account dictionaries"; - if (!account_dict_->combine_with(*sib.account_dict_)) { - return td::Status::Error(-666, "cannot merge account dictionaries of the two ancestors"); - } - sib.account_dict_.reset(); - // 3.1. check that all keys in merged account_dict have correct prefixes - td::BitArray<64> pfx{(long long)shard.shard}; - int pfx_len = shard_prefix_length(shard); - if (!account_dict_->has_common_prefix(pfx.bits(), pfx_len)) { - return td::Status::Error(-666, "merged account dictionary of previous states of "s + shard.to_str() + - " does not have " + pfx.bits().to_hex(pfx_len) + " as common key prefix"); - } - // 3.2. check total balance of the new account_dict - auto accounts_extra = account_dict_->get_root_extra(); - CurrencyCollection old_total_balance; - if (!(accounts_extra.write().advance(5) && old_total_balance.fetch(accounts_extra.write()))) { - return td::Status::Error(-666, "cannot extract total account balance from merged accounts dictionary"); - } - if (old_total_balance != total_balance_) { - return td::Status::Error( - -666, - "invalid merged account dictionary: declared total balance differs from one obtained by summing over all " - "Accounts"); - } - // 4. merge shard libraries - CHECK(shard_libraries_->is_empty() && sib.shard_libraries_->is_empty()); - // 5. merge out_msg_queue - LOG(DEBUG) << "merging outbound message queues"; - if (!out_msg_queue_->combine_with(*sib.out_msg_queue_)) { - return td::Status::Error(-666, "cannot merge outbound message queues of the two ancestor states"); - } - sib.out_msg_queue_.reset(); - // 6. merge processed_upto - LOG(DEBUG) << "merging ProcessedUpto structures"; - if (!processed_upto_->combine_with(*sib.processed_upto_)) { - return td::Status::Error(-666, "cannot merge ProcessedUpto structures of the two ancestor states"); - } - sib.processed_upto_.reset(); - // 7. merge ihr_pending - LOG(DEBUG) << "merging IhrPendingInfo"; - if (!ihr_pending_->combine_with(*sib.ihr_pending_)) { - return td::Status::Error(-666, "cannot merge IhrPendingInfo of the two ancestors"); - } - sib.ihr_pending_.reset(); - // 7.1. check whether all keys of the new ihr_pending have correct prefix - if (!ihr_pending_->has_common_prefix(pfx.bits(), pfx_len)) { - return td::Status::Error(-666, "merged IhrPendingInfo of the two previous states of "s + shard.to_str() + - " does not have " + pfx.bits().to_hex(pfx_len) + " as common key prefix"); - } - // 8. compute merged utime_ and lt_ - utime_ = std::max(utime_, sib.utime_); - lt_ = std::max(lt_, sib.lt_); - // 9. compute underload & overload history - underload_history_ = overload_history_ = 0; - // 10. compute vert_seqno - vert_seqno_ = std::max(vert_seqno_, sib.vert_seqno_); - // Anything else? add here - // ... - - // 100. compute new root - if (!block::gen::t_ShardState.cell_pack_split_state(root_, std::move(root_), std::move(sib.root_))) { - return td::Status::Error(-667, "cannot construct a virtual split_state after a merge"); - } - // 101. invalidate sibling, change id_ to the (virtual) common parent - sib.invalidate(); - id_.id.shard = shard.shard; - id_.file_hash.set_zero(); - id_.root_hash.set_zero(); - return td::Status::OK(); -} - -td::Result> ShardState::compute_split_out_msg_queue( - ton::ShardIdFull subshard) { - auto shard = id_.shard_full(); - if (!ton::shard_is_parent(shard, subshard)) { - return td::Status::Error(-666, "cannot split subshard "s + subshard.to_str() + " from state of " + id_.to_str() + - " because it is not a parent"); - } - CHECK(out_msg_queue_); - auto subqueue = std::make_unique(*out_msg_queue_); - int res = block::filter_out_msg_queue(*subqueue, shard, subshard); - if (res < 0) { - return td::Status::Error(-666, "error splitting OutMsgQueue of "s + id_.to_str()); - } - LOG(DEBUG) << "OutMsgQueue split counter: " << res << " messages"; - return std::move(subqueue); -} - -td::Result> ShardState::compute_split_processed_upto( - ton::ShardIdFull subshard) { - if (!ton::shard_is_parent(id_.shard_full(), subshard)) { - return td::Status::Error(-666, "cannot split subshard "s + subshard.to_str() + " from state of " + id_.to_str() + - " because it is not a parent"); - } - CHECK(processed_upto_); - auto sub_processed_upto = std::make_shared(*processed_upto_); - if (!sub_processed_upto->split(subshard)) { - return td::Status::Error(-666, "error splitting ProcessedUpto of "s + id_.to_str()); - } - return std::move(sub_processed_upto); -} - -td::Status ShardState::split(ton::ShardIdFull subshard) { - if (!ton::shard_is_parent(id_.shard_full(), subshard)) { - return td::Status::Error(-666, "cannot split subshard "s + subshard.to_str() + " from state of " + id_.to_str() + - " because it is not a parent"); - } - // Have to split: - // 1. account_dict - LOG(DEBUG) << "splitting account dictionary"; - td::BitArray<64> pfx{(long long)subshard.shard}; - int pfx_len = shard_prefix_length(subshard); - CHECK(account_dict_); - CHECK(account_dict_->cut_prefix_subdict(pfx.bits(), pfx_len)); - CHECK(account_dict_->has_common_prefix(pfx.bits(), pfx_len)); - // 2. out_msg_queue - LOG(DEBUG) << "splitting OutMsgQueue"; - auto shard1 = id_.shard_full(); - CHECK(ton::shard_is_parent(shard1, subshard)); - CHECK(out_msg_queue_); - int res1 = block::filter_out_msg_queue(*out_msg_queue_, shard1, subshard); - if (res1 < 0) { - return td::Status::Error(-666, "error splitting OutMsgQueue of "s + id_.to_str()); - } - LOG(DEBUG) << "split counters: " << res1; - // 3. processed_upto - LOG(DEBUG) << "splitting ProcessedUpto"; - CHECK(processed_upto_); - if (!processed_upto_->split(subshard)) { - return td::Status::Error(-666, "error splitting ProcessedUpto of "s + id_.to_str()); - } - // 4. ihr_pending - LOG(DEBUG) << "splitting IhrPending"; - CHECK(ihr_pending_->cut_prefix_subdict(pfx.bits(), pfx_len)); - CHECK(ihr_pending_->has_common_prefix(pfx.bits(), pfx_len)); - // 5. adjust total_balance - LOG(DEBUG) << "splitting total_balance"; - auto old_total_balance = total_balance_; - auto accounts_extra = account_dict_->get_root_extra(); - if (!(accounts_extra.write().advance(5) && total_balance_.validate_unpack(accounts_extra, 1024))) { - LOG(ERROR) << "cannot unpack CurrencyCollection from the root of newly-split accounts dictionary"; - return td::Status::Error( - -666, "error splitting total balance in account dictionary of shardchain state "s + id_.to_str()); - } - LOG(DEBUG) << "split total balance from " << old_total_balance.to_str() << " to our share of " - << total_balance_.to_str(); - // 6. adjust total_fees - LOG(DEBUG) << "split total validator fees (current value is " << total_validator_fees_.to_str() << ")"; - total_validator_fees_.grams = (total_validator_fees_.grams + is_right_child(subshard)) >> 1; - LOG(DEBUG) << "new total_validator_fees is " << total_validator_fees_.to_str(); - // NB: if total_fees_extra will be allowed to be non-empty, split it here too - // 7. reset overload/underload history - overload_history_ = underload_history_ = 0; - // 999. anything else? - id_.id.shard = subshard.shard; - id_.file_hash.set_zero(); - id_.root_hash.set_zero(); - return td::Status::OK(); -} - -int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard) { - return out_queue.filter([subshard, old_shard](vm::CellSlice& cs, td::ConstBitPtr key, int key_len) -> int { - CHECK(key_len == 352); - LOG(DEBUG) << "scanning OutMsgQueue entry with key " << key.to_hex(key_len); - block::tlb::MsgEnvelope::Record_std env; - block::gen::CommonMsgInfo::Record_int_msg_info info; - if (!(cs.size_ext() == 0x10080 // (uint64) enqueued_lt:uint64 out_msg:^MsgEnvelope - && tlb::unpack_cell(cs.prefetch_ref(), env) && tlb::unpack_cell_inexact(env.msg, info))) { - LOG(ERROR) << "cannot unpack OutMsgQueue entry with key " << key.to_hex(key_len); - return -1; - } - auto src_prefix = block::tlb::t_MsgAddressInt.get_prefix(info.src); - auto dest_prefix = block::tlb::t_MsgAddressInt.get_prefix(info.dest); - auto cur_prefix = block::interpolate_addr(src_prefix, dest_prefix, env.cur_addr); - if (!(src_prefix.is_valid() && dest_prefix.is_valid() && cur_prefix.is_valid())) { - LOG(ERROR) << "OutMsgQueue message with key " << key.to_hex(key_len) - << " has invalid source or destination address"; - return -1; - } - if (!ton::shard_contains(old_shard, cur_prefix)) { - LOG(ERROR) << "OutMsgQueue message with key " << key.to_hex(key_len) - << " does not contain current address belonging to shard " << old_shard.to_str(); - return -1; - } - return ton::shard_contains(subshard, cur_prefix); - }); -} - -bool CurrencyCollection::validate(int max_cells) const { - return is_valid() && td::sgn(grams) >= 0 && validate_extra(max_cells); -} - -bool CurrencyCollection::validate_extra(int max_cells) const { - if (extra.is_null()) { - return true; - } - vm::CellBuilder cb; - return cb.store_maybe_ref(extra) && block::tlb::t_ExtraCurrencyCollection.validate_ref(max_cells, cb.finalize()); -} - -bool CurrencyCollection::add(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c) { - return (a.is_valid() && b.is_valid() && (c.grams = a.grams + b.grams).not_null() && c.grams->is_valid() && - add_extra_currency(a.extra, b.extra, c.extra)) || - c.invalidate(); -} - -bool CurrencyCollection::add(const CurrencyCollection& a, CurrencyCollection&& b, CurrencyCollection& c) { - return (a.is_valid() && b.is_valid() && (c.grams = a.grams + std::move(b.grams)).not_null() && c.grams->is_valid() && - add_extra_currency(a.extra, std::move(b.extra), c.extra)) || - c.invalidate(); -} - -CurrencyCollection& CurrencyCollection::operator+=(const CurrencyCollection& other) { - if (!is_valid()) { - return *this; - } - if (!(other.is_valid() && (grams += other.grams).not_null() && grams->is_valid() && - add_extra_currency(extra, other.extra, extra))) { - invalidate(); - } - return *this; -} - -CurrencyCollection& CurrencyCollection::operator+=(CurrencyCollection&& other) { - if (!is_valid()) { - return *this; - } - if (!(other.is_valid() && (grams += std::move(other.grams)).not_null() && grams->is_valid() && - add_extra_currency(extra, std::move(other.extra), extra))) { - invalidate(); - } - return *this; -} - -CurrencyCollection& CurrencyCollection::operator+=(td::RefInt256 other_grams) { - if (!is_valid()) { - return *this; - } - if (!(other_grams.not_null() && (grams += other_grams).not_null())) { - invalidate(); - } - return *this; -} - -CurrencyCollection CurrencyCollection::operator+(const CurrencyCollection& other) const { - CurrencyCollection res; - add(*this, other, res); - return res; -} - -CurrencyCollection CurrencyCollection::operator+(CurrencyCollection&& other) const { - CurrencyCollection res; - add(*this, std::move(other), res); - return res; -} - -CurrencyCollection CurrencyCollection::operator+(td::RefInt256 other_grams) { - if (!is_valid()) { - return *this; - } - auto sum = grams + other_grams; - if (sum.not_null()) { - return CurrencyCollection{std::move(sum), extra}; - } else { - return CurrencyCollection{}; - } -} - -bool CurrencyCollection::sub(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c) { - return (a.is_valid() && b.is_valid() && (c.grams = a.grams - b.grams).not_null() && c.grams->is_valid() && - td::sgn(c.grams) >= 0 && sub_extra_currency(a.extra, b.extra, c.extra)) || - c.invalidate(); -} - -bool CurrencyCollection::sub(const CurrencyCollection& a, CurrencyCollection&& b, CurrencyCollection& c) { - return (a.is_valid() && b.is_valid() && (c.grams = a.grams - std::move(b.grams)).not_null() && c.grams->is_valid() && - td::sgn(c.grams) >= 0 && sub_extra_currency(a.extra, std::move(b.extra), c.extra)) || - c.invalidate(); -} - -CurrencyCollection& CurrencyCollection::operator-=(const CurrencyCollection& other) { - if (!is_valid()) { - return *this; - } - if (!(other.is_valid() && (grams -= other.grams).not_null() && grams->is_valid() && td::sgn(grams) >= 0 && - sub_extra_currency(extra, other.extra, extra))) { - invalidate(); - } - return *this; -} - -CurrencyCollection& CurrencyCollection::operator-=(CurrencyCollection&& other) { - if (!is_valid()) { - return *this; - } - if (!(other.is_valid() && (grams -= std::move(other.grams)).not_null() && grams->is_valid() && td::sgn(grams) >= 0 && - sub_extra_currency(extra, std::move(other.extra), extra))) { - invalidate(); - } - return *this; -} - -CurrencyCollection& CurrencyCollection::operator-=(td::RefInt256 other_grams) { - if (!is_valid()) { - return *this; - } - if (!(other_grams.not_null() && (grams -= other_grams).not_null() && td::sgn(grams) >= 0)) { - invalidate(); - } - return *this; -} - -CurrencyCollection CurrencyCollection::operator-(const CurrencyCollection& other) const { - CurrencyCollection res; - sub(*this, other, res); - return res; -} - -CurrencyCollection CurrencyCollection::operator-(CurrencyCollection&& other) const { - CurrencyCollection res; - sub(*this, std::move(other), res); - return res; -} - -CurrencyCollection CurrencyCollection::operator-(td::RefInt256 other_grams) const { - if (!(is_valid() && other_grams.not_null())) { - return {}; - } - auto x = grams - other_grams; - if (td::sgn(x) >= 0) { - return CurrencyCollection{std::move(x), extra}; - } else { - return {}; - } -} - -bool CurrencyCollection::operator==(const CurrencyCollection& other) const { - return is_valid() && other.is_valid() && !td::cmp(grams, other.grams) && - (extra.not_null() == other.extra.not_null()) && - (extra.is_null() || extra->get_hash() == other.extra->get_hash()); -} - -bool CurrencyCollection::operator>=(const CurrencyCollection& other) const { - Ref tmp; - return is_valid() && other.is_valid() && td::cmp(grams, other.grams) >= 0 && - sub_extra_currency(extra, other.extra, tmp); -} - -bool CurrencyCollection::store(vm::CellBuilder& cb) const { - return is_valid() && store_CurrencyCollection(cb, grams, extra); -} - -bool CurrencyCollection::store_or_zero(vm::CellBuilder& cb) const { - return is_valid() ? store(cb) : cb.store_long_bool(0, 5); -} - -bool CurrencyCollection::fetch(vm::CellSlice& cs) { - return block::tlb::t_CurrencyCollection.unpack_special(cs, *this, true) || invalidate(); -} - -bool CurrencyCollection::fetch_exact(vm::CellSlice& cs) { - return block::tlb::t_CurrencyCollection.unpack_special(cs, *this, false) || invalidate(); -} - -bool CurrencyCollection::unpack(Ref csr) { - return unpack_CurrencyCollection(std::move(csr), grams, extra) || invalidate(); -} - -bool CurrencyCollection::validate_unpack(Ref csr, int max_cells) { - return (csr.not_null() && block::tlb::t_CurrencyCollection.validate_upto(max_cells, *csr) && - unpack_CurrencyCollection(std::move(csr), grams, extra)) || - invalidate(); -} - -Ref CurrencyCollection::pack() const { - vm::CellBuilder cb; - if (store(cb)) { - return vm::load_cell_slice_ref(cb.finalize()); - } else { - return {}; - } -} - -bool CurrencyCollection::show(std::ostream& os) const { - if (!is_valid()) { - os << ""; - return false; - } - if (extra.not_null()) { - os << '('; - } - os << grams << "ng"; - if (extra.not_null()) { - vm::Dictionary dict{extra, 32}; - if (!dict.check_for_each([&os](Ref csr, td::ConstBitPtr key, int n) { - CHECK(n == 32); - int x = (int)key.get_int(n); - auto val = block::tlb::t_VarUIntegerPos_32.as_integer_skip(csr.write()); - if (val.is_null() || !csr->empty_ext()) { - os << "+.$" << x << "...)"; - return false; - } - os << '+' << val << ".$" << x; - return true; - })) { - return false; - } - os << ')'; - } - return true; -} - -std::string CurrencyCollection::to_str() const { - std::ostringstream os; - show(os); - return os.str(); -} - -std::ostream& operator<<(std::ostream& os, const CurrencyCollection& cc) { - cc.show(os); - return os; -} - -bool ValueFlow::set_zero() { - return from_prev_blk.set_zero() && to_next_blk.set_zero() && imported.set_zero() && exported.set_zero() && - fees_collected.set_zero() && fees_imported.set_zero() && recovered.set_zero() && created.set_zero() && - minted.set_zero(); -} - -bool ValueFlow::validate() const { - return is_valid() && from_prev_blk + imported + fees_imported + created + minted + recovered == - to_next_blk + exported + fees_collected; -} - -bool ValueFlow::store(vm::CellBuilder& cb) const { - vm::CellBuilder cb2; - return cb.store_long_bool(block::gen::ValueFlow::cons_tag[0], 32) // value_flow ^[ - && from_prev_blk.store(cb2) // from_prev_blk:CurrencyCollection - && to_next_blk.store(cb2) // to_next_blk:CurrencyCollection - && imported.store(cb2) // imported:CurrencyCollection - && exported.store(cb2) // exported:CurrencyCollection - && cb.store_ref_bool(cb2.finalize()) // ] - && fees_collected.store(cb) // fees_collected:CurrencyCollection - && fees_imported.store(cb2) // ^[ fees_imported:CurrencyCollection - && recovered.store(cb2) // recovered:CurrencyCollection - && created.store(cb2) // created:CurrencyCollection - && minted.store(cb2) // minted:CurrencyCollection - && cb.store_ref_bool(cb2.finalize()); // ] = ValueFlow; -} - -bool ValueFlow::fetch(vm::CellSlice& cs) { - block::gen::ValueFlow::Record f; - if (!(tlb::unpack(cs, f) && from_prev_blk.validate_unpack(std::move(f.r1.from_prev_blk)) && - to_next_blk.validate_unpack(std::move(f.r1.to_next_blk)) && - imported.validate_unpack(std::move(f.r1.imported)) && exported.validate_unpack(std::move(f.r1.exported)) && - fees_collected.validate_unpack(std::move(f.fees_collected)) && - fees_imported.validate_unpack(std::move(f.r2.fees_imported)) && - recovered.validate_unpack(std::move(f.r2.recovered)) && created.validate_unpack(std::move(f.r2.created)) && - minted.validate_unpack(std::move(f.r2.minted)))) { - return invalidate(); - } - return true; -} - -bool ValueFlow::unpack(Ref csr) { - return (csr.not_null() && fetch(csr.write()) && csr->empty_ext()) || invalidate(); -} - -static inline bool say(std::ostream& os, const char* str) { - os << str; - return true; -} - -bool ValueFlow::show_one(std::ostream& os, const char* str, const CurrencyCollection& cc) const { - return say(os, str) && cc.show(os); -} - -bool ValueFlow::show(std::ostream& os) const { - if (!is_valid()) { - os << ""; - return false; - } - return (say(os, "(value-flow ") && show_one(os, "from_prev_blk:", from_prev_blk) && - show_one(os, " to_next_blk:", to_next_blk) && show_one(os, " imported:", imported) && - show_one(os, " exported:", exported) && show_one(os, " fees_collected:", fees_collected) && - show_one(os, " fees_imported:", fees_imported) && show_one(os, " recovered:", recovered) && - show_one(os, " created:", created) && show_one(os, " minted:", minted) && say(os, ")")) || - (say(os, "...)") && false); -} - -std::string ValueFlow::to_str() const { - std::ostringstream os; - show(os); - return os.str(); -} - -std::ostream& operator<<(std::ostream& os, const ValueFlow& vflow) { - vflow.show(os); - return os; -} - -bool DiscountedCounter::increase_by(unsigned count, ton::UnixTime now) { - if (!validate()) { - return false; - } - td::uint64 scaled = (td::uint64(count) << 32); - if (!total) { - last_updated = now; - total = count; - cnt2048 = scaled; - cnt65536 = scaled; - return true; - } - if (count > ~total || cnt2048 > ~scaled || cnt65536 > ~scaled) { - return false /* invalidate() */; // overflow - } - unsigned dt = (now >= last_updated ? now - last_updated : 0); - if (dt > 0) { - // more precise version of cnt2048 = llround(cnt2048 * exp(-dt / 2048.)); - // (rounding error has absolute value < 1) - cnt2048 = (dt >= 48 * 2048 ? 0 : td::umulnexps32(cnt2048, dt << 5)); - // more precise version of cnt65536 = llround(cnt65536 * exp(-dt / 65536.)); - // (rounding error has absolute value < 1) - cnt65536 = td::umulnexps32(cnt65536, dt); - } - total += count; - cnt2048 += scaled; - cnt65536 += scaled; - last_updated = now; - return true; -} - -bool DiscountedCounter::validate() { - if (!is_valid()) { - return false; - } - if (!total) { - if (cnt2048 | cnt65536) { - return invalidate(); - } - } else if (!last_updated) { - return invalidate(); - } - return true; -} - -bool DiscountedCounter::fetch(vm::CellSlice& cs) { - valid = (cs.fetch_uint_to(32, last_updated) && cs.fetch_uint_to(64, total) && cs.fetch_uint_to(64, cnt2048) && - cs.fetch_uint_to(64, cnt65536)); - return validate() || invalidate(); -} - -bool DiscountedCounter::unpack(Ref csr) { - return (csr.not_null() && fetch(csr.write()) && csr->empty_ext()) || invalidate(); -} - -bool DiscountedCounter::store(vm::CellBuilder& cb) const { - return is_valid() && cb.store_long_bool(last_updated, 32) && cb.store_long_bool(total, 64) && - cb.store_long_bool(cnt2048, 64) && cb.store_long_bool(cnt65536, 64); -} - -Ref DiscountedCounter::pack() const { - vm::CellBuilder cb; - if (store(cb)) { - return vm::load_cell_slice_ref(cb.finalize()); - } else { - return {}; - } -} - -bool DiscountedCounter::show(std::ostream& os) const { - if (!is_valid()) { - os << ""; - return false; - } - os << "(counter last_updated:" << last_updated << " total:" << total << " cnt2048: " << (double)cnt2048 / (1LL << 32) - << " cnt65536: " << (double)cnt65536 / (1LL << 32) << ")"; - return true; -} - -std::string DiscountedCounter::to_str() const { - std::ostringstream stream; - if (show(stream)) { - return stream.str(); - } else { - return ""; - } -} - -bool fetch_CreatorStats(vm::CellSlice& cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt) { - return cs.fetch_ulong(4) == 4 // creator_info#4 - && mc_cnt.fetch(cs) // mc_blocks:Counters - && shard_cnt.fetch(cs); // shard_blocks:Counters -} - -bool store_CreatorStats(vm::CellBuilder& cb, const DiscountedCounter& mc_cnt, const DiscountedCounter& shard_cnt) { - return cb.store_long_bool(4, 4) // creator_info#4 - && mc_cnt.store(cb) // mc_blocks:Counters - && shard_cnt.store(cb); // shard_blocks:Counters -} - -bool unpack_CreatorStats(Ref cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt) { - if (cs.is_null()) { - return mc_cnt.set_zero() && shard_cnt.set_zero(); - } else { - return fetch_CreatorStats(cs.write(), mc_cnt, shard_cnt) && cs->empty_ext(); - } -} - -/* - * - * Monte Carlo simulator for computing the share of shardchain blocks generated by each validator - * - */ - -bool MtCarloComputeShare::compute() { - ok = false; - if (W.size() >= (1U << 31) || W.empty()) { - return false; - } - K = std::min(K, N); - if (K <= 0 || iterations <= 0) { - return false; - } - double tot_weight = 0., acc = 0.; - for (int i = 0; i < N; i++) { - if (W[i] <= 0.) { - return false; - } - tot_weight += W[i]; - } - CW.resize(N); - RW.resize(N); - for (int i = 0; i < N; i++) { - CW[i] = acc; - acc += W[i] /= tot_weight; - RW[i] = 0.; - } - R0 = 0.; - H.resize(N); - A.resize(K); - for (long long it = 0; it < iterations; ++it) { - gen_vset(); - } - for (int i = 0; i < N; i++) { - RW[i] = W[i] * (RW[i] + R0) / (double)iterations; - } - return ok = true; -} - -void MtCarloComputeShare::gen_vset() { - double total_wt = 1.; - int hc = 0; - for (int i = 0; i < K; i++) { - CHECK(total_wt > 0); - double inv_wt = 1. / total_wt; - R0 += inv_wt; - for (int j = 0; j < i; j++) { - RW[A[j]] -= inv_wt; - } - // double p = drand48() * total_wt; - double p = (double)td::Random::fast_uint64() * total_wt / (1. * (1LL << 32) * (1LL << 32)); - for (int h = 0; h < hc; h++) { - if (p < H[h].first) { - break; - } - p += H[h].second; - } - int a = -1, b = N, c; - while (b - a > 1) { - c = ((a + b) >> 1); - if (CW[c] <= p) { - a = c; - } else { - b = c; - } - } - CHECK(a >= 0 && a < N); - CHECK(total_wt >= W[a]); - total_wt -= W[a]; - double x = CW[a]; - c = hc++; - while (c > 0 && H[c - 1].first > x) { - H[c] = H[c - 1]; - --c; - } - H[c].first = x; - H[c].second = W[a]; - A[i] = a; - } -} - -/* - * - * Other block-related functions - * - */ - -bool store_UInt7(vm::CellBuilder& cb, unsigned long long value) { - return block::tlb::t_VarUInteger_7.store_long(cb, (long long)value); -} - -bool store_UInt7(vm::CellBuilder& cb, unsigned long long value1, unsigned long long value2) { - return store_UInt7(cb, value1) && store_UInt7(cb, value2); -} - -bool store_Maybe_Grams(vm::CellBuilder& cb, td::RefInt256 value) { - if (value.is_null()) { - return cb.store_long_bool(0, 1); - } else { - return cb.store_long_bool(1, 1) && block::tlb::t_Grams.store_integer_ref(cb, std::move(value)); - } -} - -bool store_Maybe_Grams_nz(vm::CellBuilder& cb, td::RefInt256 value) { - if (value.is_null() || !value->sgn()) { - return cb.store_long_bool(0, 1); - } else { - return cb.store_long_bool(1, 1) && block::tlb::t_Grams.store_integer_ref(cb, std::move(value)); - } -} - -bool store_CurrencyCollection(vm::CellBuilder& cb, td::RefInt256 value, Ref extra) { - return block::tlb::t_CurrencyCollection.pack_special(cb, std::move(value), std::move(extra)); -} - -bool fetch_CurrencyCollection(vm::CellSlice& cs, td::RefInt256& value, Ref& extra, bool inexact) { - return block::tlb::t_CurrencyCollection.unpack_special(cs, value, extra, inexact); -} - -bool unpack_CurrencyCollection(Ref csr, td::RefInt256& value, Ref& extra) { - if (csr.is_null()) { - return false; - } else if (csr->is_unique()) { - return block::tlb::t_CurrencyCollection.unpack_special(csr.write(), value, extra); - } else { - vm::CellSlice cs{*csr}; - return block::tlb::t_CurrencyCollection.unpack_special(cs, value, extra); - } -} - -bool check_one_library(Ref cs_ref, td::ConstBitPtr key, int n) { - assert(n == 256); - if (cs_ref->size_ext() != 0x10001) { - return false; - } - Ref cell = cs_ref->prefetch_ref(); - const auto& cell_hash = cell->get_hash(); - return !td::bitstring::bits_memcmp(cell_hash.bits(), key, n); -} - -bool valid_library_collection(Ref cell, bool catch_errors) { - if (cell.is_null()) { - return true; - } - if (!catch_errors) { - vm::Dictionary dict{std::move(cell), 256}; - return dict.check_for_each(check_one_library); - } - try { - vm::Dictionary dict{std::move(cell), 256}; - return dict.check_for_each(check_one_library); - } catch (vm::VmError&) { - return false; - } -} - -bool check_one_config_param(Ref cs_ref, td::ConstBitPtr key, td::ConstBitPtr addr, bool relax_par0) { - if (cs_ref->size_ext() != 0x10000) { - return false; - } - Ref cell = cs_ref->prefetch_ref(); - int idx = (int)key.get_int(32); - if (!idx) { - auto cs = load_cell_slice(std::move(cell)); - return cs.size_ext() == 256 && (relax_par0 || cs.fetch_bits(256) == addr); - } else if (idx < 0) { - return true; - } - bool ok = block::gen::ConfigParam{idx}.validate_ref(1024, std::move(cell)); - if (!ok) { - LOG(ERROR) << "configuration parameter #" << idx << " is invalid"; - } - return ok; -} - -const int mandatory_config_params[] = {18, 20, 21, 22, 23, 24, 25, 28, 34}; - -bool valid_config_data(Ref cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0, - Ref old_mparams) { - using namespace std::placeholders; - if (cell.is_null()) { - return false; - } - if (catch_errors) { - try { - return valid_config_data(std::move(cell), addr, false, relax_par0, std::move(old_mparams)); - } catch (vm::VmError&) { - return false; - } - } - vm::Dictionary dict{std::move(cell), 32}; - if (!dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0))) { - return false; - } - for (int x : mandatory_config_params) { - if (!dict.int_key_exists(x)) { - LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing"; - return false; - } - } - return config_params_present(dict, dict.lookup_ref(td::BitArray<32>{9})) && - config_params_present(dict, std::move(old_mparams)); -} - -bool config_params_present(vm::Dictionary& dict, Ref param_dict_root) { - auto res = block::Config::unpack_param_dict(std::move(param_dict_root)); - if (res.is_error()) { - LOG(ERROR) - << "invalid mandatory parameters dictionary while checking existence of all mandatory configuration parameters"; - return false; - } - for (int x : res.move_as_ok()) { - // LOG(DEBUG) << "checking whether mandatory configuration parameter #" << x << " exists"; - if (!dict.int_key_exists(x)) { - LOG(ERROR) << "configuration parameter #" << x - << " (declared as mandatory in configuration parameter #9) is missing"; - return false; - } - } - // LOG(DEBUG) << "all mandatory configuration parameters present"; - return true; -} - -bool add_extra_currency(Ref extra1, Ref extra2, Ref& res) { - if (extra2.is_null()) { - res = extra1; - return true; - } else if (extra1.is_null()) { - res = extra2; - return true; - } else { - return block::tlb::t_ExtraCurrencyCollection.add_values_ref(res, std::move(extra1), std::move(extra2)); - } -} - -bool sub_extra_currency(Ref extra1, Ref extra2, Ref& res) { - if (extra2.is_null()) { - res = extra1; - return true; - } else if (extra1.is_null()) { - res.clear(); - return false; - } else { - return block::tlb::t_ExtraCurrencyCollection.sub_values_ref(res, std::move(extra1), std::move(extra2)) >= 0; - } -} - -// combine d bits from dest, remaining 64 - d bits from src -ton::AccountIdPrefixFull interpolate_addr(const ton::AccountIdPrefixFull& src, const ton::AccountIdPrefixFull& dest, - int d) { - if (d <= 0) { - return src; - } else if (d >= 96) { - return dest; - } else if (d >= 32) { - unsigned long long mask = (std::numeric_limits::max() >> (d - 32)); - return ton::AccountIdPrefixFull{dest.workchain, (dest.account_id_prefix & ~mask) | (src.account_id_prefix & mask)}; - } else { - int mask = (int)(~0U >> d); - return ton::AccountIdPrefixFull{(dest.workchain & ~mask) | (src.workchain & mask), src.account_id_prefix}; - } -} - -bool interpolate_addr_to(const ton::AccountIdPrefixFull& src, const ton::AccountIdPrefixFull& dest, int d, - ton::AccountIdPrefixFull& res) { - res = interpolate_addr(src, dest, d); - return true; -} - -// result: (transit_addr_dest_bits, nh_addr_dest_bits) -std::pair perform_hypercube_routing(ton::AccountIdPrefixFull src, ton::AccountIdPrefixFull dest, - ton::ShardIdFull cur, int used_dest_bits) { - ton::AccountIdPrefixFull transit = interpolate_addr(src, dest, used_dest_bits); - if (!ton::shard_contains(cur, transit)) { - return {-1, -1}; - } - if (ton::shard_contains(cur, dest)) { - // if destination is in this shard, set cur:=next_hop:=dest - return {96, 96}; - } - if (transit.workchain == ton::masterchainId || dest.workchain == ton::masterchainId) { - return {used_dest_bits, 96}; // route messages to/from masterchain directly - } - if (transit.workchain != dest.workchain) { - return {used_dest_bits, 32}; - } - unsigned long long x = cur.shard & (cur.shard - 1), y = cur.shard | (cur.shard - 1); - unsigned long long t = transit.account_id_prefix, q = dest.account_id_prefix ^ t; - int i = (td::count_leading_zeroes64(q) & -4); // top i bits match, next 4 bits differ - unsigned long long m = (std::numeric_limits::max() >> i), h; - do { - m >>= 4; - h = t ^ (q & ~m); - i += 4; - } while (h >= x && h <= y); - return {28 + i, 32 + i}; -} - -bool compute_out_msg_queue_key(Ref msg_env, td::BitArray<352>& key) { - block::tlb::MsgEnvelope::Record_std env; - block::gen::CommonMsgInfo::Record_int_msg_info info; - if (!(tlb::unpack_cell(msg_env, env) && tlb::unpack_cell_inexact(env.msg, info))) { - return false; - } - auto src_prefix = block::tlb::t_MsgAddressInt.get_prefix(std::move(info.src)); - auto dest_prefix = block::tlb::t_MsgAddressInt.get_prefix(std::move(info.dest)); - auto next_hop = interpolate_addr(src_prefix, dest_prefix, env.next_addr); - key.bits().store_int(next_hop.workchain, 32); - (key.bits() + 32).store_int(next_hop.account_id_prefix, 64); - (key.bits() + 96).copy_from(env.msg->get_hash().bits(), 256); - return true; -} - -bool unpack_block_prev_blk(Ref block_root, const ton::BlockIdExt& id, std::vector& prev, - ton::BlockIdExt& mc_blkid, bool& after_split, ton::BlockIdExt* fetch_blkid) { - return unpack_block_prev_blk_ext(std::move(block_root), id, prev, mc_blkid, after_split, fetch_blkid).is_ok(); -} - -td::Status unpack_block_prev_blk_try(Ref block_root, const ton::BlockIdExt& id, - std::vector& prev, ton::BlockIdExt& mc_blkid, bool& after_split, - ton::BlockIdExt* fetch_blkid) { - try { - return unpack_block_prev_blk_ext(std::move(block_root), id, prev, mc_blkid, after_split, fetch_blkid); - } catch (vm::VmError err) { - return td::Status::Error(std::string{"error while processing Merkle proof: "} + err.get_msg()); - } catch (vm::VmVirtError err) { - return td::Status::Error(std::string{"error while processing Merkle proof: "} + err.get_msg()); - } -} - -td::Status unpack_block_prev_blk_ext(Ref block_root, const ton::BlockIdExt& id, - std::vector& prev, ton::BlockIdExt& mc_blkid, bool& after_split, - ton::BlockIdExt* fetch_blkid) { - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - block::gen::ExtBlkRef::Record mcref; // _ ExtBlkRef = BlkMasterInfo; - ton::ShardIdFull shard; - if (!(tlb::unpack_cell(block_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version && - block::tlb::t_ShardIdent.unpack(info.shard.write(), shard) && - (!info.not_master || tlb::unpack_cell(info.master_ref, mcref)))) { - return td::Status::Error("cannot unpack block header"); - } - if (fetch_blkid) { - fetch_blkid->id = ton::BlockId{shard, (unsigned)info.seq_no}; - fetch_blkid->root_hash = block_root->get_hash().bits(); - fetch_blkid->file_hash.clear(); - } else { - ton::BlockId hdr_id{shard, (unsigned)info.seq_no}; - if (id.id != hdr_id) { - return td::Status::Error("block header contains block id "s + hdr_id.to_str() + ", expected " + id.id.to_str()); - } - if (id.root_hash != block_root->get_hash().bits()) { - return td::Status::Error("block header has incorrect root hash "s + block_root->get_hash().bits().to_hex(256) + - " instead of expected " + id.root_hash.to_hex()); - } - } - if (info.not_master != !shard.is_masterchain()) { - return td::Status::Error("block has invalid not_master flag in its (Merkelized) header"); - } - after_split = info.after_split; - block::gen::ExtBlkRef::Record prev1, prev2; - if (info.after_merge) { - auto cs = vm::load_cell_slice(std::move(info.prev_ref)); - CHECK(cs.size_ext() == 0x20000); // prev_blks_info$_ prev1:^ExtBlkRef prev2:^ExtBlkRef = BlkPrevInfo 1; - if (!(tlb::unpack_cell(cs.prefetch_ref(0), prev1) && tlb::unpack_cell(cs.prefetch_ref(1), prev2))) { - return td::Status::Error("cannot unpack two previous block references from block header"); - } - } else { - // prev_blk_info$_ prev:ExtBlkRef = BlkPrevInfo 0; - if (!(tlb::unpack_cell(std::move(info.prev_ref), prev1))) { - return td::Status::Error("cannot unpack previous block reference from block header"); - } - } - prev.clear(); - ton::BlockSeqno prev_seqno = prev1.seq_no; - if (!info.after_merge) { - prev.emplace_back(shard.workchain, info.after_split ? ton::shard_parent(shard.shard) : shard.shard, prev1.seq_no, - prev1.root_hash, prev1.file_hash); - if (info.after_split && !prev1.seq_no) { - return td::Status::Error("shardchains cannot be split immediately after initial state"); - } - } else { - if (info.after_split) { - return td::Status::Error("shardchains cannot be simultaneously split and merged at the same block"); - } - prev.emplace_back(shard.workchain, ton::shard_child(shard.shard, true), prev1.seq_no, prev1.root_hash, - prev1.file_hash); - prev.emplace_back(shard.workchain, ton::shard_child(shard.shard, false), prev2.seq_no, prev2.root_hash, - prev2.file_hash); - prev_seqno = std::max(prev1.seq_no, prev2.seq_no); - if (!prev1.seq_no || !prev2.seq_no) { - return td::Status::Error("shardchains cannot be merged immediately after initial state"); - } - } - if (id.id.seqno != prev_seqno + 1) { - return td::Status::Error("new block has invalid seqno (not equal to one plus maximum of seqnos of its ancestors)"); - } - if (shard.is_masterchain()) { - mc_blkid = prev.at(0); - } else { - mc_blkid = ton::BlockIdExt{ton::masterchainId, ton::shardIdAll, mcref.seq_no, mcref.root_hash, mcref.file_hash}; - } - if (shard.is_masterchain() && info.vert_seqno_incr && !info.key_block) { - return td::Status::Error("non-key masterchain block cannot have vert_seqno_incr set"); - } - return td::Status::OK(); -} - -td::Status check_block_header(Ref block_root, const ton::BlockIdExt& id, ton::Bits256* store_shard_hash_to) { - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - ton::ShardIdFull shard; - if (!(tlb::unpack_cell(block_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version && - block::tlb::t_ShardIdent.unpack(info.shard.write(), shard))) { - return td::Status::Error("cannot unpack block header"); - } - ton::BlockId hdr_id{shard, (unsigned)info.seq_no}; - if (id.id != hdr_id) { - return td::Status::Error("block header contains block id "s + hdr_id.to_str() + ", expected " + id.id.to_str()); - } - if (id.root_hash != block_root->get_hash().bits()) { - return td::Status::Error("block header has incorrect root hash "s + block_root->get_hash().bits().to_hex(256) + - " instead of expected " + id.root_hash.to_hex()); - } - if (info.not_master != !shard.is_masterchain()) { - return td::Status::Error("block has invalid not_master flag in its (Merkelized) header"); - } - if (store_shard_hash_to) { - vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; - if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update - && upd_cs.size_ext() == 0x20228)) { - return td::Status::Error("invalid Merkle update in block header"); - } - auto upd_hash = upd_cs.prefetch_ref(1)->get_hash(0); - *store_shard_hash_to = upd_hash.bits(); - } - return td::Status::OK(); -} - -std::unique_ptr get_block_create_stats_dict(Ref state_root) { - block::gen::ShardStateUnsplit::Record info; - block::gen::McStateExtra::Record extra; - block::gen::BlockCreateStats::Record_block_create_stats cstats; - if (!(::tlb::unpack_cell(std::move(state_root), info) && info.custom->size_refs() && - ::tlb::unpack_cell(info.custom->prefetch_ref(), extra) && (extra.r1.flags & 1) && - ::tlb::csr_unpack(std::move(extra.r1.block_create_stats), cstats))) { - return {}; - } - return std::make_unique(std::move(cstats.counters), 256); -} - -std::unique_ptr get_prev_blocks_dict(Ref state_root) { - block::gen::ShardStateUnsplit::Record info; - block::gen::McStateExtra::Record extra_info; - if (!(::tlb::unpack_cell(std::move(state_root), info) && info.custom->size_refs() && - ::tlb::unpack_cell(info.custom->prefetch_ref(), extra_info))) { - return {}; - } - return std::make_unique(extra_info.r1.prev_blocks, 32, block::tlb::aug_OldMcBlocksInfo); -} - -bool get_old_mc_block_id(vm::AugmentedDictionary* prev_blocks_dict, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt) { - return prev_blocks_dict && get_old_mc_block_id(*prev_blocks_dict, seqno, blkid, end_lt); -} - -bool get_old_mc_block_id(vm::AugmentedDictionary& prev_blocks_dict, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt) { - return unpack_old_mc_block_id(prev_blocks_dict.lookup(td::BitArray<32>{seqno}), seqno, blkid, end_lt); -} - -bool unpack_old_mc_block_id(Ref old_blk_info, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt) { - return old_blk_info.not_null() && old_blk_info.write().advance(1) && - block::tlb::t_ExtBlkRef.unpack(std::move(old_blk_info), blkid, end_lt) && blkid.seqno() == seqno; -} - -bool check_old_mc_block_id(vm::AugmentedDictionary* prev_blocks_dict, const ton::BlockIdExt& blkid) { - return prev_blocks_dict && check_old_mc_block_id(*prev_blocks_dict, blkid); -} - -bool check_old_mc_block_id(vm::AugmentedDictionary& prev_blocks_dict, const ton::BlockIdExt& blkid) { - if (!blkid.id.is_masterchain_ext()) { - return false; - } - ton::BlockIdExt old_blkid; - return unpack_old_mc_block_id(prev_blocks_dict.lookup(td::BitArray<32>{blkid.id.seqno}), blkid.id.seqno, old_blkid) && - old_blkid == blkid; -} - -td::Result> get_block_transaction(Ref block_root, ton::WorkchainId workchain, - const ton::StdSmcAddress& addr, ton::LogicalTime lt) { - block::gen::Block::Record block; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(std::move(block_root), block) && tlb::unpack_cell(std::move(block.info), info))) { - return td::Status::Error("cannot unpack block header"); - } - Ref trans_root; - if (lt > info.start_lt && lt < info.end_lt) { - // lt belongs to this block - block::gen::BlockExtra::Record extra; - if (!(tlb::unpack_cell(block.extra, extra))) { - return td::Status::Error("cannot unpack block extra information"); - } - vm::AugmentedDictionary account_blocks_dict{vm::load_cell_slice_ref(extra.account_blocks), 256, - block::tlb::aug_ShardAccountBlocks}; - auto ab_csr = account_blocks_dict.lookup(addr); - if (ab_csr.not_null()) { - // account block for this account exists - block::gen::AccountBlock::Record acc_block; - if (!(tlb::csr_unpack(std::move(ab_csr), acc_block) && acc_block.account_addr == addr)) { - return td::Status::Error("cannot unpack AccountBlock"); - } - vm::AugmentedDictionary trans_dict{vm::DictNonEmpty(), acc_block.transactions, 64, - block::tlb::aug_AccountTransactions}; - return trans_dict.lookup_ref(td::BitArray<64>{static_cast(lt)}); - } - } - return Ref{}; -} - -td::Result> get_block_transaction_try(Ref block_root, ton::WorkchainId workchain, - const ton::StdSmcAddress& addr, ton::LogicalTime lt) { - try { - return get_block_transaction(std::move(block_root), workchain, addr, lt); - } catch (vm::VmError err) { - return td::Status::Error(std::string{"error while extracting transaction from block : "} + err.get_msg()); - } catch (vm::VmVirtError err) { - return td::Status::Error(std::string{"virtualization error while traversing transaction proof : "} + err.get_msg()); - } -} - -bool get_transaction_in_msg(Ref trans_ref, Ref& in_msg) { - block::gen::Transaction::Record trans; - if (!tlb::unpack_cell(std::move(trans_ref), trans)) { - return false; - } else { - in_msg = trans.r1.in_msg->prefetch_ref(); - return true; - } -} - -bool is_transaction_in_msg(Ref trans_ref, Ref msg) { - Ref imsg; - return get_transaction_in_msg(std::move(trans_ref), imsg) && imsg.not_null() == msg.not_null() && - (imsg.is_null() || imsg->get_hash() == msg->get_hash()); -} - -bool is_transaction_out_msg(Ref trans_ref, Ref msg) { - block::gen::Transaction::Record trans; - vm::CellSlice cs; - unsigned long long created_lt; - if (!(trans_ref.not_null() && msg.not_null() && tlb::unpack_cell(std::move(trans_ref), trans) && cs.load_ord(msg) && - block::tlb::t_CommonMsgInfo.get_created_lt(cs, created_lt))) { - return false; - } - if (created_lt <= trans.lt || created_lt > trans.lt + trans.outmsg_cnt) { - return false; - } - try { - auto o_msg = - vm::Dictionary{trans.r1.out_msgs, 15}.lookup_ref(td::BitArray<15>{(long long)(created_lt - trans.lt - 1)}); - return o_msg.not_null() && o_msg->get_hash() == msg->get_hash(); - } catch (vm::VmError&) { - return false; - } -} - -// transaction$0111 account_addr:bits256 lt:uint64 ... -bool get_transaction_id(Ref trans_ref, ton::StdSmcAddress& account_addr, ton::LogicalTime& lt) { - if (trans_ref.is_null()) { - return false; - } - vm::CellSlice cs{vm::NoVmOrd(), trans_ref}; - return cs.fetch_ulong(4) == 7 // transaction$0111 - && cs.fetch_bits_to(account_addr) // account_addr:bits256 - && cs.fetch_uint_to(64, lt); // lt:uint64 -} - -bool get_transaction_owner(Ref trans_ref, ton::StdSmcAddress& addr) { - ton::LogicalTime lt; - return get_transaction_id(std::move(trans_ref), addr, lt); -} - -td::uint32 compute_validator_set_hash(ton::CatchainSeqno cc_seqno, ton::ShardIdFull from, - const std::vector& nodes) { - /* - std::vector> s_vec; - - for (auto& n : nodes) { - auto id = ValidatorFullId{n.key}.short_id(); - s_vec.emplace_back(create_tl_object(id, n.weight)); - } - - auto obj = create_tl_object(cc_seqno, std::move(s_vec)); - auto B = serialize_tl_object(obj, true); - return td::crc32c(B.as_slice()); - */ - CHECK(nodes.size() <= 0xffffffff); - auto tot_size = 1 + 1 + 1 + nodes.size() * (8 + 2 + 8); - auto buff = std::make_unique(tot_size); - td::TlStorerUnsafe storer(reinterpret_cast(buff.get())); - auto* begin = storer.get_buf(); - storer.store_int(-1877581587); // magic inherited from test0.validatorSet - storer.store_int(cc_seqno); - storer.store_binary((td::uint32)nodes.size()); - for (auto& n : nodes) { - storer.store_binary(n.key.as_bits256()); - storer.store_long(n.weight); - storer.store_binary(n.addr); - } - auto* end = storer.get_buf(); - CHECK(static_cast(end - begin) == 4 * tot_size); - return td::crc32c(td::Slice(begin, end)); -} - -td::Result> get_config_data_from_smc(Ref acc_root) { - if (acc_root.is_null()) { - return td::Status::Error("configuration smart contract not found or it has no state, cannot extract configuration"); - } - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record storage; - block::gen::StateInit::Record state; - if (!(tlb::unpack_cell(acc_root, acc) && tlb::csr_unpack(acc.storage, storage) && - storage.state.write().fetch_ulong(1) == 1 && tlb::csr_unpack(storage.state, state) && - state.data->have_refs(1))) { - return td::Status::Error("cannot extract persistent data from configuration smart contract state"); - } - Ref data_cell = state.data->prefetch_ref(); - auto res = vm::load_cell_slice(data_cell).prefetch_ref(); - if (res.is_null()) { - return td::Status::Error( - "configuration smart contract does not contain a valid configuration in the first reference of its persistent " - "data"); - } - return std::move(res); -} - -td::Result> get_config_data_from_smc(Ref acc_csr) { - if (acc_csr.is_null()) { - return td::Status::Error("configuration smart contract not found, cannot extract configuration"); - } - if (acc_csr->size_ext() != 0x10140) { - return td::Status::Error("configuration smart contract does not have a valid non-empty state"); - } - return get_config_data_from_smc(acc_csr->prefetch_ref()); -} - -// when these parameters change, the block must be marked as a key block -bool important_config_parameters_changed(Ref old_cfg_root, Ref new_cfg_root, bool coarse) { - if (old_cfg_root->get_hash() == new_cfg_root->get_hash()) { - return false; - } - if (coarse) { - return true; - } - // for now, all parameters are "important" - // at least the parameters affecting the computations of validator sets must be considered important - // ... - return true; -} - -bool is_public_library(td::ConstBitPtr key, Ref val) { - return val.not_null() && val->prefetch_ulong(1) == 1 && val->have_refs() && - !key.compare(val->prefetch_ref()->get_hash().bits(), 256); -} - -bool parse_hex_hash(const char* str, const char* end, td::Bits256& hash) { - if (end - str != 64) { - return false; - } - int y = 0; - for (int i = 0; i < 64; i++) { - int c = *str++, x = c - '0'; - if (x < 0) { - return false; - } else if (x > 10) { - x = (c | 0x20) - ('a' - 10); - if (x < 10 || x > 16) { - return false; - } - } - y = (y << 4) | x; - if (i & 1) { - hash.data()[i >> 1] = (unsigned char)y; - y = 0; - } - } - return true; -} - -bool parse_hex_hash(td::Slice str, td::Bits256& hash) { - return parse_hex_hash(str.begin(), str.end(), hash); -} - -bool parse_block_id_ext(const char* str, const char* end, ton::BlockIdExt& blkid) { - blkid.invalidate(); - if (!str || !end || str >= end || end - str > 255) { - return false; - } - if (*str != '(') { - return false; - } - if (!std::memchr(str, ')', end - str)) { - return false; - } - int wc, pos = 0; - unsigned seqno; - unsigned long long shard; - if (std::sscanf(str, "(%d,%llx,%u):%n", &wc, &shard, &seqno, &pos) < 3 || pos <= 0 || pos >= end - str) { - return false; - } - if (!shard || wc == ton::workchainInvalid) { - return false; - } - str += pos; - if (end - str != 64 * 2 + 1 || str[64] != ':') { - return false; - } - blkid.id = ton::BlockId{wc, shard, seqno}; - return (parse_hex_hash(str, str + 64, blkid.root_hash) && parse_hex_hash(str + 65, end, blkid.file_hash)) || - blkid.invalidate(); -} - -bool parse_block_id_ext(td::Slice str, ton::BlockIdExt& blkid) { - return parse_block_id_ext(str.begin(), str.end(), blkid); -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block.h b/submodules/ton/tonlib-src/crypto/block/block.h deleted file mode 100644 index 6c460e31..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block.h +++ /dev/null @@ -1,746 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/dict.h" -#include "vm/boc.h" -#include "vm/stack.hpp" -#include -#include "tl/tlblib.hpp" -#include "td/utils/bits.h" -#include "td/utils/CancellationToken.h" -#include "td/utils/StringBuilder.h" -#include "ton/ton-types.h" - -namespace block { - -using td::Ref; - -struct PublicKey { - std::string key; - - static td::Result from_bytes(td::Slice key); - - static td::Result parse(td::Slice key); - - std::string serialize(bool base64_url = false); -}; - -struct StdAddress { - ton::WorkchainId workchain{ton::workchainInvalid}; - bool bounceable{true}; // addresses must be bounceable by default - bool testnet{false}; - ton::StdSmcAddress addr; - StdAddress() = default; - StdAddress(ton::WorkchainId _wc, const ton::StdSmcAddress& _addr, bool _bounce = true, bool _testnet = false) - : workchain(_wc), bounceable(_bounce), testnet(_testnet), addr(_addr) { - } - StdAddress(ton::WorkchainId _wc, td::ConstBitPtr _addr, bool _bounce = true, bool _testnet = false) - : workchain(_wc), bounceable(_bounce), testnet(_testnet), addr(_addr) { - } - explicit StdAddress(std::string serialized); - explicit StdAddress(td::Slice from); - bool is_valid() const { - return workchain != ton::workchainInvalid; - } - bool invalidate() { - workchain = ton::workchainInvalid; - return false; - } - std::string rserialize(bool base64_url = false) const; - bool rserialize_to(td::MutableSlice to, bool base64_url = false) const; - bool rserialize_to(char to[48], bool base64_url = false) const; - bool rdeserialize(td::Slice from); - bool rdeserialize(std::string from); - bool rdeserialize(const char from[48]); - bool parse_addr(td::Slice acc_string); - bool operator==(const StdAddress& other) const; - - static td::Result parse(td::Slice acc_string); -}; - -inline td::StringBuilder& operator<<(td::StringBuilder& sb, const StdAddress& addr) { - return sb << addr.workchain << " : " << addr.addr.to_hex(); -} - -bool parse_std_account_addr(td::Slice acc_string, ton::WorkchainId& wc, ton::StdSmcAddress& addr, - bool* bounceable = nullptr, bool* testnet_only = nullptr); - -struct ShardId { - ton::WorkchainId workchain_id; - int shard_pfx_len; - unsigned long long shard_pfx; - ShardId(ton::WorkchainId wc_id = ton::workchainInvalid) - : workchain_id(wc_id), shard_pfx_len(0), shard_pfx(1ULL << 63) { - } - ShardId(ton::WorkchainId wc_id, unsigned long long sh_pfx); - ShardId(ton::ShardIdFull ton_shard); - ShardId(ton::BlockId ton_block); - ShardId(const ton::BlockIdExt& ton_block); - ShardId(ton::WorkchainId wc_id, unsigned long long sh_pfx, int sh_pfx_len); - ShardId(vm::CellSlice& cs) { - deserialize(cs); - } - ShardId(Ref cs_ref) { - vm::CellSlice cs{*cs_ref}; - deserialize(cs); - } - explicit operator ton::ShardIdFull() const { - return ton::ShardIdFull{workchain_id, shard_pfx}; - } - bool operator==(const ShardId& other) const { - return workchain_id == other.workchain_id && shard_pfx == other.shard_pfx; - } - void invalidate() { - workchain_id = ton::workchainInvalid; - shard_pfx_len = 0; - } - bool is_valid() const { - return workchain_id != ton::workchainInvalid; - } - void show(std::ostream& os) const; - std::string to_str() const; - bool serialize(vm::CellBuilder& cb) const; - bool deserialize(vm::CellSlice& cs); - - private: - void init(); -}; - -struct EnqueuedMsgDescr { - ton::AccountIdPrefixFull src_prefix_, cur_prefix_, next_prefix_, dest_prefix_; - ton::LogicalTime lt_; - ton::LogicalTime enqueued_lt_; - ton::Bits256 hash_; - Ref msg_; - Ref msg_env_; - EnqueuedMsgDescr() = default; - EnqueuedMsgDescr(ton::AccountIdPrefixFull cur_pfx, ton::AccountIdPrefixFull next_pfx, ton::LogicalTime lt, - ton::LogicalTime enqueued_lt, td::ConstBitPtr hash) - : cur_prefix_(cur_pfx), next_prefix_(next_pfx), lt_(lt), enqueued_lt_(enqueued_lt), hash_(hash) { - } - bool is_valid() const { - return next_prefix_.is_valid(); - } - bool check_key(td::ConstBitPtr key) const; - bool invalidate() { - next_prefix_.workchain = cur_prefix_.workchain = ton::workchainInvalid; - return false; - } - bool unpack(vm::CellSlice& cs); - bool same_workchain() const { - return cur_prefix_.workchain == next_prefix_.workchain; - } -}; - -using compute_shard_end_lt_func_t = std::function; - -struct MsgProcessedUpto { - ton::ShardId shard; - ton::BlockSeqno mc_seqno; - ton::LogicalTime last_inmsg_lt; - ton::Bits256 last_inmsg_hash; - compute_shard_end_lt_func_t compute_shard_end_lt; - MsgProcessedUpto() = default; - MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash) - : shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) { - } - bool operator<(const MsgProcessedUpto& other) const& { - return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno); - } - bool contains(const MsgProcessedUpto& other) const&; - bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash, - ton::BlockSeqno other_mc_seqno) const&; - // NB: this is for checking whether we have already imported an internal message - bool already_processed(const EnqueuedMsgDescr& msg) const; - bool can_check_processed() const { - return (bool)compute_shard_end_lt; - } - std::ostream& print(std::ostream& os) const; - std::string to_str() const; -}; - -static inline std::ostream& operator<<(std::ostream& os, const MsgProcessedUpto& proc) { - return proc.print(os); -} - -struct MsgProcessedUptoCollection { - ton::ShardIdFull owner; - bool valid{false}; - std::vector list; - MsgProcessedUptoCollection(ton::ShardIdFull _owner) : owner(_owner) { - } - MsgProcessedUptoCollection(ton::ShardIdFull _owner, Ref cs_ref); - static std::unique_ptr unpack(ton::ShardIdFull _owner, Ref cs_ref); - bool is_valid() const { - return valid; - } - bool insert(ton::BlockSeqno mc_seqno, ton::LogicalTime last_proc_lt, td::ConstBitPtr last_proc_hash); - bool insert_infty(ton::BlockSeqno mc_seqno, ton::LogicalTime last_proc_lt = ~0ULL); - bool compactify(); - bool pack(vm::CellBuilder& cb); - bool is_reduced() const; - bool contains(const MsgProcessedUpto& other) const; - bool contains(const MsgProcessedUptoCollection& other) const; - const MsgProcessedUpto* is_simple_update_of(const MsgProcessedUptoCollection& other, bool& ok) const; - ton::BlockSeqno min_mc_seqno() const; - bool split(ton::ShardIdFull new_owner); - bool combine_with(const MsgProcessedUptoCollection& other); - // NB: this is for checking whether we have already imported an internal message - bool already_processed(const EnqueuedMsgDescr& msg) const; - bool can_check_processed() const; - bool for_each_mcseqno(std::function) const; - std::ostream& print(std::ostream& os) const; - std::string to_str() const; -}; - -static inline std::ostream& operator<<(std::ostream& os, const MsgProcessedUptoCollection& proc_coll) { - return proc_coll.print(os); -} - -struct ParamLimits { - enum { limits_cnt = 4 }; - enum { cl_underload = 0, cl_normal = 1, cl_soft = 2, cl_medium = 3, cl_hard = 4 }; - ParamLimits() = default; - ParamLimits(td::uint32 underload, td::uint32 soft_lim, td::uint32 hard_lim) - : limits_{underload, soft_lim, (soft_lim + hard_lim) / 2, hard_lim} { - } - td::uint32 underload() const { - return limits_[0]; - } - td::uint32 soft() const { - return limits_[1]; - } - td::uint32 hard() const { - return limits_[3]; - } - bool compute_medium_limit() { - limits_[2] = soft() + ((hard() - soft()) >> 1); - return true; - } - bool deserialize(vm::CellSlice& cs); - int classify(td::uint64 value) const; - bool fits(unsigned cls, td::uint64 value) const; - - private: - std::array limits_; -}; - -struct BlockLimits { - ParamLimits bytes, gas, lt_delta; - ton::LogicalTime start_lt{0}; - const vm::CellUsageTree* usage_tree{nullptr}; - bool deserialize(vm::CellSlice& cs); - int classify_size(td::uint64 size) const; - int classify_gas(td::uint64 gas) const; - int classify_lt(ton::LogicalTime lt) const; - int classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const; - bool fits(unsigned cls, td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const; -}; - -struct BlockLimitStatus { - const BlockLimits& limits; - ton::LogicalTime cur_lt; - td::uint64 gas_used{}; - vm::NewCellStorageStat st_stat; - unsigned accounts{}, transactions{}; - BlockLimitStatus(const BlockLimits& limits_, ton::LogicalTime lt = 0) - : limits(limits_), cur_lt(std::max(limits_.start_lt, lt)) { - } - void reset() { - cur_lt = limits.start_lt; - st_stat.set_zero(); - transactions = accounts = 0; - gas_used = 0; - } - td::uint64 estimate_block_size(const vm::NewCellStorageStat::Stat* extra = nullptr) const; - int classify() const; - bool fits(unsigned cls) const; - bool would_fit(unsigned cls, ton::LogicalTime end_lt, td::uint64 more_gas, - const vm::NewCellStorageStat::Stat* extra = nullptr) const; - bool add_cell(Ref cell) { - st_stat.add_cell(std::move(cell)); - return true; - } - bool add_proof(Ref cell) { - st_stat.add_proof(std::move(cell), limits.usage_tree); - return true; - } - bool update_lt(ton::LogicalTime lt) { - cur_lt = std::max(lt, cur_lt); - return true; - } - bool update_gas(td::uint64 more_gas) { - gas_used += more_gas; - return true; - } - bool add_transaction(unsigned cnt = 1) { - transactions += cnt; - return true; - } - bool add_account(unsigned cnt = 1) { - accounts += cnt; - return true; - } -}; - -namespace tlb { -struct CurrencyCollection; -} // namespace tlb - -struct CurrencyCollection { - using type_class = block::tlb::CurrencyCollection; - td::RefInt256 grams; - Ref extra; - CurrencyCollection() = default; - explicit CurrencyCollection(td::RefInt256 _grams, Ref _extra = {}) - : grams(std::move(_grams)), extra(std::move(_extra)) { - } - explicit CurrencyCollection(long long _grams, Ref _extra = {}) - : grams(true, _grams), extra(std::move(_extra)) { - } - bool set_zero() { - grams = td::RefInt256{true, 0}; - extra.clear(); - return true; - } - static CurrencyCollection zero() { - return CurrencyCollection(td::RefInt256{true, 0}); - } - bool is_valid() const { - return grams.not_null(); - } - bool is_zero() const { - return is_valid() && extra.is_null() && !td::sgn(grams); - } - bool has_extra() const { - return extra.not_null(); - } - bool invalidate() { - extra.clear(); - grams.clear(); - return false; - } - bool validate(int max_cells = 1024) const; - bool validate_extra(int max_cells = 1024) const; - bool operator==(const CurrencyCollection& other) const; - bool operator!=(const CurrencyCollection& other) const { - return !operator==(other); - } - bool operator==(td::RefInt256 other_grams) const { - return is_valid() && !has_extra() && !td::cmp(grams, other_grams); - } - bool operator!=(td::RefInt256 other_grams) const { - return !operator==(std::move(other_grams)); - } - bool operator>=(const CurrencyCollection& other) const; - bool operator<=(const CurrencyCollection& other) const { - return other >= *this; - } - static bool add(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c); - static bool add(const CurrencyCollection& a, CurrencyCollection&& b, CurrencyCollection& c); - CurrencyCollection& operator+=(const CurrencyCollection& other); - CurrencyCollection& operator+=(CurrencyCollection&& other); - CurrencyCollection& operator+=(td::RefInt256 other_grams); - CurrencyCollection operator+(const CurrencyCollection& other) const; - CurrencyCollection operator+(CurrencyCollection&& other) const; - CurrencyCollection operator+(td::RefInt256 other_grams); - static bool sub(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c); - static bool sub(const CurrencyCollection& a, CurrencyCollection&& b, CurrencyCollection& c); - CurrencyCollection& operator-=(const CurrencyCollection& other); - CurrencyCollection& operator-=(CurrencyCollection&& other); - CurrencyCollection& operator-=(td::RefInt256 other_grams); - CurrencyCollection operator-(const CurrencyCollection& other) const; - CurrencyCollection operator-(CurrencyCollection&& other) const; - CurrencyCollection operator-(td::RefInt256 other_grams) const; - bool store(vm::CellBuilder& cb) const; - bool store_or_zero(vm::CellBuilder& cb) const; - bool fetch(vm::CellSlice& cs); - bool fetch_exact(vm::CellSlice& cs); - bool unpack(Ref csr); - bool validate_unpack(Ref csr, int max_cells = 1024); - Ref pack() const; - bool pack_to(Ref& csr) const { - return (csr = pack()).not_null(); - } - Ref as_vm_tuple() const { - if (is_valid()) { - return vm::make_tuple_ref(grams, vm::StackEntry::maybe(extra)); - } else { - return {}; - } - } - bool show(std::ostream& os) const; - std::string to_str() const; -}; - -std::ostream& operator<<(std::ostream& os, const CurrencyCollection& cc); - -struct ShardState { - enum { verbosity = 0 }; - ton::BlockIdExt id_; - Ref root_; - int global_id_; - ton::UnixTime utime_; - ton::LogicalTime lt_; - ton::BlockSeqno mc_blk_seqno_, min_ref_mc_seqno_, vert_seqno_; - ton::BlockIdExt mc_blk_ref_; - ton::LogicalTime mc_blk_lt_; - bool before_split_{false}; - std::unique_ptr account_dict_; - std::unique_ptr shard_libraries_; - Ref mc_state_extra_; - td::uint64 overload_history_{0}, underload_history_{0}; - CurrencyCollection total_balance_, total_validator_fees_, global_balance_; - std::unique_ptr out_msg_queue_; - std::unique_ptr ihr_pending_; - std::unique_ptr block_create_stats_; - std::shared_ptr processed_upto_; - - bool is_valid() const { - return id_.is_valid(); - } - bool is_masterchain() const { - return id_.is_masterchain(); - } - bool invalidate() { - id_.invalidate(); - return false; - } - td::Status unpack_state(ton::BlockIdExt id, Ref state_root); - td::Status unpack_state_ext(ton::BlockIdExt id, Ref state_root, int global_id, - ton::BlockSeqno prev_mc_block_seqno, bool after_split, bool clear_history, - std::function for_each_mcseqno); - td::Status merge_with(ShardState& sib); - td::Result> compute_split_out_msg_queue(ton::ShardIdFull subshard); - td::Result> compute_split_processed_upto( - ton::ShardIdFull subshard); - td::Status split(ton::ShardIdFull subshard); - td::Status unpack_out_msg_queue_info(Ref out_msg_queue_info); - bool clear_load_history() { - overload_history_ = underload_history_ = 0; - return true; - } - bool clear_load_history_if(bool cond) { - return !cond || clear_load_history(); - } - td::Status check_before_split(bool before_split) const; - td::Status check_global_id(int req_global_id) const; - td::Status check_mc_blk_seqno(ton::BlockSeqno last_mc_block_seqno) const; - bool update_prev_utime_lt(ton::UnixTime& prev_utime, ton::LogicalTime& prev_lt) const; - - bool for_each_mcseqno(std::function func) const { - return processed_upto_ && processed_upto_->for_each_mcseqno(std::move(func)); - } -}; - -struct ValueFlow { - struct SetZero {}; - CurrencyCollection from_prev_blk, to_next_blk, imported, exported, fees_collected, fees_imported, recovered, created, - minted; - ValueFlow() = default; - ValueFlow(SetZero) - : from_prev_blk{0} - , to_next_blk{0} - , imported{0} - , exported{0} - , fees_collected{0} - , fees_imported{0} - , recovered{0} - , created{0} - , minted{0} { - } - bool is_valid() const { - return from_prev_blk.is_valid() && minted.is_valid(); - } - bool validate() const; - bool invalidate() { - return from_prev_blk.invalidate(); - } - bool set_zero(); - bool store(vm::CellBuilder& cb) const; - bool fetch(vm::CellSlice& cs); - bool unpack(Ref csr); - bool show(std::ostream& os) const; - std::string to_str() const; - - private: - bool show_one(std::ostream& os, const char* str, const CurrencyCollection& cc) const; -}; - -std::ostream& operator<<(std::ostream& os, const ValueFlow& vflow); - -struct DiscountedCounter { - struct SetZero {}; - bool valid; - ton::UnixTime last_updated; - td::uint64 total; - td::uint64 cnt2048; - td::uint64 cnt65536; - DiscountedCounter() : valid(false) { - } - DiscountedCounter(SetZero) : valid(true), last_updated(0), total(0), cnt2048(0), cnt65536(0) { - } - DiscountedCounter(ton::UnixTime _lastupd, td::uint64 _total, td::uint64 _cnt2048, td::uint64 _cnt65536) - : valid(true), last_updated(_lastupd), total(_total), cnt2048(_cnt2048), cnt65536(_cnt65536) { - } - static DiscountedCounter Zero() { - return SetZero(); - } - bool is_valid() const { - return valid; - } - bool invalidate() { - return (valid = false); - } - bool set_zero() { - last_updated = 0; - total = cnt2048 = cnt65536 = 0; - return (valid = true); - } - bool is_zero() const { - return !total; - } - bool almost_zero() const { - return (cnt2048 | cnt65536) <= 1; - } - bool operator==(const DiscountedCounter& other) const { - return last_updated == other.last_updated && total == other.total && cnt2048 == other.cnt2048 && - cnt65536 == other.cnt65536; - } - bool almost_equals(const DiscountedCounter& other) const { - return last_updated == other.last_updated && total == other.total && cnt2048 <= other.cnt2048 + 1 && - other.cnt2048 <= cnt2048 + 1 && cnt65536 <= other.cnt65536 + 1 && other.cnt65536 <= cnt65536 + 1; - } - bool modified_since(ton::UnixTime utime) const { - return last_updated >= utime; - } - bool validate(); - bool increase_by(unsigned count, ton::UnixTime now); - bool fetch(vm::CellSlice& cs); - bool unpack(Ref csr); - bool store(vm::CellBuilder& cb) const; - Ref pack() const; - bool show(std::ostream& os) const; - std::string to_str() const; -}; - -static inline std::ostream& operator<<(std::ostream& os, const DiscountedCounter& dcount) { - dcount.show(os); - return os; -} - -bool fetch_CreatorStats(vm::CellSlice& cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt); -bool store_CreatorStats(vm::CellBuilder& cb, const DiscountedCounter& mc_cnt, const DiscountedCounter& shard_cnt); -bool unpack_CreatorStats(Ref cs, DiscountedCounter& mc_cnt, DiscountedCounter& shard_cnt); - -struct BlockProofLink { - ton::BlockIdExt from, to; - bool is_key{false}, is_fwd{false}; - Ref dest_proof, state_proof, proof; - ton::CatchainSeqno cc_seqno{0}; - td::uint32 validator_set_hash{0}; - std::vector signatures; - BlockProofLink(ton::BlockIdExt _from, ton::BlockIdExt _to, bool _iskey = false) - : from(_from), to(_to), is_key(_iskey), is_fwd(to.seqno() > from.seqno()) { - } - bool incomplete() const { - return dest_proof.is_null(); - } - td::Status validate(td::uint32* save_utime = nullptr) const; -}; - -struct BlockProofChain { - ton::BlockIdExt from, to; - int mode; - td::uint32 last_utime{0}; - bool complete{false}, has_key_block{false}, has_utime{false}, valid{false}; - ton::BlockIdExt key_blkid; - std::vector links; - std::size_t link_count() const { - return links.size(); - } - BlockProofChain(ton::BlockIdExt _from, ton::BlockIdExt _to, int _mode = 0) : from(_from), to(_to), mode(_mode) { - } - BlockProofLink& new_link(const ton::BlockIdExt& cur, const ton::BlockIdExt& next, bool iskey = false) { - links.emplace_back(cur, next, iskey); - return links.back(); - } - const BlockProofLink& last_link() const { - return links.back(); - } - BlockProofLink& last_link() { - return links.back(); - } - bool last_link_incomplete() const { - return !links.empty() && last_link().incomplete(); - } - td::Status validate(td::CancellationToken cancellation_token = {}); -}; - -// compute the share of shardchain blocks generated by each validator using Monte Carlo method -class MtCarloComputeShare { - int K, N; - long long iterations; - std::vector W; - std::vector CW, RW; - std::vector> H; - std::vector A; - double R0; - bool ok; - - public: - MtCarloComputeShare(int subset_size, const std::vector& weights, long long iteration_count = 1000000) - : K(subset_size), N((int)weights.size()), iterations(iteration_count), W(weights), ok(false) { - compute(); - } - MtCarloComputeShare(int subset_size, int set_size, const double* weights, long long iteration_count = 1000000) - : K(subset_size), N(set_size), iterations(iteration_count), W(weights, weights + set_size), ok(false) { - compute(); - } - bool is_ok() const { - return ok; - } - const double* share_array() const { - return ok ? RW.data() : nullptr; - } - const double* weights_array() const { - return ok ? W.data() : nullptr; - } - double operator[](int i) const { - return ok ? RW.at(i) : -1.; - } - double share(int i) const { - return ok ? RW.at(i) : -1.; - } - double weight(int i) const { - return ok ? W.at(i) : -1.; - } - int size() const { - return N; - } - int subset_size() const { - return K; - } - long long performed_iterations() const { - return iterations; - } - - private: - bool set_error() { - return ok = false; - } - bool compute(); - void gen_vset(); -}; - -int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard); - -std::ostream& operator<<(std::ostream& os, const ShardId& shard_id); - -bool pack_std_smc_addr_to(char result[48], bool base64_url, ton::WorkchainId wc, const ton::StdSmcAddress& addr, - bool bounceable, bool testnet); -std::string pack_std_smc_addr(bool base64_url, ton::WorkchainId wc, const ton::StdSmcAddress& addr, bool bounceable, - bool testnet); -bool unpack_std_smc_addr(const char packed[48], ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet); -bool unpack_std_smc_addr(td::Slice packed, ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet); -bool unpack_std_smc_addr(std::string packed, ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool& bounceable, - bool& testnet); - -bool store_UInt7(vm::CellBuilder& cb, unsigned long long value); -bool store_UInt7(vm::CellBuilder& cb, unsigned long long value1, unsigned long long value2); -bool store_Maybe_Grams(vm::CellBuilder& cb, td::RefInt256 value); -bool store_Maybe_Grams_nz(vm::CellBuilder& cb, td::RefInt256 value); -bool store_CurrencyCollection(vm::CellBuilder& cb, td::RefInt256 value, Ref extra); -bool fetch_CurrencyCollection(vm::CellSlice& cs, td::RefInt256& value, Ref& extra, bool inexact = false); -bool unpack_CurrencyCollection(Ref csr, td::RefInt256& value, Ref& extra); - -bool valid_library_collection(Ref cell, bool catch_errors = true); - -bool valid_config_data(Ref cell, const td::BitArray<256>& addr, bool catch_errors = true, - bool relax_par0 = false, Ref old_mparams = {}); -bool config_params_present(vm::Dictionary& dict, Ref param_dict_root); - -bool add_extra_currency(Ref extra1, Ref extra2, Ref& res); -bool sub_extra_currency(Ref extra1, Ref extra2, Ref& res); - -ton::AccountIdPrefixFull interpolate_addr(const ton::AccountIdPrefixFull& src, const ton::AccountIdPrefixFull& dest, - int used_dest_bits); -bool interpolate_addr_to(const ton::AccountIdPrefixFull& src, const ton::AccountIdPrefixFull& dest, int used_dest_bits, - ton::AccountIdPrefixFull& res); -// result: (transit_addr_dest_bits, nh_addr_dest_bits) -std::pair perform_hypercube_routing(ton::AccountIdPrefixFull src, ton::AccountIdPrefixFull dest, - ton::ShardIdFull cur, int used_dest_bits = 0); - -bool compute_out_msg_queue_key(Ref msg_env, td::BitArray<352>& key); - -bool unpack_block_prev_blk(Ref block_root, const ton::BlockIdExt& id, std::vector& prev, - ton::BlockIdExt& mc_blkid, bool& after_split, ton::BlockIdExt* fetch_blkid = nullptr); -td::Status unpack_block_prev_blk_ext(Ref block_root, const ton::BlockIdExt& id, - std::vector& prev, ton::BlockIdExt& mc_blkid, bool& after_split, - ton::BlockIdExt* fetch_blkid = nullptr); -td::Status unpack_block_prev_blk_try(Ref block_root, const ton::BlockIdExt& id, - std::vector& prev, ton::BlockIdExt& mc_blkid, bool& after_split, - ton::BlockIdExt* fetch_blkid = nullptr); -td::Status check_block_header(Ref block_root, const ton::BlockIdExt& id, - ton::Bits256* store_shard_hash_to = nullptr); - -std::unique_ptr get_block_create_stats_dict(Ref state_root); - -std::unique_ptr get_prev_blocks_dict(Ref state_root); -bool get_old_mc_block_id(vm::AugmentedDictionary* prev_blocks_dict, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt = nullptr); -bool get_old_mc_block_id(vm::AugmentedDictionary& prev_blocks_dict, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt = nullptr); -bool unpack_old_mc_block_id(Ref old_blk_info, ton::BlockSeqno seqno, ton::BlockIdExt& blkid, - ton::LogicalTime* end_lt = nullptr); -bool check_old_mc_block_id(vm::AugmentedDictionary* prev_blocks_dict, const ton::BlockIdExt& blkid); -bool check_old_mc_block_id(vm::AugmentedDictionary& prev_blocks_dict, const ton::BlockIdExt& blkid); - -td::Result> get_block_transaction(Ref block_root, ton::WorkchainId workchain, - const ton::StdSmcAddress& addr, ton::LogicalTime lt); -td::Result> get_block_transaction_try(Ref block_root, ton::WorkchainId workchain, - const ton::StdSmcAddress& addr, ton::LogicalTime lt); - -bool get_transaction_in_msg(Ref trans_ref, Ref& in_msg); -bool is_transaction_in_msg(Ref trans_ref, Ref msg); -bool is_transaction_out_msg(Ref trans_ref, Ref msg); -bool get_transaction_id(Ref trans_ref, ton::StdSmcAddress& account_addr, ton::LogicalTime& lt); -bool get_transaction_owner(Ref trans_ref, ton::StdSmcAddress& addr); - -td::uint32 compute_validator_set_hash(ton::CatchainSeqno cc_seqno, ton::ShardIdFull from, - const std::vector& nodes); - -td::Result> get_config_data_from_smc(Ref acc_root); -td::Result> get_config_data_from_smc(Ref acc_csr); -bool important_config_parameters_changed(Ref old_cfg_root, Ref new_cfg_root, bool coarse = false); - -bool is_public_library(td::ConstBitPtr key, Ref val); - -bool parse_hex_hash(const char* str, const char* end, td::Bits256& hash); -bool parse_hex_hash(td::Slice str, td::Bits256& hash); - -bool parse_block_id_ext(const char* str, const char* end, ton::BlockIdExt& blkid); -bool parse_block_id_ext(td::Slice str, ton::BlockIdExt& blkid); - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/block.tlb b/submodules/ton/tonlib-src/crypto/block/block.tlb deleted file mode 100644 index 5f122d9d..00000000 --- a/submodules/ton/tonlib-src/crypto/block/block.tlb +++ /dev/null @@ -1,840 +0,0 @@ -unit$_ = Unit; -true$_ = True; -// EMPTY False; -bool_false$0 = Bool; -bool_true$1 = Bool; -bool_false$0 = BoolFalse; -bool_true$1 = BoolTrue; -nothing$0 {X:Type} = Maybe X; -just$1 {X:Type} value:X = Maybe X; -left$0 {X:Type} {Y:Type} value:X = Either X Y; -right$1 {X:Type} {Y:Type} value:Y = Either X Y; -pair$_ {X:Type} {Y:Type} first:X second:Y = Both X Y; - -bit$_ (## 1) = Bit; -/* - * - * FROM hashmap.tlb - * - */ -// ordinary Hashmap / HashmapE, with fixed length keys -// -hm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X; - -hmn_leaf#_ {X:Type} value:X = HashmapNode 0 X; -hmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X) - right:^(Hashmap n X) = HashmapNode (n + 1) X; - -hml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m; -hml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m; -hml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m; - -unary_zero$0 = Unary ~0; -unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1); - -hme_empty$0 {n:#} {X:Type} = HashmapE n X; -hme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X; - -// true#_ = True; -_ {n:#} _:(Hashmap n True) = BitstringSet n; - -// HashmapAug, hashmap with an extra value -// (augmentation) of type Y at every node -// -ahm_edge#_ {n:#} {X:Type} {Y:Type} {l:#} {m:#} - label:(HmLabel ~l n) {n = (~m) + l} - node:(HashmapAugNode m X Y) = HashmapAug n X Y; -ahmn_leaf#_ {X:Type} {Y:Type} extra:Y value:X = HashmapAugNode 0 X Y; -ahmn_fork#_ {n:#} {X:Type} {Y:Type} left:^(HashmapAug n X Y) - right:^(HashmapAug n X Y) extra:Y = HashmapAugNode (n + 1) X Y; - -ahme_empty$0 {n:#} {X:Type} {Y:Type} extra:Y - = HashmapAugE n X Y; -ahme_root$1 {n:#} {X:Type} {Y:Type} root:^(HashmapAug n X Y) - extra:Y = HashmapAugE n X Y; - -// VarHashmap / VarHashmapE, with variable-length keys -// -vhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(VarHashmapNode m X) - = VarHashmap n X; -vhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X; -vhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X) - right:^(VarHashmap n X) value:(Maybe X) - = VarHashmapNode (n + 1) X; -vhmn_cont$1 {n:#} {X:Type} branch:Bit child:^(VarHashmap n X) - value:X = VarHashmapNode (n + 1) X; - -// nothing$0 {X:Type} = Maybe X; -// just$1 {X:Type} value:X = Maybe X; - -vhme_empty$0 {n:#} {X:Type} = VarHashmapE n X; -vhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X) - = VarHashmapE n X; - -// -// PfxHashmap / PfxHashmapE, with variable-length keys -// constituting a prefix code -// - -phm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(PfxHashmapNode m X) - = PfxHashmap n X; - -phmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X; -phmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X) - right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X; - -phme_empty$0 {n:#} {X:Type} = PfxHashmapE n X; -phme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X) - = PfxHashmapE n X; -/* - * - * END hashmap.tlb - * - */ -// -// TON BLOCK LAYOUT -// -addr_none$00 = MsgAddressExt; -addr_extern$01 len:(## 9) external_address:(bits len) - = MsgAddressExt; -anycast_info$_ depth:(#<= 30) { depth >= 1 } - rewrite_pfx:(bits depth) = Anycast; -addr_std$10 anycast:(Maybe Anycast) - workchain_id:int8 address:bits256 = MsgAddressInt; -addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) - workchain_id:int32 address:(bits addr_len) = MsgAddressInt; -_ _:MsgAddressInt = MsgAddress; -_ _:MsgAddressExt = MsgAddress; -// -var_uint$_ {n:#} len:(#< n) value:(uint (len * 8)) - = VarUInteger n; -var_int$_ {n:#} len:(#< n) value:(int (len * 8)) - = VarInteger n; -nanograms$_ amount:(VarUInteger 16) = Grams; -// -extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32)) - = ExtraCurrencyCollection; -currencies$_ grams:Grams other:ExtraCurrencyCollection - = CurrencyCollection; -// -int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - src:MsgAddressInt dest:MsgAddressInt - value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - created_lt:uint64 created_at:uint32 = CommonMsgInfo; -ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt - import_fee:Grams = CommonMsgInfo; -ext_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt - created_lt:uint64 created_at:uint32 = CommonMsgInfo; - -int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - src:MsgAddress dest:MsgAddressInt - value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; -ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt - created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; - -tick_tock$_ tick:Bool tock:Bool = TickTock; - -_ split_depth:(Maybe (## 5)) special:(Maybe TickTock) - code:(Maybe ^Cell) data:(Maybe ^Cell) - library:(HashmapE 256 SimpleLib) = StateInit; - -simple_lib$_ public:Bool root:^Cell = SimpleLib; - -message$_ {X:Type} info:CommonMsgInfo - init:(Maybe (Either StateInit ^StateInit)) - body:(Either X ^X) = Message X; - -message$_ {X:Type} info:CommonMsgInfoRelaxed - init:(Maybe (Either StateInit ^StateInit)) - body:(Either X ^X) = MessageRelaxed X; - -_ (Message Any) = MessageAny; - -// -interm_addr_regular$0 use_dest_bits:(#<= 96) - = IntermediateAddress; -interm_addr_simple$10 workchain_id:int8 addr_pfx:uint64 - = IntermediateAddress; -interm_addr_ext$11 workchain_id:int32 addr_pfx:uint64 - = IntermediateAddress; -msg_envelope#4 cur_addr:IntermediateAddress - next_addr:IntermediateAddress fwd_fee_remaining:Grams - msg:^(Message Any) = MsgEnvelope; -// -msg_import_ext$000 msg:^(Message Any) transaction:^Transaction - = InMsg; -msg_import_ihr$010 msg:^(Message Any) transaction:^Transaction - ihr_fee:Grams proof_created:^Cell = InMsg; -msg_import_imm$011 in_msg:^MsgEnvelope - transaction:^Transaction fwd_fee:Grams = InMsg; -msg_import_fin$100 in_msg:^MsgEnvelope - transaction:^Transaction fwd_fee:Grams = InMsg; -msg_import_tr$101 in_msg:^MsgEnvelope out_msg:^MsgEnvelope - transit_fee:Grams = InMsg; -msg_discard_fin$110 in_msg:^MsgEnvelope transaction_id:uint64 - fwd_fee:Grams = InMsg; -msg_discard_tr$111 in_msg:^MsgEnvelope transaction_id:uint64 - fwd_fee:Grams proof_delivered:^Cell = InMsg; -// -import_fees$_ fees_collected:Grams - value_imported:CurrencyCollection = ImportFees; - -_ (HashmapAugE 256 InMsg ImportFees) = InMsgDescr; - -msg_export_ext$000 msg:^(Message Any) - transaction:^Transaction = OutMsg; -msg_export_imm$010 out_msg:^MsgEnvelope - transaction:^Transaction reimport:^InMsg = OutMsg; -msg_export_new$001 out_msg:^MsgEnvelope - transaction:^Transaction = OutMsg; -msg_export_tr$011 out_msg:^MsgEnvelope - imported:^InMsg = OutMsg; -msg_export_deq$1100 out_msg:^MsgEnvelope - import_block_lt:uint63 = OutMsg; -msg_export_deq_short$1101 msg_env_hash:bits256 - next_workchain:int32 next_addr_pfx:uint64 - import_block_lt:uint64 = OutMsg; -msg_export_tr_req$111 out_msg:^MsgEnvelope - imported:^InMsg = OutMsg; -msg_export_deq_imm$100 out_msg:^MsgEnvelope - reimport:^InMsg = OutMsg; - -_ enqueued_lt:uint64 out_msg:^MsgEnvelope = EnqueuedMsg; - -_ (HashmapAugE 256 OutMsg CurrencyCollection) = OutMsgDescr; - -_ (HashmapAugE 352 EnqueuedMsg uint64) = OutMsgQueue; - -processed_upto$_ last_msg_lt:uint64 last_msg_hash:bits256 = ProcessedUpto; -// key is [ shard:uint64 mc_seqno:uint32 ] -_ (HashmapE 96 ProcessedUpto) = ProcessedInfo; - -ihr_pending$_ import_lt:uint64 = IhrPendingSince; -_ (HashmapE 320 IhrPendingSince) = IhrPendingInfo; - -_ out_queue:OutMsgQueue proc_info:ProcessedInfo - ihr_pending:IhrPendingInfo = OutMsgQueueInfo; -// -storage_used$_ cells:(VarUInteger 7) bits:(VarUInteger 7) - public_cells:(VarUInteger 7) = StorageUsed; - -storage_used_short$_ cells:(VarUInteger 7) - bits:(VarUInteger 7) = StorageUsedShort; - -storage_info$_ used:StorageUsed last_paid:uint32 - due_payment:(Maybe Grams) = StorageInfo; - -account_none$0 = Account; -account$1 addr:MsgAddressInt storage_stat:StorageInfo - storage:AccountStorage = Account; - -account_storage$_ last_trans_lt:uint64 - balance:CurrencyCollection state:AccountState - = AccountStorage; - -account_uninit$00 = AccountState; -account_active$1 _:StateInit = AccountState; -account_frozen$01 state_hash:bits256 = AccountState; - -acc_state_uninit$00 = AccountStatus; -acc_state_frozen$01 = AccountStatus; -acc_state_active$10 = AccountStatus; -acc_state_nonexist$11 = AccountStatus; - -/* duplicates -tick_tock$_ tick:Bool tock:Bool = TickTock; - -_ split_depth:(Maybe (## 5)) special:(Maybe TickTock) - code:(Maybe ^Cell) data:(Maybe ^Cell) - library:(Maybe ^Cell) = StateInit; -*/ - -account_descr$_ account:^Account last_trans_hash:bits256 - last_trans_lt:uint64 = ShardAccount; - -depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection = DepthBalanceInfo; - -_ (HashmapAugE 256 ShardAccount DepthBalanceInfo) = ShardAccounts; - -transaction$0111 account_addr:bits256 lt:uint64 - prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 - outmsg_cnt:uint15 - orig_status:AccountStatus end_status:AccountStatus - ^[ in_msg:(Maybe ^(Message Any)) out_msgs:(HashmapE 15 ^(Message Any)) ] - total_fees:CurrencyCollection state_update:^(HASH_UPDATE Account) - description:^TransactionDescr = Transaction; - -!merkle_update#02 {X:Type} old_hash:bits256 new_hash:bits256 - old:^X new:^X = MERKLE_UPDATE X; -update_hashes#72 {X:Type} old_hash:bits256 new_hash:bits256 - = HASH_UPDATE X; -!merkle_proof#03 {X:Type} virtual_hash:bits256 depth:uint16 virtual_root:^X = MERKLE_PROOF X; - -acc_trans#5 account_addr:bits256 - transactions:(HashmapAug 64 ^Transaction CurrencyCollection) - state_update:^(HASH_UPDATE Account) - = AccountBlock; - -_ (HashmapAugE 256 AccountBlock CurrencyCollection) = ShardAccountBlocks; -// -tr_phase_storage$_ storage_fees_collected:Grams - storage_fees_due:(Maybe Grams) - status_change:AccStatusChange - = TrStoragePhase; - -acst_unchanged$0 = AccStatusChange; // x -> x -acst_frozen$10 = AccStatusChange; // init -> frozen -acst_deleted$11 = AccStatusChange; // frozen -> deleted - -tr_phase_credit$_ due_fees_collected:(Maybe Grams) - credit:CurrencyCollection = TrCreditPhase; - -tr_phase_compute_skipped$0 reason:ComputeSkipReason - = TrComputePhase; -tr_phase_compute_vm$1 success:Bool msg_state_used:Bool - account_activated:Bool gas_fees:Grams - ^[ gas_used:(VarUInteger 7) - gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3)) - mode:int8 exit_code:int32 exit_arg:(Maybe int32) - vm_steps:uint32 - vm_init_state_hash:bits256 vm_final_state_hash:bits256 ] - = TrComputePhase; -cskip_no_state$00 = ComputeSkipReason; -cskip_bad_state$01 = ComputeSkipReason; -cskip_no_gas$10 = ComputeSkipReason; - -tr_phase_action$_ success:Bool valid:Bool no_funds:Bool - status_change:AccStatusChange - total_fwd_fees:(Maybe Grams) total_action_fees:(Maybe Grams) - result_code:int32 result_arg:(Maybe int32) tot_actions:uint16 - spec_actions:uint16 skipped_actions:uint16 msgs_created:uint16 - action_list_hash:bits256 tot_msg_size:StorageUsedShort - = TrActionPhase; - -tr_phase_bounce_negfunds$00 = TrBouncePhase; -tr_phase_bounce_nofunds$01 msg_size:StorageUsedShort - req_fwd_fees:Grams = TrBouncePhase; -tr_phase_bounce_ok$1 msg_size:StorageUsedShort - msg_fees:Grams fwd_fees:Grams = TrBouncePhase; -// -trans_ord$0000 credit_first:Bool - storage_ph:(Maybe TrStoragePhase) - credit_ph:(Maybe TrCreditPhase) - compute_ph:TrComputePhase action:(Maybe ^TrActionPhase) - aborted:Bool bounce:(Maybe TrBouncePhase) - destroyed:Bool - = TransactionDescr; - -trans_storage$0001 storage_ph:TrStoragePhase - = TransactionDescr; - -trans_tick_tock$001 is_tock:Bool storage_ph:TrStoragePhase - compute_ph:TrComputePhase action:(Maybe ^TrActionPhase) - aborted:Bool destroyed:Bool = TransactionDescr; -// -split_merge_info$_ cur_shard_pfx_len:(## 6) - acc_split_depth:(## 6) this_addr:bits256 sibling_addr:bits256 - = SplitMergeInfo; -trans_split_prepare$0100 split_info:SplitMergeInfo - storage_ph:(Maybe TrStoragePhase) - compute_ph:TrComputePhase action:(Maybe ^TrActionPhase) - aborted:Bool destroyed:Bool - = TransactionDescr; -trans_split_install$0101 split_info:SplitMergeInfo - prepare_transaction:^Transaction - installed:Bool = TransactionDescr; - -trans_merge_prepare$0110 split_info:SplitMergeInfo - storage_ph:TrStoragePhase aborted:Bool - = TransactionDescr; -trans_merge_install$0111 split_info:SplitMergeInfo - prepare_transaction:^Transaction - storage_ph:(Maybe TrStoragePhase) - credit_ph:(Maybe TrCreditPhase) - compute_ph:TrComputePhase action:(Maybe ^TrActionPhase) - aborted:Bool destroyed:Bool - = TransactionDescr; - -smc_info#076ef1ea actions:uint16 msgs_sent:uint16 - unixtime:uint32 block_lt:uint64 trans_lt:uint64 - rand_seed:bits256 balance_remaining:CurrencyCollection - myself:MsgAddressInt = SmartContractInfo; -// -// -out_list_empty$_ = OutList 0; -out_list$_ {n:#} prev:^(OutList n) action:OutAction - = OutList (n + 1); -action_send_msg#0ec3c86d mode:(## 8) - out_msg:^(MessageRelaxed Any) = OutAction; -action_set_code#ad4de08e new_code:^Cell = OutAction; -action_reserve_currency#36e6b809 mode:(## 8) - currency:CurrencyCollection = OutAction; -libref_hash$0 lib_hash:bits256 = LibRef; -libref_ref$1 library:^Cell = LibRef; -action_change_library#26fa1dd4 mode:(## 7) { mode <= 2 } - libref:LibRef = OutAction; - -out_list_node$_ prev:^Cell action:OutAction = OutListNode; -// -// -shard_ident$00 shard_pfx_bits:(#<= 60) - workchain_id:int32 shard_prefix:uint64 = ShardIdent; - -ext_blk_ref$_ end_lt:uint64 - seq_no:uint32 root_hash:bits256 file_hash:bits256 - = ExtBlkRef; - -block_id_ext$_ shard_id:ShardIdent seq_no:uint32 - root_hash:bits256 file_hash:bits256 = BlockIdExt; - -master_info$_ master:ExtBlkRef = BlkMasterInfo; - -shard_state#9023afe2 global_id:int32 - shard_id:ShardIdent - seq_no:uint32 vert_seq_no:# - gen_utime:uint32 gen_lt:uint64 - min_ref_mc_seqno:uint32 - out_msg_queue_info:^OutMsgQueueInfo - before_split:(## 1) - accounts:^ShardAccounts - ^[ overload_history:uint64 underload_history:uint64 - total_balance:CurrencyCollection - total_validator_fees:CurrencyCollection - libraries:(HashmapE 256 LibDescr) - master_ref:(Maybe BlkMasterInfo) ] - custom:(Maybe ^McStateExtra) - = ShardStateUnsplit; - -_ ShardStateUnsplit = ShardState; -split_state#5f327da5 left:^ShardStateUnsplit right:^ShardStateUnsplit = ShardState; - -shared_lib_descr$00 lib:^Cell publishers:(Hashmap 256 True) - = LibDescr; - -block_info#9bc7a987 version:uint32 - not_master:(## 1) - after_merge:(## 1) before_split:(## 1) - after_split:(## 1) - want_split:Bool want_merge:Bool - key_block:Bool vert_seqno_incr:(## 1) - flags:(## 8) { flags <= 1 } - seq_no:# vert_seq_no:# { vert_seq_no >= vert_seqno_incr } - { prev_seq_no:# } { ~prev_seq_no + 1 = seq_no } - shard:ShardIdent gen_utime:uint32 - start_lt:uint64 end_lt:uint64 - gen_validator_list_hash_short:uint32 - gen_catchain_seqno:uint32 - min_ref_mc_seqno:uint32 - prev_key_block_seqno:uint32 - gen_software:flags . 0?GlobalVersion - master_ref:not_master?^BlkMasterInfo - prev_ref:^(BlkPrevInfo after_merge) - prev_vert_ref:vert_seqno_incr?^(BlkPrevInfo 0) - = BlockInfo; - -prev_blk_info$_ prev:ExtBlkRef = BlkPrevInfo 0; -prev_blks_info$_ prev1:^ExtBlkRef prev2:^ExtBlkRef = BlkPrevInfo 1; - -block#11ef55aa global_id:int32 - info:^BlockInfo value_flow:^ValueFlow - state_update:^(MERKLE_UPDATE ShardState) - extra:^BlockExtra = Block; - -block_extra in_msg_descr:^InMsgDescr - out_msg_descr:^OutMsgDescr - account_blocks:^ShardAccountBlocks - rand_seed:bits256 - created_by:bits256 - custom:(Maybe ^McBlockExtra) = BlockExtra; -// -value_flow ^[ from_prev_blk:CurrencyCollection - to_next_blk:CurrencyCollection - imported:CurrencyCollection - exported:CurrencyCollection ] - fees_collected:CurrencyCollection - ^[ - fees_imported:CurrencyCollection - recovered:CurrencyCollection - created:CurrencyCollection - minted:CurrencyCollection - ] = ValueFlow; - -// -// -bt_leaf$0 {X:Type} leaf:X = BinTree X; -bt_fork$1 {X:Type} left:^(BinTree X) right:^(BinTree X) - = BinTree X; - -fsm_none$0 = FutureSplitMerge; -fsm_split$10 split_utime:uint32 interval:uint32 = FutureSplitMerge; -fsm_merge$11 merge_utime:uint32 interval:uint32 = FutureSplitMerge; - -shard_descr#b seq_no:uint32 reg_mc_seqno:uint32 - start_lt:uint64 end_lt:uint64 - root_hash:bits256 file_hash:bits256 - before_split:Bool before_merge:Bool - want_split:Bool want_merge:Bool - nx_cc_updated:Bool flags:(## 3) { flags = 0 } - next_catchain_seqno:uint32 next_validator_shard:uint64 - min_ref_mc_seqno:uint32 gen_utime:uint32 - split_merge_at:FutureSplitMerge - fees_collected:CurrencyCollection - funds_created:CurrencyCollection = ShardDescr; - -shard_descr_new#a seq_no:uint32 reg_mc_seqno:uint32 - start_lt:uint64 end_lt:uint64 - root_hash:bits256 file_hash:bits256 - before_split:Bool before_merge:Bool - want_split:Bool want_merge:Bool - nx_cc_updated:Bool flags:(## 3) { flags = 0 } - next_catchain_seqno:uint32 next_validator_shard:uint64 - min_ref_mc_seqno:uint32 gen_utime:uint32 - split_merge_at:FutureSplitMerge - ^[ fees_collected:CurrencyCollection - funds_created:CurrencyCollection ] = ShardDescr; - -_ (HashmapE 32 ^(BinTree ShardDescr)) = ShardHashes; - -bta_leaf$0 {X:Type} {Y:Type} extra:Y leaf:X = BinTreeAug X Y; -bta_fork$1 {X:Type} {Y:Type} left:^(BinTreeAug X Y) - right:^(BinTreeAug X Y) extra:Y = BinTreeAug X Y; - -_ fees:CurrencyCollection create:CurrencyCollection = ShardFeeCreated; -_ (HashmapAugE 96 ShardFeeCreated ShardFeeCreated) = ShardFees; - -_ config_addr:bits256 config:^(Hashmap 32 ^Cell) - = ConfigParams; - -validator_info$_ - validator_list_hash_short:uint32 - catchain_seqno:uint32 - nx_cc_updated:Bool -= ValidatorInfo; - -validator_base_info$_ - validator_list_hash_short:uint32 - catchain_seqno:uint32 -= ValidatorBaseInfo; - -_ key:Bool max_end_lt:uint64 = KeyMaxLt; -_ key:Bool blk_ref:ExtBlkRef = KeyExtBlkRef; - -_ (HashmapAugE 32 KeyExtBlkRef KeyMaxLt) = OldMcBlocksInfo; - - -counters#_ last_updated:uint32 total:uint64 cnt2048:uint64 cnt65536:uint64 = Counters; -creator_info#4 mc_blocks:Counters shard_blocks:Counters = CreatorStats; -block_create_stats#17 counters:(HashmapE 256 CreatorStats) = BlockCreateStats; -block_create_stats_ext#34 counters:(HashmapAugE 256 CreatorStats uint32) = BlockCreateStats; - -masterchain_state_extra#cc26 - shard_hashes:ShardHashes - config:ConfigParams - ^[ flags:(## 16) { flags <= 1 } - validator_info:ValidatorInfo - prev_blocks:OldMcBlocksInfo - after_key_block:Bool - last_key_block:(Maybe ExtBlkRef) - block_create_stats:(flags . 0)?BlockCreateStats ] - global_balance:CurrencyCollection -= McStateExtra; - -ed25519_pubkey#8e81278a pubkey:bits256 = SigPubKey; // 288 bits -ed25519_signature#5 R:bits256 s:bits256 = CryptoSignatureSimple; // 516 bits -_ CryptoSignatureSimple = CryptoSignature; -sig_pair$_ node_id_short:bits256 sign:CryptoSignature = CryptoSignaturePair; // 256+x ~ 772 bits - -certificate#4 temp_key:SigPubKey valid_since:uint32 valid_until:uint32 = Certificate; // 356 bits -certificate_env#a419b7d certificate:Certificate = CertificateEnv; // 384 bits -signed_certificate$_ certificate:Certificate certificate_signature:CryptoSignature - = SignedCertificate; // 356+516 = 872 bits -// certificate_signature is the signature of CertificateEnv (with embedded certificate) with persistent key -chained_signature#f signed_cert:^SignedCertificate temp_key_signature:CryptoSignatureSimple - = CryptoSignature; // 4+(356+516)+516 = 520 bits+ref (1392 bits total) -// temp_key_signature is the signature of whatever was originally intended to be signed with temp_key from certificate - -masterchain_block_extra#cca5 - key_block:(## 1) - shard_hashes:ShardHashes - shard_fees:ShardFees - ^[ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair) - recover_create_msg:(Maybe ^InMsg) - mint_msg:(Maybe ^InMsg) ] - config:key_block?ConfigParams -= McBlockExtra; - -// -// CONFIGURATION PARAMETERS -// - -validator#53 public_key:SigPubKey weight:uint64 = ValidatorDescr; -validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr; -validators#11 utime_since:uint32 utime_until:uint32 - total:(## 16) main:(## 16) { main <= total } { main >= 1 } - list:(Hashmap 16 ValidatorDescr) = ValidatorSet; -validators_ext#12 utime_since:uint32 utime_until:uint32 - total:(## 16) main:(## 16) { main <= total } { main >= 1 } - total_weight:uint64 list:(HashmapE 16 ValidatorDescr) = ValidatorSet; - -_ config_addr:bits256 = ConfigParam 0; -_ elector_addr:bits256 = ConfigParam 1; -_ minter_addr:bits256 = ConfigParam 2; // ConfigParam 0 is used if absent -_ fee_collector_addr:bits256 = ConfigParam 3; // ConfigParam 1 is used if absent -_ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver - -_ mint_new_price:Grams mint_add_price:Grams = ConfigParam 6; -_ to_mint:ExtraCurrencyCollection = ConfigParam 7; - -capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion; -_ GlobalVersion = ConfigParam 8; // all zero if absent -_ mandatory_params:(Hashmap 32 True) = ConfigParam 9; -_ critical_params:(Hashmap 32 True) = ConfigParam 10; - -cfg_vote_cfg#36 min_tot_rounds:uint8 max_tot_rounds:uint8 min_wins:uint8 max_losses:uint8 min_store_sec:uint32 max_store_sec:uint32 bit_price:uint32 cell_price:uint32 = ConfigProposalSetup; -cfg_vote_setup#91 normal_params:^ConfigProposalSetup critical_params:^ConfigProposalSetup = ConfigVotingSetup; -_ ConfigVotingSetup = ConfigParam 11; - -cfg_proposal#f3 param_id:int32 param_value:(Maybe ^Cell) if_hash_equal:(Maybe uint256) - = ConfigProposal; -cfg_proposal_status#ce expires:uint32 proposal:^ConfigProposal is_critical:Bool - voters:(HashmapE 16 True) remaining_weight:int64 validator_set_id:uint256 - rounds_remaining:uint8 wins:uint8 losses:uint8 = ConfigProposalStatus; - -wfmt_basic#1 vm_version:int32 vm_mode:uint64 = WorkchainFormat 1; -wfmt_ext#0 min_addr_len:(## 12) max_addr_len:(## 12) addr_len_step:(## 12) - { min_addr_len >= 64 } { min_addr_len <= max_addr_len } - { max_addr_len <= 1023 } { addr_len_step <= 1023 } - workchain_type_id:(## 32) { workchain_type_id >= 1 } - = WorkchainFormat 0; - -workchain#a6 enabled_since:uint32 actual_min_split:(## 8) - min_split:(## 8) max_split:(## 8) { actual_min_split <= min_split } -//workchain#a5 enabled_since:uint32 min_split:(## 8) max_split:(## 8) -// { min_split <= max_split } { max_split <= 60 } - basic:(## 1) active:Bool accept_msgs:Bool flags:(## 13) { flags = 0 } - zerostate_root_hash:bits256 zerostate_file_hash:bits256 - version:uint32 format:(WorkchainFormat basic) - = WorkchainDescr; - -_ workchains:(HashmapE 32 WorkchainDescr) = ConfigParam 12; - -complaint_prices#1a deposit:Grams bit_price:Grams cell_price:Grams = ComplaintPricing; -_ ComplaintPricing = ConfigParam 13; - -block_grams_created#6b masterchain_block_fee:Grams basechain_block_fee:Grams - = BlockCreateFees; -_ BlockCreateFees = ConfigParam 14; - -_ validators_elected_for:uint32 elections_start_before:uint32 - elections_end_before:uint32 stake_held_for:uint32 - = ConfigParam 15; - -_ max_validators:(## 16) max_main_validators:(## 16) min_validators:(## 16) - { max_validators >= max_main_validators } - { max_main_validators >= min_validators } - { min_validators >= 1 } - = ConfigParam 16; - -_ min_stake:Grams max_stake:Grams min_total_stake:Grams max_stake_factor:uint32 = ConfigParam 17; - -_#cc utime_since:uint32 bit_price_ps:uint64 cell_price_ps:uint64 - mc_bit_price_ps:uint64 mc_cell_price_ps:uint64 = StoragePrices; -_ (Hashmap 32 StoragePrices) = ConfigParam 18; - -gas_prices#dd gas_price:uint64 gas_limit:uint64 gas_credit:uint64 - block_gas_limit:uint64 freeze_due_limit:uint64 delete_due_limit:uint64 - = GasLimitsPrices; - -gas_prices_ext#de gas_price:uint64 gas_limit:uint64 special_gas_limit:uint64 gas_credit:uint64 - block_gas_limit:uint64 freeze_due_limit:uint64 delete_due_limit:uint64 - = GasLimitsPrices; - -gas_flat_pfx#d1 flat_gas_limit:uint64 flat_gas_price:uint64 other:GasLimitsPrices - = GasLimitsPrices; - -config_mc_gas_prices#_ GasLimitsPrices = ConfigParam 20; -config_gas_prices#_ GasLimitsPrices = ConfigParam 21; - -param_limits#c3 underload:# soft_limit:# { underload <= soft_limit } - hard_limit:# { soft_limit <= hard_limit } = ParamLimits; -block_limits#5d bytes:ParamLimits gas:ParamLimits lt_delta:ParamLimits - = BlockLimits; - -config_mc_block_limits#_ BlockLimits = ConfigParam 22; -config_block_limits#_ BlockLimits = ConfigParam 23; - -// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms -// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms -// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) -msg_forward_prices#ea lump_price:uint64 bit_price:uint64 cell_price:uint64 - ihr_price_factor:uint32 first_frac:uint16 next_frac:uint16 = MsgForwardPrices; - -// used for messages to/from masterchain -config_mc_fwd_prices#_ MsgForwardPrices = ConfigParam 24; -// used for all other messages -config_fwd_prices#_ MsgForwardPrices = ConfigParam 25; - -catchain_config#c1 mc_catchain_lifetime:uint32 shard_catchain_lifetime:uint32 - shard_validators_lifetime:uint32 shard_validators_num:uint32 = CatchainConfig; - -catchain_config_new#c2 flags:(## 7) { flags = 0 } shuffle_mc_validators:Bool - mc_catchain_lifetime:uint32 shard_catchain_lifetime:uint32 - shard_validators_lifetime:uint32 shard_validators_num:uint32 = CatchainConfig; - -consensus_config#d6 round_candidates:# { round_candidates >= 1 } - next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32 - fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32 - max_block_bytes:uint32 max_collated_bytes:uint32 = ConsensusConfig; - -consensus_config_new#d7 flags:(## 7) { flags = 0 } new_catchain_ids:Bool - round_candidates:(## 8) { round_candidates >= 1 } - next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32 - fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32 - max_block_bytes:uint32 max_collated_bytes:uint32 = ConsensusConfig; - -_ CatchainConfig = ConfigParam 28; -_ ConsensusConfig = ConfigParam 29; - -_ fundamental_smc_addr:(HashmapE 256 True) = ConfigParam 31; -_ prev_validators:ValidatorSet = ConfigParam 32; -_ prev_temp_validators:ValidatorSet = ConfigParam 33; -_ cur_validators:ValidatorSet = ConfigParam 34; -_ cur_temp_validators:ValidatorSet = ConfigParam 35; -_ next_validators:ValidatorSet = ConfigParam 36; -_ next_temp_validators:ValidatorSet = ConfigParam 37; - -validator_temp_key#3 adnl_addr:bits256 temp_public_key:SigPubKey seqno:# valid_until:uint32 = ValidatorTempKey; -signed_temp_key#4 key:^ValidatorTempKey signature:CryptoSignature = ValidatorSignedTempKey; -_ (HashmapE 256 ValidatorSignedTempKey) = ConfigParam 39; - -// -// PROOFS -// -block_signatures_pure#_ sig_count:uint32 sig_weight:uint64 - signatures:(HashmapE 16 CryptoSignaturePair) = BlockSignaturesPure; -block_signatures#11 validator_info:ValidatorBaseInfo pure_signatures:BlockSignaturesPure = BlockSignatures; -block_proof#c3 proof_for:BlockIdExt root:^Cell signatures:(Maybe ^BlockSignatures) = BlockProof; - -chain_empty$_ = ProofChain 0; -chain_link$_ {n:#} root:^Cell prev:n?^(ProofChain n) = ProofChain (n + 1); -top_block_descr#d5 proof_for:BlockIdExt signatures:(Maybe ^BlockSignatures) - len:(## 8) { len >= 1 } { len <= 8 } chain:(ProofChain len) = TopBlockDescr; - -// -// COLLATED DATA -// -top_block_descr_set#4ac789f3 collection:(HashmapE 96 ^TopBlockDescr) = TopBlockDescrSet; - -// -// VALIDATOR MISBEHAVIOR COMPLAINTS -// -prod_info#34 utime:uint32 mc_blk_ref:ExtBlkRef state_proof:^(MERKLE_PROOF Block) - prod_proof:^(MERKLE_PROOF ShardState) = ProducerInfo; -no_blk_gen from_utime:uint32 prod_info:^ProducerInfo = ComplaintDescr; -no_blk_gen_diff prod_info_old:^ProducerInfo prod_info_new:^ProducerInfo = ComplaintDescr; -validator_complaint#bc validator_pubkey:bits256 description:^ComplaintDescr created_at:uint32 severity:uint8 reward_addr:uint256 paid:Grams suggested_fine:Grams suggested_fine_part:uint32 = ValidatorComplaint; -complaint_status#2d complaint:^ValidatorComplaint voters:(HashmapE 16 True) vset_id:uint256 weight_remaining:int64 = ValidatorComplaintStatus; - -// -// TVM REFLECTION -// -vm_stk_null#00 = VmStackValue; -vm_stk_tinyint#01 value:int64 = VmStackValue; -vm_stk_int#0201_ value:int257 = VmStackValue; -vm_stk_nan#02ff = VmStackValue; -vm_stk_cell#03 cell:^Cell = VmStackValue; -_ cell:^Cell st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits } - st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice; -vm_stk_slice#04 _:VmCellSlice = VmStackValue; -vm_stk_builder#05 cell:^Cell = VmStackValue; -vm_stk_cont#06 cont:VmCont = VmStackValue; -vm_tupref_nil$_ = VmTupleRef 0; -vm_tupref_single$_ entry:^VmStackValue = VmTupleRef 1; -vm_tupref_any$_ {n:#} ref:^(VmTuple (n + 2)) = VmTupleRef (n + 2); -vm_tuple_nil$_ = VmTuple 0; -vm_tuple_tcons$_ {n:#} head:(VmTupleRef n) tail:^VmStackValue = VmTuple (n + 1); -vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue; - -vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack; -vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1); -vm_stk_nil#_ = VmStackList 0; - -_ cregs:(HashmapE 4 VmStackValue) = VmSaveList; -gas_limits#_ remaining:int64 _:^[ max_limit:int64 cur_limit:int64 credit:int64 ] - = VmGasLimits; -_ libraries:(HashmapE 256 ^Cell) = VmLibraries; - -vm_ctl_data$_ nargs:(Maybe uint13) stack:(Maybe VmStack) save:VmSaveList -cp:(Maybe int16) = VmControlData; -vmc_std$00 cdata:VmControlData code:VmCellSlice = VmCont; -vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont; -vmc_quit$1000 exit_code:int32 = VmCont; -vmc_quit_exc$1001 = VmCont; -vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont; -vmc_until$110000 body:^VmCont after:^VmCont = VmCont; -vmc_again$110001 body:^VmCont = VmCont; -vmc_while_cond$110010 cond:^VmCont body:^VmCont -after:^VmCont = VmCont; -vmc_while_body$110011 cond:^VmCont body:^VmCont -after:^VmCont = VmCont; -vmc_pushint$1111 value:int32 next:^VmCont = VmCont; - -// -// DNS RECORDS -// -_ (HashmapE 16 ^DNSRecord) = DNS_RecordSet; - -chunk_ref$_ {n:#} ref:^(TextChunks (n + 1)) = TextChunkRef (n + 1); -chunk_ref_empty$_ = TextChunkRef 0; -text_chunk$_ {n:#} len:(## 8) data:(bits (len * 8)) next:(TextChunkRef n) = TextChunks (n + 1); -text_chunk_empty$_ = TextChunks 0; -text$_ chunks:(## 8) rest:(TextChunks chunks) = Text; -dns_text#1eda _:Text = DNSRecord; - -dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord; // usually in record #-1 - -dns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 } - proto_list:flags . 0?ProtoList = DNSRecord; // often in record #2 -proto_list_nil$0 = ProtoList; -proto_list_next$1 head:Protocol tail:ProtoList = ProtoList; -proto_http#4854 = Protocol; - -dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 } - cap_list:flags . 0?SmcCapList = DNSRecord; // often in record #1 -cap_list_nil$0 = SmcCapList; -cap_list_next$1 head:SmcCapability tail:SmcCapList = SmcCapList; -cap_method_seqno#5371 = SmcCapability; -cap_method_pubkey#71f4 = SmcCapability; -cap_is_wallet#2177 = SmcCapability; -cap_name#ff name:Text = SmcCapability; - -// -// PAYMENT CHANNELS -// - -chan_config$_ init_timeout:uint32 close_timeout:uint32 a_key:bits256 b_key:bits256 - a_addr:^MsgAddressInt b_addr:^MsgAddressInt channel_id:uint64 min_A_extra:Grams = ChanConfig; - -chan_state_init$000 signed_A:Bool signed_B:Bool min_A:Grams min_B:Grams expire_at:uint32 A:Grams B:Grams = ChanState; -chan_state_close$001 signed_A:Bool signed_B:Bool promise_A:Grams promise_B:Grams expire_at:uint32 A:Grams B:Grams = ChanState; -chan_state_payout$010 A:Grams B:Grams = ChanState; - -chan_promise$_ channel_id:uint64 promise_A:Grams promise_B:Grams = ChanPromise; -chan_signed_promise#_ sig:(Maybe ^bits512) promise:ChanPromise = ChanSignedPromise; - -chan_msg_init#27317822 inc_A:Grams inc_B:Grams min_A:Grams min_B:Grams channel_id:uint64 = ChanMsg; -chan_msg_close#f28ae183 extra_A:Grams extra_B:Grams promise:ChanSignedPromise = ChanMsg; -chan_msg_timeout#43278a28 = ChanMsg; -chan_msg_payout#37fe7810 = ChanMsg; - -chan_signed_msg$_ sig_A:(Maybe ^bits512) sig_B:(Maybe ^bits512) msg:ChanMsg = ChanSignedMsg; - -chan_op_cmd#912838d1 msg:ChanSignedMsg = ChanOp; - - -chan_data$_ config:^ChanConfig state:^ChanState = ChanData; - diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp b/submodules/ton/tonlib-src/crypto/block/check-proof.cpp deleted file mode 100644 index 6720ad40..00000000 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "check-proof.h" -#include "block/block.h" -#include "block/block-parse.h" -#include "block/block-auto.h" -#include "block/mc-config.h" - -#include "ton/ton-shard.h" - -#include "vm/cells/MerkleProof.h" -#include "openssl/digest.hpp" -#include "Ed25519.h" - -namespace block { -using namespace std::literals::string_literals; - -td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, ton::Bits256* store_state_hash_to, - bool check_state_hash, td::uint32* save_utime, ton::LogicalTime* save_lt) { - ton::RootHash vhash{root->get_hash().bits()}; - if (vhash != blkid.root_hash) { - return td::Status::Error(PSTRING() << " block header for block " << blkid.to_str() << " has incorrect root hash " - << vhash.to_hex() << " instead of " << blkid.root_hash.to_hex()); - } - std::vector prev; - ton::BlockIdExt mc_blkid; - bool after_split; - TRY_STATUS(block::unpack_block_prev_blk_try(root, blkid, prev, mc_blkid, after_split)); - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) { - return td::Status::Error(std::string{"cannot unpack header for block "} + blkid.to_str()); - } - if (save_utime) { - *save_utime = info.gen_utime; - } - if (save_lt) { - *save_lt = info.end_lt; - } - if (store_state_hash_to) { - vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; - if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update - && upd_cs.size_ext() == 0x20228)) { - return td::Status::Error("invalid Merkle update in block header"); - } - auto upd_hash = upd_cs.prefetch_ref(1)->get_hash(0); - if (!check_state_hash) { - *store_state_hash_to = upd_hash.bits(); - } else if (store_state_hash_to->compare(upd_hash.bits())) { - return td::Status::Error(PSTRING() << "state hash mismatch in block header of " << blkid.to_str() - << " : header declares " << upd_hash.bits().to_hex(256) << " expected " - << store_state_hash_to->to_hex()); - } - } - return td::Status::OK(); -} - -td::Result check_state_proof(ton::BlockIdExt blkid, td::Slice proof) { - TRY_RESULT(proof_root, vm::std_boc_deserialize(proof)); - auto virt_root = vm::MerkleProof::virtualize(std::move(proof_root), 1); - if (virt_root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - td::Bits256 state_hash; - TRY_STATUS(check_block_header_proof(std::move(virt_root), blkid, &state_hash)); - return state_hash; -} - -td::Result> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data) { - try { - TRY_RESULT(state_hash, check_state_proof(blkid, proof)); - TRY_RESULT(state_root, vm::std_boc_deserialize(data)); - auto state_virt_root = vm::MerkleProof::virtualize(std::move(state_root), 1); - if (state_virt_root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - if (state_hash != state_virt_root->get_hash().bits()) { - return td::Status::Error("root hash mismatch in the shardchain state proof"); - } - return std::move(state_virt_root); - } catch (vm::VmError& err) { - return td::Status::Error(PSLICE() << "error scanning shard state proof: " << err.get_msg()); - } catch (vm::VmVirtError& err) { - return td::Status::Error(PSLICE() << "virtualization error scanning shard state proof: " << err.get_msg()); - } -} - -td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof) { - if (blk == shard_blk) { - if (!shard_proof.empty()) { - LOG(WARNING) << "Unexpected non-empty shard proof"; - } - return td::Status::OK(); - } - if (!blk.is_masterchain() || !blk.is_valid_full()) { - return td::Status::Error(PSLICE() << "reference block " << blk.to_str() - << " for a getAccountState query must belong to the masterchain"); - } - TRY_RESULT_PREFIX(P_roots, vm::std_boc_deserialize_multi(std::move(shard_proof)), - "cannot deserialize shard configuration proof"); - if (P_roots.size() != 2) { - return td::Status::Error("shard configuration proof must have exactly two roots"); - } - try { - auto mc_state_root = vm::MerkleProof::virtualize(std::move(P_roots[1]), 1); - if (mc_state_root.is_null()) { - return td::Status::Error("shard configuration proof is invalid"); - } - ton::Bits256 mc_state_hash = mc_state_root->get_hash().bits(); - TRY_STATUS_PREFIX( - check_block_header_proof(vm::MerkleProof::virtualize(std::move(P_roots[0]), 1), blk, &mc_state_hash, true), - "error in shard configuration block header proof :"); - block::gen::ShardStateUnsplit::Record sstate; - if (!(tlb::unpack_cell(mc_state_root, sstate))) { - return td::Status::Error("cannot unpack masterchain state header"); - } - auto shards_dict = block::ShardConfig::extract_shard_hashes_dict(std::move(mc_state_root)); - if (!shards_dict) { - return td::Status::Error("cannot extract shard configuration dictionary from proof"); - } - vm::CellSlice cs; - ton::ShardIdFull true_shard; - if (!block::ShardConfig::get_shard_hash_raw_from(*shards_dict, cs, shard_blk.shard_full(), true_shard)) { - return td::Status::Error(PSLICE() << "masterchain state contains no information for shard " - << shard_blk.shard_full().to_str()); - } - auto shard_info = block::McShardHash::unpack(cs, true_shard); - if (shard_info.is_null()) { - return td::Status::Error(PSLICE() << "cannot unpack information for shard " << shard_blk.shard_full().to_str() - << " from masterchain state"); - } - if (shard_info->top_block_id() != shard_blk) { - return td::Status::Error(PSLICE() << "shard configuration mismatch: expected to find block " << shard_blk.to_str() - << " , found " << shard_info->top_block_id().to_str()); - } - } catch (vm::VmError err) { - return td::Status::Error(PSLICE() << "error while traversing shard configuration proof : " << err.get_msg()); - } catch (vm::VmVirtError err) { - return td::Status::Error(PSLICE() << "virtualization error while traversing shard configuration proof : " - << err.get_msg()); - } - return td::Status::OK(); -} - -td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, - td::Ref root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash, - td::uint32* save_utime, ton::LogicalTime* save_lt) { - TRY_RESULT_PREFIX(Q_roots, vm::std_boc_deserialize_multi(std::move(proof)), "cannot deserialize account proof"); - if (Q_roots.size() != 2) { - return td::Status::Error(PSLICE() << "account state proof must have exactly two roots"); - } - - if (last_trans_lt) { - last_trans_hash->set_zero(); - } - - try { - auto state_root = vm::MerkleProof::virtualize(std::move(Q_roots[1]), 1); - if (state_root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - ton::Bits256 state_hash = state_root->get_hash().bits(); - TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk, - &state_hash, true, save_utime, save_lt), - "error in account shard block header proof : "); - block::gen::ShardStateUnsplit::Record sstate; - if (!(tlb::unpack_cell(std::move(state_root), sstate))) { - return td::Status::Error("cannot unpack state header"); - } - vm::AugmentedDictionary accounts_dict{vm::load_cell_slice(sstate.accounts).prefetch_ref(), 256, - block::tlb::aug_ShardAccounts}; - auto acc_csr = accounts_dict.lookup(addr.addr); - if (acc_csr.not_null()) { - if (root.is_null()) { - return td::Status::Error(PSLICE() << "account state proof shows that account state for " << addr - << " must be non-empty, but it actually is empty"); - } - block::gen::ShardAccount::Record acc_info; - if (!tlb::csr_unpack(std::move(acc_csr), acc_info)) { - return td::Status::Error("cannot unpack ShardAccount from proof"); - } - if (acc_info.account->get_hash().bits().compare(root->get_hash().bits(), 256)) { - return td::Status::Error(PSLICE() << "account state hash mismatch: Merkle proof expects " - << acc_info.account->get_hash().bits().to_hex(256) - << " but received data has " << root->get_hash().bits().to_hex(256)); - } - if (last_trans_hash) { - *last_trans_hash = acc_info.last_trans_hash; - } - if (last_trans_lt) { - *last_trans_lt = acc_info.last_trans_lt; - } - } else if (root.not_null()) { - return td::Status::Error(PSLICE() << "account state proof shows that account state for " << addr - << " must be empty, but it is not"); - } - } catch (vm::VmError err) { - return td::Status::Error(PSLICE() << "error while traversing account proof : " << err.get_msg()); - } catch (vm::VmVirtError err) { - return td::Status::Error(PSLICE() << "virtualization error while traversing account proof : " << err.get_msg()); - } - return td::Status::OK(); -} - -td::Result AccountState::validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const { - TRY_RESULT_PREFIX(true_root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state"); - Ref root; - - if (is_virtualized && true_root.not_null()) { - root = vm::MerkleProof::virtualize(true_root, 1); - if (root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - } else { - root = true_root; - } - - if (blk != ref_blk && ref_blk.id.seqno != ~0U) { - return td::Status::Error(PSLICE() << "obtained getAccountState() for a different reference block " << blk.to_str() - << " instead of requested " << ref_blk.to_str()); - } - - if (!shard_blk.is_valid_full()) { - return td::Status::Error(PSLICE() << "shard block id " << shard_blk.to_str() << " in answer is invalid"); - } - - if (!ton::shard_contains(shard_blk.shard_full(), ton::extract_addr_prefix(addr.workchain, addr.addr))) { - return td::Status::Error(PSLICE() << "received data from shard block " << shard_blk.to_str() - << " that cannot contain requested account"); - } - - TRY_STATUS(block::check_shard_proof(blk, shard_blk, shard_proof.as_slice())); - - Info res; - TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt, - &res.last_trans_hash, &res.gen_utime, &res.gen_lt)); - res.root = std::move(root); - res.true_root = std::move(true_root); - - return res; -} - -td::Result Transaction::validate() { - if (root.is_null()) { - return td::Status::Error("transactions are expected to be non-empty"); - } - if (hash != root->get_hash().bits()) { - return td::Status::Error(PSLICE() << "transaction hash mismatch: expected " << hash.to_hex() << ", found " - << root->get_hash().bits().to_hex(256)); - } - block::gen::Transaction::Record trans; - if (!tlb::unpack_cell(root, trans)) { - return td::Status::Error("cannot unpack transaction #"); - } - - if (trans.lt != lt) { - return td::Status::Error(PSLICE() << "transaction lt mismatch: expected " << lt << ", found " << trans.lt); - } - Info res; - res.blkid = blkid; - res.now = trans.now; - res.prev_trans_lt = trans.prev_trans_lt; - res.prev_trans_hash = trans.prev_trans_hash; - res.transaction = root; - return std::move(res); -} - -td::Result TransactionList::validate() const { - if (blkids.empty()) { - return td::Status::Error("transaction list must be non-empty"); - } - auto R = vm::std_boc_deserialize_multi(std::move(transactions_boc)); - if (R.is_error()) { - return td::Status::Error("cannot deserialize transactions BoC"); - } - auto list = R.move_as_ok(); - if (list.size() != blkids.size()) { - return td::Status::Error(PSLICE() << "transaction list size " << list.size() - << " must be equal to the size of block id list " << blkids.size()); - } - size_t c = 0; - Info res; - auto current_lt = lt; - auto current_hash = hash; - res.lt = lt; - res.hash = hash; - for (auto& root : list) { - const auto& blkid = blkids[c++]; - Transaction transaction; - transaction.blkid = std::move(blkid); - transaction.lt = current_lt; - transaction.hash = current_hash; - transaction.root = root; - TRY_RESULT(info, transaction.validate()); - current_lt = info.prev_trans_lt; - current_hash = info.prev_trans_hash; - res.transactions.push_back(std::move(info)); - } - return std::move(res); -} - -td::Status BlockProofLink::validate(td::uint32* save_utime) const { - if (save_utime) { - *save_utime = 0; - } - if (!(from.is_masterchain_ext() && to.is_masterchain_ext())) { - return td::Status::Error("BlockProofLink must have both source and destination blocks in the masterchain"); - } - if (from.seqno() == to.seqno()) { - return td::Status::Error("BlockProofLink connects two masterchain blocks "s + from.to_str() + " and " + - to.to_str() + " of equal height"); - } - if (is_fwd != (from.seqno() < to.seqno())) { - return td::Status::Error("BlockProofLink from "s + from.to_str() + " to " + to.to_str() + - " is incorrectly declared as a " + (is_fwd ? "forward" : "backward") + " link"); - } - if (dest_proof.is_null() && to.seqno()) { - return td::Status::Error("BlockProofLink contains no proof for destination block "s + to.to_str()); - } - if (proof.is_null()) { - return td::Status::Error("BlockProofLink contains no proof for source block "s + from.to_str()); - } - if (!is_fwd && state_proof.is_null()) { - return td::Status::Error("a backward BlockProofLink contains no proof for the source state of "s + from.to_str()); - } - if (is_fwd && signatures.empty()) { - return td::Status::Error("a forward BlockProofLink from "s + from.to_str() + " to " + to.to_str() + - " contains no signatures"); - } - try { - // virtualize Merkle proof roots - auto vs_root = vm::MerkleProof::virtualize(proof, 1); - if (vs_root.is_null()) { - return td::Status::Error("BlockProofLink contains an invalid Merkle proof for source block "s + from.to_str()); - } - ton::Bits256 state_hash; - if (from.seqno()) { - TRY_STATUS(check_block_header(vs_root, from, is_fwd ? nullptr : &state_hash)); - } - auto vd_root = dest_proof.not_null() ? vm::MerkleProof::virtualize(dest_proof, 1) : Ref{}; - if (vd_root.is_null() && to.seqno()) { - return td::Status::Error("BlockProofLink contains an invalid Merkle proof for destination block "s + to.to_str()); - } - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (to.seqno()) { - TRY_STATUS(check_block_header(vd_root, to)); - if (!(tlb::unpack_cell(vd_root, blk) && tlb::unpack_cell(blk.info, info))) { - return td::Status::Error("cannot unpack header for block "s + from.to_str()); - } - if (info.key_block != is_key) { - return td::Status::Error(PSTRING() << "incorrect is_key_block value " << is_key << " for destination block " - << to.to_str()); - } - if (save_utime) { - *save_utime = info.gen_utime; - } - } else if (!is_key) { - // return td::Status::Error("Zerostate destination block "s + to.to_str() + " does not have is_key_block set"); - } - if (!is_fwd) { - // check a backward link - auto vstate_root = vm::MerkleProof::virtualize(state_proof, 1); - if (vstate_root.is_null()) { - return td::Status::Error("backward BlockProofLink contains an invalid Merkle proof for source state "s + - from.to_str()); - } - if (state_hash != vstate_root->get_hash().bits()) { - return td::Status::Error("BlockProofLink contains a state proof for "s + from.to_str() + - " with incorrect root hash"); - } - TRY_RESULT(config, block::ConfigInfo::extract_config(vstate_root, block::ConfigInfo::needPrevBlocks)); - if (!config->check_old_mc_block_id(to, true)) { - return td::Status::Error("cannot check that "s + to.to_str() + " is indeed a previous masterchain block of " + - from.to_str() + " using the presented Merkle proof of masterchain state"); - } - return td::Status::OK(); - } else { - // check a forward link - // extract configuration from source key block or zerostate - auto cfg_res = from.seqno() ? block::Config::extract_from_key_block(vs_root, block::ConfigInfo::needValidatorSet) - : block::Config::extract_from_state(vs_root, block::ConfigInfo::needValidatorSet); - if (cfg_res.is_error()) { - return td::Status::Error("cannot extract configuration from source key block "s + from.to_str() + - " of a forward BlockProofLink: " + cfg_res.move_as_error().to_string()); - } - auto config = cfg_res.move_as_ok(); - // compute validator set - ton::ShardIdFull shard{ton::masterchainId}; - auto nodes = config->compute_validator_set(shard, info.gen_utime, info.gen_catchain_seqno); - if (nodes.empty()) { - return td::Status::Error(PSTRING() - << "while checking a forward BlockProofLink: cannot compute validator set for block " - << to.to_str() << " with utime " << info.gen_utime << " and cc_seqno " - << info.gen_catchain_seqno << " starting from previous key block " << from.to_str()); - } - // check computed validator set hash - auto vset_hash = compute_validator_set_hash(cc_seqno, shard, nodes); - if (vset_hash != info.gen_validator_list_hash_short) { - return td::Status::Error( - PSTRING() << "while checking a forward BlockProofLink: computed validator set for block " << to.to_str() - << " with utime " << info.gen_utime << " and cc_seqno " << info.gen_catchain_seqno - << " starting from previous key block " << from.to_str() << " has hash " << vset_hash - << " different from " << info.gen_validator_list_hash_short << " stated in block header"); - } - // check signatures - auto err = check_block_signatures(nodes, signatures, to); - if (err.is_error()) { - return td::Status::Error("error checking signatures for block "s + to.to_str() + - " in a forward BlockProofLink: " + err.to_string()); - } - return td::Status::OK(); - } - } catch (vm::VmError& err) { - return td::Status::Error("vm error while checking BlockProofLink from "s + from.to_str() + " to " + to.to_str() + - " : " + err.get_msg()); - } catch (vm::VmVirtError& err) { - return td::Status::Error("virtualization error while checking BlockProofLink from "s + from.to_str() + " to " + - to.to_str() + " : " + err.get_msg()); - } -} - -td::Status BlockProofChain::validate(td::CancellationToken cancellation_token) { - valid = false; - has_key_block = false; - has_utime = false; - last_utime = 0; - key_blkid.invalidate(); - if (!(from.is_masterchain_ext() && to.is_masterchain_ext())) { - return td::Status::Error("BlockProofChain must have both source and destination blocks in the masterchain"); - } - if (!link_count()) { - if (from != to) { - return td::Status::Error("BlockProofChain has no links, but its source block "s + from.to_str() + - " and destination block " + to.to_str() + " differ"); - } - valid = true; - return td::Status::OK(); - } - ton::BlockIdExt cur = from; - int i = 0; - for (const auto& link : links) { - ++i; - if (link.from != cur) { - return td::Status::Error(PSTRING() << "link #" << i << " in a BlockProofChain begins with block " - << link.from.to_str() << " but the previous link ends at different block " - << cur.to_str()); - } - if (cancellation_token) { - return td::Status::Error("Cancelled"); - } - auto err = link.validate(&last_utime); - if (err.is_error()) { - return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string()); - } - if (link.is_key && (!has_key_block || key_blkid.seqno() < link.to.seqno())) { - key_blkid = link.to; - has_key_block = true; - } - cur = link.to; - } - if (cur != to) { - return td::Status::Error("last link of BlockProofChain ends at block "s + cur.to_str() + - " different from declared chain destination block " + to.to_str()); - } - has_utime = (last_utime > 0); - valid = true; - return td::Status::OK(); -} - -td::Bits256 compute_node_id_short(td::Bits256 ed25519_pubkey) { - // pub.ed25519#4813b4c6 key:int256 = PublicKey; - struct pubkey { - int magic = 0x4813b4c6; - unsigned char ed25519_key[32]; - } PK; - std::memcpy(PK.ed25519_key, ed25519_pubkey.data(), 32); - static_assert(sizeof(pubkey) == 36, "PublicKey structure is not 36 bytes long"); - td::Bits256 hash; - digest::hash_str(hash.data(), (void*)&PK, sizeof(pubkey)); - return hash; -} - -td::Status check_block_signatures(const std::vector& nodes, - const std::vector& signatures, const ton::BlockIdExt& blkid) { - if (nodes.empty()) { - return td::Status::Error("empty validator public keys set"); - } - if (signatures.empty()) { - return td::Status::Error("empty validator signature set"); - } - // compute the string to be signed and its hash - unsigned char to_sign[68]; - td::as(to_sign) = 0xc50b6e70; // ton.blockId root_cell_hash:int256 file_hash:int256 = ton.BlockId; - memcpy(to_sign + 4, blkid.root_hash.data(), 32); - memcpy(to_sign + 36, blkid.file_hash.data(), 32); - // unsigned char hash[32]; - // digest::hash_str(hash, (void*)to_sign, sizeof(to_sign)); - - ton::ValidatorWeight total_weight = 0, signed_weight = 0; - std::vector> node_map; - for (unsigned i = 0; i < nodes.size(); i++) { - total_weight += nodes[i].weight; - node_map.emplace_back(compute_node_id_short(nodes[i].key), i); - } - std::sort(node_map.begin(), node_map.end()); - std::vector seen; - for (auto& sig : signatures) { - // lookup node in validator set - auto& id = sig.node; - auto it = std::lower_bound(node_map.begin(), node_map.end(), id, - [](const auto& p, const auto& x) { return p.first < x; }); - if (it == node_map.end() || it->first != id) { - return td::Status::Error("signature set contains unknown NodeIdShort "s + id.to_hex()); - } - unsigned i = it->second; - seen.emplace_back(i); - // check one signature - td::Ed25519::PublicKey pub_key{td::SecureString{nodes.at(i).key.as_slice()}}; - auto res = pub_key.verify_signature(td::Slice{to_sign, 68}, sig.signature.as_slice()); - if (res.is_error()) { - return res; - } - signed_weight += nodes[i].weight; - if (signed_weight > total_weight) { - break; - } - } - std::sort(seen.begin(), seen.end()); - for (std::size_t i = 1; i < seen.size(); i++) { - if (seen[i] == seen[i - 1]) { - return td::Status::Error("signature set contains duplicate signature for NodeIdShort "s + - compute_node_id_short(nodes.at(seen[i]).key).to_hex()); - } - } - if (3 * signed_weight <= 2 * total_weight) { - return td::Status::Error(PSTRING() << "insufficient total signature weight: only " << signed_weight << " out of " - << total_weight); - } - return td::Status::OK(); -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.h b/submodules/ton/tonlib-src/crypto/block/check-proof.h deleted file mode 100644 index 527f3138..00000000 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "vm/cells.h" -#include "block/block.h" - -namespace block { -using td::Ref; - -td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, - ton::Bits256* store_state_hash_to = nullptr, bool check_state_hash = false, - td::uint32* save_utime = nullptr, ton::LogicalTime* save_lt = nullptr); -td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof); -td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, - td::Ref root, ton::LogicalTime* last_trans_lt = nullptr, - ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr, - ton::LogicalTime* save_lt = nullptr); -td::Result check_state_proof(ton::BlockIdExt blkid, td::Slice proof); -td::Result> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data); - -td::Status check_block_signatures(const std::vector& nodes, - const std::vector& signatures, const ton::BlockIdExt& blkid); - -struct AccountState { - ton::BlockIdExt blk; - ton::BlockIdExt shard_blk; - td::BufferSlice shard_proof; - td::BufferSlice proof; - td::BufferSlice state; - bool is_virtualized{false}; - - struct Info { - td::Ref root, true_root; - ton::LogicalTime last_trans_lt{0}; - ton::Bits256 last_trans_hash; - ton::LogicalTime gen_lt{0}; - td::uint32 gen_utime{0}; - }; - - td::Result validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const; -}; - -struct Transaction { - ton::BlockIdExt blkid; - ton::LogicalTime lt; - ton::Bits256 hash; - td::Ref root; - - struct Info { - ton::BlockIdExt blkid; - td::uint32 now; - ton::LogicalTime prev_trans_lt; - ton::Bits256 prev_trans_hash; - td::Ref transaction; - }; - td::Result validate(); -}; - -struct TransactionList { - ton::LogicalTime lt; - ton::Bits256 hash; - std::vector blkids; - td::BufferSlice transactions_boc; - - struct Info { - ton::LogicalTime lt; - ton::Bits256 hash; - std::vector transactions; - }; - - td::Result validate() const; -}; - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/create-state.cpp b/submodules/ton/tonlib-src/crypto/block/create-state.cpp deleted file mode 100644 index 15c3e800..00000000 --- a/submodules/ton/tonlib-src/crypto/block/create-state.cpp +++ /dev/null @@ -1,941 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vm/stack.hpp" -#include "vm/boc.h" - -#include "fift/Fift.h" -#include "fift/Dictionary.h" -#include "fift/SourceLookup.h" -#include "fift/words.h" - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Parser.h" -#include "td/utils/port/path.h" -#include "td/utils/port/signals.h" - -#include "block.h" -#include "block-parse.h" -#include "block-auto.h" -#include "mc-config.h" - -#if defined(_INTERNAL_COMPILE) || defined(_TONLIB_COMPILE) -#define WITH_TONLIB -#include "tonlib/keys/Mnemonic.h" -#endif - -#define PDO(__op) \ - if (!(__op)) { \ - ok = false; \ - } -#define THRERR(__msg) \ - if (!ok) { \ - throw fift::IntError{__msg}; \ - } -#define RETERR \ - if (!ok) { \ - return false; \ - } - -using td::Ref; - -int verbosity; - -enum { wc_master = -1, wc_base = 0 }; -constexpr int wc_undef = std::numeric_limits::min(); - -int workchain_id = wc_undef; -int global_id = 0; - -typedef td::BitArray<256> hash_t; - -struct SmcDescr { - hash_t addr; - int split_depth; - bool preinit_only; - td::RefInt256 gram_balance; - Ref state_init; // StateInit - Ref account; // Account - SmcDescr(const hash_t& _addr) : addr(_addr), split_depth(0), preinit_only(false) { - } -}; - -std::map smart_contracts; -td::RefInt256 total_smc_balance{true, 0}, max_total_smc_balance; - -struct PublicLibDescr { - Ref root; - std::set publishers; - PublicLibDescr(Ref _root) : root(std::move(_root)) { - } -}; - -std::map public_libraries; - -hash_t config_addr; -Ref config_param_root; -bool config_addr_set; -vm::Dictionary config_dict{32}; - -ton::UnixTime now; - -bool set_config_smc(const SmcDescr& smc) { - if (config_addr_set || smc.preinit_only || workchain_id != wc_master || smc.split_depth) { - return false; - } - vm::CellSlice cs = load_cell_slice(smc.state_init); - bool ok = true; - PDO(block::gen::t_Maybe_natwidth_5.skip(cs) && block::gen::t_Maybe_TickTock.skip(cs) && - block::gen::t_Maybe_Ref_Cell.skip(cs)); - RETERR; - Ref data; - PDO(cs.fetch_ulong(1) == 1 && cs.fetch_ref_to(data)); - THRERR("config smart contract must have non-empty data"); - vm::CellSlice cs2 = load_cell_slice(data); - PDO(cs2.fetch_ref_to(data)); - THRERR("first reference in config smart contract data must point to initial configuration"); - PDO(block::valid_config_data(data, smc.addr)); - THRERR("invalid smart contract configuration data"); - config_addr = smc.addr; - config_param_root = std::move(data); - config_addr_set = true; - if (verbosity > 2) { - std::cerr << "set smart contract " << config_addr << " as the configuration smart contract with configuration:\n"; - load_cell_slice(config_param_root).print_rec(std::cerr); - } - return true; -} - -void interpret_set_workchain(vm::Stack& stack) { - workchain_id = stack.pop_smallint_range(0x7fffffff, -0x7fffffff); -} - -void interpret_get_workchain(vm::Stack& stack) { - stack.push_smallint(workchain_id); -} - -void interpret_set_global_id(vm::Stack& stack) { - global_id = stack.pop_smallint_range(0x7fffffff, -0x7fffffff); -} - -void interpret_get_global_id(vm::Stack& stack) { - stack.push_smallint(global_id); -} - -void interpret_get_verbosity(vm::Stack& stack) { - stack.push_smallint(GET_VERBOSITY_LEVEL()); -} - -void interpret_set_verbosity(vm::Stack& stack) { - int x = stack.pop_smallint_range(15); - SET_VERBOSITY_LEVEL(x); -} - -void interpret_set_config_smartcontract(vm::Stack& stack) { - if (workchain_id != wc_master) { - throw fift::IntError{"configuration smart contract may be selected in masterchain only"}; - } - if (config_addr_set) { - throw fift::IntError{"configuration smart contract already selected"}; - } - td::RefInt256 int_addr = stack.pop_int_finite(); - hash_t addr; - if (!int_addr->export_bits(addr.bits(), 256, false)) { - throw fift::IntError{"not a valid smart-contract address"}; - } - auto it = smart_contracts.find(addr); - if (it == smart_contracts.end()) { - throw fift::IntError{"unknown smart contract"}; - } - const SmcDescr& smc = it->second; - assert(smc.addr == addr); - if (smc.preinit_only) { - throw fift::IntError{"configuration smart contract must be completely initialized"}; - } - if (!set_config_smc(smc)) { - throw fift::IntError{"invalid configuration smart contract"}; - } -} - -bool is_empty_cell(Ref cell) { - bool is_special; - auto cs = load_cell_slice_special(std::move(cell), is_special); - return !is_special && cs.empty_ext(); -} - -bool add_public_library(hash_t lib_addr, hash_t smc_addr, Ref lib_root) { - if (lib_root.is_null() || lib_root->get_hash().as_array() != lib_addr.as_array()) { - return false; - } - auto ins = public_libraries.emplace(lib_addr, lib_root); - PublicLibDescr& lib = ins.first->second; - lib.publishers.insert(smc_addr); - if (verbosity > 2) { - std::cerr << "added " << (ins.second ? "new " : "") << "public library " << lib_addr << " with publisher " - << smc_addr << std::endl; - } - return true; -} - -td::RefInt256 create_smartcontract(td::RefInt256 smc_addr, Ref code, Ref data, - Ref library, td::RefInt256 balance, int special, int split_depth, - int mode) { - if (is_empty_cell(code)) { - code.clear(); - } - if (is_empty_cell(data)) { - data.clear(); - } - if (is_empty_cell(library)) { - library.clear(); - } - bool ok = true; - if (library.not_null()) { - PDO(block::valid_library_collection(library, false)); - THRERR("not a valid library collection"); - } - vm::CellBuilder cb; - if (!split_depth) { - PDO(cb.store_long_bool(0, 1)); - } else { - PDO(cb.store_long_bool(1, 1) && cb.store_ulong_rchk_bool(split_depth, 5)); - } - THRERR("invalid split_depth for a smart contract"); - if (!special) { - PDO(cb.store_long_bool(0, 1)); - } else { - PDO(cb.store_long_bool(1, 1) && cb.store_ulong_rchk_bool(special, 2)); - } - THRERR("invalid special TickTock argument for a smart contract"); - PDO(cb.store_maybe_ref(std::move(code)) && cb.store_maybe_ref(std::move(data)) && cb.store_maybe_ref(library)); - THRERR("cannot store smart-contract code, data or library"); - Ref state_init = cb.finalize(); - hash_t addr; - if (smc_addr.is_null()) { - addr = state_init->get_hash().as_array(); - smc_addr = td::RefInt256{true}; - PDO(smc_addr.write().import_bits(addr.data(), 0, 256, false)); - } else if (mode == 1) { - throw fift::IntError{"cannot create uninitialized smart contracts with specified addresses"}; - } else { - PDO(smc_addr->export_bits(addr.data(), 0, 256, false)); - } - THRERR("cannot initialize smart-contract address"); - if (verbosity > 2) { - std::cerr << "smart-contract address is "; - std::cerr << addr << " = " << smc_addr << std::endl; - } - PDO(mode || !sgn(balance)); - THRERR("cannot set non-zero balance to smart contract unless it is initialized"); - PDO(sgn(balance) >= 0); - THRERR("balance cannot be negative"); - if (!mode) { - if (verbosity > 2) { - std::cerr << "StateInit used for computing address: "; - block::gen::t_StateInit.print_ref(std::cerr, state_init); - } - return smc_addr; // compute address only - } - auto it = smart_contracts.find(addr); - if (it != smart_contracts.end()) { - std::cerr << "smart contract " << addr << " already defined\n"; - throw fift::IntError{"smart contract already exists"}; - } - auto ins = smart_contracts.emplace(addr, addr); - assert(ins.second); - SmcDescr& smc = ins.first->second; - smc.split_depth = split_depth; - smc.preinit_only = (mode == 1); - smc.gram_balance = balance; - total_smc_balance += balance; - if (mode > 1) { - smc.state_init = std::move(state_init); - } - if (max_total_smc_balance.not_null() && total_smc_balance > max_total_smc_balance) { - throw fift::IntError{"total smart-contract balance exceeds limit"}; - } - cb.reset(); - PDO(cb.store_long_bool(0, 64) // account_storage$_ last_trans_lt:uint64 - && block::tlb::t_Grams.store_integer_value(cb, *balance) // balance.grams:Grams - && cb.store_long_bool(0, 1)); // balance.other:ExtraCurrencyCollection - if (mode == 1) { - PDO(block::gen::t_AccountState.pack_account_uninit(cb)); - } else { - PDO(block::gen::t_AccountState.pack_account_active(cb, vm::load_cell_slice_ref(smc.state_init))); - } - THRERR("cannot create smart-contract AccountStorage"); - Ref storage = cb.finalize(); - vm::CellStorageStat stats; - PDO(stats.compute_used_storage(Ref(storage))); - if (verbosity > 2) { - std::cerr << "storage is:\n"; - vm::load_cell_slice(storage).print_rec(std::cerr); - std::cerr << "stats: bits=" << stats.bits << ", cells=" << stats.cells << std::endl; - std::cerr << "block::gen::AccountStorage.validate_ref() = " << block::gen::t_AccountStorage.validate_ref(storage) - << std::endl; - std::cerr << "block::tlb::AccountStorage.validate_ref() = " << block::tlb::t_AccountStorage.validate_ref(storage) - << std::endl; - } - PDO(block::gen::t_AccountStorage.validate_ref(storage)); - THRERR("AccountStorage of created smart-contract is invalid (?)"); - cb.reset(); // build Account - PDO(cb.store_long_bool(1, 1)); // account$1 - int ctor = 3; // addr_var$11 - if (workchain_id >= -128 && workchain_id <= 127) { - ctor = 2; // addr_std$10 - } - PDO(cb.store_long_bool(ctor, 2)); // addr_std$10 or addr_var$11 - if (split_depth) { - PDO(cb.store_long_bool(1, 1) // just$1 - && cb.store_ulong_rchk_bool(split_depth, 5) // depth:(## 5) - && cb.store_bits_bool(addr.cbits(), split_depth)); // rewrite pfx:(depth * Bit) - } else { - PDO(cb.store_long_bool(0, 1)); // nothing$0 - } - PDO(cb.store_long_rchk_bool(workchain_id, ctor == 2 ? 8 : 32) && cb.store_bits_bool(addr.cbits(), 256)); - THRERR("Cannot serialize addr:MsgAddressInt of the new smart contract"); - // storage_stat:StorageInfo -> storage_stat.used:StorageUsed - PDO(block::store_UInt7(cb, stats.cells) // cells:(VarUInteger 7) - && block::store_UInt7(cb, stats.bits) // bits:(VarUInteger 7) - && block::store_UInt7(cb, stats.public_cells)); // public_cells:(VarUInteger 7) - THRERR("Cannot serialize used:StorageUsed of the new smart contract"); - PDO(cb.store_long_bool(0, 33)); // last_paid:uint32 due_payment:(Maybe Grams) - PDO(cb.append_data_cell_bool(storage)); // storage:AccountStorage - THRERR("Cannot create Account of the new smart contract"); - smc.account = cb.finalize(); - if (verbosity > 2) { - std::cerr << "account is:\n"; - vm::load_cell_slice(smc.account).print_rec(std::cerr); - std::cerr << "block::gen::Account.validate_ref() = " << block::gen::t_Account.validate_ref(smc.account) - << std::endl; - std::cerr << "block::tlb::Account.validate_ref() = " << block::tlb::t_Account.validate_ref(smc.account) - << std::endl; - } - PDO(block::gen::t_Account.validate_ref(smc.account)); - THRERR("Account of created smart contract is invalid (?)"); - if (library.not_null()) { - vm::Dictionary dict{std::move(library), 256}; - ok &= dict.check_for_each([addr](Ref cs, td::ConstBitPtr key, int n) -> bool { - return !cs->prefetch_ulong(1) || add_public_library(key, addr, cs->prefetch_ref()); - }); - THRERR("Error processing libraries published by new smart contract"); - } - return smc_addr; -} - -// stores accounts:ShardAccounts -bool store_accounts(vm::CellBuilder& cb) { - vm::AugmentedDictionary dict{256, block::tlb::aug_ShardAccounts}; - for (const auto& smc_pair : smart_contracts) { - const SmcDescr& smc = smc_pair.second; - CHECK(smc_pair.first == smc.addr); - vm::CellBuilder cb; - bool ok = cb.store_ref_bool(smc.account) // account_descr$_ acc:^Account - && cb.store_zeroes_bool(256 + 64) // last_trans_hash:bits256 last_trans_lt:uint64 - && dict.set_builder(smc.addr.cbits(), 256, cb, vm::Dictionary::SetMode::Add); - CHECK(ok); - } - return std::move(dict).append_dict_to_bool(cb); -} - -// stores libraries:(HashmapE 256 LibDescr) -bool store_public_libraries(vm::CellBuilder& cb) { - vm::Dictionary dict{256}; - bool ok = true; - vm::CellBuilder empty_cb; - for (const auto& lib_pair : public_libraries) { - const PublicLibDescr pl = lib_pair.second; - PDO(pl.root->get_hash().as_array() == lib_pair.first.as_array()); - vm::Dictionary publishers{256}; - for (const auto& publisher : pl.publishers) { - PDO(publishers.set_builder(publisher.cbits(), 256, empty_cb, vm::Dictionary::SetMode::Add)); - } - Ref root = std::move(publishers).extract_root_cell(); - PDO(root.not_null()); - THRERR("public library has an empty or invalid set of publishers"); - vm::CellBuilder value_cb; // LibDescr - PDO(value_cb.store_long_bool(0, 2) && value_cb.store_ref_bool(pl.root) && - value_cb.append_cellslice_bool(vm::load_cell_slice(std::move(root)))); - THRERR("cannot create LibDescr for a public library"); - PDO(dict.set_builder(lib_pair.first.cbits(), 256, value_cb, vm::Dictionary::SetMode::Add)); - THRERR("cannot insert LibDescr of a public library into the public library collection"); - } - PDO(std::move(dict).append_dict_to_bool(cb)); - return ok; -} - -// stores config:ConfigParams -bool store_config_params(vm::CellBuilder& cb) { - return config_addr_set && config_param_root.not_null() && - cb.store_bits_bool(config_addr.cbits(), 256) // _ config_addr:bits256 - && cb.store_ref_bool(config_param_root); // config:^(Hashmap 32 ^Cell) -} - -// stores hash of initial masterchain validator set computed from configuration parameter 34 -bool store_validator_list_hash(vm::CellBuilder& cb) { - Ref vset_cell = config_dict.lookup_ref(td::BitArray<32>{34}); - auto res = block::Config::unpack_validator_set(std::move(vset_cell)); - if (res.is_error()) { - LOG(ERROR) << "cannot unpack current validator set: " << res.move_as_error().to_string(); - return false; - } - auto vset = res.move_as_ok(); - LOG_CHECK(vset) << "unpacked validator set is empty"; - auto ccvc = block::Config::unpack_catchain_validators_config(config_dict.lookup_ref(td::BitArray<32>{28})); - ton::ShardIdFull shard{ton::masterchainId}; - auto nodes = block::Config::do_compute_validator_set(ccvc, shard, *vset, now, 0); - LOG_CHECK(!nodes.empty()) << "validator node list in unpacked validator set is empty"; - auto vset_hash = block::compute_validator_set_hash(0, shard, std::move(nodes)); - LOG(DEBUG) << "initial validator set hash is " << vset_hash; - return cb.store_long_bool(vset_hash, 32); -} - -// stores custom:(Maybe ^McStateExtra) -bool store_custom(vm::CellBuilder& cb) { - if (workchain_id != wc_master) { - return cb.store_long_bool(0, 1); // nothing - } - vm::CellBuilder cb2, cb3; - bool ok = true; - PDO(cb2.store_long_bool(0xcc26, 16) // masterchain_state_extra#cc26 - && cb2.store_long_bool(0, 1) // shard_hashes:ShardHashes = (HashmapE 32 ^(BinTree ShardDescr)) - && store_config_params(cb2) // config:ConfigParams - && cb3.store_long_bool(0, 16) // ^[ flags:(## 16) { flags = 0 } - && store_validator_list_hash(cb3) // validator_list_hash_short:uint32 - && cb3.store_long_bool(0, 32) // catchain_seqno:uint32 - && cb3.store_bool_bool(true) // nx_cc_updated:Bool - && cb3.store_zeroes_bool(1 + 65) // prev_blocks:OldMcBlocksInfo - && cb3.store_long_bool(2, 1 + 1) // after_key_block:Bool last_key_block:(Maybe ...) - && cb2.store_ref_bool(cb3.finalize()) // ] - && block::CurrencyCollection{total_smc_balance}.store(cb2) // global_balance:CurrencyCollection - && cb.store_long_bool(1, 1) // just - && cb.store_ref_bool(cb2.finalize())); - return ok; -} - -Ref create_state() { - vm::CellBuilder cb, cb2; - now = static_cast(time(0)); - bool ok = true; - PDO(workchain_id != wc_undef); - THRERR("workchain_id is unset, cannot generate state"); - PDO(workchain_id != wc_master || config_addr_set); - THRERR("configuration smart contract must be selected"); - PDO(cb.store_long_bool(0x9023afe2, 32) // shard_state#9023afe2 - && cb.store_long_bool(global_id, 32)); // global_id:int32 - PDO(cb.store_long_bool(0, 8) && cb.store_long_bool(workchain_id, 32) && - cb.store_long_bool(0, 64) // shard_id:ShardIdent - && cb.store_long_bool(0, 32) // seq_no:# - && cb.store_zeroes_bool(32) // vert_seq_no:# - && cb.store_long_bool(now, 32) // gen_utime:uint32 - && cb.store_zeroes_bool(64) // gen_lt:uint64 - && cb.store_ones_bool(32) // min_ref_mc_seqno:uint32 - && cb2.store_zeroes_bool(1 + 64 + 2) // OutMsgQueueInfo - && cb.store_ref_bool(cb2.finalize()) // out_msg_queue_info:^OutMsgQueueInfo - && cb.store_long_bool(0, 1) // before_split:Bool - && store_accounts(cb2) // accounts:^ShardAccounts - && cb.store_ref_bool(cb2.finalize()) // ... - && cb2.store_zeroes_bool(128) // ^[ overload_history:uint64 underload_history:uint64 - && block::CurrencyCollection{total_smc_balance}.store(cb2) // total_balance:CurrencyCollection - && block::tlb::t_CurrencyCollection.null_value(cb2) // total_validator_fees:CurrencyCollection - && store_public_libraries(cb2) // libraries:(Hashmap 256 LibDescr) - && cb2.store_long_bool(0, 1) // master_ref:(Maybe BlkMasterInfo) - && cb.store_ref_bool(cb2.finalize()) // ] - && store_custom(cb)); // custom:(Maybe ^McStateExtra) - THRERR("cannot create blockchain state"); - Ref cell = cb.finalize(); - if (verbosity > 2) { - std::cerr << "shard_state is:\n"; - vm::load_cell_slice(cell).print_rec(std::cerr); - std::cerr << "pretty-printed shard_state is:\n"; - block::gen::t_ShardState.print_ref(std::cerr, cell); - std::cerr << "\n"; - std::cerr << "block::gen::ShardState.validate_ref() = " << block::gen::t_ShardState.validate_ref(cell) << std::endl; - std::cerr << "block::tlb::ShardState.validate_ref() = " << block::tlb::t_ShardState.validate_ref(cell) << std::endl; - block::gen::ShardStateUnsplit::Record data; - bool ok1 = tlb::unpack_cell(cell, data); - std::cerr << "block::gen::ShardState.unpack_cell() = " << ok1 << std::endl; - if (ok1) { - std::cerr << "shard_id = " << data.shard_id - << "; out_msg_queue_info = " << load_cell_slice(data.out_msg_queue_info) - << "; total_balance = " << data.r1.total_balance << std::endl; - } - } - PDO(block::gen::t_ShardState.validate_ref(cell)); - PDO(block::tlb::t_ShardState.validate_ref(cell)); - THRERR("created an invalid ShardState record"); - return cell; -} - -// code (cell) -// data (cell) -// library (cell) -// balance (int) -// split_depth (int 0..32) -// special (int 0..3, +2 = tick, +1 = tock) -// [ address (uint256) ] -// mode (0 = compute address only, 1 = create uninit, 2 = create complete; +4 = with specified address) -// --> 256-bit address -void interpret_register_smartcontract(vm::Stack& stack) { - if (workchain_id == wc_undef) { - throw fift::IntError{"cannot register a smartcontract unless the workchain is specified first"}; - } - td::RefInt256 spec_addr; - int mode = stack.pop_smallint_range(2 + 4); // allowed modes: 0 1 2 4 5 6 - if (mode == 3) { - throw fift::IntError{"invalid mode"}; - } - if (mode & 4) { - spec_addr = stack.pop_int_finite(); - mode &= ~4; - } - int special = stack.pop_smallint_range(3); - if (special && workchain_id != wc_master) { - throw fift::IntError{"cannot create special smartcontracts outside of the masterchain"}; - } - int split_depth = stack.pop_smallint_range(32); - td::RefInt256 balance = stack.pop_int_finite(); - if (sgn(balance) < 0) { - throw fift::IntError{"initial balance of a smartcontract cannot be negative"}; - } - if (sgn(balance) > 0 && !mode) { - throw fift::IntError{"cannot set non-zero balance if an account is not created"}; - } - Ref library = stack.pop_cell(); - Ref data = stack.pop_cell(); - Ref code = stack.pop_cell(); - td::RefInt256 addr = create_smartcontract(std::move(spec_addr), std::move(code), std::move(data), std::move(library), - std::move(balance), special, split_depth, mode); - if (addr.is_null()) { - throw fift::IntError{"internal error while creating smartcontract"}; - } - stack.push(std::move(addr)); -} - -void interpret_create_state(vm::Stack& stack) { - if (!global_id) { - throw fift::IntError{ - "(global) blockchain id must be set to a non-zero value: negative for test chains, positive for production"}; - } - Ref state = create_state(); - if (state.is_null()) { - throw fift::IntError{"could not create blockchain state"}; - } - stack.push(std::move(state)); -} - -void interpret_get_config_dict(vm::Stack& stack) { - Ref value = config_dict.get_root_cell(); - if (value.is_null()) { - stack.push_bool(false); - } else { - stack.push_cell(std::move(value)); - stack.push_bool(true); - } -} - -void interpret_get_config_param(vm::Stack& stack) { - int x = stack.pop_smallint_range(0x7fffffff, 0x80000000); - Ref value = config_dict.lookup_ref(td::BitArray<32>{x}); - if (value.is_null()) { - stack.push_bool(false); - } else { - stack.push_cell(std::move(value)); - stack.push_bool(true); - } -} - -void interpret_set_config_param(vm::Stack& stack) { - int x = stack.pop_smallint_range(0x7fffffff, 0x80000000); - Ref value = stack.pop_cell(); - if (verbosity > 2 && x >= 0) { - std::cerr << "setting configuration parameter #" << x << " to "; - // vm::load_cell_slice(value).print_rec(std::cerr); - block::gen::ConfigParam{x}.print_ref(std::cerr, value); - std::cerr << std::endl; - } - if (x >= 0 && !block::gen::ConfigParam{x}.validate_ref(value)) { - throw fift::IntError{"invalid value for indicated configuration parameter"}; - } - if (!config_dict.set_ref(td::BitArray<32>{x}, std::move(value))) { - throw fift::IntError{"cannot set value of configuration parameter (value too long?)"}; - } -} - -void interpret_check_config_param(vm::Stack& stack) { - int x = stack.pop_smallint_range(0x7fffffff, 0x80000000); - Ref value = stack.pop_cell(); - if (verbosity > 2 && x >= 0) { - std::cerr << "checking validity as configuration parameter #" << x << " of "; - // vm::load_cell_slice(value).print_rec(std::cerr); - block::gen::ConfigParam{x}.print_ref(std::cerr, value); - std::cerr << std::endl; - } - stack.push_bool(x < 0 || block::gen::ConfigParam{x}.validate_ref(value)); -} - -void interpret_is_shard_state(vm::Stack& stack) { - Ref cell = stack.pop_cell(); - if (verbosity > 4) { - std::cerr << "custom shard state is:\n"; - vm::load_cell_slice(cell).print_rec(std::cerr); - std::cerr << "pretty-printed custom shard state is:\n"; - block::gen::t_ShardState.print_ref(std::cerr, cell); - } - stack.push_bool(block::gen::t_ShardState.validate_ref(std::move(cell))); -} - -void interpret_is_workchain_descr(vm::Stack& stack) { - Ref cell = stack.pop_cell(); - if (verbosity > 4) { - std::cerr << "WorkchainDescr is:\n"; - vm::load_cell_slice(cell).print_rec(std::cerr); - std::cerr << "pretty-printed WorkchainDescr is:\n"; - block::gen::t_WorkchainDescr.print_ref(std::cerr, cell); - } - stack.push_bool(block::gen::t_WorkchainDescr.validate_ref(std::move(cell))); -} - -void interpret_add_extra_currencies(vm::Stack& stack) { - Ref y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res; - bool ok = block::add_extra_currency(std::move(x), std::move(y), res); - if (ok) { - stack.push_maybe_cell(std::move(res)); - } - stack.push_bool(ok); -} - -void interpret_sub_extra_currencies(vm::Stack& stack) { - Ref y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res; - bool ok = block::sub_extra_currency(std::move(x), std::move(y), res); - if (ok) { - stack.push_maybe_cell(std::move(res)); - } - stack.push_bool(ok); -} - -void interpret_allocated_balance(vm::Stack& stack) { - stack.push_int(total_smc_balance); -} - -#ifdef WITH_TONLIB -void interpret_mnemonic_to_privkey(vm::Stack& stack, int mode) { - td::SecureString str{td::Slice{stack.pop_string()}}; - auto res = tonlib::Mnemonic::create(std::move(str), td::SecureString()); - if (res.is_error()) { - throw fift::IntError{res.move_as_error().to_string()}; - } - auto privkey = res.move_as_ok().to_private_key(); - td::SecureString key; - if (mode & 1) { - auto pub = privkey.get_public_key(); - key = pub.move_as_ok().as_octet_string(); - } else { - key = privkey.as_octet_string(); - } - stack.push_bytes(key.as_slice()); -} -#endif - -void init_words_custom(fift::Dictionary& d) { - using namespace std::placeholders; - d.def_stack_word("verb@ ", interpret_get_verbosity); - d.def_stack_word("verb! ", interpret_set_verbosity); - d.def_stack_word("wcid@ ", interpret_get_workchain); - d.def_stack_word("wcid! ", interpret_set_workchain); - d.def_stack_word("globalid@ ", interpret_get_global_id); - d.def_stack_word("globalid! ", interpret_set_global_id); - d.def_stack_word("config@ ", interpret_get_config_param); - d.def_stack_word("config! ", interpret_set_config_param); - d.def_stack_word("config-valid? ", interpret_check_config_param); - d.def_stack_word("(configdict) ", interpret_get_config_dict); - d.def_stack_word("register_smc ", interpret_register_smartcontract); - d.def_stack_word("set_config_smc ", interpret_set_config_smartcontract); - d.def_stack_word("create_state ", interpret_create_state); - d.def_stack_word("isShardState? ", interpret_is_shard_state); - d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr); - d.def_stack_word("CC+? ", interpret_add_extra_currencies); - d.def_stack_word("CC-? ", interpret_sub_extra_currencies); - d.def_stack_word("allocated-balance ", interpret_allocated_balance); -#ifdef WITH_TONLIB - d.def_stack_word("mnemo>priv ", std::bind(interpret_mnemonic_to_privkey, _1, 0)); - d.def_stack_word("mnemo>pub ", std::bind(interpret_mnemonic_to_privkey, _1, 1)); -#endif -} - -tlb::TypenameLookup tlb_dict; - -// ( S -- T -1 or 0 ) Looks up TLB type by name -void interpret_tlb_type_lookup(vm::Stack& stack) { - auto ptr = tlb_dict.lookup(stack.pop_string()); - if (ptr) { - stack.push_make_object(ptr); - } - stack.push_bool(ptr); -} - -td::Ref pop_tlb_type(vm::Stack& stack) { - auto res = stack.pop_object(); - if (res.is_null()) { - throw vm::VmError{vm::Excno::type_chk, "not a TLB type"}; - } - return res; -} - -// ( T -- S ) Gets TLB type name -void interpret_tlb_type_name(vm::Stack& stack) { - stack.push_string((*pop_tlb_type(stack))->get_type_name()); -} - -// ( T -- ) Prints TLB type name -void interpret_print_tlb_type(vm::Stack& stack) { - std::cout << (*pop_tlb_type(stack))->get_type_name(); -} - -// ( s T -- ) Dumps (part of) slice s as a value of TLB type T -void interpret_tlb_dump_as(vm::Stack& stack) { - auto tp = pop_tlb_type(stack); - (*tp)->print(std::cout, stack.pop_cellslice()); -} - -// ( s T -- s' S -1 or 0 ) -// Detects prefix of slice s that is a value of TLB type T, returns the remainder as s', and prints the value into String S. -void interpret_tlb_dump_to_str(vm::Stack& stack) { - auto tp = pop_tlb_type(stack); - auto cs = stack.pop_cellslice(); - std::ostringstream os; - bool ok = (*tp)->print_skip(os, cs.write()); - if (ok) { - stack.push(std::move(cs)); - stack.push_string(os.str()); - } - stack.push_bool(ok); -} - -// ( s T -- s' -1 or 0 ) Skips the only prefix of slice s that can be a value of TLB type T -void interpret_tlb_skip(vm::Stack& stack) { - auto tp = pop_tlb_type(stack); - auto cs = stack.pop_cellslice(); - bool ok = (*tp)->skip(cs.write()); - if (ok) { - stack.push(std::move(cs)); - } - stack.push_bool(ok); -} - -// ( s T -- s' -1 or 0 ) Checks whether a prefix of slice s is a valid value of TLB type T, and skips it -void interpret_tlb_validate_skip(vm::Stack& stack) { - auto tp = pop_tlb_type(stack); - auto cs = stack.pop_cellslice(); - bool ok = (*tp)->validate_skip_upto(1048576, cs.write()); - if (ok) { - stack.push(std::move(cs)); - } - stack.push_bool(ok); -} - -void interpret_tlb_type_const(vm::Stack& stack, const tlb::TLB* ptr) { - stack.push_make_object(ptr); -} - -void init_words_tlb(fift::Dictionary& d) { - using namespace std::placeholders; - tlb_dict.register_types(block::gen::register_simple_types); - d.def_stack_word("tlb-type-lookup ", interpret_tlb_type_lookup); - d.def_stack_word("tlb-type-name ", interpret_tlb_type_name); - d.def_stack_word("tlb. ", interpret_print_tlb_type); - d.def_stack_word("tlb-dump-as ", interpret_tlb_dump_as); - d.def_stack_word("(tlb-dump-str?) ", interpret_tlb_dump_to_str); - d.def_stack_word("tlb-skip ", interpret_tlb_skip); - d.def_stack_word("tlb-validate-skip ", interpret_tlb_validate_skip); - d.def_stack_word("ExtraCurrencyCollection", - std::bind(interpret_tlb_type_const, _1, &block::tlb::t_ExtraCurrencyCollection)); -} - -void usage(const char* progname) { - std::cerr - << "Creates initial state for a TON blockchain, using configuration defined by Fift-language source files\n"; - std::cerr - << "usage: " << progname - << " [-i] [-n] [-I ] {-L } ...\n"; - std::cerr << "\t-n\tDo not preload preamble files `Fift.fif` and `CreateState.fif`\n" - "\t-i\tForce interactive mode even if explicit source file names are indicated\n" - "\t-I\tSets colon-separated library source include path. If not indicated, " - "$FIFTPATH is used instead.\n" - "\t-L\tPre-loads a library source file\n" - "\t-v\tSet verbosity level\n"; - std::exit(2); -} - -void parse_include_path_set(std::string include_path_set, std::vector& res) { - td::Parser parser(include_path_set); - while (!parser.empty()) { - auto path = parser.read_till_nofail(':'); - if (!path.empty()) { - res.push_back(path.str()); - } - parser.skip_nofail(':'); - } -} - -void preload_preamble(fift::Fift& fift, std::string filename, bool standard = true) { - auto status = fift.interpret_file(filename, ""); - if (status.is_error()) { - LOG(ERROR) << "Error interpreting " << (standard ? "standard" : "application-specific") << " preamble file `" - << filename << "`: " << status.error().message() - << "\nCheck that correct include path is set by -I or by FIFTPATH environment variable, or disable " - "standard preamble by -n.\n"; - std::exit(2); - } -} - -int main(int argc, char* const argv[]) { - td::set_default_failure_signal_handler().ensure(); - bool interactive = false; - bool fift_preload = true, no_env = false, script_mode = false; - std::vector library_source_files, source_list; - std::vector source_include_path; - std::string ton_db_path; - - fift::Fift::Config config; - - int i; - int new_verbosity_level = VERBOSITY_NAME(INFO); - while (!script_mode && (i = getopt(argc, argv, "hinsI:L:v:")) != -1) { - switch (i) { - case 'i': - interactive = true; - break; - case 'n': - fift_preload = false; - break; - case 'I': - LOG(ERROR) << source_include_path; - parse_include_path_set(optarg, source_include_path); - no_env = true; - break; - case 's': - script_mode = true; - break; - case 'L': - library_source_files.emplace_back(optarg); - break; - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer(td::Slice(optarg))); - break; - case 'h': - default: - usage(argv[0]); - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - - while (optind < argc) { - source_list.emplace_back(argv[optind++]); - if (script_mode) { - break; - } - } - - if (!no_env) { - const char* path = std::getenv("FIFTPATH"); - if (path) { - parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path); - } - } - std::string current_dir; - auto r_current_dir = td::realpath("."); - if (r_current_dir.is_ok()) { - current_dir = r_current_dir.move_as_ok(); - source_include_path.push_back(current_dir); - } - config.source_lookup = fift::SourceLookup(std::make_unique()); - for (auto& path : source_include_path) { - config.source_lookup.add_include_path(path); - } - - fift::init_words_common(config.dictionary); - fift::init_words_vm(config.dictionary); - fift::init_words_ton(config.dictionary); - init_words_custom(config.dictionary); - init_words_tlb(config.dictionary); - - if (script_mode) { - fift::import_cmdline_args(config.dictionary, source_list.empty() ? "" : source_list[0], argc - optind, - argv + optind); - } - - fift::Fift fift(std::move(config)); - - if (fift_preload) { - preload_preamble(fift, "Fift.fif", true); - preload_preamble(fift, "CreateState.fif", false); - } - - for (auto source : library_source_files) { - auto status = fift.interpret_file(source, ""); - if (status.is_error()) { - std::cerr << "Error interpreting preloaded file `" << source << "`: " << status.error().to_string() << std::endl; - std::exit(2); - } - } - - if (source_list.empty() && !interactive) { - std::cerr << "No Fift source files specified" << std::endl; - std::exit(2); - } - - for (const auto& source : source_list) { - auto status = fift.interpret_file(source, current_dir); - if (status.is_error()) { - std::cerr << "Error interpreting file `" << source << "`: " << status.error().to_string() << std::endl; - std::exit(2); - } - } - - if (interactive) { - fift.interpret_istream(std::cin, current_dir).ensure(); - } - // show_total_cells(); -} diff --git a/submodules/ton/tonlib-src/crypto/block/dump-block.cpp b/submodules/ton/tonlib-src/crypto/block/dump-block.cpp deleted file mode 100644 index 32b28b91..00000000 --- a/submodules/ton/tonlib-src/crypto/block/dump-block.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "block/block.h" -#include "vm/boc.h" -#include -#include "block-db.h" -#include "block-auto.h" -#include "block-parse.h" -#include "mc-config.h" -#include "vm/cp0.h" -#include - -using td::Ref; -using namespace std::literals::string_literals; - -int verbosity; - -struct IntError { - std::string err_msg; - IntError(std::string _msg) : err_msg(_msg) { - } - IntError(const char* _msg) : err_msg(_msg) { - } -}; - -void throw_err(td::Status err) { - if (err.is_error()) { - throw IntError{err.to_string()}; - } -} - -td::Ref load_boc(std::string filename) { - std::cerr << "loading bag-of-cell file " << filename << std::endl; - auto bytes_res = block::load_binary_file(filename); - if (bytes_res.is_error()) { - throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()}; - } - vm::BagOfCells boc; - auto res = boc.deserialize(bytes_res.move_as_ok()); - if (res.is_error()) { - throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()}; - } - if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) { - throw IntError{"cannot deserialize bag-of-cells "}; - } - return boc.get_root_cell(); -} - -std::vector> loaded_boc; - -void test1() { - block::ShardId id{ton::masterchainId}, id2{ton::basechainId, 0x11efULL << 48}; - std::cout << '[' << id << "][" << id2 << ']' << std::endl; - vm::CellBuilder cb; - cb << id << id2; - std::cout << "ShardIdent.pack() = " << block::tlb::t_ShardIdent.pack(cb, {12, 3, 0x3aeULL << 52}) << std::endl; - std::cout << cb << std::endl; - auto cref = cb.finalize(); - td::Ref cs{true, cref}, cs2; - block::ShardId id3{cs.write()}, id4, id5; - cs >> id4 >> id5; - std::cout << '[' << id3 << "][" << id4 << "][" << id5 << ']' << std::endl; - vm::CellSlice csl{std::move(cref)}; - std::cout << "ShardIdent.get_size() = " << block::tlb::t_ShardIdent.get_size(csl) << std::endl; - std::cout << "MsgAddress.get_size() = " << block::tlb::t_MsgAddress.get_size(csl) << std::endl; - std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl) << std::endl; - std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl) << std::endl; - (csl + 8).print_rec(std::cout); - std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl + 8) << std::endl; - std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl + 8) << std::endl; - - vm::CellSlice csl2{csl}; - block::gen::ShardIdent::Record sh_id; - for (int i = 0; i < 3; i++) { - std::cout << csl2 << std::endl; - bool ok = tlb::unpack(csl2, sh_id); - std::cout << "block::gen::ShardIdent.unpack() = " << ok << std::endl; - if (ok) { - std::cout << " (shard_ident shard_pfx_bits:" << sh_id.shard_pfx_bits << " workchain_id:" << sh_id.workchain_id - << " shard_prefix:" << std::hex << sh_id.shard_prefix << std::dec << ")" << std::endl; - } - } - - block::tlb::ShardIdent::Record shard_id; - for (int i = 0; i < 3; i++) { - std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate_upto(1024, csl) << std::endl; - csl.print_rec(std::cerr); - csl.dump(std::cerr, 7); - std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl; - if (shard_id.is_valid()) { - std::cout << "shard_pfx_bits:" << shard_id.shard_pfx_bits << " workchain_id:" << shard_id.workchain_id - << " shard_prefix:" << shard_id.shard_prefix << std::endl; - } - } - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl; - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl; - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl; - using namespace td::literals; - std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl; - std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl; - std::cout << "Grams.store_intval(-17) = " << block::tlb::t_Grams.store_integer_value(cb, "-17"_i256) << std::endl; - std::cout << "Grams.store_intval(0) = " << block::tlb::t_Grams.store_integer_value(cb, "0"_i256) << std::endl; - std::cout << cb << std::endl; - cs = td::Ref{true, cb.finalize()}; - std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl; - std::cout << cb << std::endl; - cs2 = td::Ref{true, cb.finalize()}; - std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate_upto(1024, *cs) << std::endl; - std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate_upto(1024, *cs2) << std::endl; - // - block::gen::SplitMergeInfo::Record data; - block::gen::Grams::Record data2; - std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate_upto(1024, *cs) << std::endl; - std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate_upto(1024, *cs2) << std::endl; - std::cout << "[cs = " << cs << "]" << std::endl; - bool ok = tlb::csr_unpack_inexact(cs, data); - std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl; - if (ok) { - std::cout << " cur_shard_pfx_len = " << data.cur_shard_pfx_len << "; acc_split_depth = " << data.acc_split_depth - << "; this_addr = " << data.this_addr << "; sibling_addr = " << data.sibling_addr << std::endl; - } - ok = tlb::csr_unpack_inexact(cs, data2); - std::cout << "block::gen::Grams.unpack(cs, data2) = " << ok << std::endl; - if (ok) { - std::cout << " amount = " << data2.amount << std::endl; - block::gen::VarUInteger::Record data3; - ok = tlb::csr_type_unpack(data2.amount, block::gen::t_VarUInteger_16, data3); - std::cout << " block::gen::VarUInteger16.unpack(amount, data3) = " << ok << std::endl; - if (ok) { - std::cout << " len = " << data3.len << "; value = " << data3.value << std::endl; - vm::CellBuilder cb; - std::cout << " block::gen::VarUInteger16.pack(cb, data3) = " - << tlb::type_pack(cb, block::gen::t_VarUInteger_16, data3) << std::endl; - std::cout << " cb = " << cb.finalize() << std::endl; - } - } - /* - { - vm::CellBuilder cb; - td::BitArray<256> hash; - std::memset(hash.data(), 0x69, 32); - bool ok = tlb::pack( - cb, block::gen::Test::Record{1000000000000, {170239, -888, {239017, "1000000000000000000"_ri256}, hash}, 17}); - std::cout << " block::gen::Test::pack(cb, {1000000000000, ...}) = " << ok << std::endl; - std::cout << " cb = " << cb << std::endl; - auto cell = cb.finalize(); - vm::CellSlice cs{cell}; - cs.print_rec(std::cout); - block::gen::Test::Record data; - std::cout << " block::gen::Test::validate_ref(cell) = " << block::gen::t_Test.validate_ref(cell) << std::endl; - ok = tlb::unpack(cs, data); - std::cout << " block::gen::Test::unpack(cs, data) = " << ok << std::endl; - if (ok) { - std::cout << "a:" << data.a << " b:" << data.r1.b << " c:" << data.r1.c << " d:" << data.r1.r1.d - << " e:" << data.r1.r1.e << " f:" << data.r1.f << " g:" << data.g << std::endl; - } - std::cout << " block::gen::Test::print_ref(cell) = "; - block::gen::t_Test.print_ref(std::cout, cell, 2); - block::gen::t_CurrencyCollection.print_ref(std::cout, cell, 2); - std::cout << std::endl; - } - */ - std::cout << "Grams.add_values() = " << block::tlb::t_Grams.add_values(cb, cs.write(), cs2.write()) << std::endl; - std::cout << cb << std::endl; - std::cout << "block::gen::t_HashmapAug_64_...print_type() = " - << block::gen::t_HashmapAug_64_Ref_Transaction_CurrencyCollection << std::endl; -} - -void test2(vm::CellSlice& cs) { - std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate_upto(1024, cs) << std::endl; - std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate_upto(1024, cs) << std::endl; - std::cout << "HashmapE(32,UInt16).validate() = " - << block::tlb::HashmapE(32, block::tlb::t_uint16).validate_upto(1024, cs) << std::endl; - std::cout << "block::gen::HashmapE(32,UInt16).validate() = " - << block::gen::HashmapE{32, block::gen::t_uint16}.validate_upto(1024, cs) << std::endl; -} - -td::Status test_vset() { - if (loaded_boc.size() != 2) { - return td::Status::Error( - "must have exactly two boc files (with a masterchain Block and with ConfigParams) for vset compute test"); - } - std::cerr << "running test_vset()\n"; - TRY_RESULT(config, block::Config::unpack_config(vm::load_cell_slice_ref(loaded_boc[1]))); - std::cerr << "config unpacked\n"; - auto cv_root = config->get_config_param(34); - if (cv_root.is_null()) { - return td::Status::Error("no config parameter 34"); - } - std::cerr << "config param #34 obtained\n"; - TRY_RESULT(cur_validators, block::Config::unpack_validator_set(std::move(cv_root))); - // auto vconf = config->get_catchain_validators_config(); - std::cerr << "validator set unpacked\n"; - std::cerr << "unpacking ShardHashes\n"; - block::ShardConfig shards; - if (!shards.unpack(vm::load_cell_slice_ref(loaded_boc[0]))) { - return td::Status::Error("cannot unpack ShardConfig"); - } - std::cerr << "ShardHashes initialized\n"; - ton::ShardIdFull shard{0, 0x6e80000000000000}; - ton::CatchainSeqno cc_seqno = std::max(48763, 48763) + 1 + 1; - ton::UnixTime now = 1586169666; - cc_seqno = shards.get_shard_cc_seqno(shard); - std::cerr << "shard=" << shard.to_str() << " cc_seqno=" << cc_seqno << " time=" << now << std::endl; - if (cc_seqno == ~0U) { - return td::Status::Error("cannot compute cc_seqno for shard "s + shard.to_str()); - } - auto nodes = config->compute_validator_set(shard, *cur_validators, now, cc_seqno); - if (nodes.empty()) { - return td::Status::Error(PSTRING() << "compute_validator_set() for " << shard.to_str() << "," << now << "," - << cc_seqno << " returned empty list"); - } - for (auto& x : nodes) { - std::cout << "weight=" << x.weight << " key=" << x.key.as_bits256().to_hex() << " addr=" << x.addr.to_hex() - << std::endl; - } - // ... - return td::Status::OK(); -} - -void usage() { - std::cout << "usage: dump-block [-t][-S][]\n\tor dump-block -h\n\tDumps specified blockchain " - "block or state " - "from , or runs some tests\n\t-S\tDump a blockchain state instead of a block\n"; - std::exit(2); -} - -int main(int argc, char* const argv[]) { - int i; - int new_verbosity_level = VERBOSITY_NAME(INFO); - const char* tname = nullptr; - const tlb::TLB* type = &block::gen::t_Block; - bool vset_compute_test = false; - bool store_loaded = false; - int dump = 3; - auto zerostate = std::make_unique(); - while ((i = getopt(argc, argv, "CSt:hqv:")) != -1) { - switch (i) { - case 'C': - type = &block::gen::t_VmCont; - break; - case 'S': - type = &block::gen::t_ShardStateUnsplit; - break; - case 't': - tname = optarg; - type = nullptr; - break; - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer(td::Slice(optarg))); - break; - case 'q': - type = &block::gen::t_ShardHashes; - vset_compute_test = true; - store_loaded = true; - dump = 0; - break; - case 'h': - usage(); - std::exit(2); - default: - usage(); - std::exit(2); - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - try { - int loaded = 0; - while (optind < argc) { - auto boc = load_boc(argv[optind++]); - if (boc.is_null()) { - std::cerr << "(invalid boc in file" << argv[optind - 1] << ")" << std::endl; - std::exit(2); - } else { - if (store_loaded) { - loaded_boc.push_back(boc); - } - ++loaded; - if (dump & 1) { - vm::CellSlice cs{vm::NoVm(), boc}; - cs.print_rec(std::cout); - std::cout << std::endl; - } - if (!type) { - tlb::TypenameLookup dict(block::gen::register_simple_types); - type = dict.lookup(tname); - if (!type) { - std::cerr << "unknown TL-B type " << tname << std::endl; - std::exit(3); - } - } - if (dump & 2) { - type->print_ref(std::cout, boc); - std::cout << std::endl; - } - bool ok = type->validate_ref(1048576, boc); - std::cout << "(" << (ok ? "" : "in") << "valid " << *type << ")" << std::endl; - if (vset_compute_test) { - if (!ok || loaded > 2) { - std::cerr << "fatal: validity check failed\n"; - exit(3); - } - type = &block::gen::t_ConfigParams; - } - } - } - if (vset_compute_test) { - throw_err(test_vset()); - } else if (!loaded) { - test1(); - } - } catch (IntError& err) { - std::cerr << "internal error: " << err.err_msg << std::endl; - return 1; - } catch (vm::VmError& err) { - std::cerr << "vm error: " << err.get_msg() << std::endl; - return 1; - } - return 0; -} diff --git a/submodules/ton/tonlib-src/crypto/block/mc-config.cpp b/submodules/ton/tonlib-src/crypto/block/mc-config.cpp deleted file mode 100644 index 7fab4750..00000000 --- a/submodules/ton/tonlib-src/crypto/block/mc-config.cpp +++ /dev/null @@ -1,2105 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "mc-config.h" -#include "block/block.h" -#include "block/block-parse.h" -#include "block/block-auto.h" -#include "common/bitstring.h" -#include "vm/dict.h" -#include "td/utils/bits.h" -#include "td/utils/uint128.h" -#include "ton/ton-types.h" -#include "ton/ton-shard.h" -#include "openssl/digest.hpp" -#include -#include - -namespace block { -using namespace std::literals::string_literals; -using td::Ref; - -#define DBG(__n) dbg(__n)&& -#define DSTART int __dcnt = 0; -#define DEB DBG(++__dcnt) - -static inline bool dbg(int c) TD_UNUSED; -static inline bool dbg(int c) { - std::cerr << '[' << (char)('0' + c / 10) << (char)('0' + c % 10) << ']'; - return true; -} - -Config::Config(Ref config_root, const td::Bits256& config_addr, int _mode) - : mode(_mode), config_addr(config_addr), config_root(std::move(config_root)) { -} - -td::Result> Config::unpack_config(Ref config_root, const td::Bits256& config_addr, - int mode) { - std::unique_ptr ptr{new Config(std::move(config_root), config_addr, mode)}; - TRY_STATUS(ptr->unpack_wrapped()); - return std::move(ptr); -} - -td::Result> Config::unpack_config(Ref config_csr, int mode) { - std::unique_ptr ptr{new Config(mode)}; - TRY_STATUS(ptr->unpack_wrapped(std::move(config_csr))); - return std::move(ptr); -} - -td::Result> Config::extract_from_key_block(Ref key_block_root, int mode) { - block::gen::Block::Record blk; - block::gen::BlockExtra::Record extra; - block::gen::McBlockExtra::Record mc_extra; - if (!(tlb::unpack_cell(key_block_root, blk) && tlb::unpack_cell(std::move(blk.extra), extra) && - tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra) && mc_extra.key_block && mc_extra.config.not_null())) { - return td::Status::Error(-400, "cannot unpack extra header of key block to extract configuration"); - } - return block::Config::unpack_config(std::move(mc_extra.config), mode); -} - -td::Result> Config::extract_from_state(Ref mc_state_root, int mode) { - gen::ShardStateUnsplit::Record state; - gen::McStateExtra::Record extra; - if (!(tlb::unpack_cell(mc_state_root, state) && state.global_id && - tlb::unpack_cell(state.custom->prefetch_ref(), extra))) { - return td::Status::Error("cannot extract configuration from masterchain state extra information"); - } - return unpack_config(std::move(extra.config), mode); -} - -td::Result> ConfigInfo::extract_config(std::shared_ptr static_boc, - int mode) { - TRY_RESULT(rc, static_boc->get_root_count()); - if (rc != 1) { - return td::Status::Error(-668, "Masterchain state BoC is invalid"); - } - TRY_RESULT(root, static_boc->get_root_cell(0)); - return extract_config(std::move(root), mode); -} - -td::Result> ConfigInfo::extract_config(Ref mc_state_root, int mode) { - if (mc_state_root.is_null()) { - return td::Status::Error("configuration state root cell is null"); - } - auto config = std::unique_ptr{new ConfigInfo(std::move(mc_state_root), mode)}; - TRY_STATUS(config->unpack_wrapped()); - return std::move(config); -} - -ConfigInfo::ConfigInfo(Ref mc_state_root, int _mode) : Config(_mode), state_root(std::move(mc_state_root)) { - block_id.root_hash.set_zero(); - block_id.file_hash.set_zero(); -} - -td::Status ConfigInfo::unpack_wrapped() { - try { - return unpack(); - } catch (vm::VmError& err) { - return td::Status::Error(PSLICE() << "error unpacking block state header and configuration: " << err.get_msg()); - } catch (vm::VmVirtError& err) { - return td::Status::Error(PSLICE() << "virtualization error while unpacking block state header and configuration: " - << err.get_msg()); - } -} - -td::Status ConfigInfo::unpack() { - gen::ShardStateUnsplit::Record root_info; - if (!tlb::unpack_cell(state_root, root_info) || !root_info.global_id) { - return td::Status::Error("configuration state root cannot be deserialized"); - } - global_id_ = root_info.global_id; - block::ShardId shard_id{root_info.shard_id}; - block_id.id = ton::BlockId{ton::ShardIdFull(shard_id), (unsigned)root_info.seq_no}; - block_id.root_hash.set_zero(); - block_id.file_hash.set_zero(); - vert_seqno = root_info.vert_seq_no; - utime = root_info.gen_utime; - lt = root_info.gen_lt; - min_ref_mc_seqno_ = root_info.min_ref_mc_seqno; - if (!root_info.custom->size_refs()) { - return td::Status::Error("state does not have a `custom` field with masterchain configuration"); - } - if (mode & needLibraries) { - lib_root_ = root_info.r1.libraries->prefetch_ref(); - libraries_dict_ = std::make_unique(lib_root_, 256); - } - if (mode & needAccountsRoot) { - accounts_root = vm::load_cell_slice_ref(root_info.accounts); - LOG(DEBUG) << "requested accounts dictionary"; - accounts_dict = std::make_unique(accounts_root, 256, block::tlb::aug_ShardAccounts); - LOG(DEBUG) << "accounts dictionary created"; - } - state_extra_root_ = root_info.custom->prefetch_ref(); - if (!is_masterchain()) { - if (mode & (needShardHashes | needValidatorSet | needSpecialSmc | needPrevBlocks | needWorkchainInfo)) { - return td::Status::Error("cannot extract masterchain-specific configuration data from a non-masterchain state"); - } - cleanup(); - return td::Status::OK(); - } - gen::McStateExtra::Record extra_info; - if (!tlb::unpack_cell(state_extra_root_, extra_info)) { - vm::load_cell_slice(state_extra_root_).print_rec(std::cerr); - block::gen::t_McStateExtra.print_ref(std::cerr, state_extra_root_); - return td::Status::Error("state extra information is invalid"); - } - gen::ValidatorInfo::Record validator_info; - if (!tlb::csr_unpack(extra_info.r1.validator_info, validator_info)) { - return td::Status::Error("validator_info in state extra information is invalid"); - } - cc_seqno_ = validator_info.catchain_seqno; - nx_cc_updated = validator_info.nx_cc_updated; - if ((mode & needShardHashes) && !ShardConfig::unpack(extra_info.shard_hashes)) { - return td::Status::Error("cannot unpack Shard configuration"); - } - is_key_state_ = extra_info.r1.after_key_block; - if (extra_info.r1.last_key_block->size() > 1) { - auto& cs = extra_info.r1.last_key_block.write(); - block::gen::ExtBlkRef::Record ext_ref; - if (!(cs.advance(1) && tlb::unpack_exact(cs, ext_ref))) { - return td::Status::Error("cannot unpack last_key_block from masterchain state"); - } - last_key_block_.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, ext_ref.seq_no}; - last_key_block_.root_hash = ext_ref.root_hash; - last_key_block_.file_hash = ext_ref.file_hash; - last_key_block_lt_ = ext_ref.end_lt; - } else { - last_key_block_.invalidate(); - last_key_block_.id.seqno = 0; - last_key_block_lt_ = 0; - } - // unpack configuration - TRY_STATUS(Config::unpack_wrapped(std::move(extra_info.config))); - // unpack previous masterchain block collection - std::unique_ptr prev_blocks_dict = - std::make_unique(extra_info.r1.prev_blocks, 32, block::tlb::aug_OldMcBlocksInfo); - if (block_id.id.seqno) { - block::gen::ExtBlkRef::Record extref = {}; - auto ref = prev_blocks_dict->lookup(td::BitArray<32>::zero()); - if (!(ref.not_null() && ref.write().advance(1) && tlb::csr_unpack(ref, extref) && !extref.seq_no)) { - return td::Status::Error("OldMcBlocks in masterchain state does not contain a valid zero state reference"); - } - zerostate_id_.root_hash = extref.root_hash; - zerostate_id_.file_hash = extref.file_hash; - } else { - zerostate_id_.root_hash.set_zero(); - zerostate_id_.file_hash.set_zero(); - } - zerostate_id_.workchain = ton::masterchainId; - if (mode & needPrevBlocks) { - prev_blocks_dict_ = std::move(prev_blocks_dict); - } - // ... - cleanup(); - return td::Status::OK(); -} - -td::Status Config::unpack_wrapped(Ref config_csr) { - try { - return unpack(std::move(config_csr)); - } catch (vm::VmError err) { - return td::Status::Error(PSLICE() << "error unpacking masterchain configuration: " << err.get_msg()); - } -} - -td::Status Config::unpack_wrapped() { - try { - return unpack(); - } catch (vm::VmError err) { - return td::Status::Error(PSLICE() << "error unpacking masterchain configuration: " << err.get_msg()); - } -} - -td::Status Config::unpack(Ref config_cs) { - gen::ConfigParams::Record config_params; - if (!tlb::csr_unpack(std::move(config_cs), config_params)) { - return td::Status::Error("cannot unpack ConfigParams"); - } - config_addr = config_params.config_addr; - config_root = std::move(config_params.config); - return unpack(); -} - -td::Status Config::unpack() { - if (config_root.is_null()) { - return td::Status::Error("configuration root not set"); - } - config_dict = std::make_unique(config_root, 32); - if (mode & needValidatorSet) { - auto vset_res = unpack_validator_set(get_config_param(35, 34)); - if (vset_res.is_error()) { - return vset_res.move_as_error(); - } - cur_validators_ = vset_res.move_as_ok(); - } - if (mode & needSpecialSmc) { - LOG(DEBUG) << "needSpecialSmc flag set"; - auto param = get_config_param(31); - if (param.is_null()) { - special_smc_dict = std::make_unique(256); - } else { - special_smc_dict = std::make_unique(vm::load_cell_slice_ref(std::move(param)), 256); - LOG(DEBUG) << "smc dictionary created"; - } - } - if (mode & needWorkchainInfo) { - TRY_RESULT(pair, unpack_workchain_list_ext(get_config_param(12))); - workchains_ = std::move(pair.first); - workchains_dict_ = std::move(pair.second); - } - if (mode & needCapabilities) { - auto cell = get_config_param(8); - if (cell.is_null()) { - version_ = 0; - capabilities_ = 0; - } else { - block::gen::GlobalVersion::Record gv; - if (!tlb::unpack_cell(std::move(cell), gv)) { - return td::Status::Error( - "cannot extract global blockchain version and capabilities from GlobalVersion in configuration parameter " - "#8"); - } - version_ = gv.version; - capabilities_ = gv.capabilities; - } - } - // ... - return td::Status::OK(); -} - -td::Status Config::visit_validator_params() const { - { - // current validator set - TRY_RESULT(vset, unpack_validator_set(get_config_param(34))); - } - for (int i = 32; i < 38; i++) { - // prev/current/next persistent and temporary validator sets - auto vs = get_config_param(i); - if (vs.not_null()) { - TRY_RESULT(vset, unpack_validator_set(std::move(vs))); - } - } - get_catchain_validators_config(); - return td::Status::OK(); -} - -ton::ValidatorSessionConfig Config::get_consensus_config() const { - auto cc = get_config_param(29); - ton::ValidatorSessionConfig c; - auto set = [&c](auto& r, bool new_cc_ids) { - c.catchain_idle_timeout = r.consensus_timeout_ms * 0.001; - c.catchain_max_deps = r.catchain_max_deps; - c.round_candidates = r.round_candidates; - c.next_candidate_delay = r.next_candidate_delay_ms * 0.001; - c.round_attempt_duration = r.attempt_duration; - c.max_round_attempts = r.fast_attempts; - c.max_block_size = r.max_block_bytes; - c.max_collated_data_size = r.max_collated_bytes; - c.new_catchain_ids = new_cc_ids; - return true; - }; - if (cc.not_null()) { - block::gen::ConsensusConfig::Record_consensus_config_new r1; - block::gen::ConsensusConfig::Record_consensus_config r0; - (tlb::unpack_cell(cc, r1) && set(r1, r1.new_catchain_ids)) || (tlb::unpack_cell(cc, r0) && set(r0, false)); - } - return c; -} - -bool Config::foreach_config_param(std::function)> scan_func) const { - if (!config_dict) { - return false; - } - return config_dict->check_for_each([scan_func](Ref cs_ref, td::ConstBitPtr key, int n) { - return n == 32 && cs_ref.not_null() && cs_ref->size_ext() == 0x10000 && - scan_func((int)key.get_int(n), cs_ref->prefetch_ref()); - }); -} - -std::unique_ptr ShardConfig::extract_shard_hashes_dict(Ref mc_state_root) { - gen::ShardStateUnsplit::Record root_info; - gen::McStateExtra::Record extra_info; - if (mc_state_root.not_null() // - && tlb::unpack_cell(mc_state_root, root_info) // - && tlb::unpack_cell(root_info.custom->prefetch_ref(), extra_info)) { - return std::make_unique(std::move(extra_info.shard_hashes), 32); - } else { - return {}; - } -} - -td::Result> Config::unpack_param_dict(vm::Dictionary& dict) { - try { - std::vector vect; - if (dict.check_for_each( - [&vect](Ref value, td::ConstBitPtr key, int key_len) { - bool ok = (key_len == 32 && value->empty_ext()); - if (ok) { - vect.push_back((int)key.get_int(32)); - } - return ok; - }, - true)) { - return std::move(vect); - } else { - return td::Status::Error("invalid parameter list dictionary"); - } - } catch (vm::VmError& vme) { - return td::Status::Error("error unpacking parameter list dictionary: "s + vme.get_msg()); - } -} - -td::Result> Config::unpack_param_dict(Ref dict_root) { - vm::Dictionary dict{std::move(dict_root), 32}; - return unpack_param_dict(dict); -} - -std::unique_ptr Config::get_param_dict(int idx) const { - return std::make_unique(get_config_param(idx), 32); -} - -td::Result> Config::unpack_param_list(int idx) const { - return unpack_param_dict(*get_param_dict(idx)); -} - -bool Config::all_mandatory_params_defined(int* bad_idx_ptr) const { - auto res = get_mandatory_param_list(); - if (res.is_error()) { - if (bad_idx_ptr) { - *bad_idx_ptr = -1; - } - return false; - } - for (int x : res.move_as_ok()) { - if (get_config_param(x).is_null()) { - if (bad_idx_ptr) { - *bad_idx_ptr = x; - } - return false; - } - } - return true; -} - -std::unique_ptr ConfigInfo::create_accounts_dict() const { - if (mode & needAccountsRoot) { - return std::make_unique(accounts_root, 256, block::tlb::aug_ShardAccounts); - } else { - return nullptr; - } -} - -const vm::AugmentedDictionary& ConfigInfo::get_accounts_dict() const { - return *accounts_dict; -} - -bool ConfigInfo::get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& blklt, bool strict) const { - if (strict || !is_key_state_) { - blkid = last_key_block_; - blklt = last_key_block_lt_; - } else { - blkid = block_id; - blklt = lt; - } - return blkid.is_valid(); -} - -td::Result>> Config::unpack_workchain_list_ext( - Ref root) { - if (root.is_null()) { - LOG(DEBUG) << "workchain description dictionary is empty (no configuration parameter #12)"; - return std::make_pair(WorkchainSet{}, std::make_unique(32)); - } else { - auto wc_dict = std::make_unique(vm::load_cell_slice_ref(std::move(root)), 32); - WorkchainSet wc_list; - LOG(DEBUG) << "workchain description dictionary created"; - if (!(wc_dict->check_for_each([&wc_list](Ref cs_ref, td::ConstBitPtr key, int n) -> bool { - ton::WorkchainId wc = ton::WorkchainId(key.get_int(32)); - Ref wc_info{true}; - return wc_info.unique_write().unpack(wc, cs_ref.write()) && wc_list.emplace(wc, std::move(wc_info)).second; - }))) { - return td::Status::Error("cannot unpack WorkchainDescr from masterchain configuration"); - } - return std::make_pair(std::move(wc_list), std::move(wc_dict)); - } -} - -td::Result Config::unpack_workchain_list(Ref root) { - TRY_RESULT(pair, unpack_workchain_list_ext(std::move(root))); - return std::move(pair.first); -} - -td::Result> Config::unpack_validator_set(Ref vset_root) { - if (vset_root.is_null()) { - return td::Status::Error("validator set is absent"); - } - gen::ValidatorSet::Record_validators_ext rec; - Ref dict_root; - if (!tlb::unpack_cell(vset_root, rec)) { - gen::ValidatorSet::Record_validators rec0; - if (!tlb::unpack_cell(std::move(vset_root), rec0)) { - return td::Status::Error("validator set is invalid"); - } - rec.utime_since = rec0.utime_since; - rec.utime_until = rec0.utime_until; - rec.total = rec0.total; - rec.main = rec0.main; - dict_root = vm::Dictionary::construct_root_from(*rec0.list); - rec.total_weight = 0; - } else if (rec.total_weight) { - dict_root = rec.list->prefetch_ref(); - } else { - return td::Status::Error("validator set cannot have zero total weight"); - } - vm::Dictionary dict{std::move(dict_root), 16}; - td::BitArray<16> key_buffer; - auto last = dict.get_minmax_key(key_buffer.bits(), 16, true); - if (last.is_null() || (int)key_buffer.to_ulong() != rec.total - 1) { - return td::Status::Error( - "maximal index in a validator set dictionary must be one less than the total number of validators"); - } - auto ptr = std::make_unique(rec.utime_since, rec.utime_until, rec.total, rec.main); - for (int i = 0; i < rec.total; i++) { - key_buffer.store_ulong(i); - auto descr_cs = dict.lookup(key_buffer.bits(), 16); - if (descr_cs.is_null()) { - return td::Status::Error("indices in a validator set dictionary must be integers 0..total-1"); - } - gen::ValidatorDescr::Record_validator_addr descr; - if (!tlb::csr_unpack(descr_cs, descr)) { - descr.adnl_addr.set_zero(); - if (!(gen::t_ValidatorDescr.unpack_validator(descr_cs.write(), descr.public_key, descr.weight) && - descr_cs->empty_ext())) { - return td::Status::Error(PSLICE() << "validator #" << i - << " has an invalid ValidatorDescr record in the validator set dictionary"); - } - } - gen::SigPubKey::Record sig_pubkey; - if (!tlb::csr_unpack(std::move(descr.public_key), sig_pubkey)) { - return td::Status::Error(PSLICE() << "validator #" << i - << " has no public key or its public key is in unsupported format"); - } - if (!descr.weight) { - return td::Status::Error(PSLICE() << "validator #" << i << " has zero weight"); - } - if (descr.weight > ~(ptr->total_weight)) { - return td::Status::Error("total weight of all validators in validator set exceeds 2^64"); - } - ptr->list.emplace_back(sig_pubkey.pubkey, descr.weight, ptr->total_weight, descr.adnl_addr); - ptr->total_weight += descr.weight; - } - if (rec.total_weight && rec.total_weight != ptr->total_weight) { - return td::Status::Error("validator set declares incorrect total weight"); - } - return std::move(ptr); -} - -bool Config::set_block_id_ext(const ton::BlockIdExt& block_id_ext) { - if (block_id.id == block_id_ext.id) { - block_id = block_id_ext; - return true; - } else { - return false; - } -} - -bool ConfigInfo::set_block_id_ext(const ton::BlockIdExt& block_id_ext) { - if (!Config::set_block_id_ext(block_id_ext)) { - return false; - } - if (!block_id.seqno()) { - zerostate_id_.workchain = ton::masterchainId; - zerostate_id_.root_hash = block_id_ext.root_hash; - zerostate_id_.file_hash = block_id_ext.file_hash; - } - reset_mc_hash(); - return true; -} - -void ConfigInfo::cleanup() { - if (!(mode & needStateRoot)) { - state_root.clear(); - } - if (!(mode & needStateExtraRoot)) { - state_extra_root_.clear(); - } -} - -Ref Config::get_config_param(int idx) const { - if (!config_dict) { - return {}; - } - return config_dict->lookup_ref(td::BitArray<32>{idx}); -} - -Ref Config::get_config_param(int idx, int idx2) const { - if (!config_dict) { - return {}; - } - auto res = config_dict->lookup_ref(td::BitArray<32>{idx}); - if (res.not_null()) { - return res; - } else { - return config_dict->lookup_ref(td::BitArray<32>{idx2}); - } -} - -td::Result> Config::get_block_limits(bool is_masterchain) const { - int param = (is_masterchain ? 22 : 23); - auto cell = get_config_param(param); - if (cell.is_null()) { - return td::Status::Error(PSTRING() << "configuration parameter " << param << " with block limits is absent"); - } - auto cs = vm::load_cell_slice(std::move(cell)); - auto ptr = std::make_unique(); - if (!ptr->deserialize(cs) || cs.size_ext()) { - return td::Status::Error(PSTRING() << "cannot deserialize BlockLimits obtained from configuration parameter " - << param); - } - return std::move(ptr); -} - -td::Result> Config::get_storage_prices() const { - auto cell = get_config_param(18); - std::vector res; - if (cell.is_null()) { - return td::Status::Error("configuration parameter 18 with storage prices dictionary is absent"); - } - vm::Dictionary dict{std::move(cell), 32}; - if (!dict.check_for_each([&res](Ref cs_ref, td::ConstBitPtr key, int n) -> bool { - block::gen::StoragePrices::Record data; - if (!tlb::csr_unpack(std::move(cs_ref), data) || data.utime_since != key.get_uint(n)) { - return false; - } - res.emplace_back(data.utime_since, data.bit_price_ps, data.cell_price_ps, data.mc_bit_price_ps, - data.mc_cell_price_ps); - return true; - })) { - return td::Status::Error("invalid storage prices dictionary in configuration parameter 18"); - } - return std::move(res); -} - -td::Result Config::do_get_gas_limits_prices(td::Ref cell, int id) { - GasLimitsPrices res; - auto cs = vm::load_cell_slice(cell); - block::gen::GasLimitsPrices::Record_gas_flat_pfx flat; - if (tlb::unpack(cs, flat)) { - cs = *flat.other; - res.flat_gas_limit = flat.flat_gas_limit; - res.flat_gas_price = flat.flat_gas_price; - } else { - cs = vm::load_cell_slice(cell); - } - auto f = [&](const auto& r, td::uint64 spec_limit) { - res.gas_limit = r.gas_limit; - res.special_gas_limit = spec_limit; - res.gas_credit = r.gas_credit; - res.gas_price = r.gas_price; - res.freeze_due_limit = r.freeze_due_limit; - res.delete_due_limit = r.delete_due_limit; - }; - block::gen::GasLimitsPrices::Record_gas_prices_ext rec; - if (tlb::unpack(cs, rec)) { - f(rec, rec.special_gas_limit); - } else { - block::gen::GasLimitsPrices::Record_gas_prices rec0; - if (tlb::unpack(cs, rec0)) { - f(rec0, rec0.gas_limit); - } else { - return td::Status::Error(PSLICE() << "configuration parameter " << id - << " with gas prices is invalid - can't parse"); - } - } - return res; -} - -td::Result Config::get_dns_root_addr() const { - auto cell = get_config_param(4); - if (cell.is_null()) { - return td::Status::Error(PSLICE() << "configuration parameter " << 4 << " with dns root address is absent"); - } - auto cs = vm::load_cell_slice(std::move(cell)); - if (cs.size() != 0x100) { - return td::Status::Error(PSLICE() << "configuration parameter " << 4 << " with dns root address has wrong size"); - } - ton::StdSmcAddress res; - CHECK(cs.fetch_bits_to(res)); - return res; -} - -td::Result Config::get_gas_limits_prices(bool is_masterchain) const { - auto id = is_masterchain ? 20 : 21; - auto cell = get_config_param(id); - if (cell.is_null()) { - return td::Status::Error(PSLICE() << "configuration parameter " << id << " with gas prices is absent"); - } - return do_get_gas_limits_prices(std::move(cell), id); -} - -td::Result Config::get_msg_prices(bool is_masterchain) const { - auto id = is_masterchain ? 24 : 25; - auto cell = get_config_param(id); - if (cell.is_null()) { - return td::Status::Error(PSLICE() << "configuration parameter " << id << " with msg prices is absent"); - } - auto cs = vm::load_cell_slice(std::move(cell)); - block::gen::MsgForwardPrices::Record rec; - if (!tlb::unpack(cs, rec)) { - return td::Status::Error(PSLICE() << "configuration parameter " << id - << " with msg prices is invalid - can't parse"); - } - return MsgPrices(rec.lump_price, rec.bit_price, rec.cell_price, rec.ihr_price_factor, rec.first_frac, rec.next_frac); -} - -CatchainValidatorsConfig Config::unpack_catchain_validators_config(Ref cell) { - if (cell.not_null()) { - block::gen::CatchainConfig::Record_catchain_config cfg; - if (tlb::unpack_cell(cell, cfg)) { - return {cfg.mc_catchain_lifetime, cfg.shard_catchain_lifetime, cfg.shard_validators_lifetime, - cfg.shard_validators_num}; - } - block::gen::CatchainConfig::Record_catchain_config_new cfg2; - if (tlb::unpack_cell(std::move(cell), cfg2)) { - return {cfg2.mc_catchain_lifetime, cfg2.shard_catchain_lifetime, cfg2.shard_validators_lifetime, - cfg2.shard_validators_num, cfg2.shuffle_mc_validators}; - } - } - return {default_mc_catchain_lifetime, default_shard_catchain_lifetime, default_shard_validators_lifetime, - default_shard_validators_num}; -} - -CatchainValidatorsConfig Config::get_catchain_validators_config() const { - return unpack_catchain_validators_config(get_config_param(28)); -} - -// compares all fields except fsm*, before_merge_, nx_cc_updated_, next_catchain_seqno_ -bool McShardHash::basic_info_equal(const McShardHash& other, bool compare_fees, bool compare_reg_seqno) const { - return blk_ == other.blk_ && start_lt_ == other.start_lt_ && end_lt_ == other.end_lt_ && - (!compare_reg_seqno || reg_mc_seqno_ == other.reg_mc_seqno_) && gen_utime_ == other.gen_utime_ && - min_ref_mc_seqno_ == other.min_ref_mc_seqno_ && before_split_ == other.before_split_ && - want_split_ == other.want_split_ && want_merge_ == other.want_merge_ && - (!compare_fees || (fees_collected_ == other.fees_collected_ && funds_created_ == other.funds_created_)); -} - -void McShardHash::set_fsm(FsmState fsm, ton::UnixTime fsm_utime, ton::UnixTime fsm_interval) { - fsm_ = fsm; - fsm_utime_ = fsm_utime; - fsm_interval_ = fsm_interval; -} - -Ref McShardHash::unpack(vm::CellSlice& cs, ton::ShardIdFull id) { - int tag = gen::t_ShardDescr.get_tag(cs); - if (tag < 0) { - return {}; - } - auto create = [&id](auto& descr, Ref fees, Ref funds) { - CurrencyCollection fees_collected, funds_created; - if (!(fees_collected.unpack(std::move(fees)) && funds_created.unpack(std::move(funds)))) { - return Ref{}; - } - return td::make_ref(ton::BlockId{id, (unsigned)descr.seq_no}, descr.start_lt, descr.end_lt, - descr.gen_utime, descr.root_hash, descr.file_hash, fees_collected, funds_created, - descr.reg_mc_seqno, descr.min_ref_mc_seqno, descr.next_catchain_seqno, - descr.next_validator_shard, /* descr.nx_cc_updated */ false, descr.before_split, - descr.before_merge, descr.want_split, descr.want_merge); - }; - Ref res; - Ref fsm_cs; - if (tag == gen::ShardDescr::shard_descr) { - gen::ShardDescr::Record_shard_descr descr; - if (tlb::unpack_exact(cs, descr)) { - fsm_cs = std::move(descr.split_merge_at); - res = create(descr, std::move(descr.fees_collected), std::move(descr.funds_created)); - } - } else { - gen::ShardDescr::Record_shard_descr_new descr; - if (tlb::unpack_exact(cs, descr)) { - fsm_cs = std::move(descr.split_merge_at); - res = create(descr, std::move(descr.r1.fees_collected), std::move(descr.r1.funds_created)); - } - } - if (res.is_null()) { - return res; - } - McShardHash& sh = res.unique_write(); - switch (gen::t_FutureSplitMerge.get_tag(*fsm_cs)) { - case gen::FutureSplitMerge::fsm_none: - return res; - case gen::FutureSplitMerge::fsm_split: - if (gen::t_FutureSplitMerge.unpack_fsm_split(fsm_cs.write(), sh.fsm_utime_, sh.fsm_interval_)) { - sh.fsm_ = FsmState::fsm_split; - return res; - } - break; - case gen::FutureSplitMerge::fsm_merge: - if (gen::t_FutureSplitMerge.unpack_fsm_merge(fsm_cs.write(), sh.fsm_utime_, sh.fsm_interval_)) { - sh.fsm_ = FsmState::fsm_merge; - return res; - } - break; - default: - break; - } - return {}; -} - -bool McShardHash::pack(vm::CellBuilder& cb) const { - if (!(is_valid() // (validate) - && cb.store_long_bool(10, 4) // shard_descr_new#a - && cb.store_long_bool(blk_.id.seqno, 32) // seq_no:uint32 - && cb.store_long_bool(reg_mc_seqno_, 32) // reg_mc_seqno:uint32 - && cb.store_long_bool(start_lt_, 64) // start_lt:uint64 - && cb.store_long_bool(end_lt_, 64) // end_lt:uint64 - && cb.store_bits_bool(blk_.root_hash) // root_hash:bits256 - && cb.store_bits_bool(blk_.file_hash) // file_hash:bits256 - && cb.store_bool_bool(before_split_) // before_split:Bool - && cb.store_bool_bool(before_merge_) // before_merge:Bool - && cb.store_bool_bool(want_split_) // want_split:Bool - && cb.store_bool_bool(want_merge_) // want_merge:Bool - && cb.store_bool_bool(false) // nx_cc_updated:Bool - && cb.store_long_bool(0, 3) // flags:(## 3) { flags = 0 } - && cb.store_long_bool(next_catchain_seqno_, 32) // next_catchain_seqno:uint32 - && cb.store_long_bool(next_validator_shard_, 64) // next_validator_shard:uint64 - && cb.store_long_bool(min_ref_mc_seqno_, 32) // min_ref_mc_seqno:uint32 - && cb.store_long_bool(gen_utime_, 32) // gen_utime:uint32 - )) { - return false; - } - bool ok; - switch (fsm_) { // split_merge_at:FutureSplitMerge - case FsmState::fsm_none: - ok = gen::t_FutureSplitMerge.pack_fsm_none(cb); - break; - case FsmState::fsm_split: - ok = gen::t_FutureSplitMerge.pack_fsm_split(cb, fsm_utime_, fsm_interval_); - break; - case FsmState::fsm_merge: - ok = gen::t_FutureSplitMerge.pack_fsm_merge(cb, fsm_utime_, fsm_interval_); - break; - default: - return false; - } - vm::CellBuilder cb2; - return ok // split_merge_at:FutureSplitMerge - && fees_collected_.store_or_zero(cb2) // ^[ fees_collected:CurrencyCollection - && funds_created_.store_or_zero(cb2) // funds_created:CurrencyCollection ] - && cb.store_builder_ref_bool(std::move(cb2)); // = ShardDescr; -} - -Ref McShardHash::from_block(Ref block_root, const ton::FileHash& fhash, bool init_fees) { - if (block_root.is_null()) { - return {}; - } - block::gen::Block::Record rec; - block::gen::BlockInfo::Record info; - block::ShardId shard; - if (!(tlb::unpack_cell(block_root, rec) && tlb::unpack_cell(rec.info, info) && - shard.deserialize(info.shard.write()))) { - return {}; - } - ton::RootHash rhash = block_root->get_hash().bits(); - CurrencyCollection fees_collected, funds_created; - if (init_fees) { - block::gen::ValueFlow::Record flow; - if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) && - funds_created.unpack(flow.r2.created))) { - return {}; - } - } - return Ref(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt, - info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U, - info.min_ref_mc_seqno, info.gen_catchain_seqno, shard.shard_pfx, false, info.before_split, - false, info.want_split, info.want_merge); -} - -McShardDescr::McShardDescr(const McShardDescr& other) - : McShardHash(other) - , block_root(other.block_root) - , state_root(other.state_root) - , processed_upto(other.processed_upto) { - set_queue_root(other.outmsg_root); -} - -McShardDescr& McShardDescr::operator=(const McShardDescr& other) { - McShardHash::operator=(other); - block_root = other.block_root; - outmsg_root = other.outmsg_root; - processed_upto = other.processed_upto; - set_queue_root(other.outmsg_root); - return *this; -} - -Ref McShardDescr::from_block(Ref block_root, Ref state_root, - const ton::FileHash& fhash, bool init_fees) { - if (block_root.is_null()) { - return {}; - } - block::gen::Block::Record rec; - block::gen::BlockInfo::Record info; - block::ShardId shard; - if (!(tlb::unpack_cell(block_root, rec) && tlb::unpack_cell(rec.info, info) && - shard.deserialize(info.shard.write()))) { - return {}; - } - // TODO: use a suitable vm::MerkleUpdate method here - vm::CellSlice cs(vm::NoVmSpec(), rec.state_update); - if (!cs.is_valid() || cs.special_type() != vm::Cell::SpecialType::MerkleUpdate) { - LOG(ERROR) << "state update in a block is not a Merkle update"; - return {}; - } - if (cs.size_refs() != 2 || cs.prefetch_ref(1)->get_hash(0) != state_root->get_hash()) { - LOG(ERROR) << "invalid Merkle update for block state : resulting state hash mismatch"; - return {}; - } - ton::RootHash rhash = block_root->get_hash().bits(); - CurrencyCollection fees_collected, funds_created; - if (init_fees) { - block::gen::ValueFlow::Record flow; - if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) && - funds_created.unpack(flow.r2.created))) { - return {}; - } - } - auto res = Ref(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt, - info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U, - info.min_ref_mc_seqno, info.gen_catchain_seqno, shard.shard_pfx, false, - info.before_split, false, info.want_split, info.want_merge); - auto& descr = res.unique_write(); - descr.block_root = std::move(block_root); - descr.state_root = std::move(state_root); - return res; -} - -Ref McShardDescr::from_state(ton::BlockIdExt blkid, Ref state_root) { - if (state_root.is_null()) { - return {}; - } - block::gen::ShardStateUnsplit::Record info; - block::gen::OutMsgQueueInfo::Record qinfo; - block::ShardId shard; - if (!(tlb::unpack_cell(state_root, info) && shard.deserialize(info.shard_id.write()) && - tlb::unpack_cell(info.out_msg_queue_info, qinfo))) { - LOG(DEBUG) << "cannot create McShardDescr from a shardchain state"; - return {}; - } - if (ton::ShardIdFull(shard) != ton::ShardIdFull(blkid) || info.seq_no != blkid.seqno()) { - LOG(DEBUG) << "shard id mismatch, cannot construct McShardDescr"; - return {}; - } - auto res = Ref(true, blkid.id, info.gen_lt, info.gen_lt, info.gen_utime, blkid.root_hash, - blkid.file_hash, CurrencyCollection{}, CurrencyCollection{}, ~0U, info.min_ref_mc_seqno, - 0, shard.shard_pfx, false, info.before_split); - res.unique_write().state_root = state_root; - res.unique_write().set_queue_root(qinfo.out_queue->prefetch_ref(0)); - return res; -} - -bool McShardDescr::set_queue_root(Ref queue_root) { - outmsg_root = std::move(queue_root); - out_msg_queue = std::make_unique(outmsg_root, 352, block::tlb::aug_OutMsgQueue); - return true; -} - -void McShardDescr::disable() { - block_root.clear(); - state_root.clear(); - outmsg_root.clear(); - out_msg_queue.reset(); - processed_upto.reset(); - McShardHash::disable(); -} - -void ConfigInfo::reset_mc_hash() { - if (block_id.is_masterchain() && !block_id.root_hash.is_zero()) { - // TODO: use block_start_lt instead of lt if available - set_mc_hash(Ref(true, block_id.id, lt, lt, utime, block_id.root_hash, block_id.file_hash)); - } else { - set_mc_hash(Ref{}); - } -} - -Ref ShardConfig::get_root_csr() const { - if (!shard_hashes_dict_) { - return {}; - } - return shard_hashes_dict_->get_root(); -} - -bool ShardConfig::unpack(Ref shard_hashes, Ref mc_shard_hash) { - shard_hashes_ = std::move(shard_hashes); - mc_shard_hash_ = std::move(mc_shard_hash); - return init(); -} - -bool ShardConfig::unpack(Ref shard_hashes, Ref mc_shard_hash) { - shard_hashes_ = shard_hashes->prefetch_ref(); - mc_shard_hash_ = std::move(mc_shard_hash); - return init(); -} - -bool ShardConfig::init() { - shard_hashes_dict_ = std::make_unique(shard_hashes_, 32); - valid_ = true; - return true; -} - -ShardConfig::ShardConfig(const ShardConfig& other) - : shard_hashes_(other.shard_hashes_), mc_shard_hash_(other.mc_shard_hash_) { - init(); -} - -bool ShardConfig::get_shard_hash_raw_from(vm::Dictionary& dict, vm::CellSlice& cs, ton::ShardIdFull id, - ton::ShardIdFull& true_id, bool exact, Ref* leaf) { - if (id.is_masterchain() || !id.is_valid()) { - return false; - } - auto root = dict.lookup_ref(td::BitArray<32>{id.workchain}); - if (root.is_null()) { - return false; - } - unsigned long long z = id.shard, m = std::numeric_limits::max(); - int len = id.pfx_len(); - while (true) { - cs.load(vm::NoVmOrd(), leaf ? root : std::move(root)); - int t = (int)cs.fetch_ulong(1); - if (t < 0) { - return false; // throw DictError ? - } else if (!t) { - if (len && exact) { - return false; - } - true_id = ton::ShardIdFull{id.workchain, (id.shard | m) - (m >> 1)}; - if (leaf) { - *leaf = std::move(root); - } - return true; - } - if (!len || cs.size_ext() != 0x20000) { - return false; // throw DictError in the second case? - } - root = cs.prefetch_ref((unsigned)(z >> 63)); - z <<= 1; - --len; - m >>= 1; - } -} - -bool ShardConfig::get_shard_hash_raw(vm::CellSlice& cs, ton::ShardIdFull id, ton::ShardIdFull& true_id, - bool exact) const { - return shard_hashes_dict_ && get_shard_hash_raw_from(*shard_hashes_dict_, cs, id, true_id, exact); -} - -Ref ShardConfig::get_shard_hash(ton::ShardIdFull id, bool exact) const { - if (id.is_masterchain()) { - return (!exact || id.shard == ton::shardIdAll) ? get_mc_hash() : Ref{}; - } - ton::ShardIdFull true_id; - vm::CellSlice cs; - if (get_shard_hash_raw(cs, id, true_id, exact)) { - // block::gen::t_ShardDescr.print(std::cerr, vm::CellSlice{cs}); - return McShardHash::unpack(cs, true_id); - } else { - return {}; - } -} - -bool McShardHash::extract_cc_seqno(vm::CellSlice& cs, ton::CatchainSeqno* cc) { - auto get = [&cs, cc](auto& rec) { - if (tlb::unpack_exact(cs, rec)) { - *cc = rec.next_catchain_seqno; - return true; - } else { - *cc = std::numeric_limits::max(); - return false; - } - }; - if (block::gen::t_ShardDescr.get_tag(cs) == block::gen::ShardDescr::shard_descr) { - gen::ShardDescr::Record_shard_descr rec; - return get(rec); - } else { - gen::ShardDescr::Record_shard_descr_new rec; - return get(rec); - } -} - -ton::CatchainSeqno ShardConfig::get_shard_cc_seqno(ton::ShardIdFull shard) const { - if (shard.is_masterchain() || !shard.is_valid()) { - return std::numeric_limits::max(); - } - ton::ShardIdFull true_id; - ton::CatchainSeqno cc_seqno, cc_seqno2; - vm::CellSlice cs; - if (!(get_shard_hash_raw(cs, shard - 1, true_id, false) && - (ton::shard_is_ancestor(true_id, shard) || ton::shard_is_parent(shard, true_id)) && - McShardHash::extract_cc_seqno(cs, &cc_seqno))) { - return std::numeric_limits::max(); - } - if (ton::shard_is_ancestor(true_id, shard)) { - return cc_seqno; - } - if (!(get_shard_hash_raw(cs, shard + 1, true_id, false) && ton::shard_is_parent(shard, true_id) && - McShardHash::extract_cc_seqno(cs, &cc_seqno2))) { - return std::numeric_limits::max(); - } - return std::max(cc_seqno, cc_seqno2) + 1; -} - -ton::LogicalTime ShardConfig::get_shard_end_lt_ext(ton::AccountIdPrefixFull acc, ton::ShardIdFull& actual_shard) const { - if (!acc.is_valid()) { - actual_shard.workchain = ton::workchainInvalid; - return 0; - } - if (acc.is_masterchain()) { - actual_shard = ton::ShardIdFull(ton::masterchainId); - CHECK(mc_shard_hash_.not_null()); - return mc_shard_hash_->end_lt_; - } - vm::CellSlice cs; - unsigned long long end_lt; - return get_shard_hash_raw(cs, acc.as_leaf_shard(), actual_shard, false) // lookup ShardDescr containing acc - && cs.advance(4 + 128) // shard_descr#b seq_no:uint32 reg_mc_seqno:uint32 start_lt:uint64 - && cs.fetch_ulong_bool(64, end_lt) // end_lt:uint64 - ? end_lt - : 0; -} - -ton::LogicalTime ShardConfig::get_shard_end_lt(ton::AccountIdPrefixFull acc) const { - ton::ShardIdFull tmp; - return get_shard_end_lt_ext(acc, tmp); -} - -bool ShardConfig::contains(ton::BlockIdExt blkid) const { - auto entry = get_shard_hash(blkid.shard_full()); - return entry.not_null() && entry->blk_ == blkid; -} - -static int process_workchain_shard_hashes(Ref& branch, ton::ShardIdFull shard, - std::function& func) { - auto cs = vm::load_cell_slice(branch); - int f = (int)cs.fetch_ulong(1); - if (f == 1) { - if ((shard.shard & 1) || cs.size_ext() != 0x20000) { - return -1; - } - auto left = cs.prefetch_ref(0), right = cs.prefetch_ref(1); - int r = process_workchain_shard_hashes(left, ton::shard_child(shard, true), func); - if (r < 0) { - return r; - } - r |= process_workchain_shard_hashes(right, ton::shard_child(shard, false), func); - if (r <= 0) { - return r; - } - vm::CellBuilder cb; - return cb.store_bool_bool(true) && cb.store_ref_bool(std::move(left)) && cb.store_ref_bool(std::move(right)) && - cb.finalize_to(branch) - ? r - : -1; - } else if (!f) { - auto shard_info = McShardHash::unpack(cs, shard); - if (shard_info.is_null()) { - return -1; - } - int r = func(shard_info.write()); - if (r <= 0) { - return r; - } - vm::CellBuilder cb; - return cb.store_bool_bool(false) && shard_info->pack(cb) && cb.finalize_to(branch) ? r : -1; - } else { - return -1; - } -} - -bool ShardConfig::process_shard_hashes(std::function func) { - if (!shard_hashes_dict_) { - return false; - } - bool ok = true; - shard_hashes_dict_->map( - [&ok, &func](vm::CellBuilder& cb, Ref csr, td::ConstBitPtr key, int n) -> bool { - Ref root; - ok = ok && (n == 32) && csr->size_ext() == 0x10000 && std::move(csr)->prefetch_ref_to(root) && - process_workchain_shard_hashes(root, ton::ShardIdFull{(int)key.get_int(32)}, func) >= 0 && - cb.store_ref_bool(std::move(root)); - return true; - }); - return ok; -} - -static int process_workchain_sibling_shard_hashes(Ref& branch, Ref sibling, ton::ShardIdFull shard, - std::function& func) { - auto cs = vm::load_cell_slice(branch); - int f = (int)cs.fetch_ulong(1); - if (f == 1) { - if ((shard.shard & 1) || cs.size_ext() != 0x20000) { - return false; - } - auto left = cs.prefetch_ref(0), right = cs.prefetch_ref(1); - auto orig_left = left; - int r = process_workchain_sibling_shard_hashes(left, right, ton::shard_child(shard, true), func); - if (r < 0) { - return r; - } - r |= process_workchain_sibling_shard_hashes(right, std::move(orig_left), ton::shard_child(shard, false), func); - if (r <= 0) { - return r; - } - vm::CellBuilder cb; - return cb.store_bool_bool(true) && cb.store_ref_bool(std::move(left)) && cb.store_ref_bool(std::move(right)) && - cb.finalize_to(branch) - ? r - : -1; - } else if (!f) { - auto shard_info = McShardHash::unpack(cs, shard); - if (shard_info.is_null()) { - return -1; - } - Ref sibling_info; - if (sibling.not_null()) { - auto cs2 = vm::load_cell_slice(sibling); - if (!cs2.fetch_ulong(1)) { - sibling_info = McShardHash::unpack(cs2, ton::shard_sibling(shard)); - if (sibling_info.is_null()) { - return -1; - } - } - } - int r = func(shard_info.write(), sibling_info.get()); - if (r <= 0) { - return r; - } - vm::CellBuilder cb; - return cb.store_bool_bool(false) && shard_info->pack(cb) && cb.finalize_to(branch) ? r : -1; - } else { - return -1; - } -} - -bool ShardConfig::process_sibling_shard_hashes(std::function func) { - if (!shard_hashes_dict_) { - return false; - } - bool ok = true; - shard_hashes_dict_->map([&ok, &func](vm::CellBuilder& cb, Ref csr, td::ConstBitPtr key, - int n) -> bool { - Ref root; - ok = ok && (n == 32) && csr->size_ext() == 0x10000 && std::move(csr)->prefetch_ref_to(root) && - process_workchain_sibling_shard_hashes(root, Ref{}, ton::ShardIdFull{(int)key.get_int(32)}, func) >= - 0; - bool f = cb.store_ref_bool(std::move(root)); - ok &= f; - return f; - }); - return ok; -} - -std::vector ShardConfig::get_shard_hash_ids( - const std::function& filter) const { - if (!shard_hashes_dict_) { - return {}; - } - std::vector res; - bool mcout = mc_shard_hash_.is_null() || !mc_shard_hash_->seqno(); // include masterchain as a shard if seqno > 0 - bool ok = shard_hashes_dict_->check_for_each( - [&res, &mcout, mc_shard_hash_ = mc_shard_hash_, &filter](Ref cs_ref, td::ConstBitPtr key, - int n) -> bool { - int workchain = (int)key.get_int(n); - if (workchain >= 0 && !mcout) { - if (filter(ton::ShardIdFull{ton::masterchainId}, true)) { - res.emplace_back(mc_shard_hash_->blk_.id); - } - mcout = true; - } - if (!cs_ref->have_refs()) { - return false; - } - std::stack, unsigned long long>> stack; - stack.emplace(cs_ref->prefetch_ref(), ton::shardIdAll); - while (!stack.empty()) { - vm::CellSlice cs{vm::NoVmOrd(), std::move(stack.top().first)}; - unsigned long long shard = stack.top().second; - stack.pop(); - int t = (int)cs.fetch_ulong(1); - if (t < 0) { - return false; - } - if (!filter(ton::ShardIdFull{workchain, shard}, !t)) { - continue; - } - if (!t) { - if (!(cs.advance(4) && cs.have(32))) { - return false; - } - res.emplace_back(workchain, shard, (int)cs.prefetch_ulong(32)); - continue; - } - unsigned long long delta = (td::lower_bit64(shard) >> 1); - if (!delta || cs.size_ext() != 0x20000) { - return false; - } - stack.emplace(cs.prefetch_ref(1), shard + delta); - stack.emplace(cs.prefetch_ref(0), shard - delta); - } - return true; - }, - true); - if (!ok) { - return {}; - } - if (!mcout && filter(ton::ShardIdFull{ton::masterchainId}, true)) { - res.emplace_back(mc_shard_hash_->blk_.id); - } - return res; -} - -std::vector ShardConfig::get_shard_hash_ids(bool skip_mc) const { - return get_shard_hash_ids( - [skip_mc](ton::ShardIdFull shard, bool) -> bool { return !(skip_mc && shard.is_masterchain()); }); -} - -std::vector ShardConfig::get_intersecting_shard_hash_ids(ton::ShardIdFull myself) const { - return get_shard_hash_ids( - [myself](ton::ShardIdFull shard, bool) -> bool { return ton::shard_intersects(myself, shard); }); -} - -std::vector ShardConfig::get_neighbor_shard_hash_ids(ton::ShardIdFull myself) const { - return get_shard_hash_ids([myself](ton::ShardIdFull shard, bool) -> bool { return is_neighbor(myself, shard); }); -} - -std::vector ShardConfig::get_proper_neighbor_shard_hash_ids(ton::ShardIdFull myself) const { - return get_shard_hash_ids([myself](ton::ShardIdFull shard, bool leaf) -> bool { - return is_neighbor(myself, shard) && !(leaf && ton::shard_intersects(myself, shard)); - }); -} - -bool ShardConfig::is_neighbor(ton::ShardIdFull x, ton::ShardIdFull y) { - if (x.is_masterchain() || y.is_masterchain()) { - return true; - } - unsigned long long xs = x.shard, ys = y.shard; - unsigned long long xl = td::lower_bit64(xs), yl = td::lower_bit64(ys); - unsigned long long z = (xs ^ ys) & td::bits_negate64(std::max(xl, yl) << 1); - if (!z) { - return true; - } - if (x.workchain != y.workchain) { - return false; - } - int c1 = (td::count_leading_zeroes_non_zero64(z) >> 2); - int c2 = (td::count_trailing_zeroes_non_zero64(z) >> 2); - return c1 + c2 == 15; -} - -bool ShardConfig::has_workchain(ton::WorkchainId workchain) const { - return shard_hashes_dict_ && shard_hashes_dict_->key_exists(td::BitArray<32>{workchain}); -} - -std::vector ShardConfig::get_workchains() const { - if (!shard_hashes_dict_) { - return {}; - } - std::vector res; - if (!shard_hashes_dict_->check_for_each([&res](Ref val, td::ConstBitPtr key, int n) { - CHECK(n == 32); - ton::WorkchainId w = (int)key.get_int(32); - res.push_back(w); - return true; - })) { - return {}; - } - return res; -} - -bool ShardConfig::new_workchain(ton::WorkchainId workchain, ton::BlockSeqno reg_mc_seqno, - const ton::RootHash& zerostate_root_hash, const ton::FileHash& zerostate_file_hash) { - if (!shard_hashes_dict_ || has_workchain(workchain)) { - return false; - } - vm::CellBuilder cb; - Ref cell; - return cb.store_long_bool(11, 1 + 4) // bt_leaf$0 ; shard_descr#b - && cb.store_zeroes_bool(32) // seq_no:uint32 - && cb.store_long_bool(reg_mc_seqno, 32) // reg_mc_seqno:uint32 - && cb.store_zeroes_bool(64 * 2) // start_lt:uint64 end_lt:uint64 - && cb.store_bits_bool(zerostate_root_hash) // root_hash:bits256 - && cb.store_bits_bool(zerostate_file_hash) // file_hash:bits256 - && cb.store_long_bool(0, 8) // ... nx_cc_updated:Bool ... - && cb.store_long_bool(0, 32) // next_catchain_seqno:uint32 - && cb.store_long_bool(1ULL << 63, 64) // next_validator_shard:uint64 - && cb.store_long_bool(~0U, 32) // min_ref_mc_seqno:uint32 - && cb.store_long_bool(0, 32) // gen_utime:uint32 - && - cb.store_zeroes_bool( - 1 + 5 + - 5) // split_merge_at:FutureSplitMerge fees_collected:CurrencyCollection funds_created:CurrencyCollection - && cb.finalize_to(cell) && block::gen::t_BinTree_ShardDescr.validate_ref(1024, cell) && - shard_hashes_dict_->set_ref(td::BitArray<32>{workchain}, std::move(cell), vm::Dictionary::SetMode::Add); -} - -td::Result ShardConfig::may_update_shard_block_info(Ref new_info, - const std::vector& old_blkids, - ton::LogicalTime lt_limit, Ref* ancestor) const { - if (!shard_hashes_dict_) { - return td::Status::Error(-666, "no shard top block dictionary present"); - } - if (new_info.is_null()) { - return td::Status::Error(-666, "suggested new top shard block info is empty"); - } - if (!new_info->is_valid()) { - return td::Status::Error(-666, "new top shard block description is invalid"); - } - auto wc = new_info->shard().workchain; - if (wc == ton::workchainInvalid || wc == ton::masterchainId) { - return td::Status::Error(-666, "new top shard block description belongs to an invalid workchain"); - } - if (!has_workchain(wc)) { - return td::Status::Error(-666, "new top shard block belongs to an unknown or disabled workchain"); - } - if (old_blkids.size() != 1 && old_blkids.size() != 2) { - return td::Status::Error(-666, "must have either one or two start blocks in a top shard block update"); - } - bool before_split = ton::shard_is_parent(old_blkids[0].shard_full(), new_info->shard()); - bool before_merge = (old_blkids.size() == 2); - if (before_merge) { - if (!ton::shard_is_sibling(old_blkids[0].shard_full(), old_blkids[1].shard_full())) { - return td::Status::Error(-666, "the two start blocks of a top shard block update must be siblings"); - } - if (!ton::shard_is_parent(new_info->shard(), old_blkids[0].shard_full())) { - return td::Status::Error( - -666, - std::string{"the two start blocks of a top shard block update do not merge into expected final shard "} + - old_blkids[0].shard_full().to_str()); - } - } else if (new_info->shard() != old_blkids[0].shard_full() && !before_split) { - return td::Status::Error( - -666, "the start block of a top shard block update must either coincide with the final shard or be its parent"); - } - if (ancestor) { - ancestor->clear(); - } - ton::CatchainSeqno old_cc_seqno = 0; - for (const auto& ob : old_blkids) { - auto odef = get_shard_hash(ob.shard_full()); - if (odef.is_null() || odef->blk_ != ob) { - return td::Status::Error(-666, - std::string{"the start block "} + ob.to_str() + - " of a top shard block update is not contained in the previous shard configuration"); - } - old_cc_seqno = std::max(old_cc_seqno, odef->next_catchain_seqno_); - if (shards_updated_.find(ob.shard_full()) != shards_updated_.end()) { - return td::Status::Error( - -666, std::string{"the shard of the start block "} + ob.to_str() + - " of a top shard block update has been already updated in the current shard configuration"); - } - if (odef->before_split_ != before_split) { - return td::Status::Error( - -666, PSTRING() << "the shard of the start block " << ob.to_str() - << " had before_split=" << odef->before_split_ - << " but the top shard block update is valid only if before_split=" << before_split); - } - if (odef->before_merge_ != before_merge) { - return td::Status::Error( - -666, PSTRING() << "the shard of the start block " << ob.to_str() - << " had before_merge=" << odef->before_merge_ - << " but the top shard block update is valid only if before_merge=" << before_merge); - } - if (new_info->before_split_) { - if (before_merge || before_split) { - return td::Status::Error( - -666, PSTRING() << "cannot register a before-split block " << new_info->top_block_id().to_str() - << " at the end of a chain that itself starts with a split/merge event"); - } - if (odef->fsm_state() != block::McShardHash::FsmState::fsm_split) { - return td::Status::Error(-666, PSTRING() << "cannot register a before-split block " - << new_info->top_block_id().to_str() - << " because fsm_split state was not set for this shard beforehand"); - } - if (new_info->gen_utime_ < odef->fsm_utime_ || new_info->gen_utime_ >= odef->fsm_utime_ + odef->fsm_interval_) { - return td::Status::Error(-666, PSTRING() << "cannot register a before-split block " - << new_info->top_block_id().to_str() - << " because fsm_split state was enabled for unixtime " - << odef->fsm_utime_ << " .. " << odef->fsm_utime_ + odef->fsm_interval_ - << " but the block is generated at " << new_info->gen_utime_); - } - } - if (before_merge) { - if (odef->fsm_state() != block::McShardHash::FsmState::fsm_merge) { - return td::Status::Error(-666, PSTRING() << "cannot register merged block " << new_info->top_block_id().to_str() - << " because fsm_merge state was not set for shard " - << odef->top_block_id().shard_full().to_str() << " beforehand"); - } - if (new_info->gen_utime_ < odef->fsm_utime_ || new_info->gen_utime_ >= odef->fsm_utime_ + odef->fsm_interval_) { - return td::Status::Error(-666, PSTRING() << "cannot register merged block " << new_info->top_block_id().to_str() - << " because fsm_merge state was enabled for shard " - << odef->top_block_id().shard_full().to_str() << " for unixtime " - << odef->fsm_utime_ << " .. " << odef->fsm_utime_ + odef->fsm_interval_ - << " but the block is generated at " << new_info->gen_utime_); - } - } - if (ancestor && !before_merge && !before_split) { - *ancestor = odef; - } - } - if (old_cc_seqno + before_merge != new_info->next_catchain_seqno_) { - return td::Status::Error(-666, PSTRING() - << "the top shard block update is generated with catchain_seqno=" - << new_info->next_catchain_seqno_ << " but previous shard configuration expects " - << old_cc_seqno + before_merge); - } - if (new_info->end_lt_ >= lt_limit) { - return td::Status::Error(-666, PSTRING() << "the top shard block update has end_lt " << new_info->end_lt_ - << " which is larger than the current limit " << lt_limit); - } - return !before_split; -} - -td::Result ShardConfig::update_shard_block_info(Ref new_info, - const std::vector& old_blkids) { - Ref ancestor; - auto res = may_update_shard_block_info(new_info, old_blkids, ~0ULL, &ancestor); - if (res.is_error()) { - return res; - } - if (!res.move_as_ok()) { - return td::Status::Error(-666, std::string{"cannot apply the after-split update for "} + new_info->blk_.to_str() + - " without a corresponding sibling update"); - } - if (ancestor.not_null() && ancestor->fsm_ != McShardHash::FsmState::fsm_none) { - new_info.write().set_fsm(ancestor->fsm_, ancestor->fsm_utime_, ancestor->fsm_interval_); - } - auto blk = new_info->blk_; - bool ok = do_update_shard_info(std::move(new_info)); - if (!ok) { - return td::Status::Error( - -666, - std::string{ - "unknown serialization error for (BinTree ShardDescr) while updating shard configuration to include "} + - blk.to_str()); - } else { - return true; - } -} - -td::Result ShardConfig::update_shard_block_info2(Ref new_info1, Ref new_info2, - const std::vector& old_blkids) { - auto res1 = may_update_shard_block_info(new_info1, old_blkids); - if (res1.is_error()) { - return res1; - } - auto res2 = may_update_shard_block_info(new_info2, old_blkids); - if (res2.is_error()) { - return res2; - } - if (res1.move_as_ok() || res2.move_as_ok()) { - return td::Status::Error(-666, "the two updates in update_shard_block_info2 must follow a shard split event"); - } - if (new_info1->blk_.id.shard > new_info2->blk_.id.shard) { - std::swap(new_info1, new_info2); - } - auto blk1 = new_info1->blk_, blk2 = new_info2->blk_; - bool ok = do_update_shard_info2(std::move(new_info1), std::move(new_info2)); - if (!ok) { - return td::Status::Error( - -666, - std::string{ - "unknown serialization error for (BinTree ShardDescr) while updating shard configuration to include "} + - blk1.to_str() + " and " + blk2.to_str()); - } else { - return true; - } -} - -bool ShardConfig::do_update_shard_info(Ref new_info) { - vm::CellBuilder cb; - Ref ref; - return new_info.not_null() && cb.store_bool_bool(false) // bt_leaf$0 - && new_info->pack(cb) // leaf:ShardDescr - && cb.finalize_to(ref) && set_shard_info(new_info->shard(), std::move(ref)); -} - -bool ShardConfig::do_update_shard_info2(Ref new_info1, Ref new_info2) { - if (new_info1.is_null() || new_info2.is_null() || !ton::shard_is_sibling(new_info1->shard(), new_info2->shard())) { - return false; - } - if (new_info1->blk_.id.shard > new_info2->blk_.id.shard) { - std::swap(new_info1, new_info2); - } - vm::CellBuilder cb, cb1; - Ref ref; - return cb.store_bool_bool(true) // bt_node$1 - && cb1.store_bool_bool(false) // ( bt_leaf$0 - && new_info1->pack(cb1) // leaf:ShardDescr - && cb1.finalize_to(ref) // ) -> ref - && cb.store_ref_bool(std::move(ref)) // left:^(BinTree ShardDescr) - && cb1.store_bool_bool(false) // ( bt_leaf$0 - && new_info2->pack(cb1) // leaf:ShardDescr - && cb1.finalize_to(ref) // ) -> ref - && cb.store_ref_bool(std::move(ref)) // right:^(BinTree ShardDescr) - && cb.finalize_to(ref) && set_shard_info(ton::shard_parent(new_info1->shard()), std::move(ref)); -} - -static bool btree_set(Ref& root, ton::ShardId shard, Ref value) { - if (!shard) { - return false; - } - if (shard == ton::shardIdAll) { - root = value; - return true; - } - auto cs = vm::load_cell_slice(std::move(root)); - if (cs.size_ext() != 0x20001 || cs.prefetch_ulong(1) != 1) { - return false; // branch does not exist - } - Ref left = cs.prefetch_ref(0), right = cs.prefetch_ref(1); - if (!(btree_set(shard & (1ULL << 63) ? right : left, shard << 1, std::move(value)))) { - return false; - } - vm::CellBuilder cb; - return cb.store_bool_bool(true) // bt_node$1 - && cb.store_ref_bool(std::move(left)) // left:^(BinTree ShardDescr) - && cb.store_ref_bool(std::move(right)) // right:^(BinTree ShardDescr) - && cb.finalize_to(root); // = BinTree ShardDescr -} - -bool ShardConfig::set_shard_info(ton::ShardIdFull shard, Ref value) { - if (!gen::t_BinTree_ShardDescr.validate_ref(1024, value)) { - LOG(ERROR) << "attempting to store an invalid (BinTree ShardDescr) at shard configuration position " - << shard.to_str(); - gen::t_BinTree_ShardDescr.print_ref(std::cerr, value); - vm::load_cell_slice(value).print_rec(std::cerr); - return false; - } - auto root = shard_hashes_dict_->lookup_ref(td::BitArray<32>{shard.workchain}); - if (root.is_null()) { - LOG(ERROR) << "attempting to store a new ShardDescr for shard " << shard.to_str() << " in an undefined workchain"; - return false; - } - if (!btree_set(root, shard.shard, value)) { - LOG(ERROR) << "error while storing a new ShardDescr for shard " << shard.to_str() << " into shard configuration"; - return false; - } - if (!shard_hashes_dict_->set_ref(td::BitArray<32>{shard.workchain}, std::move(root), - vm::Dictionary::SetMode::Replace)) { - return false; - } - auto ins = shards_updated_.insert(shard); - CHECK(ins.second); - return true; -} - -bool Config::is_special_smartcontract(const ton::StdSmcAddress& addr) const { - CHECK(special_smc_dict); - return special_smc_dict->lookup(addr).not_null() || addr == config_addr; -} - -td::Result> Config::get_special_smartcontracts(bool without_config) const { - if (!special_smc_dict) { - return td::Status::Error(-666, "configuration loaded without fundamental smart contract list"); - } - std::vector res; - if (!special_smc_dict->check_for_each([&res, &without_config, conf_addr = config_addr.bits()]( - Ref cs_ref, td::ConstBitPtr key, int n) { - if (cs_ref->size_ext() || n != 256) { - return false; - } - res.emplace_back(key); - if (!without_config && key.equals(conf_addr, 256)) { - without_config = true; - } - return true; - })) { - return td::Status::Error(-666, "invalid fundamental smart contract set in configuration parameter 31"); - } - if (!without_config) { - res.push_back(config_addr); - } - return std::move(res); -} - -td::Result>> ConfigInfo::get_special_ticktock_smartcontracts( - int tick_tock) const { - if (!special_smc_dict) { - return td::Status::Error(-666, "configuration loaded without fundamental smart contract list"); - } - if (!accounts_dict) { - return td::Status::Error(-666, "state loaded without accounts information"); - } - std::vector> res; - if (!special_smc_dict->check_for_each( - [this, &res, tick_tock](Ref cs_ref, td::ConstBitPtr key, int n) -> bool { - if (cs_ref->size_ext() || n != 256) { - return false; - } - int tt = get_smc_tick_tock(key); - if (tt < -1) { - return false; - } - if (tt >= 0 && (tt & tick_tock) != 0) { - res.emplace_back(key, tt); - } - return true; - })) { - return td::Status::Error(-666, - "invalid fundamental smart contract set in configuration parameter 31, or unable to " - "recover tick-tock value from one of them"); - } - return std::move(res); -} - -int ConfigInfo::get_smc_tick_tock(td::ConstBitPtr smc_addr) const { - if (!accounts_dict) { - return -2; - } - auto acc_csr = accounts_dict->lookup(smc_addr, 256); - Ref acc_cell; - if (acc_csr.is_null() || !acc_csr->prefetch_ref_to(acc_cell)) { - return -1; - } - auto acc_cs = vm::load_cell_slice(std::move(acc_cell)); - if (block::gen::t_Account.get_tag(acc_cs) == block::gen::Account::account_none) { - return 0; - } - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record storage; - int ticktock; - return (tlb::unpack_exact(acc_cs, acc) && tlb::csr_unpack(acc.storage, storage) && - block::tlb::t_AccountState.get_ticktock(storage.state.write(), ticktock)) - ? ticktock - : -2; -} - -ton::CatchainSeqno ConfigInfo::get_shard_cc_seqno(ton::ShardIdFull shard) const { - return shard.is_masterchain() ? cc_seqno_ : ShardConfig::get_shard_cc_seqno(shard); -} - -std::vector Config::compute_validator_set(ton::ShardIdFull shard, const block::ValidatorSet& vset, - ton::UnixTime time, ton::CatchainSeqno cc_seqno) const { - return do_compute_validator_set(get_catchain_validators_config(), shard, vset, time, cc_seqno); -} - -std::vector Config::compute_validator_set(ton::ShardIdFull shard, ton::UnixTime time, - ton::CatchainSeqno cc_seqno) const { - if (!cur_validators_) { - LOG(DEBUG) << "failed to compute validator set: cur_validators_ is empty"; - return {}; - } else { - return compute_validator_set(shard, *cur_validators_, time, cc_seqno); - } -} - -std::vector ConfigInfo::compute_validator_set_cc(ton::ShardIdFull shard, - const block::ValidatorSet& vset, - ton::UnixTime time, - ton::CatchainSeqno* cc_seqno_delta) const { - if (cc_seqno_delta && (*cc_seqno_delta & -2)) { - return {}; - } - ton::CatchainSeqno cc_seqno = get_shard_cc_seqno(shard); - if (cc_seqno == ~0U) { - return {}; - } - if (cc_seqno_delta) { - cc_seqno = *cc_seqno_delta += cc_seqno; - } - return do_compute_validator_set(get_catchain_validators_config(), shard, vset, time, cc_seqno); -} - -std::vector ConfigInfo::compute_validator_set_cc(ton::ShardIdFull shard, ton::UnixTime time, - ton::CatchainSeqno* cc_seqno_delta) const { - auto vset = get_cur_validator_set(); - if (!vset) { - return {}; - } else { - return compute_validator_set_cc(shard, *vset, time, cc_seqno_delta); - } -} - -void validator_set_descr::incr_seed() { - for (int i = 31; i >= 0 && !++(seed[i]); --i) { - } -} - -void validator_set_descr::hash_to(unsigned char hash_buffer[64]) const { - digest::hash_str(hash_buffer, (const void*)this, sizeof(*this)); -} - -td::uint64 ValidatorSetPRNG::next_ulong() { - if (pos < limit) { - return td::bswap64(hash_longs[pos++]); - } - data.hash_to(hash); - data.incr_seed(); - pos = 1; - limit = 8; - return td::bswap64(hash_longs[0]); -} - -td::uint64 ValidatorSetPRNG::next_ranged(td::uint64 range) { - td::uint64 y = next_ulong(); - return td::uint128(range).mult(y).hi(); -} - -inline bool operator<(td::uint64 pos, const ValidatorDescr& descr) { - return pos < descr.cum_weight; -} - -const ValidatorDescr& ValidatorSet::at_weight(td::uint64 weight_pos) const { - CHECK(weight_pos < total_weight); - auto it = std::upper_bound(list.begin(), list.end(), weight_pos); - CHECK(it != list.begin()); - return *--it; -} - -std::vector ValidatorSet::export_validator_set() const { - std::vector l; - l.reserve(list.size()); - for (const auto& node : list) { - l.emplace_back(node.pubkey, node.weight, node.adnl_addr); - } - return l; -} - -std::map ValidatorSet::compute_validator_map() const { - std::map res; - for (int i = 0; i < (int)list.size(); i++) { - res.emplace(list[i].pubkey.as_bits256(), i); - } - return res; -} - -std::vector ValidatorSet::export_scaled_validator_weights() const { - std::vector res; - for (const auto& node : list) { - res.push_back((double)node.weight / (double)total_weight); - } - return res; -} - -int ValidatorSet::lookup_public_key(td::ConstBitPtr pubkey) const { - for (int i = 0; i < (int)list.size(); i++) { - if (list[i].pubkey.as_bits256() == pubkey) { - return i; - } - } - return -1; -} - -std::vector Config::do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf, - ton::ShardIdFull shard, - const block::ValidatorSet& vset, ton::UnixTime time, - ton::CatchainSeqno cc_seqno) { - // LOG(DEBUG) << "in Config::do_compute_validator_set() for " << shard.to_str() << " ; cc_seqno=" << cc_seqno; - std::vector nodes; - bool is_mc = shard.is_masterchain(); - unsigned count = std::min(is_mc ? vset.main : ccv_conf.shard_val_num, vset.total); - CHECK((unsigned)vset.total == vset.list.size()); - if (!count) { - return {}; // no validators? - } - nodes.reserve(count); - ValidatorSetPRNG gen{shard, cc_seqno}; // use zero seed (might use a non-trivial seed from ccv_conf in the future) - if (is_mc) { - if (ccv_conf.shuffle_mc_val) { - // shuffle mc validators from the head of the list - std::vector idx(count); - CHECK(idx.size() == count); - for (unsigned i = 0; i < count; i++) { - unsigned j = (unsigned)gen.next_ranged(i + 1); // number 0 .. i - CHECK(j <= i); - idx[i] = idx[j]; - idx[j] = i; - } - for (unsigned i = 0; i < count; i++) { - const auto& v = vset.list[idx[i]]; - nodes.emplace_back(v.pubkey, v.weight, v.adnl_addr); - } - } else { - // simply take needed number of validators from the head of the list - for (unsigned i = 0; i < count; i++) { - const auto& v = vset.list[i]; - nodes.emplace_back(v.pubkey, v.weight, v.adnl_addr); - } - } - return nodes; - } - // this is the "true" algorithm for generating shardchain validator subgroups - std::vector> holes; - holes.reserve(count); - td::uint64 total_wt = vset.total_weight; - for (unsigned i = 0; i < count; i++) { - CHECK(total_wt > 0); - auto p = gen.next_ranged(total_wt); // generate a pseudo-random number 0 .. total_wt-1 - // auto op = p; - for (auto& hole : holes) { - if (p < hole.first) { - break; - } - p += hole.second; - } - auto& entry = vset.at_weight(p); - // LOG(DEBUG) << "vset entry #" << i << ": rem_wt=" << total_wt << ", total_wt=" << vset.total_weight << ", op=" << op << ", p=" << p << "; entry.cum_wt=" << entry.cum_weight << ", entry.wt=" << entry.weight << " " << entry.cum_weight / entry.weight; - nodes.emplace_back(entry.pubkey, 1, entry.adnl_addr); // NB: shardchain validator lists have all weights = 1 - CHECK(total_wt >= entry.weight); - total_wt -= entry.weight; - std::pair new_hole{entry.cum_weight, entry.weight}; - auto it = std::upper_bound(holes.begin(), holes.end(), new_hole); - CHECK(it == holes.begin() || *(it - 1) < new_hole); - holes.insert(it, new_hole); - } - return nodes; -} - -std::vector Config::compute_total_validator_set(int next) const { - auto res = unpack_validator_set(get_config_param(next < 0 ? 32 : (next ? 36 : 34))); - if (res.is_error()) { - return {}; - } - return res.move_as_ok()->export_validator_set(); -} - -td::Result> Config::unpack_validator_set_start_stop(Ref vset_root) { - if (vset_root.is_null()) { - return td::Status::Error("validator set absent"); - } - gen::ValidatorSet::Record_validators_ext rec; - if (tlb::unpack_cell(vset_root, rec)) { - return std::pair(rec.utime_since, rec.utime_until); - } - gen::ValidatorSet::Record_validators rec0; - if (tlb::unpack_cell(std::move(vset_root), rec0)) { - return std::pair(rec0.utime_since, rec0.utime_until); - } - return td::Status::Error("validator set is invalid"); -} - -std::pair Config::get_validator_set_start_stop(int next) const { - auto res = unpack_validator_set_start_stop(get_config_param(next < 0 ? 32 : (next ? 36 : 34))); - if (res.is_error()) { - return {0, 0}; - } else { - return res.move_as_ok(); - } -} - -bool WorkchainInfo::unpack(ton::WorkchainId wc, vm::CellSlice& cs) { - workchain = ton::workchainInvalid; - if (wc == ton::workchainInvalid) { - return false; - } - block::gen::WorkchainDescr::Record info; - if (!tlb::unpack(cs, info)) { - return false; - } - enabled_since = info.enabled_since; - actual_min_split = info.actual_min_split; - min_split = info.min_split; - max_split = info.max_split; - basic = info.basic; - active = info.active; - accept_msgs = info.accept_msgs; - flags = info.flags; - zerostate_root_hash = info.zerostate_root_hash; - zerostate_file_hash = info.zerostate_file_hash; - version = info.version; - if (basic) { - min_addr_len = max_addr_len = addr_len_step = 256; - } else { - block::gen::WorkchainFormat::Record_wfmt_ext ext; - if (!tlb::type_unpack(cs, block::gen::WorkchainFormat{basic}, ext)) { - return false; - } - min_addr_len = ext.min_addr_len; - max_addr_len = ext.max_addr_len; - addr_len_step = ext.addr_len_step; - } - workchain = wc; - LOG(DEBUG) << "unpacked info for workchain " << wc << ": basic=" << basic << ", active=" << active - << ", accept_msgs=" << accept_msgs << ", min_split=" << min_split << ", max_split=" << max_split; - return true; -} - -Ref Config::get_workchain_info(ton::WorkchainId workchain_id) const { - if (!workchains_dict_) { - return {}; - } - auto it = workchains_.find(workchain_id); - if (it == workchains_.end()) { - return {}; - } else { - return it->second; - } -} - -bool ConfigInfo::get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - if (block_id.is_valid() && seqno == block_id.id.seqno) { - blkid = block_id; - if (end_lt) { - *end_lt = lt; - } - return true; - } else { - return block::get_old_mc_block_id(prev_blocks_dict_.get(), seqno, blkid, end_lt); - } -} - -bool ConfigInfo::check_old_mc_block_id(const ton::BlockIdExt& blkid, bool strict) const { - return (!strict && blkid.id.seqno == block_id.id.seqno && block_id.is_valid()) - ? blkid == block_id - : block::check_old_mc_block_id(prev_blocks_dict_.get(), blkid); -} - -// returns block with min block.seqno and req_lt <= block.end_lt -bool ConfigInfo::get_mc_block_by_lt(ton::LogicalTime req_lt, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - if (req_lt > lt) { - return false; - } - td::BitArray<32> key; - auto found = prev_blocks_dict_->traverse_extra( - key.bits(), 32, - [req_lt](td::ConstBitPtr key_prefix, int key_pfx_len, Ref extra, Ref value) { - unsigned long long found_lt; - if (!(extra.write().advance(1) && extra.write().fetch_ulong_bool(64, found_lt))) { - return -1; - } - if (found_lt < req_lt) { - return 0; // all leaves in subtree have end_lt <= found_lt < req_lt, skip - } - return 6; // visit left subtree, then right subtree; for leaf: accept and return to the top - }); - if (found.first.not_null()) { - CHECK(unpack_old_mc_block_id(std::move(found.first), (unsigned)key.to_ulong(), blkid, end_lt)); - return true; - } - if (block_id.is_valid()) { - blkid = block_id; - if (end_lt) { - *end_lt = lt; - } - return true; - } else { - return false; - } -} - -// returns key block with max block.seqno and block.seqno <= req_seqno -bool ConfigInfo::get_prev_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - if (block_id.is_valid() && is_key_state_ && block_id.seqno() <= req_seqno) { - blkid = block_id; - if (end_lt) { - *end_lt = lt; - } - return true; - } - td::BitArray<32> key; - auto found = - prev_blocks_dict_->traverse_extra(key.bits(), 32, - [req_seqno](td::ConstBitPtr key_prefix, int key_pfx_len, - Ref extra, Ref value) -> int { - if (extra->prefetch_ulong(1) != 1) { - return 0; // no key blocks in subtree, skip - } - unsigned x = (unsigned)key_prefix.get_uint(key_pfx_len); - unsigned d = 32 - key_pfx_len; - if (!d) { - return x <= req_seqno; - } - unsigned y = req_seqno >> (d - 1); - if (y < 2 * x) { - // (x << d) > req_seqno <=> x > (req_seqno >> d) = (y >> 1) <=> 2 * x > y - return 0; // all nodes in subtree have block.seqno > req_seqno => skip - } - return y == 2 * x ? 1 /* visit only left */ : 5 /* visit right, then left */; - }); - if (found.first.not_null()) { - CHECK(unpack_old_mc_block_id(std::move(found.first), (unsigned)key.to_ulong(), blkid, end_lt)); - CHECK(blkid.seqno() <= req_seqno); - return true; - } else { - blkid.invalidate(); - return false; - } -} - -// returns key block with min block.seqno and block.seqno >= req_seqno -bool ConfigInfo::get_next_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const { - td::BitArray<32> key; - auto found = prev_blocks_dict_->traverse_extra( - key.bits(), 32, - [req_seqno](td::ConstBitPtr key_prefix, int key_pfx_len, Ref extra, - Ref value) -> int { - if (extra->prefetch_ulong(1) != 1) { - return 0; // no key blocks in subtree, skip - } - unsigned x = (unsigned)key_prefix.get_uint(key_pfx_len); - unsigned d = 32 - key_pfx_len; - if (!d) { - return x >= req_seqno; - } - unsigned y = req_seqno >> (d - 1); - if (y > 2 * x + 1) { - // ((x + 1) << d) <= req_seqno <=> (x+1) <= (req_seqno >> d) = (y >> 1) <=> 2*x+2 <= y <=> y > 2*x+1 - return 0; // all nodes in subtree have block.seqno < req_seqno => skip - } - return y == 2 * x + 1 ? 2 /* visit only right */ : 6 /* visit left, then right */; - }); - if (found.first.not_null()) { - CHECK(unpack_old_mc_block_id(std::move(found.first), (unsigned)key.to_ulong(), blkid, end_lt)); - CHECK(blkid.seqno() >= req_seqno); - return true; - } - if (block_id.is_valid() && is_key_state_ && block_id.seqno() >= req_seqno) { - blkid = block_id; - if (end_lt) { - *end_lt = lt; - } - return true; - } else { - blkid.invalidate(); - return false; - } -} - -Ref ConfigInfo::lookup_library(td::ConstBitPtr root_hash) const { - if (!libraries_dict_) { - return {}; - } - auto csr = libraries_dict_->lookup(root_hash, 256); - if (csr.is_null() || csr->prefetch_ulong(8) != 0 || !csr->have_refs()) { // shared_lib_descr$00 lib:^Cell - return {}; - } - auto lib = csr->prefetch_ref(); - if (lib->get_hash().bits().compare(root_hash, 256)) { - LOG(ERROR) << "public library hash mismatch: expected " << root_hash.to_hex(256) << " , found " - << lib->get_hash().bits().to_hex(256); - return {}; - } - return lib; -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/mc-config.h b/submodules/ton/tonlib-src/crypto/block/mc-config.h deleted file mode 100644 index 8be3f6e6..00000000 --- a/submodules/ton/tonlib-src/crypto/block/mc-config.h +++ /dev/null @@ -1,713 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "vm/db/StaticBagOfCellsDb.h" -#include "vm/dict.h" -#include "ton/ton-types.h" -#include "ton/ton-shard.h" -#include "common/bitstring.h" -#include "block.h" - -#include -#include -#include -#include -#include - -namespace block { -using td::Ref; - -struct ValidatorDescr { - ton::Ed25519_PublicKey pubkey; - td::Bits256 adnl_addr; - td::uint64 weight; - td::uint64 cum_weight; - ValidatorDescr(const td::Bits256& _pubkey, td::uint64 _weight, td::uint64 _cum_weight) - : pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) { - adnl_addr.set_zero(); - } - ValidatorDescr(const td::Bits256& _pubkey, td::uint64 _weight, td::uint64 _cum_weight, const td::Bits256& _adnl_addr) - : pubkey(_pubkey), adnl_addr(_adnl_addr), weight(_weight), cum_weight(_cum_weight) { - } - ValidatorDescr(const ton::Ed25519_PublicKey& _pubkey, td::uint64 _weight, td::uint64 _cum_weight) - : pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) { - adnl_addr.set_zero(); - } - bool operator<(td::uint64 wt_pos) const& { - return cum_weight < wt_pos; - } -}; - -struct ValidatorSet { - unsigned utime_since; - unsigned utime_until; - int total; - int main; - td::uint64 total_weight; - std::vector list; - ValidatorSet() = default; - ValidatorSet(unsigned _since, unsigned _until, int _total, int _main = 0) - : utime_since(_since), utime_until(_until), total(_total), main(_main > 0 ? _main : _total), total_weight(0) { - } - const ValidatorDescr& operator[](unsigned i) const { - return list[i]; - } - const ValidatorDescr& at_weight(td::uint64 weight_pos) const; - std::vector export_validator_set() const; - std::map compute_validator_map() const; - std::vector export_scaled_validator_weights() const; - int lookup_public_key(td::ConstBitPtr pubkey) const; - int lookup_public_key(const td::Bits256& pubkey) const { - return lookup_public_key(pubkey.bits()); - } -}; - -#pragma pack(push, 1) -// this structure is hashed with SHA512 to produce pseudo-random bit stream in do_compute_validator_set() -// NB: all integers (including 256-bit seed) are actually big-endian -struct validator_set_descr { - unsigned char seed[32]; // seed for validator set computation, set to zero if none - td::uint64 shard; - td::int32 workchain; - td::uint32 cc_seqno; - validator_set_descr() = default; - validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, bool flag) - : shard(td::bswap64(shard_id.shard)) - , workchain(td::bswap32(shard_id.workchain)) - , cc_seqno(td::bswap32(cc_seqno_)) { - } - validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_) - : validator_set_descr(shard_id, cc_seqno_, false) { - std::memset(seed, 0, 32); - } - validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const unsigned char seed_[32]) - : validator_set_descr(shard_id, cc_seqno_, false) { - std::memcpy(seed, seed_, 32); - } - validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, td::ConstBitPtr seed_) - : validator_set_descr(shard_id, cc_seqno_, false) { - td::BitPtr{seed}.copy_from(seed_, 256); - } - validator_set_descr(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const td::Bits256& seed_) - : validator_set_descr(shard_id, cc_seqno_, false) { - td::BitPtr{seed}.copy_from(seed_.cbits(), 256); - } - void incr_seed(); - void hash_to(unsigned char hash_buffer[64]) const; -}; -#pragma pack(pop) - -class ValidatorSetPRNG { - validator_set_descr data; - union { - unsigned char hash[64]; - td::uint64 hash_longs[8]; - }; - int pos{0}, limit{0}; - - public: - ValidatorSetPRNG() = default; - ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_) : data(shard_id, cc_seqno_) { - } - ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const unsigned char seed_[32]) - : data(shard_id, cc_seqno_, seed_) { - } - ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, td::ConstBitPtr seed_) - : data(shard_id, cc_seqno_, std::move(seed_)) { - } - ValidatorSetPRNG(ton::ShardIdFull shard_id, ton::CatchainSeqno cc_seqno_, const td::Bits256& seed_) - : data(shard_id, cc_seqno_, seed_) { - } - td::uint64 next_ulong(); - td::uint64 next_ranged(td::uint64 range); // integer in 0 .. range-1 - ValidatorSetPRNG& operator>>(td::uint64& x) { - x = next_ulong(); - return *this; - } -}; - -class McShardHashI : public td::CntObject { - public: - enum class FsmState { fsm_none, fsm_split, fsm_merge }; - virtual ton::BlockIdExt top_block_id() const = 0; - virtual ton::LogicalTime start_lt() const = 0; - virtual ton::LogicalTime end_lt() const = 0; - virtual ton::UnixTime fsm_utime() const = 0; - virtual FsmState fsm_state() const = 0; - virtual ton::ShardIdFull shard() const = 0; - virtual bool before_split() const = 0; - virtual bool before_merge() const = 0; -}; - -struct McShardHash : public McShardHashI { - ton::BlockIdExt blk_; - ton::LogicalTime start_lt_, end_lt_; - ton::UnixTime gen_utime_{0}; - ton::UnixTime fsm_utime_{0}; - ton::UnixTime fsm_interval_{0}; - ton::BlockSeqno min_ref_mc_seqno_{std::numeric_limits::max()}; - ton::BlockSeqno reg_mc_seqno_{std::numeric_limits::max()}; - FsmState fsm_{FsmState::fsm_none}; - bool disabled_{false}; - bool before_split_{false}, before_merge_{false}, want_split_{false}, want_merge_{false}; - ton::CatchainSeqno next_catchain_seqno_{std::numeric_limits::max()}; - ton::ShardId next_validator_shard_{ton::shardIdAll}; - CurrencyCollection fees_collected_, funds_created_; - McShardHash(const ton::BlockId& id, ton::LogicalTime start_lt, ton::LogicalTime end_lt, ton::UnixTime gen_utime, - const ton::BlockHash& root_hash, const ton::FileHash& file_hash, CurrencyCollection fees_collected = {}, - CurrencyCollection funds_created = {}, - ton::BlockSeqno reg_mc_seqno = std::numeric_limits::max(), - ton::BlockSeqno min_ref_mc_seqno = std::numeric_limits::max(), - ton::CatchainSeqno cc_seqno = std::numeric_limits::max(), ton::ShardId val_shard = 0, - bool nx_cc_updated = false, bool before_split = false, bool before_merge = false, bool want_split = false, - bool want_merge = false) - : blk_(id, root_hash, file_hash) - , start_lt_(start_lt) - , end_lt_(end_lt) - , gen_utime_(gen_utime) - , min_ref_mc_seqno_(min_ref_mc_seqno) - , reg_mc_seqno_(reg_mc_seqno) - , before_split_(before_split) - , before_merge_(before_merge) - , want_split_(want_split) - , want_merge_(want_merge) - , next_catchain_seqno_(cc_seqno) - , next_validator_shard_(val_shard ? val_shard : id.shard) - , fees_collected_(fees_collected) - , funds_created_(funds_created) { - } - McShardHash(const ton::BlockIdExt& blk, ton::LogicalTime start_lt, ton::LogicalTime end_lt) - : blk_(blk), start_lt_(start_lt), end_lt_(end_lt) { - } - McShardHash(const McShardHash&) = default; - bool is_valid() const { - return blk_.is_valid(); - } - ton::BlockIdExt top_block_id() const override final { - return blk_; - } - // ZeroStateIdExt zero_state() const override; - ton::LogicalTime start_lt() const override final { - return start_lt_; - } - ton::LogicalTime end_lt() const override final { - return end_lt_; - } - ton::UnixTime fsm_utime() const override final { - return fsm_utime_; - } - ton::UnixTime fsm_utime_end() const { - return fsm_utime_ + fsm_interval_; - } - ton::UnixTime created_at() const { - return gen_utime_; - } - FsmState fsm_state() const override final { - return fsm_; - } - bool is_fsm_none() const { - return fsm_ == FsmState::fsm_none; - } - bool is_fsm_split() const { - return fsm_ == FsmState::fsm_split; - } - bool is_fsm_merge() const { - return fsm_ == FsmState::fsm_merge; - } - ton::ShardIdFull shard() const override final { - return ton::ShardIdFull(blk_); - } - ton::WorkchainId workchain() const { - return blk_.id.workchain; - } - bool contains(const ton::AccountIdPrefixFull& pfx) const { - return ton::shard_contains(shard(), pfx); - } - bool before_split() const override final { - return before_split_; - } - bool before_merge() const override final { - return before_merge_; - } - bool is_disabled() const { - return disabled_; - } - void disable() { - blk_.invalidate(); - disabled_ = true; - } - ton::BlockSeqno seqno() const { - return blk_.id.seqno; - } - bool set_reg_mc_seqno(ton::BlockSeqno reg_mc_seqno) { - reg_mc_seqno_ = reg_mc_seqno; - return true; - } - // compares all fields except fsm*, before_merge_, nx_cc_updated_, next_catchain_seqno_, fees_collected_ - bool basic_info_equal(const McShardHash& other, bool compare_fees = false, bool compare_reg_seqno = true) const; - void clear_fsm() { - fsm_ = FsmState::fsm_none; - } - void set_fsm(FsmState fsm, ton::UnixTime fsm_utime, ton::UnixTime fsm_interval); - void set_fsm_split(ton::UnixTime fsm_utime, ton::UnixTime fsm_interval) { - set_fsm(FsmState::fsm_split, fsm_utime, fsm_interval); - } - void set_fsm_merge(ton::UnixTime fsm_utime, ton::UnixTime fsm_interval) { - set_fsm(FsmState::fsm_merge, fsm_utime, fsm_interval); - } - bool fsm_equal(const McShardHash& other) const { - return fsm_ == other.fsm_ && - (is_fsm_none() || (fsm_utime_ == other.fsm_utime_ && fsm_interval_ == other.fsm_interval_)); - } - bool pack(vm::CellBuilder& cb) const; - static Ref unpack(vm::CellSlice& cs, ton::ShardIdFull id); - static Ref from_block(Ref block_root, const ton::FileHash& _fhash, bool init_fees = false); - static bool extract_cc_seqno(vm::CellSlice& cs, ton::CatchainSeqno* cc); - McShardHash* make_copy() const override { - return new McShardHash(*this); - } -}; - -struct McShardDescr final : public McShardHash { - Ref block_root; - Ref state_root; - Ref outmsg_root; - std::unique_ptr out_msg_queue; - std::shared_ptr processed_upto; - McShardDescr(const ton::BlockId& id, ton::LogicalTime start_lt, ton::LogicalTime end_lt, ton::UnixTime gen_utime, - const ton::BlockHash& root_hash, const ton::FileHash& file_hash, CurrencyCollection fees_collected = {}, - CurrencyCollection funds_created = {}, - ton::BlockSeqno reg_mc_seqno = std::numeric_limits::max(), - ton::BlockSeqno min_ref_mc_seqno = std::numeric_limits::max(), - ton::CatchainSeqno cc_seqno = std::numeric_limits::max(), - ton::ShardId val_shard = ton::shardIdAll, bool nx_cc_updated = false, bool before_split = false, - bool before_merge = false, bool want_split = false, bool want_merge = false) - : McShardHash(id, start_lt, end_lt, gen_utime, root_hash, file_hash, fees_collected, funds_created, reg_mc_seqno, - min_ref_mc_seqno, cc_seqno, val_shard, nx_cc_updated, before_split, before_merge, want_split, - want_merge) { - } - McShardDescr(const ton::BlockIdExt& blk, ton::LogicalTime start_lt, ton::LogicalTime end_lt) - : McShardHash(blk, start_lt, end_lt) { - } - McShardDescr(const McShardHash& shard_hash) : McShardHash(shard_hash) { - } - McShardDescr(const McShardDescr& other); - McShardDescr(McShardDescr&& other) = default; - McShardDescr& operator=(const McShardDescr& other); - McShardDescr& operator=(McShardDescr&& other) = default; - bool set_queue_root(Ref queue_root); - void disable(); - static Ref from_block(Ref block_root, Ref state_root, const ton::FileHash& _fhash, - bool init_fees = false); - static Ref from_state(ton::BlockIdExt blkid, Ref state_root); -}; - -struct StoragePrices { - ton::UnixTime valid_since{0}; - td::uint64 bit_price{0}; - td::uint64 cell_price{0}; - td::uint64 mc_bit_price{0}; - td::uint64 mc_cell_price{0}; - StoragePrices() = default; - StoragePrices(ton::UnixTime _valid_since, td::uint64 _bprice, td::uint64 _cprice, td::uint64 _mc_bprice, - td::uint64 _mc_cprice) - : valid_since(_valid_since) - , bit_price(_bprice) - , cell_price(_cprice) - , mc_bit_price(_mc_bprice) - , mc_cell_price(_mc_cprice) { - } - static td::RefInt256 compute_storage_fees(ton::UnixTime now, const std::vector& pricing, - const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid, - bool is_special, bool is_masterchain); -}; - -struct GasLimitsPrices { - td::uint64 flat_gas_limit{0}; - td::uint64 flat_gas_price{0}; - td::uint64 gas_price{0}; - td::uint64 special_gas_limit{0}; - td::uint64 gas_limit{0}; - td::uint64 gas_credit{0}; - td::uint64 block_gas_limit{0}; - td::uint64 freeze_due_limit{0}; - td::uint64 delete_due_limit{0}; - - td::RefInt256 compute_gas_price(td::uint64 gas_used) const; -}; - -// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms -// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms -// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) - -struct MsgPrices { - td::uint64 lump_price; - td::uint64 bit_price; - td::uint64 cell_price; - td::uint32 ihr_factor; - td::uint32 first_frac; - td::uint32 next_frac; - td::uint64 compute_fwd_fees(td::uint64 cells, td::uint64 bits) const; - std::pair compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits, - bool ihr_disabled = false) const; - MsgPrices() = default; - MsgPrices(td::uint64 lump, td::uint64 bitp, td::uint64 cellp, td::uint32 ihrf, td::uint32 firstf, td::uint32 nextf) - : lump_price(lump), bit_price(bitp), cell_price(cellp), ihr_factor(ihrf), first_frac(firstf), next_frac(nextf) { - } - td::RefInt256 get_first_part(td::RefInt256 total) const; - td::uint64 get_first_part(td::uint64 total) const; - td::RefInt256 get_next_part(td::RefInt256 total) const; -}; - -struct CatchainValidatorsConfig { - td::uint32 mc_cc_lifetime, shard_cc_lifetime, shard_val_lifetime, shard_val_num; - bool shuffle_mc_val; - CatchainValidatorsConfig(td::uint32 mc_cc_lt_, td::uint32 sh_cc_lt_, td::uint32 sh_val_lt_, td::uint32 sh_val_num_, - bool shuffle_mc = false) - : mc_cc_lifetime(mc_cc_lt_) - , shard_cc_lifetime(sh_cc_lt_) - , shard_val_lifetime(sh_val_lt_) - , shard_val_num(sh_val_num_) - , shuffle_mc_val(shuffle_mc) { - } -}; - -struct WorkchainInfo : public td::CntObject { - ton::WorkchainId workchain{ton::workchainInvalid}; - ton::UnixTime enabled_since; - td::uint32 actual_min_split; - td::uint32 min_split, max_split; - bool basic; - bool active; - bool accept_msgs; - int flags; - td::uint32 version; - ton::RootHash zerostate_root_hash; - ton::FileHash zerostate_file_hash; - int min_addr_len, max_addr_len, addr_len_step; - bool is_valid() const { - return workchain != ton::workchainInvalid; - } - bool is_valid_addr_len(int addr_len) const { - return addr_len >= min_addr_len && addr_len <= max_addr_len && - (addr_len == min_addr_len || addr_len == max_addr_len || - (addr_len_step > 0 && !((addr_len - min_addr_len) % addr_len_step))); - } - bool unpack(ton::WorkchainId wc, vm::CellSlice& cs); -}; - -using WorkchainSet = std::map>; - -class ShardConfig { - Ref shard_hashes_; - Ref mc_shard_hash_; - std::unique_ptr shard_hashes_dict_; - std::set shards_updated_; - bool valid_{false}; - - public: - ShardConfig() = default; - ShardConfig(const ShardConfig& other); - ShardConfig(ShardConfig&& other) = default; - ShardConfig(Ref shard_hashes, Ref mc_shard_hash = {}) - : shard_hashes_(std::move(shard_hashes)), mc_shard_hash_(std::move(mc_shard_hash)) { - init(); - } - bool is_valid() const { - return valid_; - } - bool unpack(Ref shard_hashes, Ref mc_shard_hash = {}); - bool unpack(Ref shard_hashes, Ref mc_shard_hash = {}); - Ref get_root_csr() const; - bool has_workchain(ton::WorkchainId workchain) const; - std::vector get_workchains() const; - Ref get_shard_hash(ton::ShardIdFull id, bool exact = true) const; - bool contains(ton::BlockIdExt blkid) const; - bool get_shard_hash_raw(vm::CellSlice& cs, ton::ShardIdFull id, ton::ShardIdFull& true_id, bool exact = true) const; - ton::LogicalTime get_shard_end_lt(ton::AccountIdPrefixFull acc) const; - ton::LogicalTime get_shard_end_lt_ext(ton::AccountIdPrefixFull acc, ton::ShardIdFull& actual_shard) const; - static bool get_shard_hash_raw_from(vm::Dictionary& shard_hashes_dict, vm::CellSlice& cs, ton::ShardIdFull id, - ton::ShardIdFull& true_id, bool exact = true, Ref* leaf = nullptr); - std::vector get_shard_hash_ids(bool skip_mc = false) const; - std::vector get_shard_hash_ids(const std::function& filter) const; - std::vector get_intersecting_shard_hash_ids(ton::ShardIdFull myself) const; - std::vector get_neighbor_shard_hash_ids(ton::ShardIdFull myself) const; - std::vector get_proper_neighbor_shard_hash_ids(ton::ShardIdFull myself) const; - static std::unique_ptr extract_shard_hashes_dict(Ref mc_state_root); - bool process_shard_hashes(std::function func); - bool process_sibling_shard_hashes(std::function func); - // may become non-static const in the future - static bool is_neighbor(ton::ShardIdFull x, ton::ShardIdFull y); - Ref get_mc_hash() const { - return mc_shard_hash_; - } - void set_mc_hash(Ref mc_shard_hash) { - mc_shard_hash_ = std::move(mc_shard_hash); - } - ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const; - block::compute_shard_end_lt_func_t get_compute_shard_end_lt_func() const { - return std::bind(&ShardConfig::get_shard_end_lt, *this, std::placeholders::_1); - } - bool new_workchain(ton::WorkchainId workchain, ton::BlockSeqno reg_mc_seqno, const ton::RootHash& zerostate_root_hash, - const ton::FileHash& zerostate_file_hash); - td::Result update_shard_block_info(Ref new_info, const std::vector& old_blkids); - td::Result update_shard_block_info2(Ref new_info1, Ref new_info2, - const std::vector& old_blkids); - td::Result may_update_shard_block_info(Ref new_info, - const std::vector& old_blkids, - ton::LogicalTime lt_limit = std::numeric_limits::max(), - Ref* ancestor = nullptr) const; - - private: - bool init(); - bool do_update_shard_info(Ref new_info); - bool do_update_shard_info2(Ref new_info1, Ref new_info2); - bool set_shard_info(ton::ShardIdFull shard, Ref value); -}; - -class Config { - enum { - default_mc_catchain_lifetime = 200, - default_shard_catchain_lifetime = 200, - default_shard_validators_lifetime = 3000, - default_shard_validators_num = 7 - }; - - public: - enum { needValidatorSet = 16, needSpecialSmc = 32, needWorkchainInfo = 256, needCapabilities = 512 }; - int mode{0}; - ton::BlockIdExt block_id; - - private: - td::BitArray<256> config_addr; - Ref config_root; - std::unique_ptr config_dict; - std::unique_ptr cur_validators_; - std::unique_ptr workchains_dict_; - WorkchainSet workchains_; - int version_{-1}; - long long capabilities_{-1}; - - protected: - std::unique_ptr special_smc_dict; - - public: - static constexpr ton::LogicalTime get_lt_align() { - return 1000000; - } - static constexpr ton::LogicalTime get_max_lt_growth() { - return 10 * get_lt_align() - 1; - } - Ref get_config_param(int idx) const; - Ref get_config_param(int idx, int idx2) const; - Ref operator[](int idx) const { - return get_config_param(idx); - } - Ref get_root_cell() const { - return config_root; - } - bool is_masterchain() const { - return block_id.is_masterchain(); - } - bool has_capabilities() const { - return capabilities_ >= 0; - } - long long get_capabilities() const { - return capabilities_; - } - int get_global_version() const { - return version_; - } - bool has_capability(long long cap_set) const { - return has_capabilities() && (capabilities_ & cap_set) == cap_set; - } - bool ihr_enabled() const { - return has_capability(ton::capIhrEnabled); - } - bool create_stats_enabled() const { - return has_capability(ton::capCreateStatsEnabled); - } - std::unique_ptr get_param_dict(int idx) const; - td::Result> unpack_param_list(int idx) const; - std::unique_ptr get_mandatory_param_dict() const { - return get_param_dict(9); - } - std::unique_ptr get_critical_param_dict() const { - return get_param_dict(10); - } - td::Result> get_mandatory_param_list() const { - return unpack_param_list(9); - } - td::Result> get_critical_param_list() const { - return unpack_param_list(10); - } - bool all_mandatory_params_defined(int* bad_idx_ptr = nullptr) const; - td::Result get_dns_root_addr() const; - bool set_block_id_ext(const ton::BlockIdExt& block_id_ext); - td::Result> get_special_smartcontracts(bool without_config = false) const; - bool is_special_smartcontract(const ton::StdSmcAddress& addr) const; - static td::Result> unpack_validator_set(Ref valset_root); - td::Result> get_storage_prices() const; - td::Result get_gas_limits_prices(bool is_masterchain = false) const; - static td::Result do_get_gas_limits_prices(td::Ref cell, int id); - td::Result get_msg_prices(bool is_masterchain = false) const; - static CatchainValidatorsConfig unpack_catchain_validators_config(Ref cell); - CatchainValidatorsConfig get_catchain_validators_config() const; - td::Status visit_validator_params() const; - td::Result> get_block_limits(bool is_masterchain = false) const; - auto get_mc_block_limits() const { - return get_block_limits(true); - } - static td::Result>> unpack_workchain_list_ext( - Ref cell); - static td::Result unpack_workchain_list(Ref cell); - const WorkchainSet& get_workchain_list() const { - return workchains_; - } - const ValidatorSet* get_cur_validator_set() const { - return cur_validators_.get(); - } - std::pair get_validator_set_start_stop(int next = 0) const; - ton::ValidatorSessionConfig get_consensus_config() const; - bool foreach_config_param(std::function)> scan_func) const; - Ref get_workchain_info(ton::WorkchainId workchain_id) const; - std::vector compute_validator_set(ton::ShardIdFull shard, const block::ValidatorSet& vset, - ton::UnixTime time, ton::CatchainSeqno cc_seqno) const; - std::vector compute_validator_set(ton::ShardIdFull shard, ton::UnixTime time, - ton::CatchainSeqno cc_seqno) const; - std::vector compute_total_validator_set(int next) const; - static std::vector do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf, - ton::ShardIdFull shard, - const block::ValidatorSet& vset, ton::UnixTime time, - ton::CatchainSeqno cc_seqno); - - static td::Result> unpack_config(Ref config_root, - const td::Bits256& config_addr = td::Bits256::zero(), - int mode = 0); - static td::Result> unpack_config(Ref config_csr, int mode = 0); - static td::Result> extract_from_state(Ref mc_state_root, int mode = 0); - static td::Result> extract_from_key_block(Ref key_block_root, int mode = 0); - static td::Result> unpack_validator_set_start_stop(Ref root); - static td::Result> unpack_param_dict(vm::Dictionary& dict); - static td::Result> unpack_param_dict(Ref dict_root); - - protected: - Config(int _mode) : mode(_mode) { - config_addr.set_zero(); - } - Config(Ref config_root, const td::Bits256& config_addr = td::Bits256::zero(), int _mode = 0); - td::Status unpack_wrapped(Ref config_csr); - td::Status unpack(Ref config_csr); - td::Status unpack_wrapped(); - td::Status unpack(); -}; - -class ConfigInfo : public Config, public ShardConfig { - public: - enum { - needStateRoot = 1, - needLibraries = 2, - needStateExtraRoot = 4, - needShardHashes = 8, - needAccountsRoot = 64, - needPrevBlocks = 128 - }; - ton::BlockSeqno vert_seqno{~0U}; - int global_id_{0}; - ton::UnixTime utime{0}; - ton::LogicalTime lt{0}; - ton::BlockSeqno min_ref_mc_seqno_{std::numeric_limits::max()}; - ton::CatchainSeqno cc_seqno_{std::numeric_limits::max()}; - int shard_cc_updated{-1}; - bool nx_cc_updated; - bool is_key_state_{false}; - - private: - Ref state_root; - Ref lib_root_; - Ref state_extra_root_; - Ref accounts_root; - ton::ZeroStateIdExt zerostate_id_; - ton::BlockIdExt last_key_block_; - ton::LogicalTime last_key_block_lt_; - Ref shard_hashes; - std::unique_ptr shard_hashes_dict; - std::unique_ptr accounts_dict; - std::unique_ptr prev_blocks_dict_; - std::unique_ptr libraries_dict_; - - public: - bool set_block_id_ext(const ton::BlockIdExt& block_id_ext); - bool rotated_all_shards() const { - return nx_cc_updated; - } - int get_global_blockchain_id() const { - return global_id_; - } - ton::ZeroStateIdExt get_zerostate_id() const { - return zerostate_id_; - } - Ref lookup_library(const ton::Bits256& root_hash) const { - return lookup_library(root_hash.bits()); - } - Ref lookup_library(td::ConstBitPtr root_hash) const; - Ref get_libraries_root() const { - return lib_root_; - } - bool is_key_state() const { - return is_key_state_; - } - Ref get_state_extra_root() const { - return state_extra_root_; - } - ton::BlockSeqno get_vert_seqno() const { - return vert_seqno; - } - ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const; - bool get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& blklt, bool strict = false) const; - bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - bool check_old_mc_block_id(const ton::BlockIdExt& blkid, bool strict = false) const; - // returns block with min seqno and req_lt <= block.end_lt - bool get_mc_block_by_lt(ton::LogicalTime lt, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - bool get_prev_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - bool get_next_key_block(ton::BlockSeqno req_seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; - td::Result>> get_special_ticktock_smartcontracts( - int tick_tock = 3) const; - int get_smc_tick_tock(td::ConstBitPtr smc_addr) const; - std::unique_ptr create_accounts_dict() const; - const vm::AugmentedDictionary& get_accounts_dict() const; - std::vector compute_validator_set_cc(ton::ShardIdFull shard, const block::ValidatorSet& vset, - ton::UnixTime time, - ton::CatchainSeqno* cc_seqno_delta = nullptr) const; - std::vector compute_validator_set_cc(ton::ShardIdFull shard, ton::UnixTime time, - ton::CatchainSeqno* cc_seqno_delta = nullptr) const; - static td::Result> extract_config(std::shared_ptr static_boc, - int mode = 0); - static td::Result> extract_config(Ref mc_state_root, int mode = 0); - - private: - ConfigInfo(Ref mc_state_root, int _mode = 0); - td::Status unpack_wrapped(); - td::Status unpack(); - void reset_mc_hash(); - void cleanup(); -}; - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/output-queue-merger.cpp b/submodules/ton/tonlib-src/crypto/block/output-queue-merger.cpp deleted file mode 100644 index 1084bb1a..00000000 --- a/submodules/ton/tonlib-src/crypto/block/output-queue-merger.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "output-queue-merger.h" - -namespace block { - -/* - * - * OUTPUT QUEUE MERGER - * - */ - -bool OutputQueueMerger::MsgKeyValue::operator<(const MsgKeyValue& other) const { - return lt < other.lt || - (lt == other.lt && td::bitstring::bits_memcmp(key.cbits() + 96, other.key.cbits() + 96, 256) < 0); -} - -bool OutputQueueMerger::MsgKeyValue::less(const std::unique_ptr& he1, - const std::unique_ptr& he2) { - return *he1 < *he2; -} - -bool OutputQueueMerger::MsgKeyValue::greater(const std::unique_ptr& he1, - const std::unique_ptr& he2) { - return *he2 < *he1; -} - -OutputQueueMerger::MsgKeyValue::MsgKeyValue(td::ConstBitPtr key_pfx, int key_pfx_len, int _src, Ref node) - : source(_src) { - unpack_node(key_pfx, key_pfx_len, std::move(node)); -} - -OutputQueueMerger::MsgKeyValue::MsgKeyValue(int _src, Ref node) : source(_src) { - unpack_node(td::ConstBitPtr{nullptr}, 0, std::move(node)); -} - -bool OutputQueueMerger::MsgKeyValue::invalidate() { - msg.clear(); - lt = 0; - source = -1; - return false; -} - -ton::LogicalTime OutputQueueMerger::MsgKeyValue::get_node_lt(Ref node, int key_pfx_len) { - if (node.is_null() || (unsigned)key_pfx_len > (unsigned)max_key_len) { - return std::numeric_limits::max(); - } - vm::dict::LabelParser label{std::move(node), max_key_len - key_pfx_len, vm::dict::LabelParser::chk_size}; - if (!label.is_valid()) { - return std::numeric_limits::max(); - } - label.skip_label(); - return label.remainder->prefetch_ulong(64); -} - -bool OutputQueueMerger::MsgKeyValue::unpack_node(td::ConstBitPtr key_pfx, int key_pfx_len, Ref node) { - if (node.is_null() || (unsigned)key_pfx_len >= (unsigned)max_key_len) { - return invalidate(); - } - if (!key_pfx.is_null()) { - td::bitstring::bits_memcpy(key.bits(), key_pfx, key_pfx_len); - } - vm::dict::LabelParser label{std::move(node), max_key_len - key_pfx_len, vm::dict::LabelParser::chk_size}; - if (!label.is_valid()) { - return invalidate(); - } - label.extract_label_to(key.bits() + key_pfx_len); - key_len = key_pfx_len + label.l_bits; - msg = std::move(label.remainder); - if (!msg.write().fetch_uint_to(64, lt)) { - return invalidate(); - } - if (is_fork() && msg->size_ext() != 0x20000) { - return invalidate(); - } - return true; -} - -bool OutputQueueMerger::MsgKeyValue::replace_with_child(bool child_idx) { - if (!is_fork() || msg.is_null() || msg->size_ext() != 0x20000) { - return false; - } - key[key_len] = child_idx; - return unpack_node(td::ConstBitPtr{nullptr}, key_len + 1, msg->prefetch_ref(child_idx)); -} - -bool OutputQueueMerger::MsgKeyValue::replace_by_prefix(td::ConstBitPtr req_pfx, int req_pfx_len) { - do { - if (td::bitstring::bits_memcmp(req_pfx, key.cbits(), std::min(req_pfx_len, key_len))) { - return false; - } - if (key_len >= req_pfx_len) { - return true; - } - } while (replace_with_child(req_pfx[key_len])); - return false; -} - -bool OutputQueueMerger::MsgKeyValue::split(MsgKeyValue& second) { - if (!is_fork() || msg.is_null()) { - return false; - } - unsigned long long keep_lt = lt; - unsigned long long left_lt = get_node_lt(msg->prefetch_ref(0), key_len + 1); - bool sw = (left_lt == lt); - second.source = source; - key[key_len] = sw; - if (!second.unpack_node(key.cbits(), key_len + 1, msg->prefetch_ref(sw))) { - return false; - } - key[key_len] = 1 - sw; - if (!unpack_node(td::ConstBitPtr{nullptr}, key_len + 1, msg->prefetch_ref(1 - sw))) { - return false; - } - if (lt != keep_lt || second.lt < keep_lt) { - return false; - } - return true; -} - -bool OutputQueueMerger::add_root(int src, Ref outmsg_root) { - if (outmsg_root.is_null()) { - return true; - } - //block::gen::HashmapAug{352, block::gen::t_EnqueuedMsg, block::gen::t_uint64}.print_ref(std::cerr, outmsg_root); - auto kv = std::make_unique(src, std::move(outmsg_root)); - if (kv->replace_by_prefix(common_pfx.cbits(), common_pfx_len)) { - heap.push_back(std::move(kv)); - } - return true; -} - -OutputQueueMerger::OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector _neighbors) - : queue_for(_queue_for), neighbors(std::move(_neighbors)), eof(false), failed(false) { - init(); -} - -void OutputQueueMerger::init() { - common_pfx.bits().store_int(queue_for.workchain, 32); - int l = queue_for.pfx_len(); - td::bitstring::bits_store_long_top(common_pfx.bits() + 32, queue_for.shard, l); - common_pfx_len = 32 + l; - int i = 0; - for (block::McShardDescr& neighbor : neighbors) { - if (!neighbor.is_disabled()) { - LOG(DEBUG) << "adding " << (neighbor.outmsg_root.is_null() ? "" : "non-") << "empty output queue for neighbor #" - << i << " (" << neighbor.blk_.to_str() << ")"; - add_root(i++, neighbor.outmsg_root); - } else { - LOG(DEBUG) << "skipping output queue for disabled neighbor #" << i; - i++; - } - } - std::make_heap(heap.begin(), heap.end(), MsgKeyValue::greater); - eof = heap.empty(); - if (!eof) { - load(); - } -} - -OutputQueueMerger::MsgKeyValue* OutputQueueMerger::cur() { - return eof ? nullptr : msg_list.at(pos).get(); -} - -std::unique_ptr OutputQueueMerger::extract_cur() { - return eof ? std::unique_ptr{} : std::move(msg_list.at(pos)); -} - -bool OutputQueueMerger::next() { - if (eof) { - return false; - } else if (++pos < msg_list.size() || load()) { - return true; - } else { - eof = true; - return false; - } -} - -bool OutputQueueMerger::load() { - if (heap.empty() || failed) { - return false; - } - unsigned long long lt = heap[0]->lt; - std::size_t orig_size = msg_list.size(); - do { - while (heap[0]->is_fork()) { - auto other = std::make_unique(); - if (!heap[0]->split(*other)) { - failed = true; - return false; - } - heap.push_back(std::move(other)); - std::push_heap(heap.begin(), heap.end(), MsgKeyValue::greater); - } - assert(heap[0]->lt == lt); - std::pop_heap(heap.begin(), heap.end(), MsgKeyValue::greater); - msg_list.push_back(std::move(heap.back())); - heap.pop_back(); - } while (!heap.empty() && heap[0]->lt <= lt); - std::sort(msg_list.begin() + orig_size, msg_list.end(), MsgKeyValue::less); - return true; -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/output-queue-merger.h b/submodules/ton/tonlib-src/crypto/block/output-queue-merger.h deleted file mode 100644 index bf3d8586..00000000 --- a/submodules/ton/tonlib-src/crypto/block/output-queue-merger.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "ton/ton-types.h" -#include "vm/cells/CellSlice.h" -#include "block/mc-config.h" - -namespace block { -using td::Ref; - -struct OutputQueueMerger { - struct MsgKeyValue { - static constexpr int max_key_len = 32 + 64 + 256; - Ref msg; - unsigned long long lt; - int source; - int key_len{0}; - td::BitArray key; - MsgKeyValue() = default; - MsgKeyValue(int src, Ref node); - MsgKeyValue(td::ConstBitPtr key_pfx, int key_pfx_len, int src, Ref node); - bool operator<(const MsgKeyValue& other) const; - bool is_fork() const { - return key_len < max_key_len; - } - bool invalidate(); - static bool less(const std::unique_ptr& he1, const std::unique_ptr& he2); - static bool greater(const std::unique_ptr& he1, const std::unique_ptr& he2); - - protected: - friend struct OutputQueueMerger; - static ton::LogicalTime get_node_lt(Ref node, int key_pfx_len); - bool replace_with_child(bool child_idx); - bool replace_by_prefix(td::ConstBitPtr req_pfx, int req_pfx_len); - bool unpack_node(td::ConstBitPtr key_pfx, int key_pfx_len, Ref node); - bool split(MsgKeyValue& second); - }; - // - ton::ShardIdFull queue_for; - std::vector> msg_list; - std::vector neighbors; - - public: - OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector _neighbors); - bool is_eof() const { - return eof; - } - MsgKeyValue* cur(); - std::unique_ptr extract_cur(); - bool next(); - - private: - td::BitArray<32 + 64> common_pfx; - int common_pfx_len; - std::vector> heap; - std::size_t pos{0}; - bool eof; - bool failed; - void init(); - bool add_root(int src, Ref outmsg_root); - bool load(); -}; - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/test-block.cpp b/submodules/ton/tonlib-src/crypto/block/test-block.cpp deleted file mode 100644 index 6e10ebe9..00000000 --- a/submodules/ton/tonlib-src/crypto/block/test-block.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2019 Telegram Systems LLP -*/ -#include "block/block.h" -#include "vm/boc.h" -#include -#include "block-db.h" -#include "block-auto.h" -#include "block-parse.h" -#include "vm/cp0.h" -#include - -using td::Ref; - -int verbosity; - -struct IntError { - std::string err_msg; - IntError(std::string _msg) : err_msg(_msg) { - } - IntError(const char* _msg) : err_msg(_msg) { - } -}; - -td::Ref load_boc(std::string filename) { - std::cerr << "loading bag-of-cell file " << filename << std::endl; - auto bytes_res = block::load_binary_file(filename); - if (bytes_res.is_error()) { - throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()}; - } - vm::BagOfCells boc; - auto res = boc.deserialize(bytes_res.move_as_ok()); - if (res.is_error()) { - throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()}; - } - if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) { - throw IntError{"cannot deserialize bag-of-cells "}; - } - return boc.get_root_cell(); -} - -void test1() { - block::ShardId id{ton::masterchainId}, id2{ton::basechainId, 0x11efULL << 48}; - std::cout << '[' << id << "][" << id2 << ']' << std::endl; - vm::CellBuilder cb; - cb << id << id2; - std::cout << "ShardIdent.pack() = " << block::tlb::t_ShardIdent.pack(cb, {12, 3, 0x3aeULL << 52}) << std::endl; - std::cout << cb << std::endl; - auto cref = cb.finalize(); - td::Ref cs{true, cref}, cs2; - block::ShardId id3{cs.write()}, id4, id5; - cs >> id4 >> id5; - std::cout << '[' << id3 << "][" << id4 << "][" << id5 << ']' << std::endl; - vm::CellSlice csl{std::move(cref)}; - std::cout << "ShardIdent.get_size() = " << block::tlb::t_ShardIdent.get_size(csl) << std::endl; - std::cout << "MsgAddress.get_size() = " << block::tlb::t_MsgAddress.get_size(csl) << std::endl; - std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl) << std::endl; - std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl) << std::endl; - (csl + 8).print_rec(std::cout); - std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl + 8) << std::endl; - std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl + 8) << std::endl; - - vm::CellSlice csl2{csl}; - block::gen::ShardIdent::Record sh_id; - for (int i = 0; i < 3; i++) { - std::cout << csl2 << std::endl; - bool ok = tlb::unpack(csl2, sh_id); - std::cout << "block::gen::ShardIdent.unpack() = " << ok << std::endl; - if (ok) { - std::cout << " (shard_ident shard_pfx_bits:" << sh_id.shard_pfx_bits << " workchain_id:" << sh_id.workchain_id - << " shard_prefix:" << std::hex << sh_id.shard_prefix << std::dec << ")" << std::endl; - } - } - - block::tlb::ShardIdent::Record shard_id; - for (int i = 0; i < 3; i++) { - std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate(csl) << std::endl; - csl.print_rec(std::cerr); - csl.dump(std::cerr, 7); - std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl; - if (shard_id.is_valid()) { - std::cout << "shard_pfx_bits:" << shard_id.shard_pfx_bits << " workchain_id:" << shard_id.workchain_id - << " shard_prefix:" << shard_id.shard_prefix << std::endl; - } - } - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl; - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl; - std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl; - using namespace td::literals; - std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl; - std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl; - std::cout << "Grams.store_intval(-17) = " << block::tlb::t_Grams.store_integer_value(cb, "-17"_i256) << std::endl; - std::cout << "Grams.store_intval(0) = " << block::tlb::t_Grams.store_integer_value(cb, "0"_i256) << std::endl; - std::cout << cb << std::endl; - cs = td::Ref{true, cb.finalize()}; - std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl; - std::cout << cb << std::endl; - cs2 = td::Ref{true, cb.finalize()}; - std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate(*cs) << std::endl; - std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate(*cs2) << std::endl; - // - block::gen::SplitMergeInfo::Record data; - block::gen::Grams::Record data2; - std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate(*cs) << std::endl; - std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate(*cs2) << std::endl; - std::cout << "[cs = " << cs << "]" << std::endl; - bool ok = tlb::csr_unpack_inexact(cs, data); - std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl; - if (ok) { - std::cout << " cur_shard_pfx_len = " << data.cur_shard_pfx_len << "; acc_split_depth = " << data.acc_split_depth - << "; this_addr = " << data.this_addr << "; sibling_addr = " << data.sibling_addr << std::endl; - } - ok = tlb::csr_unpack_inexact(cs, data2); - std::cout << "block::gen::Grams.unpack(cs, data2) = " << ok << std::endl; - if (ok) { - std::cout << " amount = " << data2.amount << std::endl; - block::gen::VarUInteger::Record data3; - ok = tlb::csr_type_unpack(data2.amount, block::gen::t_VarUInteger_16, data3); - std::cout << " block::gen::VarUInteger16.unpack(amount, data3) = " << ok << std::endl; - if (ok) { - std::cout << " len = " << data3.len << "; value = " << data3.value << std::endl; - vm::CellBuilder cb; - std::cout << " block::gen::VarUInteger16.pack(cb, data3) = " - << tlb::type_pack(cb, block::gen::t_VarUInteger_16, data3) << std::endl; - std::cout << " cb = " << cb.finalize() << std::endl; - } - } - /* - { - vm::CellBuilder cb; - td::BitArray<256> hash; - std::memset(hash.data(), 0x69, 32); - bool ok = tlb::pack( - cb, block::gen::Test::Record{1000000000000, {170239, -888, {239017, "1000000000000000000"_ri256}, hash}, 17}); - std::cout << " block::gen::Test::pack(cb, {1000000000000, ...}) = " << ok << std::endl; - std::cout << " cb = " << cb << std::endl; - auto cell = cb.finalize(); - vm::CellSlice cs{cell}; - cs.print_rec(std::cout); - block::gen::Test::Record data; - std::cout << " block::gen::Test::validate_ref(cell) = " << block::gen::t_Test.validate_ref(cell) << std::endl; - ok = tlb::unpack(cs, data); - std::cout << " block::gen::Test::unpack(cs, data) = " << ok << std::endl; - if (ok) { - std::cout << "a:" << data.a << " b:" << data.r1.b << " c:" << data.r1.c << " d:" << data.r1.r1.d - << " e:" << data.r1.r1.e << " f:" << data.r1.f << " g:" << data.g << std::endl; - } - std::cout << " block::gen::Test::print_ref(cell) = "; - block::gen::t_Test.print_ref(std::cout, cell, 2); - block::gen::t_CurrencyCollection.print_ref(std::cout, cell, 2); - std::cout << std::endl; - } - */ - std::cout << "Grams.add_values() = " << block::tlb::t_Grams.add_values(cb, cs.write(), cs2.write()) << std::endl; - std::cout << cb << std::endl; - std::cout << "block::gen::t_HashmapAug_64_...print_type() = " - << block::gen::t_HashmapAug_64_Ref_Transaction_CurrencyCollection << std::endl; -} - -void test2(vm::CellSlice& cs) { - std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate(cs) << std::endl; - std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate(cs) << std::endl; - std::cout << "HashmapE(32,UInt16).validate() = " << block::tlb::HashmapE(32, block::tlb::t_uint16).validate(cs) - << std::endl; - std::cout << "block::gen::HashmapE(32,UInt16).validate() = " - << block::gen::HashmapE{32, block::gen::t_uint16}.validate(cs) << std::endl; -} - -void usage() { - std::cout << "usage: test-block []\n\tor test-block -h\n"; - std::exit(2); -} - -int main(int argc, char* const argv[]) { - int i; - int new_verbosity_level = VERBOSITY_NAME(INFO); - auto zerostate = std::make_unique(); - while ((i = getopt(argc, argv, "hv:")) != -1) { - switch (i) { - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer(td::Slice(optarg))); - break; - case 'h': - usage(); - std::exit(2); - default: - usage(); - std::exit(2); - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - try { - bool done = false; - while (optind < argc) { - auto boc = load_boc(argv[optind++]); - if (boc.is_null()) { - std::cerr << "(invalid boc)" << std::endl; - std::exit(2); - } else { - done = true; - vm::CellSlice cs{vm::NoVm(), boc}; - cs.print_rec(std::cout); - std::cout << std::endl; - block::gen::t_Block.print_ref(std::cout, boc); - std::cout << std::endl; - if (!block::gen::t_Block.validate_ref(boc)) { - std::cout << "(invalid Block)" << std::endl; - } else { - std::cout << "(valid Block)" << std::endl; - } - } - } - if (!done) { - test1(); - } - } catch (IntError& err) { - std::cerr << "caught internal error " << err.err_msg << std::endl; - return 1; - } catch (vm::VmError& err) { - std::cerr << "caught vm error " << err.get_msg() << std::endl; - return 1; - } - return 0; -} diff --git a/submodules/ton/tonlib-src/crypto/block/test-weight-distr.cpp b/submodules/ton/tonlib-src/crypto/block/test-weight-distr.cpp deleted file mode 100644 index a94b791c..00000000 --- a/submodules/ton/tonlib-src/crypto/block/test-weight-distr.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2020 Telegram Systems LLP -*/ -#include -#include "td/utils/Random.h" -#include "td/utils/misc.h" -#include "block/block.h" -#include - -const int MAX_N = 1000, MAX_K = 100, DEFAULT_K = 7; - -int verbosity; -int N, K = DEFAULT_K; -long long iterations = 1000000; - -td::uint64 TWL, WL[MAX_N]; -double W[MAX_N], CW[MAX_N + 1], RW[MAX_N], R0; -int A[MAX_N], C[MAX_N]; -long long TC; - -void gen_vset() { - static std::pair H[MAX_N]; - double total_wt = 1.; - int hc = 0; - for (int i = 0; i < K; i++) { - CHECK(total_wt > 0); - double inv_wt = 1. / total_wt; - R0 += inv_wt; // advanced mtcarlo stats - for (int j = 0; j < i; j++) { - RW[A[j]] -= inv_wt; // advanced mtcarlo stats - } - // double p = drand48() * total_wt; - double p = (double)td::Random::fast_uint64() * total_wt / (1. * (1LL << 32) * (1LL << 32)); - for (int h = 0; h < hc; h++) { - if (p < H[h].first) { - break; - } - p += H[h].second; - } - int a = -1, b = N, c; - while (b - a > 1) { - c = ((a + b) >> 1); - if (CW[c] <= p) { - a = c; - } else { - b = c; - } - } - CHECK(a >= 0 && a < N); - CHECK(total_wt >= W[a]); - total_wt -= W[a]; - double x = CW[a]; - c = hc++; - while (c > 0 && H[c - 1].first > x) { - H[c] = H[c - 1]; - --c; - } - H[c].first = x; - H[c].second = W[a]; - A[i] = a; - C[a]++; // simple mtcarlo stats - // std::cout << a << ' '; - } - // std::cout << std::endl; - ++TC; // simple mtcarlo stats -} - -void mt_carlo() { - for (int i = 0; i < N; i++) { - C[i] = 0; - RW[i] = 0.; - } - TC = 0; - R0 = 0.; - std::cout << "running " << iterations << " steps of Monte Carlo simulation\n"; - for (long long it = 0; it < iterations; ++it) { - gen_vset(); - } - for (int i = 0; i < N; i++) { - RW[i] = W[i] * (RW[i] + R0) / (double)iterations; - } -} - -double B[MAX_N]; - -void compute_bad_approx() { - static double S[MAX_K + 1]; - S[0] = 1.; - for (int i = 1; i <= K; i++) { - S[i] = 0.; - } - for (int i = 0; i < N; i++) { - double p = W[i]; - for (int j = K; j > 0; j--) { - S[j] += p * S[j - 1]; - } - } - double Sk = S[K]; - for (int i = 0; i < N; i++) { - double t = 1., p = W[i]; - for (int j = 1; j <= K; j++) { - t = S[j] - p * t; - } - B[i] = 1. - t / Sk; - } -} - -void usage() { - std::cout - << "usage: test-weight-distr [-k][-m][-s]\nReads the set of validator " - "weights from stdin and emulates validator shard distribution load\n\t-k \tSets the number of " - "validators generating each shard\n\t-m \tMonte Carlo simulation steps\n"; - std::exit(2); -} - -int main(int argc, char* const argv[]) { - int i; - int new_verbosity_level = VERBOSITY_NAME(INFO); - // long seed = 0; - while ((i = getopt(argc, argv, "hs:k:m:v:")) != -1) { - switch (i) { - case 'k': - K = td::to_integer(td::Slice(optarg)); - CHECK(K > 0 && K <= 100); - break; - case 'm': - iterations = td::to_integer(td::Slice(optarg)); - CHECK(iterations > 0); - break; - case 's': - // seed = td::to_integer(td::Slice(optarg)); - // srand48(seed); - break; - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer(td::Slice(optarg))); - break; - case 'h': - usage(); - std::exit(2); - default: - usage(); - std::exit(2); - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - for (N = 0; N < MAX_N && (std::cin >> WL[N]); N++) { - CHECK(WL[N] > 0); - TWL += WL[N]; - } - CHECK(std::cin.eof()); - CHECK(N > 0 && TWL > 0 && N <= MAX_N); - K = std::min(K, N); - CHECK(K > 0 && K <= MAX_K); - double acc = 0.; - for (i = 0; i < N; i++) { - CW[i] = acc; - acc += W[i] = (double)WL[i] / (double)TWL; - std::cout << "#" << i << ":\t" << W[i] << std::endl; - } - compute_bad_approx(); - mt_carlo(); - std::cout << "result of Monte Carlo simulation (" << iterations << " iterations):" << std::endl; - std::cout << "idx\tweight\tmtcarlo1\tmtcarlo2\tapprox\n"; - for (i = 0; i < N; i++) { - std::cout << "#" << i << ":\t" << W[i] << '\t' << (double)C[i] / (double)iterations << '\t' << RW[i] << '\t' << B[i] - << std::endl; - } - // same computation, but using a MtCarloComputeShare object - block::MtCarloComputeShare MT(K, N, W, iterations); - std::cout << "-----------------------\n"; - for (i = 0; i < N; i++) { - std::cout << '#' << i << ":\t" << MT.weight(i) << '\t' << MT.share(i) << std::endl; - } - return 0; -} diff --git a/submodules/ton/tonlib-src/crypto/block/transaction.cpp b/submodules/ton/tonlib-src/crypto/block/transaction.cpp deleted file mode 100644 index 3f5a1ae6..00000000 --- a/submodules/ton/tonlib-src/crypto/block/transaction.cpp +++ /dev/null @@ -1,2308 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "block/transaction.h" -#include "block/block.h" -#include "block/block-parse.h" -#include "block/block-auto.h" -#include "td/utils/bits.h" -#include "td/utils/uint128.h" -#include "ton/ton-shard.h" -#include "vm/vm.h" - -namespace block { -using td::Ref; - -Ref ComputePhaseConfig::lookup_library(td::ConstBitPtr key) const { - return libraries ? vm::lookup_library_in(key, libraries->get_root_cell()) : Ref{}; -} - -/* - * - * ACCOUNTS - * - */ - -bool Account::set_address(ton::WorkchainId wc, td::ConstBitPtr new_addr) { - workchain = wc; - addr = new_addr; - return true; -} - -bool Account::set_split_depth(int new_split_depth) { - if (new_split_depth < 0 || new_split_depth > 30) { - return false; // invalid value for split_depth - } - if (split_depth_set_) { - return split_depth_ == new_split_depth; - } else { - split_depth_ = (unsigned char)new_split_depth; - split_depth_set_ = true; - return true; - } -} - -bool Account::check_split_depth(int split_depth) const { - return split_depth_set_ ? (split_depth == split_depth_) : (split_depth >= 0 && split_depth <= 30); -} - -// initializes split_depth and addr_rewrite -bool Account::parse_maybe_anycast(vm::CellSlice& cs) { - int t = (int)cs.fetch_ulong(1); - if (t < 0) { - return false; - } else if (!t) { - return set_split_depth(0); - } - int depth; - return cs.fetch_uint_leq(30, depth) // anycast_info$_ depth:(#<= 30) - && depth // { depth >= 1 } - && cs.fetch_bits_to(addr_rewrite.bits(), depth) // rewrite_pfx:(bits depth) - && set_split_depth(depth); -} - -bool Account::store_maybe_anycast(vm::CellBuilder& cb) const { - if (!split_depth_set_ || !split_depth_) { - return cb.store_bool_bool(false); - } - return cb.store_bool_bool(true) // just$1 - && cb.store_uint_leq(30, split_depth_) // depth:(#<= 30) - && cb.store_bits_bool(addr_rewrite.cbits(), split_depth_); // rewrite_pfx:(bits depth) -} - -bool Account::unpack_address(vm::CellSlice& addr_cs) { - int addr_tag = block::gen::t_MsgAddressInt.get_tag(addr_cs); - int new_wc = ton::workchainInvalid; - switch (addr_tag) { - case block::gen::MsgAddressInt::addr_std: - if (!(addr_cs.advance(2) && parse_maybe_anycast(addr_cs) && addr_cs.fetch_int_to(8, new_wc) && - addr_cs.fetch_bits_to(addr_orig.bits(), 256) && addr_cs.empty_ext())) { - return false; - } - break; - case block::gen::MsgAddressInt::addr_var: - // cannot appear in masterchain / basechain - return false; - default: - return false; - } - addr_cs.clear(); - if (new_wc == ton::workchainInvalid) { - return false; - } - if (workchain == ton::workchainInvalid) { - workchain = new_wc; - addr = addr_orig; - addr.bits().copy_from(addr_rewrite.cbits(), split_depth_); - } else if (split_depth_) { - ton::StdSmcAddress new_addr = addr_orig; - new_addr.bits().copy_from(addr_rewrite.cbits(), split_depth_); - if (new_addr != addr) { - LOG(ERROR) << "error unpacking account " << workchain << ":" << addr.to_hex() - << " : account header contains different address " << new_addr.to_hex() << " (with splitting depth " - << (int)split_depth_ << ")"; - return false; - } - } else if (addr != addr_orig) { - LOG(ERROR) << "error unpacking account " << workchain << ":" << addr.to_hex() - << " : account header contains different address " << addr_orig.to_hex(); - return false; - } - if (workchain != new_wc) { - LOG(ERROR) << "error unpacking account " << workchain << ":" << addr.to_hex() - << " : account header contains different workchain " << new_wc; - return false; - } - addr_rewrite = addr.bits(); // initialize all 32 bits of addr_rewrite - if (!split_depth_) { - my_addr_exact = my_addr; - } - return true; -} - -bool Account::unpack_storage_info(vm::CellSlice& cs) { - block::gen::StorageInfo::Record info; - block::gen::StorageUsed::Record used; - if (!tlb::unpack_exact(cs, info) || !tlb::csr_unpack(info.used, used)) { - return false; - } - last_paid = info.last_paid; - if (info.due_payment->prefetch_ulong(1) == 1) { - vm::CellSlice& cs2 = info.due_payment.write(); - cs2.advance(1); - due_payment = block::tlb::t_Grams.as_integer_skip(cs2); - if (due_payment.is_null() || !cs2.empty_ext()) { - return false; - } - } else { - due_payment = td::zero_refint(); - } - unsigned long long u = 0; - u |= storage_stat.cells = block::tlb::t_VarUInteger_7.as_uint(*used.cells); - u |= storage_stat.bits = block::tlb::t_VarUInteger_7.as_uint(*used.bits); - u |= storage_stat.public_cells = block::tlb::t_VarUInteger_7.as_uint(*used.public_cells); - LOG(DEBUG) << "last_paid=" << last_paid << "; cells=" << storage_stat.cells << " bits=" << storage_stat.bits - << " public_cells=" << storage_stat.public_cells; - return (u != std::numeric_limits::max()); -} - -// initializes split_depth (from account state - StateInit) -bool Account::unpack_state(vm::CellSlice& cs) { - block::gen::StateInit::Record state; - if (!tlb::unpack_exact(cs, state)) { - return false; - } - int sd = 0; - if (state.split_depth->size() == 6) { - sd = (int)state.split_depth->prefetch_ulong(6) - 32; - } - if (!set_split_depth(sd)) { - return false; - } - if (state.special->size() > 1) { - int z = (int)state.special->prefetch_ulong(3); - if (z < 0) { - return false; - } - tick = z & 2; - tock = z & 1; - LOG(DEBUG) << "tick=" << tick << ", tock=" << tock; - } - code = state.code->prefetch_ref(); - data = state.data->prefetch_ref(); - library = orig_library = state.library->prefetch_ref(); - return true; -} - -bool Account::compute_my_addr(bool force) { - if (!force && my_addr.not_null() && my_addr_exact.not_null()) { - return true; - } - if (workchain == ton::workchainInvalid) { - my_addr.clear(); - return false; - } - vm::CellBuilder cb; - Ref cell, cell2; - if (workchain >= -128 && workchain < 127) { - if (!(cb.store_long_bool(2, 2) // addr_std$10 - && store_maybe_anycast(cb) // anycast:(Maybe Anycast) - && cb.store_long_rchk_bool(workchain, 8) // workchain_id:int8 - && cb.store_bits_bool(addr_orig) // addr:bits256 - && cb.finalize_to(cell) && cb.store_long_bool(4, 3) // addr_std$10 anycast:(Maybe Anycast) - && cb.store_long_rchk_bool(workchain, 8) // workchain_id:int8 - && cb.store_bits_bool(addr) // addr:bits256 - && cb.finalize_to(cell2))) { - return false; - } - } else { - if (!(cb.store_long_bool(3, 2) // addr_var$11 - && store_maybe_anycast(cb) // anycast:(Maybe Anycast) - && cb.store_long_bool(256, 9) // addr_len:(## 9) - && cb.store_long_rchk_bool(workchain, 32) // workchain_id:int32 - && cb.store_bits_bool(addr_orig) // addr:(bits addr_len) - && cb.finalize_to(cell) && cb.store_long_bool(6, 3) // addr_var$11 anycast:(Maybe Anycast) - && cb.store_long_bool(256, 9) // addr_len:(## 9) - && cb.store_long_rchk_bool(workchain, 32) // workchain_id:int32 - && cb.store_bits_bool(addr) // addr:(bits addr_len) - && cb.finalize_to(cell2))) { - return false; - } - } - my_addr = load_cell_slice_ref(std::move(cell)); - my_addr_exact = load_cell_slice_ref(std::move(cell2)); - return true; -} - -bool Account::recompute_tmp_addr(Ref& tmp_addr, int split_depth, - td::ConstBitPtr orig_addr_rewrite) const { - if (!split_depth && my_addr_exact.not_null()) { - tmp_addr = my_addr_exact; - return true; - } - if (split_depth == split_depth_ && my_addr.not_null()) { - tmp_addr = my_addr; - return true; - } - if (split_depth < 0 || split_depth > 30) { - return false; - } - vm::CellBuilder cb; - bool std = (workchain >= -128 && workchain < 128); - if (!cb.store_long_bool(std ? 2 : 3, 2)) { // addr_std$10 or addr_var$11 - return false; - } - if (!split_depth) { - if (!cb.store_bool_bool(false)) { // anycast:(Maybe Anycast) - return false; - } - } else if (!(cb.store_bool_bool(true) // just$1 - && cb.store_long_bool(split_depth, 5) // depth:(#<= 30) - && cb.store_bits_bool(addr.bits(), split_depth))) { // rewrite_pfx:(bits depth) - return false; - } - if (std) { - if (!cb.store_long_rchk_bool(workchain, 8)) { // workchain:int8 - return false; - } - } else if (!(cb.store_long_bool(256, 9) // addr_len:(## 9) - && cb.store_long_bool(workchain, 32))) { // workchain:int32 - return false; - } - Ref cell; - return cb.store_bits_bool(orig_addr_rewrite, split_depth) // address:(bits addr_len) or bits256 - && cb.store_bits_bool(addr.bits() + split_depth, 256 - split_depth) && cb.finalize_to(cell) && - (tmp_addr = vm::load_cell_slice_ref(std::move(cell))).not_null(); -} - -bool Account::init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewrite) { - if (split_depth_set_ || !created || !set_split_depth(split_depth)) { - return false; - } - addr_orig = addr; - addr_rewrite = addr.bits(); - addr_orig.bits().copy_from(orig_addr_rewrite, split_depth); - return compute_my_addr(true); -} - -// used to unpack previously existing accounts -bool Account::unpack(Ref shard_account, Ref extra, ton::UnixTime now, bool special) { - LOG(DEBUG) << "unpacking " << (special ? "special " : "") << "account " << addr.to_hex(); - if (shard_account.is_null()) { - LOG(ERROR) << "account " << addr.to_hex() << " does not have a valid ShardAccount to unpack"; - return false; - } - if (verbosity > 2) { - shard_account->print_rec(std::cerr, 2); - block::gen::t_ShardAccount.print(std::cerr, *shard_account); - } - block::gen::ShardAccount::Record acc_info; - if (!(block::gen::t_ShardAccount.validate_csr(shard_account) && - block::tlb::t_ShardAccount.validate_csr(shard_account) && tlb::unpack_exact(shard_account.write(), acc_info))) { - LOG(ERROR) << "account " << addr.to_hex() << " state is invalid"; - return false; - } - last_trans_lt_ = acc_info.last_trans_lt; - last_trans_hash_ = acc_info.last_trans_hash; - now_ = now; - auto account = std::move(acc_info.account); - total_state = orig_total_state = account; - auto acc_cs = load_cell_slice(std::move(account)); - if (block::gen::t_Account.get_tag(acc_cs) == block::gen::Account::account_none) { - status = acc_nonexist; - last_paid = 0; - last_trans_end_lt_ = 0; - is_special = special; - if (workchain != ton::workchainInvalid) { - addr_orig = addr; - addr_rewrite = addr.cbits(); - } - return compute_my_addr() && acc_cs.size_ext() == 1; - } - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record storage; - if (!(tlb::unpack_exact(acc_cs, acc) && (my_addr = acc.addr).not_null() && unpack_address(acc.addr.write()) && - compute_my_addr() && unpack_storage_info(acc.storage_stat.write()) && - tlb::csr_unpack(std::move(acc.storage), storage) && - std::max(storage.last_trans_lt, 1ULL) > acc_info.last_trans_lt && balance.unpack(std::move(storage.balance)))) { - return false; - } - is_special = special; - last_trans_end_lt_ = storage.last_trans_lt; - switch (block::gen::t_AccountState.get_tag(*storage.state)) { - case block::gen::AccountState::account_uninit: - status = orig_status = acc_uninit; - state_hash = addr; - break; - case block::gen::AccountState::account_frozen: - status = orig_status = acc_frozen; - if (!storage.state->have(2 + 256)) { - return false; - } - state_hash = storage.state->data_bits() + 2; - break; - case block::gen::AccountState::account_active: - status = orig_status = acc_active; - if (storage.state.write().fetch_ulong(1) != 1) { - return false; - } - inner_state = storage.state; - if (!unpack_state(storage.state.write())) { - return false; - } - state_hash.clear(); - break; - default: - return false; - } - LOG(DEBUG) << "end of Account.unpack() for " << workchain << ":" << addr.to_hex() - << " (balance = " << balance.to_str() << " ; last_trans_lt = " << last_trans_lt_ << ".." - << last_trans_end_lt_ << ")"; - return true; -} - -// used to initialize new accounts -bool Account::init_new(ton::UnixTime now) { - // only workchain and addr are initialized at this point - if (workchain == ton::workchainInvalid) { - return false; - } - addr_orig = addr; - addr_rewrite = addr.cbits(); - last_trans_lt_ = last_trans_end_lt_ = 0; - last_trans_hash_.set_zero(); - now_ = now; - last_paid = 0; - storage_stat.clear(); - due_payment = td::zero_refint(); - balance.set_zero(); - if (my_addr_exact.is_null()) { - vm::CellBuilder cb; - if (workchain >= -128 && workchain < 128) { - CHECK(cb.store_long_bool(4, 3) // addr_std$10 anycast:(Maybe Anycast) - && cb.store_long_rchk_bool(workchain, 8) // workchain:int8 - && cb.store_bits_bool(addr)); // address:bits256 - } else { - CHECK(cb.store_long_bool(0xd00, 12) // addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) - && cb.store_long_rchk_bool(workchain, 32) // workchain:int32 - && cb.store_bits_bool(addr)); // address:(bits addr_len) - } - my_addr_exact = load_cell_slice_ref(cb.finalize()); - } - if (my_addr.is_null()) { - my_addr = my_addr_exact; - } - if (total_state.is_null()) { - vm::CellBuilder cb; - CHECK(cb.store_long_bool(0, 1) // account_none$0 = Account - && cb.finalize_to(total_state)); - orig_total_state = total_state; - } - state_hash = addr_orig; - status = orig_status = acc_nonexist; - created = true; - return true; -} - -bool Account::belongs_to_shard(ton::ShardIdFull shard) const { - return workchain == shard.workchain && ton::shard_is_ancestor(shard.shard, addr); -} - -void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, const block::StoragePrices& prices, - const vm::CellStorageStat& storage, bool is_mc) { - td::BigInt256 c{(long long)storage.cells}, b{(long long)storage.bits}; - if (is_mc) { - // storage.cells * prices.mc_cell_price + storage.bits * prices.mc_bit_price; - c.mul_short(prices.mc_cell_price); - b.mul_short(prices.mc_bit_price); - } else { - // storage.cells * prices.cell_price + storage.bits * prices.bit_price; - c.mul_short(prices.cell_price); - b.mul_short(prices.bit_price); - } - b += c; - b.mul_short(delta); - CHECK(b.sgn() >= 0); - payment += b; -} - -td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std::vector& pricing, - const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid, - bool is_special, bool is_masterchain) { - if (now <= last_paid || !last_paid || is_special || pricing.empty() || now <= pricing[0].valid_since) { - return {}; - } - std::size_t n = pricing.size(), i = n; - while (i && pricing[i - 1].valid_since > last_paid) { - --i; - } - if (i) { - --i; - } - ton::UnixTime upto = std::max(last_paid, pricing[0].valid_since); - td::RefInt256 total{true, 0}; - for (; i < n && upto < now; i++) { - ton::UnixTime valid_until = (i < n - 1 ? std::min(now, pricing[i + 1].valid_since) : now); - if (upto < valid_until) { - assert(upto >= pricing[i].valid_since); - add_partial_storage_payment(total.unique_write(), valid_until - upto, pricing[i], storage_stat, is_masterchain); - } - upto = valid_until; - } - total.unique_write().rshift(16, 1); // divide by 2^16 with ceil rounding to obtain nanograms - return total; -} - -td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const { - return StoragePrices::compute_storage_fees(now, pricing, storage_stat, last_paid, is_special, is_masterchain()); -} - -Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime req_start_lt, ton::UnixTime _now, - Ref _inmsg) - : trans_type(ttype) - , is_first(_account.transactions.empty()) - , new_tick(_account.tick) - , new_tock(_account.tock) - , now(_now) - , account(_account) - , my_addr(_account.my_addr) - , my_addr_exact(_account.my_addr_exact) - , balance(_account.balance) - , original_balance(_account.balance) - , due_payment(_account.due_payment) - , last_paid(_account.last_paid) - , new_code(_account.code) - , new_data(_account.data) - , new_library(_account.library) - , in_msg(std::move(_inmsg)) { - start_lt = std::max(req_start_lt, account.last_trans_end_lt_); - end_lt = start_lt + 1; - acc_status = (account.status == Account::acc_nonexist ? Account::acc_uninit : account.status); - if (acc_status == Account::acc_frozen) { - frozen_hash = account.state_hash; - } -} - -bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* cfg) { - if (in_msg.is_null() || in_msg_type) { - return false; - } - if (verbosity > 2) { - fprintf(stderr, "unpacking inbound message for a new transaction: "); - block::gen::t_Message_Any.print_ref(std::cerr, in_msg); - load_cell_slice(in_msg).print_rec(std::cerr); - } - auto cs = vm::load_cell_slice(in_msg); - int tag = block::gen::t_CommonMsgInfo.get_tag(cs); - Ref src_addr, dest_addr; - switch (tag) { - case block::gen::CommonMsgInfo::int_msg_info: { - block::gen::CommonMsgInfo::Record_int_msg_info info; - if (!(tlb::unpack(cs, info) && msg_balance_remaining.unpack(std::move(info.value)))) { - return false; - } - if (info.ihr_disabled && ihr_delivered) { - return false; - } - bounce_enabled = info.bounce; - src_addr = std::move(info.src); - dest_addr = std::move(info.dest); - in_msg_type = 1; - td::RefInt256 ihr_fee = block::tlb::t_Grams.as_integer(std::move(info.ihr_fee)); - if (ihr_delivered) { - in_fwd_fee = std::move(ihr_fee); - } else { - in_fwd_fee = td::zero_refint(); - msg_balance_remaining += std::move(ihr_fee); - } - if (info.created_lt >= start_lt) { - start_lt = info.created_lt + 1; - end_lt = start_lt + 1; - } - // ... - break; - } - case block::gen::CommonMsgInfo::ext_in_msg_info: { - block::gen::CommonMsgInfo::Record_ext_in_msg_info info; - if (!tlb::unpack(cs, info)) { - return false; - } - src_addr = std::move(info.src); - dest_addr = std::move(info.dest); - in_msg_type = 2; - in_msg_extern = true; - // compute forwarding fees for this external message - vm::CellStorageStat sstat; // for message size - sstat.compute_used_storage(cs); // message body - sstat.bits -= cs.size(); // bits in the root cells are free - sstat.cells--; // the root cell itself is not counted as a cell - LOG(DEBUG) << "storage paid for a message: " << sstat.cells << " cells, " << sstat.bits << " bits"; - if (sstat.bits > max_msg_bits || sstat.cells > max_msg_cells) { - LOG(DEBUG) << "inbound external message too large, invalid"; - return false; - } - // fetch message pricing info - CHECK(cfg); - const MsgPrices& msg_prices = cfg->fetch_msg_prices(account.is_masterchain()); - // compute forwarding fees - auto fees_c = msg_prices.compute_fwd_ihr_fees(sstat.cells, sstat.bits, true); - LOG(DEBUG) << "computed fwd fees = " << fees_c.first << " + " << fees_c.second; - - if (account.is_special) { - LOG(DEBUG) << "computed fwd fees set to zero for special account"; - fees_c.first = fees_c.second = 0; - } - in_fwd_fee = td::make_refint(fees_c.first); - if (balance.grams < in_fwd_fee) { - LOG(DEBUG) << "cannot pay for importing this external message"; - return false; - } - // (tentatively) debit account for importing this external message - balance -= in_fwd_fee; - msg_balance_remaining.set_zero(); // external messages cannot carry value - // ... - break; - } - default: - return false; - } - // init:(Maybe (Either StateInit ^StateInit)) - switch ((int)cs.prefetch_ulong(2)) { - case 2: { // (just$1 (left$0 _:StateInit )) - Ref state_init; - vm::CellBuilder cb; - if (!(cs.advance(2) && block::gen::t_StateInit.fetch_to(cs, state_init) && - cb.append_cellslice_bool(std::move(state_init)) && cb.finalize_to(in_msg_state) && - block::gen::t_StateInit.validate_ref(in_msg_state))) { - LOG(DEBUG) << "cannot parse StateInit in inbound message"; - return false; - } - break; - } - case 3: { // (just$1 (right$1 _:^StateInit )) - if (!(cs.advance(2) && cs.fetch_ref_to(in_msg_state) && block::gen::t_StateInit.validate_ref(in_msg_state))) { - LOG(DEBUG) << "cannot parse ^StateInit in inbound message"; - return false; - } - break; - } - default: // nothing$0 - if (!cs.advance(1)) { - LOG(DEBUG) << "invalid init field in an inbound message"; - return false; - } - } - // body:(Either X ^X) - switch ((int)cs.fetch_ulong(1)) { - case 0: // left$0 _:X - in_msg_body = Ref{true, cs}; - break; - case 1: // right$1 _:^X - if (cs.size_ext() != 0x10000) { - LOG(DEBUG) << "body of an inbound message is not represented by exactly one reference"; - return false; - } - in_msg_body = load_cell_slice_ref(cs.prefetch_ref()); - break; - default: - LOG(DEBUG) << "invalid body field in an inbound message"; - return false; - } - total_fees += in_fwd_fee; - return true; -} - -bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool force_collect, bool adjust_msg_value) { - if (now < account.last_paid) { - return false; - } - auto to_pay = account.compute_storage_fees(now, *(cfg.pricing)); - if (to_pay.not_null() && sgn(to_pay) < 0) { - return false; - } - auto res = std::make_unique(); - res->is_special = account.is_special; - last_paid = res->last_paid_updated = (res->is_special ? 0 : now); - if (to_pay.is_null() || sgn(to_pay) == 0) { - res->fees_collected = res->fees_due = td::zero_refint(); - } else if (to_pay <= balance.grams) { - res->fees_collected = to_pay; - res->fees_due = td::zero_refint(); - balance -= std::move(to_pay); - } else if (acc_status == Account::acc_frozen && !force_collect && to_pay + due_payment < cfg.delete_due_limit) { - // do not collect fee - res->last_paid_updated = (res->is_special ? 0 : account.last_paid); - res->fees_collected = res->fees_due = td::zero_refint(); - } else { - res->fees_collected = balance.grams; - res->fees_due = std::move(to_pay) - std::move(balance.grams); - balance.grams = td::zero_refint(); - if (!res->is_special) { - auto total_due = res->fees_due + due_payment; - switch (acc_status) { - case Account::acc_uninit: - case Account::acc_frozen: - if (total_due > cfg.delete_due_limit) { - res->deleted = true; - acc_status = Account::acc_deleted; - if (balance.extra.not_null()) { - // collect extra currencies as a fee - total_fees += block::CurrencyCollection{0, std::move(balance.extra)}; - balance.extra.clear(); - } - } - break; - case Account::acc_active: - if (total_due > cfg.freeze_due_limit) { - res->frozen = true; - was_frozen = true; - acc_status = Account::acc_frozen; - } - break; - } - } - } - if (adjust_msg_value && msg_balance_remaining.grams > balance.grams) { - msg_balance_remaining.grams = balance.grams; - } - total_fees += res->fees_collected; - storage_phase = std::move(res); - return true; -} - -bool Transaction::prepare_credit_phase() { - credit_phase = std::make_unique(); - auto collected = std::min(msg_balance_remaining.grams, due_payment); - credit_phase->due_fees_collected = collected; - due_payment -= collected; - credit_phase->credit = msg_balance_remaining -= collected; - if (!msg_balance_remaining.is_valid()) { - LOG(ERROR) << "cannot compute the amount to be credited in the credit phase of transaction"; - return false; - } - // NB: msg_balance_remaining may be deducted from balance later during bounce phase - balance += msg_balance_remaining; - if (!balance.is_valid()) { - LOG(ERROR) << "cannot credit currency collection to account"; - return false; - } - total_fees += std::move(collected); - return true; -} - -bool ComputePhaseConfig::parse_GasLimitsPrices(Ref cell, td::RefInt256& freeze_due_limit, - td::RefInt256& delete_due_limit) { - return cell.not_null() && - parse_GasLimitsPrices(vm::load_cell_slice_ref(std::move(cell)), freeze_due_limit, delete_due_limit); -} - -bool ComputePhaseConfig::parse_GasLimitsPrices(Ref cs, td::RefInt256& freeze_due_limit, - td::RefInt256& delete_due_limit) { - if (cs.is_null()) { - return false; - } - block::gen::GasLimitsPrices::Record_gas_flat_pfx flat; - if (tlb::csr_unpack(cs, flat)) { - return parse_GasLimitsPrices_internal(std::move(flat.other), freeze_due_limit, delete_due_limit, - flat.flat_gas_limit, flat.flat_gas_price); - } else { - return parse_GasLimitsPrices_internal(std::move(cs), freeze_due_limit, delete_due_limit); - } -} - -bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref cs, td::RefInt256& freeze_due_limit, - td::RefInt256& delete_due_limit, td::uint64 _flat_gas_limit, - td::uint64 _flat_gas_price) { - auto f = [&](const auto& r, td::uint64 spec_limit) { - gas_limit = r.gas_limit; - special_gas_limit = spec_limit; - gas_credit = r.gas_credit; - gas_price = r.gas_price; - freeze_due_limit = td::make_refint(r.freeze_due_limit); - delete_due_limit = td::make_refint(r.delete_due_limit); - }; - block::gen::GasLimitsPrices::Record_gas_prices_ext rec; - if (tlb::csr_unpack(cs, rec)) { - f(rec, rec.special_gas_limit); - } else { - block::gen::GasLimitsPrices::Record_gas_prices rec0; - if (tlb::csr_unpack(std::move(cs), rec0)) { - f(rec0, rec0.gas_limit); - } else { - return false; - } - } - flat_gas_limit = _flat_gas_limit; - flat_gas_price = _flat_gas_price; - compute_threshold(); - return true; -} - -void ComputePhaseConfig::compute_threshold() { - gas_price256 = td::make_refint(gas_price); - if (gas_limit > flat_gas_limit) { - max_gas_threshold = - td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_bigint(flat_gas_price); - } else { - max_gas_threshold = td::make_refint(flat_gas_price); - } -} - -td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const { - if (nanograms.is_null() || sgn(nanograms) < 0) { - return 0; - } - if (nanograms >= max_gas_threshold) { - return gas_limit; - } - if (nanograms < flat_gas_price) { - return 0; - } - auto res = td::div((std::move(nanograms) - flat_gas_price) << 16, gas_price256); - return res->to_long() + flat_gas_limit; -} - -td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const { - return gas_used <= flat_gas_limit ? td::make_refint(flat_gas_price) - : td::rshift(gas_price256 * (gas_used - flat_gas_limit), 16, 1) + flat_gas_price; -} - -bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg) { - // Compute gas limits - if (account.is_special) { - cp.gas_max = cfg.special_gas_limit; - } else { - cp.gas_max = cfg.gas_bought_for(balance.grams); - } - cp.gas_credit = 0; - if (trans_type != tr_ord) { - // may use all gas that can be bought using remaining balance - cp.gas_limit = cp.gas_max; - } else { - // originally use only gas bought using remaining message balance - // if the message is "accepted" by the smart contract, the gas limit will be set to gas_max - cp.gas_limit = std::min(cfg.gas_bought_for(msg_balance_remaining.grams), cp.gas_max); - if (!block::tlb::t_Message.is_internal(in_msg)) { - // external messages carry no balance, give them some credit to check whether they are accepted - cp.gas_credit = std::min(cfg.gas_credit, cp.gas_max); - } - } - LOG(DEBUG) << "gas limits: max=" << cp.gas_max << ", limit=" << cp.gas_limit << ", credit=" << cp.gas_credit; - return true; -} - -Ref Transaction::prepare_vm_stack(ComputePhase& cp) { - Ref stack_ref{true}; - td::RefInt256 acc_addr{true}; - CHECK(acc_addr.write().import_bits(account.addr.cbits(), 256)); - vm::Stack& stack = stack_ref.write(); - switch (trans_type) { - case tr_tick: - case tr_tock: - stack.push_int(balance.grams); - stack.push_int(std::move(acc_addr)); - stack.push_bool(trans_type == tr_tock); - stack.push_smallint(-2); - return stack_ref; - case tr_ord: - stack.push_int(balance.grams); - stack.push_int(msg_balance_remaining.grams); - stack.push_cell(in_msg); - stack.push_cellslice(in_msg_body); - stack.push_bool(in_msg_extern); - return stack_ref; - default: - LOG(ERROR) << "cannot initialize stack for a transaction of type " << trans_type; - return {}; - } -} - -bool Transaction::prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputePhaseConfig& cfg) const { - // we might use SHA256(block_rand_seed . addr . trans_lt) - // instead, we use SHA256(block_rand_seed . addr) - // if the smart contract wants to randomize further, it can use RANDOMIZE instruction - td::BitArray<256 + 256> data; - data.bits().copy_from(cfg.block_rand_seed.cbits(), 256); - (data.bits() + 256).copy_from(account.addr_rewrite.cbits(), 256); - rand_seed.clear(); - data.compute_sha256(rand_seed); - return true; -} - -Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const { - td::BitArray<256> rand_seed; - td::RefInt256 rand_seed_int{true}; - if (!(prepare_rand_seed(rand_seed, cfg) && rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false))) { - LOG(ERROR) << "cannot compute rand_seed for transaction"; - throw CollatorError{"cannot generate valid SmartContractInfo"}; - return {}; - } - auto tuple = vm::make_tuple_ref( - td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea - td::zero_refint(), // actions:Integer - td::zero_refint(), // msgs_sent:Integer - td::make_refint(now), // unixtime:Integer - td::make_refint(account.block_lt), // block_lt:Integer - td::make_refint(start_lt), // trans_lt:Integer - std::move(rand_seed_int), // rand_seed:Integer - balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] - my_addr, // myself:MsgAddressInt - vm::StackEntry::maybe(cfg.global_config)); // global_config:(Maybe Cell) ] = SmartContractInfo; - LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); - return vm::make_tuple_ref(std::move(tuple)); -} - -int output_actions_count(Ref list) { - int i = -1; - do { - ++i; - list = load_cell_slice(std::move(list)).prefetch_ref(); - } while (list.not_null()); - return i; -} - -bool Transaction::unpack_msg_state(bool lib_only) { - block::gen::StateInit::Record state; - if (in_msg_state.is_null() || !tlb::unpack_cell(in_msg_state, state)) { - LOG(ERROR) << "cannot unpack StateInit from an inbound message"; - return false; - } - if (lib_only) { - in_msg_library = state.library->prefetch_ref(); - return true; - } - if (state.split_depth->size() == 6) { - new_split_depth = (signed char)(state.split_depth->prefetch_ulong(6) - 32); - } else { - new_split_depth = 0; - } - if (state.special->size() > 1) { - int z = (int)state.special->prefetch_ulong(3); - if (z < 0) { - return false; - } - new_tick = z & 2; - new_tock = z & 1; - LOG(DEBUG) << "tick=" << new_tick << ", tock=" << new_tock; - } - new_code = state.code->prefetch_ref(); - new_data = state.data->prefetch_ref(); - new_library = state.library->prefetch_ref(); - return true; -} - -std::vector> Transaction::compute_vm_libraries(const ComputePhaseConfig& cfg) { - std::vector> lib_set; - if (in_msg_library.not_null()) { - lib_set.push_back(in_msg_library); - } - if (new_library.not_null()) { - lib_set.push_back(new_library); - } - auto global_libs = cfg.get_lib_root(); - if (global_libs.not_null()) { - lib_set.push_back(std::move(global_libs)); - } - return lib_set; -} - -bool Transaction::check_in_msg_state_hash() { - CHECK(in_msg_state.not_null()); - CHECK(new_split_depth >= 0 && new_split_depth < 32); - td::Bits256 in_state_hash = in_msg_state->get_hash().bits(); - int d = new_split_depth; - if ((in_state_hash.bits() + d).compare(account.addr.bits() + d, 256 - d)) { - return false; - } - orig_addr_rewrite = in_state_hash.bits(); - orig_addr_rewrite_set = true; - return account.recompute_tmp_addr(my_addr, d, orig_addr_rewrite.bits()); -} - -bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { - // TODO: add more skip verifications + sometimes use state from in_msg to re-activate - // ... - compute_phase = std::make_unique(); - ComputePhase& cp = *(compute_phase.get()); - original_balance -= total_fees; - if (td::sgn(balance.grams) <= 0) { - // no gas - cp.skip_reason = ComputePhase::sk_no_gas; - return true; - } - // Compute gas limits - if (!compute_gas_limits(cp, cfg)) { - compute_phase.reset(); - return false; - } - if (!cp.gas_limit && !cp.gas_credit) { - // no gas - cp.skip_reason = ComputePhase::sk_no_gas; - return true; - } - if (in_msg_state.not_null()) { - LOG(DEBUG) << "HASH(in_msg_state) = " << in_msg_state->get_hash().bits().to_hex(256) - << ", account_state_hash = " << account.state_hash.to_hex(); - // vm::load_cell_slice(in_msg_state).print_rec(std::cerr); - } else { - LOG(DEBUG) << "in_msg_state is null"; - } - if (in_msg_state.not_null() && - (acc_status == Account::acc_uninit || - (acc_status == Account::acc_frozen && account.state_hash == in_msg_state->get_hash().bits()))) { - use_msg_state = true; - if (!(unpack_msg_state() && account.check_split_depth(new_split_depth))) { - LOG(DEBUG) << "cannot unpack in_msg_state, or it has bad split_depth; cannot init account state"; - cp.skip_reason = ComputePhase::sk_bad_state; - return true; - } - if (acc_status == Account::acc_uninit && !check_in_msg_state_hash()) { - LOG(DEBUG) << "in_msg_state hash mismatch, cannot init account state"; - cp.skip_reason = ComputePhase::sk_bad_state; - return true; - } - } else if (acc_status != Account::acc_active) { - // no state, cannot perform transactions - cp.skip_reason = in_msg_state.not_null() ? ComputePhase::sk_bad_state : ComputePhase::sk_no_state; - return true; - } else if (in_msg_state.not_null()) { - unpack_msg_state(true); // use only libraries - } - // initialize VM - Ref stack = prepare_vm_stack(cp); - if (stack.is_null()) { - compute_phase.reset(); - return false; - } - // OstreamLogger ostream_logger(error_stream); - // auto log = create_vm_log(error_stream ? &ostream_logger : nullptr); - vm::GasLimits gas{(long long)cp.gas_limit, (long long)cp.gas_max, (long long)cp.gas_credit}; - LOG(DEBUG) << "creating VM"; - - vm::VmState vm{new_code, std::move(stack), gas, 1, new_data, vm::VmLog(), compute_vm_libraries(cfg)}; - vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo - // vm.incr_stack_trace(1); // enable stack dump after each step - - LOG(DEBUG) << "starting VM"; - cp.vm_init_state_hash = vm.get_state_hash(); - cp.exit_code = ~vm.run(); - LOG(DEBUG) << "VM terminated with exit code " << cp.exit_code; - cp.out_of_gas = (cp.exit_code == ~(int)vm::Excno::out_of_gas); - cp.vm_final_state_hash = vm.get_final_state_hash(cp.exit_code); - stack = vm.get_stack_ref(); - cp.vm_steps = (int)vm.get_steps_count(); - gas = vm.get_gas_limits(); - cp.gas_used = std::min(gas.gas_consumed(), gas.gas_limit); - cp.accepted = (gas.gas_credit == 0); - cp.success = (cp.accepted && vm.committed()); - if (cp.accepted & use_msg_state) { - was_activated = true; - acc_status = Account::acc_active; - } - LOG(INFO) << "steps: " << vm.get_steps_count() << " gas: used=" << gas.gas_consumed() << ", max=" << gas.gas_max - << ", limit=" << gas.gas_limit << ", credit=" << gas.gas_credit; - LOG(INFO) << "out_of_gas=" << cp.out_of_gas << ", accepted=" << cp.accepted << ", success=" << cp.success; - if (cp.success) { - cp.new_data = vm.get_committed_state().c4; // c4 -> persistent data - cp.actions = vm.get_committed_state().c5; // c5 -> action list - int out_act_num = output_actions_count(cp.actions); - if (verbosity > 2) { - std::cerr << "new smart contract data: "; - load_cell_slice(cp.new_data).print_rec(std::cerr); - std::cerr << "output actions: "; - block::gen::OutList{out_act_num}.print_ref(std::cerr, cp.actions); - } - } - cp.mode = 0; - cp.exit_arg = 0; - if (!cp.success && stack->depth() > 0) { - td::RefInt256 tos = stack->tos().as_int(); - if (tos.not_null() && tos->signed_fits_bits(32)) { - cp.exit_arg = (int)tos->to_long(); - } - } - if (cp.accepted) { - if (account.is_special) { - cp.gas_fees = td::zero_refint(); - } else { - cp.gas_fees = cfg.compute_gas_price(cp.gas_used); - total_fees += cp.gas_fees; - balance -= cp.gas_fees; - } - LOG(DEBUG) << "gas fees: " << cp.gas_fees->to_dec_string() << " = " << cfg.gas_price256->to_dec_string() << " * " - << cp.gas_used << " /2^16 ; price=" << cfg.gas_price << "; flat rate=[" << cfg.flat_gas_price << " for " - << cfg.flat_gas_limit << "]; remaining balance=" << balance.to_str(); - CHECK(td::sgn(balance.grams) >= 0); - } - return true; -} - -bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) { - if (!compute_phase || !compute_phase->success) { - return false; - } - action_phase = std::make_unique(); - ActionPhase& ap = *(action_phase.get()); - ap.result_code = -1; - ap.result_arg = 0; - ap.tot_actions = ap.spec_actions = ap.skipped_actions = ap.msgs_created = 0; - Ref list = compute_phase->actions; - assert(list.not_null()); - ap.action_list_hash = list->get_hash().bits(); - ap.remaining_balance = balance; - ap.end_lt = end_lt; - ap.total_fwd_fees = td::zero_refint(); - ap.total_action_fees = td::zero_refint(); - ap.reserved_balance.set_zero(); - - int n = 0; - while (true) { - ap.action_list.push_back(list); - auto cs = load_cell_slice(std::move(list)); - if (!cs.size_ext()) { - break; - } - if (!cs.have_refs()) { - ap.result_code = 32; // action list invalid - ap.result_arg = n; - ap.action_list_invalid = true; - LOG(DEBUG) << "action list invalid: entry found with data but no next reference"; - return true; - } - list = cs.prefetch_ref(); - n++; - if (n > cfg.max_actions) { - ap.result_code = 33; // too many actions - ap.result_arg = n; - ap.action_list_invalid = true; - LOG(DEBUG) << "action list too long: more than " << cfg.max_actions << " actions"; - return true; - } - } - - ap.tot_actions = n; - ap.spec_actions = ap.skipped_actions = 0; - for (int i = n - 1; i >= 0; --i) { - ap.result_arg = n - 1 - i; - if (!block::gen::t_OutListNode.validate_ref(ap.action_list[i])) { - ap.result_code = 34; // action #i invalid or unsupported - ap.action_list_invalid = true; - LOG(DEBUG) << "invalid action " << ap.result_arg << " found while preprocessing action list: error code " - << ap.result_code; - return true; - } - } - ap.valid = true; - for (int i = n - 1; i >= 0; --i) { - ap.result_arg = n - 1 - i; - vm::CellSlice cs = load_cell_slice(ap.action_list[i]); - CHECK(cs.fetch_ref().not_null()); - int tag = block::gen::t_OutAction.get_tag(cs); - CHECK(tag >= 0); - int err_code = 34; - switch (tag) { - case block::gen::OutAction::action_set_code: - err_code = try_action_set_code(cs, ap, cfg); - break; - case block::gen::OutAction::action_send_msg: - err_code = try_action_send_msg(cs, ap, cfg); - if (err_code == -2) { - err_code = try_action_send_msg(cs, ap, cfg, 1); - if (err_code == -2) { - err_code = try_action_send_msg(cs, ap, cfg, 2); - } - } - break; - case block::gen::OutAction::action_reserve_currency: - err_code = try_action_reserve_currency(cs, ap, cfg); - break; - case block::gen::OutAction::action_change_library: - err_code = try_action_change_library(cs, ap, cfg); - break; - } - if (err_code) { - ap.result_code = (err_code == -1 ? 34 : err_code); - ap.end_lt = end_lt; - if (err_code == -1 || err_code == 34) { - ap.action_list_invalid = true; - } - if (err_code == 37 || err_code == 38) { - ap.no_funds = true; - } - LOG(DEBUG) << "invalid action " << ap.result_arg << " in action list: error code " << ap.result_code; - return true; - } - } - ap.result_arg = 0; - ap.result_code = 0; - CHECK(ap.remaining_balance.grams->sgn() >= 0); - CHECK(ap.reserved_balance.grams->sgn() >= 0); - ap.remaining_balance += ap.reserved_balance; - CHECK(ap.remaining_balance.is_valid()); - if (ap.acc_delete_req) { - CHECK(ap.remaining_balance.is_zero()); - ap.acc_status_change = ActionPhase::acst_deleted; - acc_status = Account::acc_deleted; - was_deleted = true; - } - ap.success = true; - end_lt = ap.end_lt; - out_msgs = std::move(ap.out_msgs); - if (ap.new_code.not_null()) { - new_code = ap.new_code; - } - new_data = compute_phase->new_data; // tentative persistent data update applied - total_fees += - ap.total_action_fees; // NB: forwarding fees are not accounted here (they are not collected by the validators in this transaction) - balance = ap.remaining_balance; - return true; -} - -int Transaction::try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { - block::gen::OutAction::Record_action_set_code rec; - if (!tlb::unpack_exact(cs, rec)) { - return -1; - } - ap.new_code = std::move(rec.new_code); - ap.code_changed = true; - ap.spec_actions++; - return 0; -} - -int Transaction::try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { - block::gen::OutAction::Record_action_change_library rec; - if (!tlb::unpack_exact(cs, rec)) { - return -1; - } - // mode: +0 = remove library, +1 = add private library, +2 = add public library - Ref lib_ref = rec.libref->prefetch_ref(); - ton::Bits256 hash; - if (lib_ref.not_null()) { - hash = lib_ref->get_hash().bits(); - } else { - CHECK(rec.libref.write().fetch_ulong(1) == 0 && rec.libref.write().fetch_bits_to(hash)); - } - try { - vm::Dictionary dict{new_library, 256}; - if (!rec.mode) { - // remove library - dict.lookup_delete(hash); - LOG(DEBUG) << "removed " << ((rec.mode >> 1) ? "public" : "private") << " library with hash " << hash.to_hex(); - } else { - auto val = dict.lookup(hash); - if (val.not_null()) { - bool is_public = val->prefetch_ulong(1); - auto ref = val->prefetch_ref(); - if (hash == ref->get_hash().bits()) { - lib_ref = ref; - if (is_public == (rec.mode >> 1)) { - // library already in required state - ap.spec_actions++; - return 0; - } - } - } - if (lib_ref.is_null()) { - // library code not found - return 41; - } - vm::CellBuilder cb; - CHECK(cb.store_bool_bool(rec.mode >> 1) && cb.store_ref_bool(std::move(lib_ref))); - CHECK(dict.set_builder(hash, cb)); - LOG(DEBUG) << "added " << ((rec.mode >> 1) ? "public" : "private") << " library with hash " << hash.to_hex(); - } - new_library = std::move(dict).extract_root_cell(); - } catch (vm::VmError& vme) { - return 42; - } - ap.spec_actions++; - return 0; -} - -// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms -// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms -// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) -td::uint64 MsgPrices::compute_fwd_fees(td::uint64 cells, td::uint64 bits) const { - return lump_price + td::uint128(bit_price) - .mult(bits) - .add(td::uint128(cell_price).mult(cells)) - .add(td::uint128(0xffffu)) - .shr(16) - .lo(); -} - -std::pair MsgPrices::compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits, - bool ihr_disabled) const { - td::uint64 fwd = compute_fwd_fees(cells, bits); - if (ihr_disabled) { - return std::pair(fwd, 0); - } - return std::pair(fwd, td::uint128(fwd).mult(ihr_factor).shr(16).lo()); -} - -td::RefInt256 MsgPrices::get_first_part(td::RefInt256 total) const { - return (std::move(total) * first_frac) >> 16; -} - -td::uint64 MsgPrices::get_first_part(td::uint64 total) const { - return td::uint128(total).mult(first_frac).shr(16).lo(); -} - -td::RefInt256 MsgPrices::get_next_part(td::RefInt256 total) const { - return (std::move(total) * next_frac) >> 16; -} - -bool Transaction::check_replace_src_addr(Ref& src_addr) const { - int t = (int)src_addr->prefetch_ulong(2); - if (!t && src_addr->size_ext() == 2) { - // addr_none$00 --> replace with the address of current smart contract - src_addr = my_addr; - return true; - } - if (t != 2) { - // invalid address (addr_extern and addr_var cannot be source addresses) - return false; - } - if (src_addr->contents_equal(*my_addr) || src_addr->contents_equal(*my_addr_exact)) { - // source address matches that of the current account - return true; - } - // only one valid case remaining: rewritten source address used, replace with the complete one - // (are we sure we want to allow this?) - return false; -} - -bool Transaction::check_rewrite_dest_addr(Ref& dest_addr, const ActionPhaseConfig& cfg, - bool* is_mc) const { - if (!dest_addr->prefetch_ulong(1)) { - // all external addresses allowed - if (is_mc) { - *is_mc = false; - } - return true; - } - bool repack = false; - int tag = block::gen::t_MsgAddressInt.get_tag(*dest_addr); - - block::gen::MsgAddressInt::Record_addr_var rec; - - if (tag == block::gen::MsgAddressInt::addr_var) { - if (!tlb::csr_unpack(dest_addr, rec)) { - // cannot unpack addr_var - LOG(DEBUG) << "cannot unpack addr_var in a destination address"; - return false; - } - if (rec.addr_len == 256 && rec.workchain_id >= -128 && rec.workchain_id < 128) { - LOG(DEBUG) << "destination address contains an addr_var to be repacked into addr_std"; - repack = true; - } - } else if (tag == block::gen::MsgAddressInt::addr_std) { - block::gen::MsgAddressInt::Record_addr_std recs; - if (!tlb::csr_unpack(dest_addr, recs)) { - // cannot unpack addr_std - LOG(DEBUG) << "cannot unpack addr_std in a destination address"; - return false; - } - rec.anycast = std::move(recs.anycast); - rec.addr_len = 256; - rec.workchain_id = recs.workchain_id; - rec.address = td::make_bitstring_ref(recs.address); - } else { - // unknown address format (not a MsgAddressInt) - LOG(DEBUG) << "destination address does not have a MsgAddressInt tag"; - return false; - } - if (rec.workchain_id != ton::masterchainId) { - // recover destination workchain info from configuration - auto it = cfg.workchains->find(rec.workchain_id); - if (it == cfg.workchains->end()) { - // undefined destination workchain - LOG(DEBUG) << "destination address contains unknown workchain_id " << rec.workchain_id; - return false; - } - if (!it->second->accept_msgs) { - // workchain does not accept new messages - LOG(DEBUG) << "destination address belongs to workchain " << rec.workchain_id << " not accepting new messages"; - return false; - } - if (!it->second->is_valid_addr_len(rec.addr_len)) { - // invalid address length for specified workchain - LOG(DEBUG) << "destination address has length " << rec.addr_len << " invalid for destination workchain " - << rec.workchain_id; - return false; - } - } - if (rec.anycast->size() > 1) { - // destination address is an anycast - if (rec.workchain_id == ton::masterchainId) { - // anycast addresses disabled in masterchain - LOG(DEBUG) << "masterchain destination address has an anycast field"; - return false; - } - vm::CellSlice cs{*rec.anycast}; - int d = (int)cs.fetch_ulong(6) - 32; - if (d <= 0 || d > 30) { - // invalid anycast prefix length - return false; - } - unsigned pfx = (unsigned)cs.fetch_ulong(d); - unsigned my_pfx = (unsigned)account.addr.cbits().get_uint(d); - if (pfx != my_pfx) { - // rewrite destination address - vm::CellBuilder cb; - CHECK(cb.store_long_bool(32 + d, 6) // just$1 depth:(#<= 30) - && cb.store_long_bool(my_pfx, d) // rewrite_pfx:(bits depth) - && (rec.anycast = load_cell_slice_ref(cb.finalize())).not_null()); - repack = true; - } - } - if (is_mc) { - *is_mc = (rec.workchain_id == ton::masterchainId); - } - if (!repack) { - return true; - } - if (rec.addr_len == 256 && rec.workchain_id >= -128 && rec.workchain_id < 128) { - // repack as an addr_std - vm::CellBuilder cb; - CHECK(cb.store_long_bool(2, 2) // addr_std$10 - && cb.append_cellslice_bool(std::move(rec.anycast)) // anycast:(Maybe Anycast) ... - && cb.store_long_bool(rec.workchain_id, 8) // workchain_id:int8 - && cb.append_bitstring(std::move(rec.address)) // address:bits256 - && (dest_addr = load_cell_slice_ref(cb.finalize())).not_null()); - } else { - // repack as an addr_var - CHECK(tlb::csr_pack(dest_addr, std::move(rec))); - } - CHECK(block::gen::t_MsgAddressInt.validate_csr(dest_addr)); - return true; -} - -int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, const ActionPhaseConfig& cfg, - int redoing) { - block::gen::OutAction::Record_action_send_msg act_rec; - // mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +32 = delete smart contract if balance becomes zero, +1 = pay message fees, +2 = skip if message cannot be sent - vm::CellSlice cs{cs0}; - if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) { - return -1; - } - bool skip_invalid = (act_rec.mode & 2); - // try to parse suggested message in act_rec.out_msg - td::RefInt256 fwd_fee, ihr_fee; - block::gen::MessageRelaxed::Record msg; - if (!tlb::type_unpack_cell(act_rec.out_msg, block::gen::t_MessageRelaxed_Any, msg)) { - return -1; - } - if (redoing >= 1) { - if (msg.init->size_refs() >= 2) { - LOG(DEBUG) << "moving the StateInit of a suggested outbound message into a separate cell"; - // init:(Maybe (Either StateInit ^StateInit)) - // transform (just (left z:StateInit)) into (just (right z:^StateInit)) - CHECK(msg.init.write().fetch_ulong(2) == 2); - vm::CellBuilder cb; - Ref cell; - CHECK(cb.append_cellslice_bool(std::move(msg.init)) // StateInit - && cb.finalize_to(cell) // -> ^StateInit - && cb.store_long_bool(3, 2) // (just (right ... )) - && cb.store_ref_bool(std::move(cell)) // z:^StateInit - && cb.finalize_to(cell)); - msg.init = vm::load_cell_slice_ref(std::move(cell)); - } else { - redoing = 2; - } - } - if (redoing >= 2 && msg.body->size_ext() > 1 && msg.body->prefetch_ulong(1) == 0) { - LOG(DEBUG) << "moving the body of a suggested outbound message into a separate cell"; - // body:(Either X ^X) - // transform (left x:X) into (right x:^X) - CHECK(msg.body.write().fetch_ulong(1) == 0); - vm::CellBuilder cb; - Ref cell; - CHECK(cb.append_cellslice_bool(std::move(msg.body)) // X - && cb.finalize_to(cell) // -> ^X - && cb.store_long_bool(1, 1) // (right ... ) - && cb.store_ref_bool(std::move(cell)) // x:^X - && cb.finalize_to(cell)); - msg.body = vm::load_cell_slice_ref(std::move(cell)); - } - - block::gen::CommonMsgInfoRelaxed::Record_int_msg_info info; - bool ext_msg = msg.info->prefetch_ulong(1); - if (ext_msg) { - // ext_out_msg_info$11 constructor of CommonMsgInfoRelaxed - block::gen::CommonMsgInfoRelaxed::Record_ext_out_msg_info erec; - if (!tlb::csr_unpack(msg.info, erec)) { - return -1; - } - if (act_rec.mode & ~3) { - return -1; // invalid mode for an external message - } - info.src = std::move(erec.src); - info.dest = std::move(erec.dest); - // created_lt and created_at are ignored - info.ihr_disabled = true; - info.bounce = false; - info.bounced = false; - fwd_fee = ihr_fee = td::zero_refint(); - } else { - // int_msg_info$0 constructor - if (!tlb::csr_unpack(msg.info, info) || !block::tlb::t_CurrencyCollection.validate_csr(info.value)) { - return -1; - } - fwd_fee = block::tlb::t_Grams.as_integer(info.fwd_fee); - ihr_fee = block::tlb::t_Grams.as_integer(info.ihr_fee); - } - // set created_at and created_lt to correct values - info.created_at = now; - info.created_lt = ap.end_lt; - // always clear bounced flag - info.bounced = false; - // have to check source address - // it must be either our source address, or empty - if (!check_replace_src_addr(info.src)) { - LOG(DEBUG) << "invalid source address in a proposed outbound message"; - return 35; // invalid source address - } - bool to_mc = false; - if (!check_rewrite_dest_addr(info.dest, cfg, &to_mc)) { - LOG(DEBUG) << "invalid destination address in a proposed outbound message"; - return skip_invalid ? 0 : 36; // invalid destination address - } - - // fetch message pricing info - const MsgPrices& msg_prices = cfg.fetch_msg_prices(to_mc || account.is_masterchain()); - // compute size of message - vm::CellStorageStat sstat; // for message size - // preliminary storage estimation of the resulting message - sstat.add_used_storage(msg.init, true, 3); // message init - sstat.add_used_storage(msg.body, true, 3); // message body (the root cell itself is not counted) - if (!ext_msg) { - sstat.add_used_storage(info.value->prefetch_ref()); - } - LOG(DEBUG) << "storage paid for a message: " << sstat.cells << " cells, " << sstat.bits << " bits"; - if (sstat.bits > max_msg_bits || sstat.cells > max_msg_cells) { - LOG(DEBUG) << "message too large, invalid"; - return skip_invalid ? 0 : 40; - } - - // compute forwarding fees - auto fees_c = msg_prices.compute_fwd_ihr_fees(sstat.cells, sstat.bits, info.ihr_disabled); - LOG(DEBUG) << "computed fwd fees = " << fees_c.first << " + " << fees_c.second; - - if (account.is_special) { - LOG(DEBUG) << "computed fwd fees set to zero for special account"; - fees_c.first = fees_c.second = 0; - } - - // set fees to computed values - if (fwd_fee->unsigned_fits_bits(63) && fwd_fee->to_long() < (long long)fees_c.first) { - fwd_fee = td::make_refint(fees_c.first); - } - if (fees_c.second && ihr_fee->unsigned_fits_bits(63) && ihr_fee->to_long() < (long long)fees_c.second) { - ihr_fee = td::make_refint(fees_c.second); - } - - Ref new_msg; - td::RefInt256 fees_collected, fees_total; - unsigned new_msg_bits; - - if (!ext_msg) { - // Process outbound internal message - // check value, check/compute ihr_fees, fwd_fees - // ... - if (!block::tlb::t_CurrencyCollection.validate_csr(info.value)) { - LOG(DEBUG) << "invalid value:CurrencyCollection in proposed outbound message"; - return skip_invalid ? 0 : 37; - } - if (info.ihr_disabled) { - // if IHR is disabled, IHR fees will be always zero - ihr_fee = td::zero_refint(); - } - // extract value to be carried by the message - block::CurrencyCollection req; - CHECK(req.unpack(info.value)); - CHECK(req.grams.not_null()); - - if (act_rec.mode & 0x80) { - // attach all remaining balance to this message - req = ap.remaining_balance; - act_rec.mode &= ~1; // pay fees from attached value - } else if (act_rec.mode & 0x40) { - // attach all remaining balance of the inbound message (in addition to the original value) - req += msg_balance_remaining; - if (!(act_rec.mode & 1) && compute_phase) { - req -= compute_phase->gas_fees; - if (!req.is_valid()) { - LOG(DEBUG) - << "not enough value to transfer with the message: all of the inbound message value has been consumed"; - return skip_invalid ? 0 : 37; - } - } - } - - // compute req_grams + fees - td::RefInt256 req_grams_brutto = req.grams; - fees_total = fwd_fee + ihr_fee; - if (act_rec.mode & 1) { - // we are going to pay the fees - req_grams_brutto += fees_total; - } else if (req.grams < fees_total) { - // receiver pays the fees (but cannot) - LOG(DEBUG) << "not enough value attached to the message to pay forwarding fees : have " << req.grams << ", need " - << fees_total; - return skip_invalid ? 0 : 37; // not enough grams - } else { - // decrease message value - req.grams -= fees_total; - } - - // check that we have at least the required value - if (ap.remaining_balance.grams < req_grams_brutto) { - LOG(DEBUG) << "not enough grams to transfer with the message : remaining balance is " - << ap.remaining_balance.to_str() << ", need " << req_grams_brutto << " (including forwarding fees)"; - return skip_invalid ? 0 : 37; // not enough grams - } - - Ref new_extra; - - if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) { - LOG(DEBUG) << "not enough extra currency to send with the message: " - << block::CurrencyCollection{0, req.extra}.to_str() << " required, only " - << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " available"; - return skip_invalid ? 0 : 38; // not enough (extra) funds - } - if (ap.remaining_balance.extra.not_null() || req.extra.not_null()) { - LOG(DEBUG) << "subtracting extra currencies: " - << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " minus " - << block::CurrencyCollection{0, req.extra}.to_str() << " equals " - << block::CurrencyCollection{0, new_extra}.to_str(); - } - - auto fwd_fee_mine = msg_prices.get_first_part(fwd_fee); - auto fwd_fee_remain = fwd_fee - fwd_fee_mine; - - // re-pack message value - CHECK(req.pack_to(info.value)); - CHECK(block::tlb::t_Grams.pack_integer(info.fwd_fee, fwd_fee_remain)); - CHECK(block::tlb::t_Grams.pack_integer(info.ihr_fee, ihr_fee)); - - // serialize message - CHECK(tlb::csr_pack(msg.info, info)); - vm::CellBuilder cb; - if (!tlb::type_pack(cb, block::gen::t_MessageRelaxed_Any, msg)) { - LOG(DEBUG) << "outbound message does not fit into a cell after rewriting"; - return redoing < 2 ? -2 : (skip_invalid ? 0 : 39); - } - - new_msg_bits = cb.size(); - new_msg = cb.finalize(); - - // clear msg_balance_remaining if it has been used - if (act_rec.mode & 0xc0) { - msg_balance_remaining.set_zero(); - } - - // update balance - ap.remaining_balance -= req_grams_brutto; - ap.remaining_balance.extra = std::move(new_extra); - CHECK(ap.remaining_balance.is_valid()); - CHECK(ap.remaining_balance.grams->sgn() >= 0); - fees_total = fwd_fee + ihr_fee; - fees_collected = fwd_fee_mine; - } else { - // external messages also have forwarding fees - if (ap.remaining_balance.grams < fwd_fee) { - LOG(DEBUG) << "not enough funds to pay for an outbound external message"; - return skip_invalid ? 0 : 37; // not enough grams - } - // repack message - // ext_out_msg_info$11 constructor of CommonMsgInfo - block::gen::CommonMsgInfo::Record_ext_out_msg_info erec; - erec.src = info.src; - erec.dest = info.dest; - erec.created_at = info.created_at; - erec.created_lt = info.created_lt; - CHECK(tlb::csr_pack(msg.info, erec)); - vm::CellBuilder cb; - if (!tlb::type_pack(cb, block::gen::t_MessageRelaxed_Any, msg)) { - LOG(DEBUG) << "outbound message does not fit into a cell after rewriting"; - return redoing < 2 ? -2 : (skip_invalid ? 0 : 39); - } - - new_msg_bits = cb.size(); - new_msg = cb.finalize(); - - // update balance - ap.remaining_balance -= fwd_fee; - CHECK(ap.remaining_balance.is_valid()); - CHECK(td::sgn(ap.remaining_balance.grams) >= 0); - fees_collected = fees_total = fwd_fee; - } - - if (!block::tlb::t_Message.validate_ref(new_msg)) { - LOG(ERROR) << "generated outbound message is not a valid (Message Any) according to hand-written check"; - return -1; - } - if (!block::gen::t_Message_Any.validate_ref(new_msg)) { - LOG(ERROR) << "generated outbound message is not a valid (Message Any) according to automated check"; - block::gen::t_Message_Any.print_ref(std::cerr, new_msg); - vm::load_cell_slice(new_msg).print_rec(std::cerr); - return -1; - } - if (verbosity > 2) { - std::cerr << "converted outbound message: "; - block::gen::t_Message_Any.print_ref(std::cerr, new_msg); - } - - ap.msgs_created++; - ap.end_lt++; - - ap.out_msgs.push_back(std::move(new_msg)); - ap.total_action_fees += fees_collected; - ap.total_fwd_fees += fees_total; - - if ((act_rec.mode & 0xa0) == 0xa0) { - CHECK(ap.remaining_balance.is_zero()); - ap.acc_delete_req = ap.reserved_balance.is_zero(); - } - - ap.tot_msg_bits += sstat.bits + new_msg_bits; - ap.tot_msg_cells += sstat.cells + 1; - - return 0; -} - -int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { - block::gen::OutAction::Record_action_reserve_currency rec; - if (!tlb::unpack_exact(cs, rec) || (rec.mode & ~15)) { - return -1; - } - int mode = rec.mode; - LOG(INFO) << "in try_action_reserve_currency(" << mode << ")"; - CurrencyCollection reserve, newc; - if (!reserve.validate_unpack(std::move(rec.currency))) { - LOG(DEBUG) << "cannot parse currency field in action_reserve_currency"; - return -1; - } - LOG(DEBUG) << "action_reserve_currency: mode=" << mode << ", reserve=" << reserve.to_str() - << ", balance=" << ap.remaining_balance.to_str() << ", original balance=" << original_balance.to_str(); - if (mode & 4) { - if (mode & 8) { - reserve = original_balance - reserve; - } else { - reserve += original_balance; - } - } else if (mode & 8) { - LOG(DEBUG) << "invalid reserve mode " << mode; - return -1; - } - if (!reserve.is_valid() || td::sgn(reserve.grams) < 0) { - LOG(DEBUG) << "cannot reserve a negative amount: " << reserve.to_str(); - return -1; - } - if (reserve.grams > ap.remaining_balance.grams) { - if (mode & 2) { - reserve.grams = ap.remaining_balance.grams; - } else { - LOG(DEBUG) << "cannot reserve " << reserve.grams << " nanograms : only " << ap.remaining_balance.grams - << " available"; - return 37; // not enough grams - } - } - if (!block::sub_extra_currency(ap.remaining_balance.extra, reserve.extra, newc.extra)) { - LOG(DEBUG) << "not enough extra currency to reserve: " << block::CurrencyCollection{0, reserve.extra}.to_str() - << " required, only " << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() - << " available"; - if (mode & 2) { - // TODO: process (mode & 2) correctly by setting res_extra := inf (reserve.extra, ap.remaining_balance.extra) - } - return 38; // not enough (extra) funds - } - newc.grams = ap.remaining_balance.grams - reserve.grams; - if (mode & 1) { - // leave only res_grams, reserve everything else - std::swap(newc, reserve); - } - // set remaining_balance to new_grams and new_extra - ap.remaining_balance = std::move(newc); - // increase reserved_balance by res_grams and res_extra - ap.reserved_balance += std::move(reserve); - CHECK(ap.reserved_balance.is_valid()); - CHECK(ap.remaining_balance.is_valid()); - LOG(INFO) << "changed remaining balance to " << ap.remaining_balance.to_str() << ", reserved balance to " - << ap.reserved_balance.to_str(); - ap.spec_actions++; - return 0; -} - -bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) { - if (in_msg.is_null() || !bounce_enabled) { - return false; - } - bounce_phase = std::make_unique(); - BouncePhase& bp = *bounce_phase; - block::gen::Message::Record msg; - block::gen::CommonMsgInfo::Record_int_msg_info info; - auto cs = vm::load_cell_slice(in_msg); - if (!(tlb::unpack(cs, info) && gen::t_Maybe_Either_StateInit_Ref_StateInit.skip(cs) && cs.have(1) && - cs.have_refs((int)cs.prefetch_ulong(1)))) { - bounce_phase.reset(); - return false; - } - if (cs.fetch_ulong(1)) { - cs = vm::load_cell_slice(cs.prefetch_ref()); - } - info.ihr_disabled = true; - info.bounce = false; - info.bounced = true; - std::swap(info.src, info.dest); - bool to_mc = false; - if (!check_rewrite_dest_addr(info.dest, cfg, &to_mc)) { - LOG(DEBUG) << "invalid destination address in a bounced message"; - bounce_phase.reset(); - return false; - } - // fetch message pricing info - const MsgPrices& msg_prices = cfg.fetch_msg_prices(to_mc || account.is_masterchain()); - // compute size of message - vm::CellStorageStat sstat; // for message size - // preliminary storage estimation of the resulting message - sstat.compute_used_storage(info.value->prefetch_ref()); - bp.msg_bits = sstat.bits; - bp.msg_cells = sstat.cells; - // compute forwarding fees - bp.fwd_fees = msg_prices.compute_fwd_fees(sstat.cells, sstat.bits); - // check whether the message has enough funds - auto msg_balance = msg_balance_remaining; - if (compute_phase && compute_phase->gas_fees.not_null()) { - msg_balance.grams -= compute_phase->gas_fees; - } - if ((msg_balance.grams < 0) || - (msg_balance.grams->signed_fits_bits(64) && msg_balance.grams->to_long() < (long long)bp.fwd_fees)) { - // not enough funds - bp.nofunds = true; - return true; - } - // debit msg_balance_remaining from account's (tentative) balance - balance -= msg_balance; - CHECK(balance.is_valid()); - // debit total forwarding fees from the message's balance, then split forwarding fees into our part and remaining part - msg_balance -= td::make_refint(bp.fwd_fees); - bp.fwd_fees_collected = msg_prices.get_first_part(bp.fwd_fees); - bp.fwd_fees -= bp.fwd_fees_collected; - total_fees += td::make_refint(bp.fwd_fees_collected); - // serialize outbound message - info.created_lt = end_lt++; - info.created_at = now; - vm::CellBuilder cb; - CHECK(cb.store_long_bool(5, 4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - && cb.append_cellslice_bool(info.src) // src:MsgAddressInt - && cb.append_cellslice_bool(info.dest) // dest:MsgAddressInt - && msg_balance.store(cb) // value:CurrencyCollection - && block::tlb::t_Grams.store_long(cb, 0) // ihr_fee:Grams - && block::tlb::t_Grams.store_long(cb, bp.fwd_fees) // fwd_fee:Grams - && cb.store_long_bool(info.created_lt, 64) // created_lt:uint64 - && cb.store_long_bool(info.created_at, 32) // created_at:uint32 - && cb.store_bool_bool(false)); // init:(Maybe ...) - if (cfg.bounce_msg_body) { - int body_bits = std::min((int)cs.size(), cfg.bounce_msg_body); - if (cb.remaining_bits() >= body_bits + 33u) { - CHECK(cb.store_bool_bool(false) // body:(Either X ^X) -> left X - && cb.store_long_bool(-1, 32) // int = -1 ("message type") - && cb.append_bitslice(cs.prefetch_bits(body_bits))); // truncated message body - } else { - vm::CellBuilder cb2; - CHECK(cb.store_bool_bool(true) // body:(Either X ^X) -> right ^X - && cb2.store_long_bool(-1, 32) // int = -1 ("message type") - && cb2.append_bitslice(cs.prefetch_bits(body_bits)) // truncated message body - && cb.store_builder_ref_bool(std::move(cb2))); // ^X - } - } else { - CHECK(cb.store_bool_bool(false)); // body:(Either ..) - } - CHECK(cb.finalize_to(bp.out_msg)); - if (verbosity > 2) { - LOG(INFO) << "generated bounced message: "; - block::gen::t_Message_Any.print_ref(std::cerr, bp.out_msg); - } - out_msgs.push_back(bp.out_msg); - bp.ok = true; - return true; -} - -/* - * - * SERIALIZE PREPARED TRANSACTION - * - */ - -bool Account::store_acc_status(vm::CellBuilder& cb, int acc_status) const { - int v; - switch (acc_status) { - case acc_nonexist: - case acc_deleted: - v = 3; // acc_state_nonexist$11 - break; - case acc_uninit: - v = 0; // acc_state_uninit$00 - break; - case acc_frozen: - v = 1; // acc_state_frozen$01 - break; - case acc_active: - v = 2; // acc_state_active$10 - break; - default: - return false; - } - return cb.store_long_bool(v, 2); -} - -bool Transaction::compute_state() { - if (new_total_state.not_null()) { - return true; - } - if (acc_status == Account::acc_uninit && !was_activated && balance.is_zero()) { - LOG(DEBUG) << "account is uninitialized and has zero balance, deleting it back"; - acc_status = Account::acc_nonexist; - was_created = false; - } - if (acc_status == Account::acc_nonexist || acc_status == Account::acc_deleted) { - CHECK(balance.is_zero()); - vm::CellBuilder cb; - CHECK(cb.store_long_bool(0, 1) // account_none$0 - && cb.finalize_to(new_total_state)); - return true; - } - vm::CellBuilder cb; - CHECK(cb.store_long_bool(end_lt, 64) // account_storage$_ last_trans_lt:uint64 - && balance.store(cb)); // balance:CurrencyCollection - int ticktock = new_tick * 2 + new_tock; - unsigned si_pos = 0; - if (acc_status == Account::acc_uninit) { - CHECK(cb.store_long_bool(0, 2)); // account_uninit$00 = AccountState - } else if (acc_status == Account::acc_frozen) { - if (was_frozen) { - vm::CellBuilder cb2; - CHECK(account.split_depth_ ? cb2.store_long_bool(account.split_depth_ + 32, 6) // _ ... = StateInit - : cb2.store_long_bool(0, 1)); // ... split_depth:(Maybe (## 5)) - CHECK(ticktock ? cb2.store_long_bool(ticktock | 4, 3) : cb2.store_long_bool(0, 1)); // special:(Maybe TickTock) - CHECK(cb2.store_maybe_ref(new_code) && cb2.store_maybe_ref(new_data) && cb2.store_maybe_ref(new_library)); - // code:(Maybe ^Cell) data:(Maybe ^Cell) library:(HashmapE 256 SimpleLib) - auto frozen_state = cb2.finalize(); - frozen_hash = frozen_state->get_hash().bits(); - if (verbosity >= 3 * 1) { // !!!DEBUG!!! - std::cerr << "freezing state of smart contract: "; - block::gen::t_StateInit.print_ref(std::cerr, frozen_state); - CHECK(block::gen::t_StateInit.validate_ref(frozen_state)); - CHECK(block::tlb::t_StateInit.validate_ref(frozen_state)); - std::cerr << "with hash " << frozen_hash.to_hex() << std::endl; - } - } - new_code.clear(); - new_data.clear(); - new_library.clear(); - if (frozen_hash == account.addr_orig) { - // if frozen_hash equals account's "original" address (before rewriting), do not need storing hash - CHECK(cb.store_long_bool(0, 2)); // account_uninit$00 = AccountState - } else { - CHECK(cb.store_long_bool(1, 2) // account_frozen$01 - && cb.store_bits_bool(frozen_hash)); // state_hash:bits256 - } - } else { - CHECK(acc_status == Account::acc_active && !was_frozen && !was_deleted); - si_pos = cb.size_ext() + 1; - CHECK(account.split_depth_ ? cb.store_long_bool(account.split_depth_ + 96, 7) // account_active$1 _:StateInit - : cb.store_long_bool(2, 2)); // ... split_depth:(Maybe (## 5)) - CHECK(ticktock ? cb.store_long_bool(ticktock | 4, 3) : cb.store_long_bool(0, 1)); // special:(Maybe TickTock) - CHECK(cb.store_maybe_ref(new_code) && cb.store_maybe_ref(new_data) && cb.store_maybe_ref(new_library)); - // code:(Maybe ^Cell) data:(Maybe ^Cell) library:(HashmapE 256 SimpleLib) - } - auto storage = cb.finalize(); - if (si_pos) { - auto cs_ref = load_cell_slice_ref(storage); - CHECK(cs_ref.unique_write().skip_ext(si_pos)); - new_inner_state = std::move(cs_ref); - } else { - new_inner_state.clear(); - } - vm::CellStorageStat& stats = new_storage_stat; - CHECK(stats.compute_used_storage(Ref(storage))); - CHECK(cb.store_long_bool(1, 1) // account$1 - && cb.append_cellslice_bool(account.my_addr) // addr:MsgAddressInt - && block::store_UInt7(cb, stats.cells) // storage_used$_ cells:(VarUInteger 7) - && block::store_UInt7(cb, stats.bits) // bits:(VarUInteger 7) - && block::store_UInt7(cb, stats.public_cells) // public_cells:(VarUInteger 7) - && cb.store_long_bool(last_paid, 32)); // last_paid:uint32 - if (due_payment.not_null() && td::sgn(due_payment) != 0) { - CHECK(cb.store_long_bool(1, 1) && block::tlb::t_Grams.store_integer_ref(cb, due_payment)); - // due_payment:(Maybe Grams) - } else { - CHECK(cb.store_long_bool(0, 1)); - } - CHECK(cb.append_data_cell_bool(std::move(storage))); - new_total_state = cb.finalize(); - if (verbosity > 2) { - std::cerr << "new account state: "; - block::gen::t_Account.print_ref(std::cerr, new_total_state); - } - CHECK(block::gen::t_Account.validate_ref(new_total_state)); - CHECK(block::tlb::t_Account.validate_ref(new_total_state)); - return true; -} - -bool Transaction::serialize() { - if (root.not_null()) { - return true; - } - if (!compute_state()) { - return false; - } - vm::Dictionary dict{15}; - for (unsigned i = 0; i < out_msgs.size(); i++) { - td::BitArray<15> key{i}; - if (!dict.set_ref(key, out_msgs[i], vm::Dictionary::SetMode::Add)) { - return false; - } - } - vm::CellBuilder cb, cb2; - if (!(cb.store_long_bool(7, 4) // transaction$0111 - && cb.store_bits_bool(account.addr) // account_addr:bits256 - && cb.store_long_bool(start_lt) // lt:uint64 - && cb.store_bits_bool(account.last_trans_hash_) // prev_trans_hash:bits256 - && cb.store_long_bool(account.last_trans_lt_, 64) // prev_trans_lt:uint64 - && cb.store_long_bool(account.now_, 32) // now:uint32 - && cb.store_ulong_rchk_bool(out_msgs.size(), 15) // outmsg_cnt:uint15 - && account.store_acc_status(cb) // orig_status:AccountStatus - && account.store_acc_status(cb, acc_status) // end_status:AccountStatus - && cb2.store_maybe_ref(in_msg) // ^[ in_msg:(Maybe ^(Message Any)) ... - && std::move(dict).append_dict_to_bool(cb2) // out_msgs:(HashmapE 15 ^(Message Any)) - && cb.store_ref_bool(cb2.finalize()) // ] - && total_fees.store(cb) // total_fees:CurrencyCollection - && cb2.store_long_bool(0x72, 8) // update_hashes#72 - && cb2.store_bits_bool(account.total_state->get_hash().bits(), 256) // old_hash:bits256 - && cb2.store_bits_bool(new_total_state->get_hash().bits(), 256) // new_hash:bits256 - && cb.store_ref_bool(cb2.finalize()))) { // state_update:^(HASH_UPDATE Account) - return false; - } - - switch (trans_type) { - case tr_tick: // fallthrough - case tr_tock: { - vm::CellBuilder cb3; - bool act = compute_phase->success; - bool act_ok = act && action_phase->success; - CHECK(cb2.store_long_bool(trans_type == tr_tick ? 2 : 3, 4) // trans_tick_tock$000 is_tock:Bool - && serialize_storage_phase(cb2) // storage:TrStoragePhase - && serialize_compute_phase(cb2) // compute_ph:TrComputePhase - && cb2.store_bool_bool(act) // action:(Maybe - && (!act || (serialize_action_phase(cb3) // ^TrActionPhase) - && cb2.store_ref_bool(cb3.finalize()))) && - cb2.store_bool_bool(!act_ok) // aborted:Bool - && cb2.store_bool_bool(was_deleted) // destroyed:Bool - && cb.store_ref_bool(cb2.finalize()) && cb.finalize_to(root)); - break; - } - case tr_ord: { - vm::CellBuilder cb3; - bool have_storage = (bool)storage_phase; - bool have_credit = (bool)credit_phase; - bool have_bounce = (bool)bounce_phase; - bool act = compute_phase->success; - bool act_ok = act && action_phase->success; - CHECK(cb2.store_long_bool(0, 4) // trans_ord$0000 - && cb2.store_long_bool(!bounce_enabled, 1) // credit_first:Bool - && cb2.store_bool_bool(have_storage) // storage_ph:(Maybe - && (!have_storage || serialize_storage_phase(cb2)) // TrStoragePhase) - && cb2.store_bool_bool(have_credit) // credit_ph:(Maybe - && (!have_credit || serialize_credit_phase(cb2)) // TrCreditPhase) - && serialize_compute_phase(cb2) // compute_ph:TrComputePhase - && cb2.store_bool_bool(act) // action:(Maybe - && (!act || (serialize_action_phase(cb3) && cb2.store_ref_bool(cb3.finalize()))) // ^TrActionPhase) - && cb2.store_bool_bool(!act_ok) // aborted:Bool - && cb2.store_bool_bool(have_bounce) // bounce:(Maybe - && (!have_bounce || serialize_bounce_phase(cb2)) // TrBouncePhase - && cb2.store_bool_bool(was_deleted) // destroyed:Bool - && cb.store_ref_bool(cb2.finalize()) && cb.finalize_to(root)); - break; - } - default: - return false; - } - if (verbosity >= 3 * 1) { - std::cerr << "new transaction: "; - block::gen::t_Transaction.print_ref(std::cerr, root); - vm::load_cell_slice(root).print_rec(std::cerr); - } - - if (!block::gen::t_Transaction.validate_ref(root)) { - LOG(ERROR) << "newly-generated transaction failed to pass automated validation:"; - vm::load_cell_slice(root).print_rec(std::cerr); - block::gen::t_Transaction.print_ref(std::cerr, root); - root.clear(); - return false; - } - if (!block::tlb::t_Transaction.validate_ref(root)) { - LOG(ERROR) << "newly-generated transaction failed to pass hand-written validation:"; - vm::load_cell_slice(root).print_rec(std::cerr); - block::gen::t_Transaction.print_ref(std::cerr, root); - root.clear(); - return false; - } - - return true; -} - -bool Transaction::serialize_storage_phase(vm::CellBuilder& cb) { - if (!storage_phase) { - return false; - } - StoragePhase& sp = *storage_phase; - bool ok; - // tr_phase_storage$_ storage_fees_collected:Grams - if (sp.fees_collected.not_null()) { - ok = block::tlb::t_Grams.store_integer_ref(cb, sp.fees_collected); - } else { - ok = block::tlb::t_Grams.null_value(cb); - } - // storage_fees_due:(Maybe Grams) - ok &= block::store_Maybe_Grams_nz(cb, sp.fees_due); - // status_change:AccStatusChange - if (sp.deleted || sp.frozen) { - ok &= cb.store_long_bool(sp.deleted ? 3 : 2, 2); // acst_frozen$10 acst_deleted$11 - } else { - ok &= cb.store_long_bool(0, 1); // acst_unchanged$0 = AccStatusChange - } - return ok; -} - -bool Transaction::serialize_credit_phase(vm::CellBuilder& cb) { - if (!credit_phase) { - return false; - } - CreditPhase& cp = *credit_phase; - // tr_phase_credit$_ due_fees_collected:(Maybe Grams) credit:CurrencyCollection - return block::store_Maybe_Grams_nz(cb, cp.due_fees_collected) && cp.credit.store(cb); -} - -bool Transaction::serialize_compute_phase(vm::CellBuilder& cb) { - if (!compute_phase) { - return false; - } - ComputePhase& cp = *compute_phase; - switch (cp.skip_reason) { - // tr_compute_phase_skipped$0 reason:ComputeSkipReason; - case ComputePhase::sk_no_state: - return cb.store_long_bool(0, 3); // cskip_no_state$00 = ComputeSkipReason; - case ComputePhase::sk_bad_state: - return cb.store_long_bool(1, 3); // cskip_bad_state$01 = ComputeSkipReason; - case ComputePhase::sk_no_gas: - return cb.store_long_bool(2, 3); // cskip_no_gas$10 = ComputeSkipReason; - case ComputePhase::sk_none: - break; - default: - return false; - } - vm::CellBuilder cb2; - bool ok, credit = (cp.gas_credit != 0), exarg = (cp.exit_arg != 0); - ok = cb.store_long_bool(1, 1) // tr_phase_compute_vm$1 - && cb.store_long_bool(cp.success, 1) // success:Bool - && cb.store_long_bool(cp.msg_state_used, 1) // msg_state_used:Bool - && cb.store_long_bool(cp.account_activated, 1) // account_activated:Bool - && block::tlb::t_Grams.store_integer_ref(cb, cp.gas_fees) // gas_fees:Grams - && block::store_UInt7(cb2, cp.gas_used) // ^[ gas_used:(VarUInteger 7) - && block::store_UInt7(cb2, cp.gas_limit) // gas_limit:(VarUInteger 7) - && cb2.store_long_bool(credit, 1) // gas_credit:(Maybe (VarUInteger 3)) - && (!credit || block::tlb::t_VarUInteger_3.store_long(cb2, cp.gas_credit)) && - cb2.store_long_rchk_bool(cp.mode, 8) // mode:int8 - && cb2.store_long_bool(cp.exit_code, 32) // exit_code:int32 - && cb2.store_long_bool(exarg, 1) // exit_arg:(Maybe int32) - && (!exarg || cb2.store_long_bool(cp.exit_arg, 32)) && - cb2.store_ulong_rchk_bool(cp.vm_steps, 32) // vm_steps:uint32 - && cb2.store_bits_bool(cp.vm_init_state_hash) // vm_init_state_hash:bits256 - && cb2.store_bits_bool(cp.vm_final_state_hash) // vm_final_state_hash:bits256 - && cb.store_ref_bool(cb2.finalize()); // ] = TrComputePhase - return ok; -} - -bool Transaction::serialize_action_phase(vm::CellBuilder& cb) { - if (!action_phase) { - return false; - } - ActionPhase& ap = *action_phase; - bool ok, arg = (ap.result_arg != 0); - ok = cb.store_long_bool(ap.success, 1) // tr_phase_action$_ success:Bool - && cb.store_long_bool(ap.valid, 1) // valid:Bool - && cb.store_long_bool(ap.no_funds, 1) // no_funds:Bool - && cb.store_long_bool(ap.acc_status_change, (ap.acc_status_change >> 1) + 1) // status_change:AccStatusChange - && block::store_Maybe_Grams_nz(cb, ap.total_fwd_fees) // total_fwd_fees:(Maybe Grams) - && block::store_Maybe_Grams_nz(cb, ap.total_action_fees) // total_action_fees:(Maybe Grams) - && cb.store_long_bool(ap.result_code, 32) // result_code:int32 - && cb.store_long_bool(arg, 1) // result_arg:(Maybe - && (!arg || cb.store_long_bool(ap.result_arg, 32)) // uint32) - && cb.store_ulong_rchk_bool(ap.tot_actions, 16) // tot_actions:uint16 - && cb.store_ulong_rchk_bool(ap.spec_actions, 16) // spec_actions:uint16 - && cb.store_ulong_rchk_bool(ap.skipped_actions, 16) // skipped_actions:uint16 - && cb.store_ulong_rchk_bool(ap.msgs_created, 16) // msgs_created:uint16 - && cb.store_bits_bool(ap.action_list_hash) // action_list_hash:bits256 - && block::store_UInt7(cb, ap.tot_msg_cells, ap.tot_msg_bits); // tot_msg_size:StorageUsed - return ok; -} - -bool Transaction::serialize_bounce_phase(vm::CellBuilder& cb) { - if (!bounce_phase) { - return false; - } - BouncePhase& bp = *bounce_phase; - if (!(bp.ok ^ bp.nofunds)) { - return false; - } - if (bp.nofunds) { - return cb.store_long_bool(1, 2) // tr_phase_bounce_nofunds$01 - && block::store_UInt7(cb, bp.msg_cells, bp.msg_bits) // msg_size:StorageUsed - && block::tlb::t_Grams.store_long(cb, bp.fwd_fees); // req_fwd_fees:Grams - } else { - return cb.store_long_bool(1, 1) // tr_phase_bounce_ok$1 - && block::store_UInt7(cb, bp.msg_cells, bp.msg_bits) // msg_size:StorageUsed - && block::tlb::t_Grams.store_long(cb, bp.fwd_fees_collected) // msg_fees:Grams - && block::tlb::t_Grams.store_long(cb, bp.fwd_fees); // fwd_fees:Grams - } -} - -td::Result Transaction::estimate_block_storage_profile_incr( - const vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const { - if (root.is_null()) { - return td::Status::Error("Cannot estimate the size profile of a transaction before it is serialized"); - } - if (new_total_state.is_null()) { - return td::Status::Error("Cannot estimate the size profile of a transaction before its new state is computed"); - } - return store_stat.tentative_add_proof(new_total_state, usage_tree) + store_stat.tentative_add_cell(root); -} - -bool Transaction::update_block_storage_profile(vm::NewCellStorageStat& store_stat, - const vm::CellUsageTree* usage_tree) const { - if (root.is_null() || new_total_state.is_null()) { - return false; - } - store_stat.add_proof(new_total_state, usage_tree); - store_stat.add_cell(root); - return true; -} - -bool Transaction::would_fit(unsigned cls, const block::BlockLimitStatus& blimst) const { - auto res = estimate_block_storage_profile_incr(blimst.st_stat, blimst.limits.usage_tree); - if (res.is_error()) { - LOG(ERROR) << res.move_as_error(); - return false; - } - auto extra = res.move_as_ok(); - return blimst.would_fit(cls, end_lt, gas_used(), &extra); -} - -bool Transaction::update_limits(block::BlockLimitStatus& blimst) const { - return blimst.update_lt(end_lt) && blimst.update_gas(gas_used()) && blimst.add_proof(new_total_state) && - blimst.add_cell(root) && blimst.add_transaction() && blimst.add_account(is_first); -} - -/* - * - * COMMIT TRANSACTION - * - */ - -Ref Transaction::commit(Account& acc) { - CHECK(account.last_trans_end_lt_ <= start_lt && start_lt < end_lt); - CHECK(root.not_null()); - CHECK(new_total_state.not_null()); - CHECK((const void*)&acc == (const void*)&account); - // export all fields modified by the Transaction into original account - // NB: this is the only method that modifies account - if (orig_addr_rewrite_set && new_split_depth >= 0 && acc.status == Account::acc_nonexist && - acc_status == Account::acc_active) { - LOG(DEBUG) << "setting address rewriting info for newly-activated account " << acc.addr.to_hex() - << " with split_depth=" << new_split_depth - << ", orig_addr_rewrite=" << orig_addr_rewrite.bits().to_hex(new_split_depth); - CHECK(acc.init_rewrite_addr(new_split_depth, orig_addr_rewrite.bits())); - } - acc.status = (acc_status == Account::acc_deleted ? Account::acc_nonexist : acc_status); - acc.last_trans_lt_ = start_lt; - acc.last_trans_end_lt_ = end_lt; - acc.last_trans_hash_ = root->get_hash().bits(); - acc.last_paid = last_paid; - acc.storage_stat = new_storage_stat; - acc.balance = std::move(balance); - acc.due_payment = std::move(due_payment); - acc.total_state = std::move(new_total_state); - acc.inner_state = std::move(new_inner_state); - if (was_frozen) { - acc.state_hash = frozen_hash; - } - acc.my_addr = std::move(my_addr); - // acc.my_addr_exact = std::move(my_addr_exact); - acc.code = std::move(new_code); - acc.data = std::move(new_data); - acc.library = std::move(new_library); - if (acc.status == Account::acc_active) { - acc.tick = new_tick; - acc.tock = new_tock; - } else { - acc.tick = acc.tock = false; - } - end_lt = 0; - acc.push_transaction(root, start_lt); - return root; -} - -LtCellRef Transaction::extract_out_msg(unsigned i) { - return {start_lt + i + 1, std::move(out_msgs.at(i))}; -} - -NewOutMsg Transaction::extract_out_msg_ext(unsigned i) { - return {start_lt + i + 1, std::move(out_msgs.at(i)), root}; -} - -void Transaction::extract_out_msgs(std::vector& list) { - for (unsigned i = 0; i < out_msgs.size(); i++) { - list.emplace_back(start_lt + i + 1, std::move(out_msgs[i])); - } -} - -void Account::push_transaction(Ref trans_root, ton::LogicalTime trans_lt) { - transactions.emplace_back(trans_lt, std::move(trans_root)); -} - -bool Account::create_account_block(vm::CellBuilder& cb) { - if (transactions.empty()) { - return false; - } - if (!(cb.store_long_bool(5, 4) // acc_trans#5 - && cb.store_bits_bool(addr))) { // account_addr:bits256 - return false; - } - vm::AugmentedDictionary dict{64, block::tlb::aug_AccountTransactions}; - for (auto& z : transactions) { - if (!dict.set_ref(td::BitArray<64>{(long long)z.first}, z.second, vm::Dictionary::SetMode::Add)) { - LOG(ERROR) << "error creating the list of transactions for account " << addr.to_hex() - << " : cannot add transaction with lt=" << z.first; - return false; - } - } - Ref dict_root = std::move(dict).extract_root_cell(); - // transactions:(HashmapAug 64 ^Transaction Grams) - if (dict_root.is_null() || !cb.append_cellslice_bool(vm::load_cell_slice(std::move(dict_root)))) { - return false; - } - vm::CellBuilder cb2; - return cb2.store_long_bool(0x72, 8) // update_hashes#72 - && cb2.store_bits_bool(orig_total_state->get_hash().bits(), 256) // old_hash:bits256 - && cb2.store_bits_bool(total_state->get_hash().bits(), 256) // new_hash:bits256 - && cb.store_ref_bool(cb2.finalize()); // state_update:^(HASH_UPDATE Account) -} - -bool Account::libraries_changed() const { - bool s = orig_library.not_null(); - bool t = library.not_null(); - if (s & t) { - return orig_library->get_hash() != library->get_hash(); - } else { - return s != t; - } -} - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/block/transaction.h b/submodules/ton/tonlib-src/crypto/block/transaction.h deleted file mode 100644 index c1cfbc54..00000000 --- a/submodules/ton/tonlib-src/crypto/block/transaction.h +++ /dev/null @@ -1,384 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "common/refint.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/dict.h" -#include "vm/boc.h" -#include -#include "tl/tlblib.hpp" -#include "td/utils/bits.h" -#include "ton/ton-types.h" -#include "block/block.h" -#include "block/mc-config.h" - -namespace block { -using td::Ref; -using LtCellRef = std::pair>; - -struct Account; -struct Transaction; - -struct CollatorError { - std::string msg; - CollatorError(std::string _msg) : msg(_msg) { - } - CollatorError(const char* _msg) : msg(_msg) { - } - std::string get_msg() const { - return msg; - } -}; - -static inline bool operator<(const LtCellRef& a, const LtCellRef& b) { - return a.first < b.first; -} - -struct LtCellCompare { - bool operator()(const LtCellRef& a, const LtCellRef& b) { - return a.first < b.first; - } -}; - -struct NewOutMsg { - ton::LogicalTime lt; - Ref msg; - Ref trans; - NewOutMsg(ton::LogicalTime _lt, Ref _msg, Ref _trans) - : lt(_lt), msg(std::move(_msg)), trans(std::move(_trans)) { - } - bool operator<(const NewOutMsg& other) const& { - return lt < other.lt || (lt == other.lt && msg->get_hash() < other.msg->get_hash()); - } - bool operator>(const NewOutMsg& other) const& { - return lt > other.lt || (lt == other.lt && other.msg->get_hash() < msg->get_hash()); - } -}; - -struct StoragePhaseConfig { - const std::vector* pricing{nullptr}; - td::RefInt256 freeze_due_limit; - td::RefInt256 delete_due_limit; - StoragePhaseConfig() = default; - StoragePhaseConfig(const std::vector* _pricing, td::RefInt256 freeze_limit = {}, - td::RefInt256 delete_limit = {}) - : pricing(_pricing), freeze_due_limit(freeze_limit), delete_due_limit(delete_limit) { - } -}; - -struct StoragePhase { - td::RefInt256 fees_collected; - td::RefInt256 fees_due; - ton::UnixTime last_paid_updated; - bool frozen{false}; - bool deleted{false}; - bool is_special{false}; -}; - -struct ComputePhaseConfig { - td::uint64 gas_price; - td::uint64 gas_limit; - td::uint64 special_gas_limit; - td::uint64 gas_credit; - td::uint64 flat_gas_limit = 0; - td::uint64 flat_gas_price = 0; - static constexpr td::uint64 gas_infty = (1ULL << 63) - 1; - td::RefInt256 gas_price256; - td::RefInt256 max_gas_threshold; - std::unique_ptr libraries; - Ref global_config; - td::BitArray<256> block_rand_seed; - ComputePhaseConfig(td::uint64 _gas_price = 0, td::uint64 _gas_limit = 0, td::uint64 _gas_credit = 0) - : gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_gas_limit), gas_credit(_gas_credit) { - compute_threshold(); - } - ComputePhaseConfig(td::uint64 _gas_price, td::uint64 _gas_limit, td::uint64 _spec_gas_limit, td::uint64 _gas_credit) - : gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_spec_gas_limit), gas_credit(_gas_credit) { - compute_threshold(); - } - void compute_threshold(); - td::uint64 gas_bought_for(td::RefInt256 nanograms) const; - td::RefInt256 compute_gas_price(td::uint64 gas_used) const; - void set_gas_price(td::uint64 _gas_price) { - gas_price = _gas_price; - compute_threshold(); - } - Ref lookup_library(td::ConstBitPtr key) const; - Ref lookup_library(const td::Bits256& key) const { - return lookup_library(key.bits()); - } - Ref get_lib_root() const { - return libraries ? libraries->get_root_cell() : Ref{}; - } - bool parse_GasLimitsPrices(Ref cs, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit); - bool parse_GasLimitsPrices(Ref cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit); - - private: - bool parse_GasLimitsPrices_internal(Ref cs, td::RefInt256& freeze_due_limit, - td::RefInt256& delete_due_limit, td::uint64 flat_gas_limit = 0, - td::uint64 flat_gas_price = 0); -}; - -struct ActionPhaseConfig { - int max_actions{255}; - int bounce_msg_body{0}; // usually 0 or 256 bits - MsgPrices fwd_std; - MsgPrices fwd_mc; // from/to masterchain - const WorkchainSet* workchains{nullptr}; - const MsgPrices& fetch_msg_prices(bool is_masterchain) const { - return is_masterchain ? fwd_mc : fwd_std; - } -}; - -struct CreditPhase { - td::RefInt256 due_fees_collected; - block::CurrencyCollection credit; -}; - -struct ComputePhase { - enum { sk_none, sk_no_state, sk_bad_state, sk_no_gas }; - int skip_reason{sk_none}; - bool success{false}; - bool msg_state_used{false}; - bool account_activated{false}; - bool out_of_gas{false}; - bool accepted{false}; - td::RefInt256 gas_fees; - td::uint64 gas_used, gas_max, gas_limit, gas_credit; - int mode; - int exit_code; - int exit_arg; - int vm_steps; - ton::Bits256 vm_init_state_hash, vm_final_state_hash; - Ref in_msg; - Ref new_data; - Ref actions; -}; - -struct ActionPhase { - bool success{false}; - bool valid{false}; - bool no_funds{false}; - bool code_changed{false}; - bool action_list_invalid{false}; - bool acc_delete_req{false}; - enum { acst_unchanged = 0, acst_frozen = 2, acst_deleted = 3 }; - int acc_status_change{acst_unchanged}; - td::RefInt256 total_fwd_fees; // all fees debited from the account - td::RefInt256 total_action_fees; // fees credited to validators in this action phase - int result_code; - int result_arg; - int tot_actions; - int spec_actions; - int skipped_actions; - int msgs_created; - Ref new_code; - td::BitArray<256> action_list_hash; - block::CurrencyCollection remaining_balance, reserved_balance; - std::vector> action_list; // processed in reverse order - std::vector> out_msgs; - ton::LogicalTime end_lt; - unsigned long long tot_msg_bits{0}, tot_msg_cells{0}; -}; - -struct BouncePhase { - bool ok{false}; - bool nofunds{false}; - unsigned long long msg_bits, msg_cells; - unsigned long long fwd_fees, fwd_fees_collected; - Ref out_msg; -}; - -struct Account { - enum { acc_nonexist = 0, acc_uninit = 1, acc_frozen = 2, acc_active = 3, acc_deleted = 4 }; - int status{acc_nonexist}, orig_status{acc_nonexist}; - bool is_special{false}; - bool tick{false}; - bool tock{false}; - bool created{false}; - bool split_depth_set_{false}; - unsigned char split_depth_{0}; - int verbosity{3 * 0}; - ton::UnixTime now_{0}; - ton::WorkchainId workchain{ton::workchainInvalid}; - td::BitArray<32> addr_rewrite; // rewrite (anycast) data, split_depth bits - ton::StdSmcAddress addr; // rewritten address (by replacing a prefix of `addr_orig` with `addr_rewrite`) - ton::StdSmcAddress addr_orig; // address indicated in smart-contract data - Ref my_addr; // address as stored in the smart contract (MsgAddressInt) - Ref my_addr_exact; // exact address without anycast info - ton::LogicalTime last_trans_end_lt_; - ton::LogicalTime last_trans_lt_; - ton::Bits256 last_trans_hash_; - ton::LogicalTime block_lt; - ton::UnixTime last_paid; - vm::CellStorageStat storage_stat; - block::CurrencyCollection balance; - td::RefInt256 due_payment; - Ref orig_total_state; // ^Account - Ref total_state; // ^Account - Ref inner_state; // StateInit - ton::Bits256 state_hash; // hash of StateInit for frozen accounts - Ref code, data, library, orig_library; - std::vector transactions; - Account() = default; - Account(ton::WorkchainId wc, td::ConstBitPtr _addr) : workchain(wc), addr(_addr) { - } - Account(ton::WorkchainId wc, td::ConstBitPtr _addr, int depth) - : split_depth_set_(true), split_depth_((unsigned char)depth), workchain(wc), addr(_addr) { - } - block::CurrencyCollection get_balance() const { - return balance; - } - bool set_address(ton::WorkchainId wc, td::ConstBitPtr new_addr); - bool unpack(Ref account, Ref extra, ton::UnixTime now, bool special = false); - bool init_new(ton::UnixTime now); - bool recompute_tmp_addr(Ref& tmp_addr, int split_depth, td::ConstBitPtr orig_addr_rewrite) const; - td::RefInt256 compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const; - bool is_masterchain() const { - return workchain == ton::masterchainId; - } - bool belongs_to_shard(ton::ShardIdFull shard) const; - bool store_acc_status(vm::CellBuilder& cb, int status) const; - bool store_acc_status(vm::CellBuilder& cb) const { - return store_acc_status(cb, status); - } - void push_transaction(Ref trans_root, ton::LogicalTime trans_lt); - bool libraries_changed() const; - bool create_account_block(vm::CellBuilder& cb); // stores an AccountBlock with all transactions - - protected: - friend struct Transaction; - bool set_split_depth(int split_depth); - bool check_split_depth(int split_depth) const; - bool init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewrite); - - private: - bool unpack_address(vm::CellSlice& addr_cs); - bool unpack_storage_info(vm::CellSlice& cs); - bool unpack_state(vm::CellSlice& cs); - bool parse_maybe_anycast(vm::CellSlice& cs); - bool store_maybe_anycast(vm::CellBuilder& cb) const; - bool compute_my_addr(bool force = false); -}; - -struct Transaction { - static constexpr unsigned max_msg_bits = (1 << 21), max_msg_cells = (1 << 13); - enum { - tr_none, - tr_ord, - tr_storage, - tr_tick, - tr_tock, - tr_split_prepare, - tr_split_install, - tr_merge_prepare, - tr_merge_install - }; - int trans_type{tr_none}; - bool was_deleted{false}; - bool was_frozen{false}; - bool was_activated{false}; - bool was_created{false}; - bool bounce_enabled{false}; - bool in_msg_extern{false}; - bool use_msg_state{false}; - bool is_first{false}; - bool orig_addr_rewrite_set{false}; - bool new_tick; - bool new_tock; - signed char new_split_depth{-1}; - ton::UnixTime now; - int acc_status; - int verbosity{3 * 0}; - int in_msg_type{0}; - const Account& account; // only `commit` method modifies the account - Ref my_addr, my_addr_exact; // almost the same as in account.* - ton::LogicalTime start_lt, end_lt; - block::CurrencyCollection balance, original_balance; - block::CurrencyCollection msg_balance_remaining; - td::RefInt256 due_payment; - td::RefInt256 in_fwd_fee, msg_fwd_fees; - block::CurrencyCollection total_fees{0}; - ton::UnixTime last_paid; - Ref root; - Ref new_total_state; - Ref new_inner_state; - Ref new_code, new_data, new_library; - Ref in_msg, in_msg_state; - Ref in_msg_body; - Ref in_msg_library; - td::BitArray<256> frozen_hash; - td::BitArray<32> orig_addr_rewrite; - std::vector> out_msgs; - std::unique_ptr storage_phase; - std::unique_ptr credit_phase; - std::unique_ptr compute_phase; - std::unique_ptr action_phase; - std::unique_ptr bounce_phase; - vm::CellStorageStat new_storage_stat; - Transaction(const Account& _account, int ttype, ton::LogicalTime req_start_lt, ton::UnixTime _now, - Ref _inmsg = {}); - bool unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* cfg); - bool check_in_msg_state_hash(); - bool prepare_storage_phase(const StoragePhaseConfig& cfg, bool force_collect = true, bool adjust_msg_value = false); - bool prepare_credit_phase(); - bool compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg); - Ref prepare_vm_stack(ComputePhase& cp); - std::vector> compute_vm_libraries(const ComputePhaseConfig& cfg); - bool prepare_compute_phase(const ComputePhaseConfig& cfg); - bool prepare_action_phase(const ActionPhaseConfig& cfg); - bool prepare_bounce_phase(const ActionPhaseConfig& cfg); - bool compute_state(); - bool serialize(); - td::uint64 gas_used() const { - return compute_phase ? compute_phase->gas_used : 0; - } - - td::Result estimate_block_storage_profile_incr( - const vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const; - bool update_block_storage_profile(vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const; - bool would_fit(unsigned cls, const block::BlockLimitStatus& blk_lim_st) const; - bool update_limits(block::BlockLimitStatus& blk_lim_st) const; - - Ref commit(Account& _account); // _account should point to the same account - LtCellRef extract_out_msg(unsigned i); - NewOutMsg extract_out_msg_ext(unsigned i); - void extract_out_msgs(std::vector& list); - - private: - Ref prepare_vm_c7(const ComputePhaseConfig& cfg) const; - bool prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputePhaseConfig& cfg) const; - int try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg); - int try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg); - int try_action_send_msg(const vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg, int redoing = 0); - int try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg); - bool check_replace_src_addr(Ref& src_addr) const; - bool check_rewrite_dest_addr(Ref& dest_addr, const ActionPhaseConfig& cfg, - bool* is_mc = nullptr) const; - bool serialize_storage_phase(vm::CellBuilder& cb); - bool serialize_credit_phase(vm::CellBuilder& cb); - bool serialize_compute_phase(vm::CellBuilder& cb); - bool serialize_action_phase(vm::CellBuilder& cb); - bool serialize_bounce_phase(vm::CellBuilder& cb); - bool unpack_msg_state(bool lib_only = false); -}; - -} // namespace block diff --git a/submodules/ton/tonlib-src/crypto/common/AtomicRef.h b/submodules/ton/tonlib-src/crypto/common/AtomicRef.h deleted file mode 100644 index e82bcda4..00000000 --- a/submodules/ton/tonlib-src/crypto/common/AtomicRef.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/SpinLock.h" -#include "common/refcnt.hpp" - -#include - -namespace td { -template -class AtomicRefSpinlock { - public: - AtomicRefSpinlock() = default; - AtomicRefSpinlock(Ref&& ref) : ref_(ref.release()) { - } - ~AtomicRefSpinlock() { - Ref(ref_.load(std::memory_order_relaxed), typename Ref::acquire_t{}); - } - AtomicRefSpinlock(AtomicRefSpinlock&&) = delete; - AtomicRefSpinlock& operator=(AtomicRefSpinlock&&) = delete; - AtomicRefSpinlock(const AtomicRefSpinlock&) = delete; - AtomicRefSpinlock& operator=(const AtomicRefSpinlock&) = delete; - - Ref load() const { - auto guard = spin_lock_.lock(); - return Ref(ref_.load(std::memory_order_relaxed)); - } - Ref extract() const { - auto guard = spin_lock_.lock(); - return Ref(ref_.exchange(nullptr, std::memory_order_release), typename Ref::acquire_t{}); - } - - Ref load_unsafe() const { - return Ref(get_unsafe()); - } - const T* get_unsafe() const { - return ref_.load(std::memory_order_acquire); - } - bool store_if_empty(Ref& desired) { - auto guard = spin_lock_.lock(); - if (ref_.load(std::memory_order_relaxed) == nullptr) { - ref_.store(desired.release(), std::memory_order_release); - return true; - } - return false; - } - - void store(Ref&& ref) { - auto guard = spin_lock_.lock(); - Ref(ref_.exchange(ref.release(), std::memory_order_acq_rel), typename Ref::acquire_t{}); - } - - private: - mutable SpinLock spin_lock_; - std::atomic ref_{nullptr}; -}; - -template -class AtomicRefLockfree { - public: - AtomicRefLockfree() = default; - static constexpr int BATCH_SIZE = 100; - AtomicRefLockfree(Ref&& ref) : ptr_(Ptr(ref.release(), BATCH_SIZE)) { - Ref::acquire_shared(ptr_.load(std::memory_order_relaxed).ptr(), BATCH_SIZE); - } - ~AtomicRefLockfree() { - auto ptr = ptr_.load(std::memory_order_relaxed); - if (ptr.ptr()) { - Ref::release_shared(ptr.ptr(), ptr.ref_cnt() + 1); - } - } - AtomicRefLockfree(AtomicRefLockfree&&) = delete; - AtomicRefLockfree& operator=(AtomicRefLockfree&&) = delete; - AtomicRefLockfree(const AtomicRefLockfree&) = delete; - AtomicRefLockfree& operator=(const AtomicRefLockfree&) = delete; - - Ref load() const { - auto ptr = ptr_.load(); - while (ptr.ptr()) { - if (ptr.ref_cnt() == 0) { - td::this_thread::yield(); - ptr = ptr_.load(); - continue; - } - auto new_ptr = Ptr(ptr.ptr(), ptr.ref_cnt() - 1); - if (ptr_.compare_exchange_weak(ptr, new_ptr)) { - if (new_ptr.ref_cnt() < BATCH_SIZE / 2) { - try_reserve(ptr.ptr()); - } - return Ref(ptr.ptr(), typename Ref::acquire_t{}); - } - } - return {}; - } - void try_reserve(T* raw_ptr) const { - int reserve_cnt = BATCH_SIZE; - Ref::acquire_shared(raw_ptr, reserve_cnt); - auto ptr = ptr_.load(); - while (ptr.ptr() == raw_ptr && ptr.ref_cnt() < BATCH_SIZE / 2) { - auto new_ptr = Ptr(ptr.ptr(), ptr.ref_cnt() + reserve_cnt); - if (ptr_.compare_exchange_weak(ptr, new_ptr)) { - return; - } - } - Ref::release_shared(raw_ptr, reserve_cnt); - } - Ref extract() { - auto ptr = ptr_.exchange({}); - if (ptr.ref_cnt() != 0) { - Ref::release_shared(ptr.ptr(), ptr.ref_cnt()); - } - - return Ref(ptr.ptr(), typename Ref::acquire_t{}); - } - - Ref load_unsafe() const { - return load(); - } - T* get_unsafe() const { - return ptr_.load().ptr(); - } - bool store_if_empty(Ref& desired) { - auto raw_ptr = desired.get(); - Ref::acquire_shared(raw_ptr, BATCH_SIZE + 1); - - Ptr new_ptr{const_cast(raw_ptr), BATCH_SIZE}; - auto ptr = ptr_.load(); - while (ptr.ptr() == nullptr) { - if (ptr_.compare_exchange_weak(ptr, new_ptr)) { - return true; - } - } - Ref::release_shared(raw_ptr, BATCH_SIZE + 1); - return false; - } - - void store(Ref&& ref) { - Ptr new_ptr = [&]() -> Ptr { - if (ref.is_null()) { - return {}; - } - auto raw_ptr = ref.release(); - Ref::acquire_shared(raw_ptr, BATCH_SIZE); - return {raw_ptr, BATCH_SIZE}; - }(); - - auto ptr = ptr_.load(); - while (!ptr_.compare_exchange_weak(ptr, new_ptr)) { - } - - if (ptr.ptr()) { - Ref::release_shared(ptr.ptr(), ptr.ref_cnt() + 1); - } - } - - private: - struct Ptr { - public: - Ptr() = default; - Ptr(T* ptr, int ref_cnt) { - data_ = reinterpret_cast(ptr); - CHECK((data_ >> 48) == 0); - data_ |= static_cast(ref_cnt) << 48; - } - T* ptr() const { - return reinterpret_cast(data_ & (std::numeric_limits::max() >> 16)); - } - int ref_cnt() const { - return static_cast(data_ >> 48); - } - - private: - td::uint64 data_{0}; - }; - static_assert(sizeof(Ptr) == 8, "sizeof(Ptr) must be 8 for atomic to work fine"); - static_assert(std::is_trivially_copyable::value, "Ptr must be tribially copyable"); - - mutable std::atomic ptr_{Ptr()}; -}; - -template -using AtomicRef = AtomicRefLockfree; -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bigexp.cpp b/submodules/ton/tonlib-src/crypto/common/bigexp.cpp deleted file mode 100644 index 365f0595..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bigexp.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "bigexp.h" -#include "td/utils/bits.h" -#include "td/utils/as.h" -#include "td/utils/misc.h" - -namespace td { - -bool NegExpBinTable::init() { - init_one(); - int k; - for (k = minpw2; k <= 0; k++) { - exp_pw2_table.emplace_back(series_exp(-k)); - exp_pw2_ref_table.emplace_back(true, exp_pw2_table.back()); - } - for (; k < maxpw2; k++) { - td::BigIntG<257 * 2> tmp{0}; - auto& x = exp_pw2_table.back(); - tmp.add_mul(x, x).rshift(precision, 0).normalize(); - exp_pw2_table.emplace_back(tmp); - exp_pw2_ref_table.emplace_back(true, exp_pw2_table.back()); - } - return true; -} - -bool NegExpBinTable::adjust_precision(int new_precision, int rmode) { - if (new_precision <= 0 || new_precision > precision) { - return false; - } - if (new_precision == precision) { - return true; - } - int s = precision - new_precision; - for (auto& x : exp_pw2_table) { - x.rshift(s, rmode).normalize(); - } - for (auto& x : exp_pw2_ref_table) { - x.write().rshift(s, rmode).normalize(); - } - precision = new_precision; - return init_one(); -} - -bool NegExpBinTable::init_one() { - One.set_pow2(precision); - return true; -} - -bool NegExpBinTable::nexpf(td::BigInt256& res, long long x, int k) const { // res := 2^precision * exp(-x * 2^k) - if (!x) { - res.set_pow2(precision); - return true; - } - if (x < 0) { - return false; - } - int s = td::count_trailing_zeroes64(x); - x >>= s; - k -= s; - if (k + minpw2 > 0) { - return false; - } - int t = 63 - td::count_leading_zeroes64(x); - if (t - k >= maxpw2) { - return false; - } - res.set_pow2(precision); - while (true) { - td::BigIntG<257 * 2> tmp{0}; - tmp.add_mul(res, exp_pw2_table.at(t - k - minpw2)).rshift(precision, 0).normalize(); - res = tmp; - x -= (1LL << t); - if (!x) { - return true; - } - t = 63 - td::count_leading_zeroes64(x); - } -} - -td::RefInt256 NegExpBinTable::nexpf(long long x, int k) const { - td::RefInt256 res{true}; - if (nexpf(res.unique_write(), x, k)) { - return res; - } else { - return {}; - } -} - -td::BigInt256 NegExpBinTable::series_exp(int k) const { // returns 2^precision * exp(-2^(-k)), k >= 0 - td::BigIntG<257 * 2> s{0}, q; - const int prec = 52 * 6; - q.set_pow2(prec); - int i = 0; - do { - s += q; - --i; - q.rshift(k).add_tiny(i / 2).divmod_short(i); - q.normalize(); - } while (q.sgn()); - s.rshift(prec - precision).normalize(); - return s; -} - -NegExpInt64Table::NegExpInt64Table() { - NegExpBinTable t{252, 8, -32}; - CHECK(t.is_valid()); - table0[0] = 0; - table0_shift[0] = 0; - for (int i = 1; i <= max_exp; i++) { - SuperFloat v(*t.nexpf(i, 0)); // compute exp(-i) - CHECK(!v.is_nan()); - if (v.is_zero()) { - table0[i] = 0; - table0_shift[i] = 0; - } else { - CHECK(v.normalize()); - int k = v.s + 64 - 252; - CHECK(k <= -64); - if (k > -128) { - table0[i] = v.top(); - table0_shift[i] = td::narrow_cast(-k - 1); - } else { - table0[i] = 0; - table0_shift[i] = 0; - } - } - // std::cerr << "table0[" << i << "] = exp(-" << i << ") : " << table0[i] << " / 2^" << table0_shift[i] + 1 << std::endl; - } - td::BigInt256 One; - One.set_pow2(252); - for (int i = 0; i < 256; i++) { - td::BigInt256 x; - CHECK(t.nexpf(x, i, 8)); - (x.negate() += One).rshift(252 - 64, 0).normalize(); - table1[i] = SuperFloat::as_uint64(x); - // std::cerr << "table1[" << i << "] = 1 - exp(-" << i << "/256) : " << table1[i] << " / 2^64" << std::endl; - } - for (int i = 0; i < 256; i++) { - td::BigInt256 x; - CHECK(t.nexpf(x, i, 16)); - (x.negate() += One).rshift(252 - 64 - 8, 0).normalize(); - table2[i] = SuperFloat::as_uint64(x); - // std::cerr << "table2[" << i << "] = 1 - exp(-" << i << "/2^16) : " << table2[i] << " / 2^72" << std::endl; - } -} - -td::uint64 NegExpInt64Table::umulnexps32(td::uint64 x, unsigned k, bool trunc) const { // compute x * exp(-k / 2^16) - if (!k || !x) { - return x; - } - unsigned k0 = (k >> 16); - if (k0 > max_exp) { - return 0; - } - unsigned s = td::count_leading_zeroes_non_zero64(x); - x <<= s; - unsigned k1 = (k >> 8) & 0xff; - unsigned k2 = k & 0xff; - if (k2) { - x -= ((td::uint128::from_unsigned(x).mult(table2[k2]).rounded_hi() + 0x80) >> 8); - } - if (k1) { - x -= td::uint128::from_unsigned(x).mult(table1[k1]).rounded_hi(); - } - if (k0) { - if (trunc) { - return td::uint128::from_unsigned(x).mult(table0[k0]).shr(table0_shift[k0] + s + 1).lo(); - } else { - return (td::uint128::from_unsigned(x).mult(table0[k0]).shr(table0_shift[k0] + s).lo() + 1) >> 1; - } - } - if (!s) { - return x; - } else if (trunc) { - return x >> s; - } else { - return ((x >> (s - 1)) + 1) >> 1; - } -} - -td::int64 NegExpInt64Table::mulnexps32(td::int64 x, unsigned k, bool trunc) const { - return x >= 0 ? umulnexps32(x, k, trunc) : -umulnexps32(-x, k, trunc); -} - -const NegExpInt64Table& NegExpInt64Table::table() { - static NegExpInt64Table tab; - return tab; -} - -td::uint64 umulnexps32(td::uint64 x, unsigned k, bool trunc) { // compute x * exp(-k / 2^16) - return NegExpInt64Table::table().umulnexps32(x, k, trunc); -} - -td::int64 mulnexps32(td::int64 x, unsigned k, bool trunc) { - return NegExpInt64Table::table().mulnexps32(x, k, trunc); -} - -td::uint128 SuperFloat::as_uint128(const td::BigInt256& x) { - td::uint64 t[2]; - if (!x.export_bytes_lsb((unsigned char*)(void*)t, sizeof(t), false)) { - return {std::numeric_limits::max(), 0}; - } else { - return {t[1], t[0]}; - } -} - -td::uint64 SuperFloat::as_uint64(const td::BigInt256& x) { - td::uint64 t; - if (!x.export_bytes_lsb((unsigned char*)&t, sizeof(t), false)) { - return std::numeric_limits::max(); - } else { - return t; - } -} - -SuperFloat::SuperFloat(td::BigInt256 x) { - if (x.unsigned_fits_bits(128)) { - m = as_uint128(x); - s = 0; - } else if (x.sgn() == 1) { - s = x.bit_size(false) - 128; - x.rshift(s, 0).normalize(); - m = as_uint128(x); - } else { - set_nan(); - } -} - -bool SuperFloat::normalize() { - if (is_nan()) { - return false; - } - if (is_zero()) { - s = 0; - return true; - } - auto hi = m.hi(); - int t = (hi ? td::count_leading_zeroes_non_zero64(hi) : 64 + td::count_leading_zeroes_non_zero64(m.lo())); - m.shl(t); - s -= t; - return true; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bigexp.h b/submodules/ton/tonlib-src/crypto/common/bigexp.h deleted file mode 100644 index 54dee48a..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bigexp.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "common/refint.h" - -namespace td { - -class NegExpBinTable { - int precision, maxpw2, minpw2; - std::vector exp_pw2_table; // table of 2^precision * exp(- 2^k) for k = max_pw2-1 .. min_pw2 - std::vector exp_pw2_ref_table; // same data - td::BigInt256 One; - - public: - NegExpBinTable(int _precision, int _maxpw2, int _minpw2) : precision(255), maxpw2(_maxpw2), minpw2(_minpw2) { - (_precision > 0 && _precision < 256 && _minpw2 <= 0 && _maxpw2 > 0 && _maxpw2 <= 256 && _minpw2 >= -256 && init() && - adjust_precision(_precision)) || - invalidate(); - } - bool is_valid() const { - return minpw2 < maxpw2; - } - int get_precision() const { - return precision; - } - int get_exponent_precision() const { - return -minpw2; - } - int get_exponent_max_log2() const { - return maxpw2; - } - const td::BigInt256* exp_pw2(int k) const { // returns 2^precision * exp(-2^k) or null - return (k >= minpw2 && k < maxpw2) ? &exp_pw2_table[k - minpw2] : nullptr; - } - td::RefInt256 exp_pw2_ref(int k) const { - if (k >= minpw2 && k < maxpw2) { - return exp_pw2_ref_table[k - minpw2]; - } else { - return {}; - } - } - bool nexpf(td::BigInt256& res, long long x, int k) const; // res := 2^precision * exp(-x * 2^k) - td::RefInt256 nexpf(long long x, int k) const; - - private: - bool init(); - bool init_one(); - bool adjust_precision(int new_precision, int rmode = 0); - bool invalidate() { - minpw2 = maxpw2 = 0; - return false; - } - td::BigInt256 series_exp(int k) const; // returns 2^precision * exp(-2^(-k)), k >= 0 -}; - -struct SuperFloat { - struct SetZero {}; - struct SetOne {}; - struct SetNan {}; - td::uint128 m; - int s; - SuperFloat() = default; - SuperFloat(SetZero) : m(0, 0), s(0) { - } - SuperFloat(SetOne) : m(0, 1), s(0) { - } - SuperFloat(SetNan) : m(0, 0), s(std::numeric_limits::min()) { - } - SuperFloat(td::uint128 _m, int _s = 0) : m(_m), s(_s) { - } - SuperFloat(td::uint64 _m, int _s = 0) : m(0, _m), s(_s) { - } - explicit SuperFloat(BigInt256 x); - static SuperFloat Zero() { - return SetZero{}; - } - static SuperFloat One() { - return SetOne{}; - } - static SuperFloat NaN() { - return SetNan{}; - } - void set_zero() { - m = td::uint128(0, 0); - s = 0; - } - void set_one() { - m = td::uint128(0, 1); - s = 0; - } - void set_nan() { - s = std::numeric_limits::min(); - } - bool is_nan() const { - return s == std::numeric_limits::min(); - } - bool is_zero() const { - return m.is_zero(); - } - bool normalize(); - td::uint64 top() const { - return m.rounded_hi(); - } - static td::uint128 as_uint128(const td::BigInt256& x); - static td::uint64 as_uint64(const td::BigInt256& x); -}; - -class NegExpInt64Table { - enum { max_exp = 45 }; - unsigned char table0_shift[max_exp + 1]; - td::uint64 table0[max_exp + 1], table1[256], table2[256]; - - public: - NegExpInt64Table(); - // compute x * exp(-k / 2^16); - // more precisely: computes 0 <= y <= x for 0 <= x < 2^60, s.that |y - x * exp(-k / 2^16)| < 1 - // two different implementations of this functions would return values differing by at most one - td::uint64 umulnexps32(td::uint64 x, unsigned k, bool trunc = false) const; - td::int64 mulnexps32(td::int64 x, unsigned k, bool trunc = false) const; - static const NegExpInt64Table& table(); - - private: -}; - -td::uint64 umulnexps32(td::uint64 x, unsigned k, bool trunc = false); // compute x * exp(-k / 2^16) -td::int64 mulnexps32(td::int64 x, unsigned k, bool trunc = false); - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bigint.cpp b/submodules/ton/tonlib-src/crypto/common/bigint.cpp deleted file mode 100644 index 41780fb9..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bigint.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "common/bigint.hpp" - -namespace td { - -template class AnyIntView; -template class BigIntG<257, BigIntInfo>; - -namespace literals { -BigInt256 operator""_i256(const char* str, std::size_t str_len) { - BigInt256 x; - x.enforce(x.parse_dec(str, (int)str_len) == (int)str_len); - return x; -} - -BigInt256 operator""_x256(const char* str, std::size_t str_len) { - BigInt256 x; - x.enforce(x.parse_hex(str, (int)str_len) == (int)str_len); - return x; -} - -} // namespace literals - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bigint.hpp b/submodules/ton/tonlib-src/crypto/common/bigint.hpp deleted file mode 100644 index cde80ce2..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bigint.hpp +++ /dev/null @@ -1,2544 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include "common/bitstring.h" - -#include "td/utils/bits.h" -#include "td/utils/Span.h" -#include "td/utils/uint128.h" - -/************************************** - * - * BIGINT256 - * - ************************************** -**/ - -namespace td { - -struct BigIntInfo { - typedef long long word_t; - typedef unsigned long long uword_t; - enum { word_bits = 64, word_shift = 52, words_for_256bit = 1 + 256 / word_shift, max_pow10_exp = 18 }; - static const word_t Base = (1LL << word_shift); - static const word_t Half = (1LL << (word_shift - 1)); - static const word_t MaxDenorm = (1LL << (word_bits - word_shift - 1)); - static const word_t max_pow10 = 1000000000000000000LL; - static constexpr double InvBase = 1.0 / (double)Base; - - static void set_mul(word_t* hi, word_t* lo, word_t x, word_t y); - static void add_mul(word_t* hi, word_t* lo, word_t x, word_t y); - static void sub_mul(word_t* hi, word_t* lo, word_t x, word_t y); - static void dbl_divmod(word_t* quot, word_t* rem, word_t hi, word_t lo, word_t y); -}; - -inline void BigIntInfo::set_mul(word_t* hi, word_t* lo, word_t x, word_t y) { - auto z = uint128::from_signed(x).mult_signed(y); - *lo = static_cast(z.lo()) & (Base - 1); - *hi = static_cast(z.shr(word_shift).lo()); -} - -inline void BigIntInfo::add_mul(word_t* hi, word_t* lo, word_t x, word_t y) { - auto z = uint128::from_signed(x).mult_signed(y); - *lo += static_cast(z.lo()) & (Base - 1); - *hi += static_cast(z.shr(word_shift).lo()); -} - -inline void BigIntInfo::sub_mul(word_t* hi, word_t* lo, word_t x, word_t y) { - auto z = uint128::from_signed(x).mult_signed(y); - *lo -= static_cast(z.lo()) & (Base - 1); - *hi -= static_cast(z.shr(word_shift).lo()); -} - -inline void BigIntInfo::dbl_divmod(word_t* quot, word_t* rem, word_t hi, word_t lo, word_t y) { - auto x = uint128::from_signed(hi).shl(word_shift).add(uint128::from_signed(lo)); - int64 a, b; - x.divmod_signed(y, &a, &b); - *quot = a; - *rem = b; -} - -namespace { - -template -struct LogOpAnd { - static T op(T x, T y) { - return x & y; - } - static const T neutral = -1; - static const T zero = 0; - static const bool has_zero = true; -}; - -template -struct LogOpOr { - static T op(T x, T y) { - return x | y; - } - static const T neutral = 0; - static const T zero = -1; - static const bool has_zero = true; -}; - -template -struct LogOpXor { - static T op(T x, T y) { - return x ^ y; - } - static const T neutral = 0; - static const T zero = -1; - static const bool has_zero = false; -}; - -template -struct TransformId { - static T eval(T x) { - return x; - } -}; - -template -struct TransformNegate { - static T eval(T x) { - return -x; - } -}; - -template -struct TransformMul { - static T eval(T x) { - return x * factor; - } -}; - -} // namespace - -struct IntOverflow {}; - -template -class PropagateConstSpan { - public: - PropagateConstSpan() = default; - PropagateConstSpan(T* ptr, size_t size) : ptr_(ptr), size_(size) { - } - - T& operator[](size_t i) { - DCHECK(i < size_); - return ptr_[i]; - } - const T& operator[](size_t i) const { - DCHECK(i < size_); - return ptr_[i]; - } - T* data() { - return ptr_; - } - const T* data() const { - return ptr_; - } - size_t size() const { - return size_; - } - - private: - T* ptr_{nullptr}; - size_t size_{0}; -}; - -struct Normalize {}; - -template -class AnyIntView { - public: - enum { word_bits = Tr::word_bits, word_shift = Tr::word_shift }; - typedef typename Tr::word_t word_t; - int& n_; - PropagateConstSpan digits; - - int max_size() const { - return static_cast(digits.size()); - } - int size() const { - return n_; - } - void set_size(int new_size) { - n_ = new_size; - } - int inc_size() { - return n_++; - } - void dec_size() { - n_--; - } - - bool is_valid() const { - return size() > 0; - } - void enforce_valid() const { - enforce(is_valid()); - } - void invalidate() { - set_size(0); - } - bool invalidate_bool() { - set_size(0); - return false; - } - void enforce(bool f) const { - if (!f) { - throw IntOverflow(); - } - } - void operator=(word_t y) { - set_size(1); - digits[0] = y; - } - - bool normalize_bool_any(); - bool set_pow2_any(int exponent); - bool set_any(const AnyIntView& yp); - bool add_pow2_any(int exponent, int factor); - bool add_any(const AnyIntView& yp); - bool sub_any(const AnyIntView& yp); - - template - bool log_op_any(const AnyIntView& yp); - - int cmp_any(const AnyIntView& yp) const; - int cmp_any(word_t y) const; - - template > - int cmp_un_any(const AnyIntView& yp) const; - - void negate_any(); - - int sgn_un_any() const; - bool get_bit_any(unsigned bit) const; - bool eq_any(const AnyIntView& yp) const; - bool eq_any(word_t y) const; - void mul_tiny_any(int y); - int divmod_tiny_any(int y); - word_t divmod_short_any(word_t y); - bool mul_add_short_any(word_t y, word_t z); - bool add_mul_any(const AnyIntView& yp, const AnyIntView& zp); - void add_mul_trunc_any(const AnyIntView& yp, const AnyIntView& zp); - bool mod_div_any(const AnyIntView& yp, AnyIntView& quot, int round_mode); - bool mod_pow2_any(int exponent); - bool mod_pow2_any(int exponent, int round_mode); - bool rshift_any(int exponent, int round_mode = -1); - bool lshift_any(int exponent); - bool unsigned_fits_bits_any(int nbits) const; - bool signed_fits_bits_any(int nbits) const; - int bit_size_any(bool sgnd = true) const; - bool export_bytes_any(unsigned char* buff, std::size_t size, bool sgnd = true) const; - bool export_bytes_lsb_any(unsigned char* buff, std::size_t size, bool sgnd = true) const; - bool import_bytes_any(const unsigned char* buff, std::size_t size, bool sgnd = true); - bool import_bytes_lsb_any(const unsigned char* buff, std::size_t size, bool sgnd = true); - bool export_bits_any(unsigned char* buff, int offs, unsigned bits, bool sgnd = true) const; - bool import_bits_any(const unsigned char* buff, int offs, unsigned bits, bool sgnd = true); - word_t top_word() const { - return digits[size() - 1]; - } - double top_double() const { - return size() > 1 ? (double)digits[size() - 1] + (double)digits[size() - 2] * (1.0 / Tr::Base) - : (double)digits[size() - 1]; - } - word_t to_long_any() const; - int parse_hex_any(const char* str, int str_len, int* frac = nullptr); - int parse_binary_any(const char* str, int str_len, int* frac = nullptr); - std::string to_dec_string_destroy_any(); - std::string to_dec_string_slow_destroy_any(); - std::string to_hex_string_any(bool upcase = false, int zero_pad = 0) const; - std::string to_hex_string_slow_destroy_any(); - std::string to_binary_string_any() const; - - int sgn() const { - return is_valid() ? (top_word() > 0 ? 1 : (top_word() < 0 ? -1 : 0)) : 0x80000000; - } -}; - -template -class BigIntG { - public: - enum { word_bits = Tr::word_bits, word_shift = Tr::word_shift, max_bits = len, word_cnt = len / word_shift + 1 }; - typedef typename Tr::word_t word_t; - typedef Tr Traits; - typedef BigIntG DoubleInt; - - AnyIntView as_any_int() { - return AnyIntView{n, PropagateConstSpan(digits, word_cnt)}; - } - - const AnyIntView as_any_int() const { - return AnyIntView{const_cast(n), PropagateConstSpan(const_cast(digits), word_cnt)}; - } - - private: - template - friend class BigIntG; - - int n; - word_t digits[word_cnt]; - - public: - BigIntG() : n(0) { - } - explicit BigIntG(word_t x) : n(1) { - digits[0] = x; - } - BigIntG(Normalize, word_t x) : n(1) { - digits[0] = x; - normalize_bool(); - } - BigIntG(const BigIntG& x) : n(x.n) { - std::memcpy(digits, x.digits, n * sizeof(word_t)); - ///std::cout << "(BiCC " << (const void*)&x << "->" << (void*)this << ")"; - } - template - BigIntG(const BigIntG& y) : n(0) { - *this = y; - } - void enforce(bool f) const { - if (!f) { - throw IntOverflow(); - } - } - void ignore(bool f) const { - } - bool is_valid() const { - return n > 0; - } - void enforce_valid() const { - enforce(is_valid()); - } - BigIntG& invalidate() { - n = 0; - return *this; - } - bool invalidate_bool() { - n = 0; - return false; - } - BigIntG& invalidate_unless(bool f) { - if (!f) { - n = 0; - } - return *this; - } - bool normalize_bool() { - return as_any_int().normalize_bool_any(); - } - BigIntG& normalize() { - ignore(normalize_bool()); - return *this; - } - BigIntG& denormalize(); - int sgn() const { - return is_valid() ? (top_word() > 0 ? 1 : (top_word() < 0 ? -1 : 0)) : 0x80000000; - } - int sgn_un() const { - return as_any_int().sgn_un_any(); - } - bool get_bit(unsigned bit) const { - return as_any_int().get_bit_any(bit); - } - BigIntG& negate() { - as_any_int().negate_any(); - return *this; - } - BigIntG& logical_not(); - - BigIntG& operator=(const BigIntG& y) { - n = y.n; - std::memcpy(digits, y.digits, n * sizeof(word_t)); - ///std::cout << "(BiC=)"; - return *this; - } - - template - BigIntG& operator=(const BigIntG& y) { - return invalidate_unless(as_any_int().set_any(y.as_any_int())); - } - - template - BigIntG& operator+=(const BigIntG& y) { - ignore(as_any_int().add_any(y.as_any_int())); - return *this; - } - - template - BigIntG& operator-=(const BigIntG& y) { - ignore(as_any_int().sub_any(y.as_any_int())); - return *this; - } - - template - BigIntG& operator&=(const BigIntG& y) { - ignore(as_any_int().template log_op_any>(y.as_any_int())); - return *this; - } - - template - BigIntG& operator|=(const BigIntG& y) { - ignore(as_any_int().template log_op_any>(y.as_any_int())); - return *this; - } - - template - BigIntG& operator^=(const BigIntG& y) { - ignore(as_any_int().template log_op_any>(y.as_any_int())); - return *this; - } - - BigIntG& operator>>=(int shift) { - as_any_int().rshift_any(shift); - return *this; - } - - BigIntG& operator<<=(int shift) { - as_any_int().lshift_any(shift); - return *this; - } - - BigIntG& rshift(int shift, int round_mode = -1) { - as_any_int().rshift_any(shift, round_mode); - return *this; - } - - template - int cmp(const BigIntG& y) const { - return as_any_int().cmp_any(y.as_any_int()); - } - - template - int cmp_un(const BigIntG& y) const { - return as_any_int().template cmp_un_any>(y.as_any_int()); - } - - template - bool operator==(const BigIntG& y) const { - return as_any_int().eq_any(y.as_any_int()); - } - - template - bool operator!=(const BigIntG& y) const { - return !(*this == y); - } - - int cmp(word_t y) const { - return as_any_int().cmp_any(y); - } - - bool operator==(word_t y) const { - return as_any_int().eq_any(y); - } - - bool operator!=(word_t y) const { - return !(*this == y); - } - bool mul_add_short_bool(word_t y, word_t z) { - return as_any_int().mul_add_short_any(y, z); - } - - template - bool add_mul_bool(const BigIntG& y, const BigIntG& z) { - return as_any_int().add_mul_any(y.as_any_int(), z.as_any_int()); - } - - template - BigIntG& add_mul(const BigIntG& y, const BigIntG& z) { - ignore(add_mul_bool(y, z)); - return *this; - } - - template - void add_mul_trunc(const BigIntG& y, const BigIntG& z) { - as_any_int().add_mul_trunc_any(y.as_any_int(), z.as_any_int()); - } - - BigIntG& mul_short(word_t y) { - return invalidate_unless(mul_add_short_bool(y, 0)); - } - - BigIntG& mul_tiny(int y) { - as_any_int().mul_tiny_any(y); - return *this; - } - - BigIntG& add_tiny(word_t y) { - digits[0] += y; - return *this; - } - - BigIntG& sub_tiny(word_t y) { - digits[0] -= y; - return *this; - } - - BigIntG& mul_short_opt(word_t y) { - if (y <= Tr::MaxDenorm && y >= -Tr::MaxDenorm) { - return mul_tiny(static_cast(y)); - } else { - return mul_short(y); - } - } - - template - bool mod_div_bool(const BigIntG& y, BigIntG& quot, int round_mode = -1) { - auto q = quot.as_any_int(); - return as_any_int().mod_div_any(y.as_any_int(), q, round_mode); - } - - template - BigIntG& mod_div(const BigIntG& y, BigIntG& quot, int round_mode = -1) { - return invalidate_unless(mod_div_bool(y, quot, round_mode)); - } - - int divmod_tiny(int y) { - return as_any_int().divmod_tiny_any(y); - } - - word_t divmod_short(word_t y) { - return as_any_int().divmod_short_any(y); - } - - BigIntG& operator=(word_t y) { - n = 1; - digits[0] = y; - return *this; - } - - BigIntG& set_zero() { - n = 1; - digits[0] = 0; - return *this; - } - - BigIntG& set_pow2(int exponent) { - return invalidate_unless(as_any_int().set_pow2_any(exponent)); - } - - bool set_pow2_bool(int exponent) { - return as_any_int().set_pow2_any(exponent); - } - - BigIntG& mod_pow2(int exponent) { - return invalidate_unless(as_any_int().mod_pow2_any(exponent)); - } - - BigIntG& mod_pow2(int exponent, int round_mode) { - return invalidate_unless(as_any_int().mod_pow2_any(exponent, round_mode)); - } - - BigIntG& add_pow2(int exponent) { - return invalidate_unless(as_any_int().add_pow2_any(exponent, 1)); - } - - BigIntG& sub_pow2(int exponent) { - return invalidate_unless(as_any_int().add_pow2_any(exponent, -1)); - } - - bool unsigned_fits_bits(int nbits) const { - return as_any_int().unsigned_fits_bits_any(nbits); - } - - bool signed_fits_bits(int nbits) const { - return as_any_int().signed_fits_bits_any(nbits); - } - - bool fits_bits(int nbits, bool sgnd = true) const { - return sgnd ? signed_fits_bits(nbits) : unsigned_fits_bits(nbits); - } - - int bit_size(bool sgnd = true) const { - return as_any_int().bit_size_any(sgnd); - } - - bool export_bytes(unsigned char* buff, std::size_t size, bool sgnd = true) const { - return as_any_int().export_bytes_any(buff, size, sgnd); - } - - bool export_bytes_lsb(unsigned char* buff, std::size_t size, bool sgnd = true) const { - return as_any_int().export_bytes_lsb_any(buff, size, sgnd); - } - - bool import_bytes(const unsigned char* buff, std::size_t size, bool sgnd = true) { - return as_any_int().import_bytes_any(buff, size, sgnd); - } - - bool import_bytes_lsb(const unsigned char* buff, std::size_t size, bool sgnd = true) { - return as_any_int().import_bytes_lsb_any(buff, size, sgnd); - } - - bool export_bits(unsigned char* buff, int offs, unsigned bits, bool sgnd = true) const { - return as_any_int().export_bits_any(buff, offs, bits, sgnd); - } - - bool export_bits(td::BitPtr bp, unsigned bits, bool sgnd = true) const { - return as_any_int().export_bits_any(bp.ptr, bp.offs, bits, sgnd); - } - - template - bool export_bits(T& bs, bool sgnd = true) const { - return export_bits(bs.bits(), bs.size(), sgnd); - } - - bool export_bits(const BitSliceWrite& bs, bool sgnd = true) const { - return export_bits(bs.bits(), bs.size(), sgnd); - } - - bool import_bits(const unsigned char* buff, int offs, unsigned bits, bool sgnd = true) { - return as_any_int().import_bits_any(buff, offs, bits, sgnd); - } - - bool import_bits(td::ConstBitPtr bp, unsigned bits, bool sgnd = true) { - return as_any_int().import_bits_any(bp.ptr, bp.offs, bits, sgnd); - } - - template - bool import_bits(const T& bs, bool sgnd = true) { - return import_bits(bs.bits(), bs.size(), sgnd); - } - - std::ostream& dump(std::ostream& os, bool nl = true) const; - std::string dump() const; - int parse_dec(const char* str, int str_len, int* frac = nullptr); - int parse_dec(const std::string str, int* frac = nullptr) { - return parse_dec(str.c_str(), (int)str.size(), frac); - } - int parse_dec_slow(const char* str, int str_len); - int parse_dec_slow(const std::string str) { - return parse_dec_slow(str.c_str(), (int)str.size()); - } - int parse_hex(const char* str, int str_len, int* frac = nullptr) { - return as_any_int().parse_hex_any(str, str_len, frac); - } - int parse_hex(const std::string str, int* frac = nullptr) { - return parse_hex(str.c_str(), (int)str.size(), frac); - } - int parse_binary(const char* str, int str_len, int* frac = nullptr) { - return as_any_int().parse_binary_any(str, str_len, frac); - } - int parse_binary(const std::string str, int* frac = nullptr) { - return parse_binary(str.c_str(), (int)str.size(), frac); - } - std::string to_dec_string() const; - std::string to_dec_string_destroy(); - std::string to_dec_string_slow() const; - std::string to_hex_string_slow() const; - std::string to_hex_string(bool upcase = false, int zero_pad = 0) const; - std::string to_binary_string() const; - double to_double() const { - return is_valid() ? ldexp(top_double(), (n - 1) * word_shift) : NAN; - } - word_t to_long() const { - return as_any_int().to_long_any(); - } - - private: - word_t top_word() const { - return digits[n - 1]; - } - double top_double() const { - return n > 1 ? (double)digits[n - 1] + (double)digits[n - 2] * (1.0 / Tr::Base) : (double)digits[n - 1]; - } -}; - -template -bool AnyIntView::normalize_bool_any() { - word_t val = 0; - int i; - if (!is_valid()) { - return false; - } - for (i = 0; i < size() && digits[i] < Tr::Half && digits[i] >= -Tr::Half; i++) { - } - for (; i < size(); i++) { - val += digits[i] + Tr::Half; - digits[i] = (val & (Tr::Base - 1)) - Tr::Half; - val >>= word_shift; - } - if (val) { - do { - if (size() == max_size()) { - return invalidate_bool(); - } - val += Tr::Half; - digits[inc_size()] = (val & (Tr::Base - 1)) - Tr::Half; - val >>= word_shift; - } while (val); - } - while (size() > 1 && !digits[size() - 1]) { - dec_size(); - } - return true; -} - -template -bool AnyIntView::set_pow2_any(int exponent) { - if (exponent < 0 || exponent >= max_size() * word_shift) { - invalidate(); - return false; - } - auto dm = std::div(exponent, word_shift); - int k = dm.quot; - std::memset(digits.data(), 0, k * sizeof(word_t)); - if (dm.rem == word_shift - 1 && k + 1 < max_size()) { - digits[k] = -Tr::Half; - digits[k + 1] = 1; - set_size(k + 2); - return true; - } - digits[k] = ((word_t)1 << dm.rem); - set_size(k + 1); - return true; -} - -template -bool AnyIntView::set_any(const AnyIntView& yp) { - if (yp.size() <= max_size()) { - set_size(yp.size()); - std::memcpy(digits.data(), yp.digits.data(), size() * sizeof(word_t)); - return true; - } else { - set_size(max_size()); - std::memcpy(digits.data(), yp.digits.data(), size() * sizeof(word_t)); - return false; - } -} - -template -bool AnyIntView::add_pow2_any(int exponent, int factor) { - if (exponent < 0 || exponent >= max_size() * word_shift) { - invalidate(); - return false; - } - if (!is_valid()) { - return false; - } - auto dm = std::div(exponent, word_shift); - int k = dm.quot; - while (size() <= k) { - digits[inc_size()] = 0; - } - digits[k] += (factor << dm.rem); - return true; -} - -template -bool AnyIntView::add_any(const AnyIntView& yp) { - if (yp.size() <= size()) { - if (!yp.is_valid()) { - return invalidate_bool(); - } - for (int i = 0; i < yp.size(); i++) { - digits[i] += yp.digits[i]; - } - return true; - } else { - if (!is_valid()) { - return false; - } - if (yp.size() > max_size()) { - return invalidate_bool(); - } - for (int i = 0; i < size(); i++) { - digits[i] += yp.digits[i]; - } - for (int i = size(); i < yp.size(); i++) { - digits[i] = yp.digits[i]; - } - set_size(yp.size()); - return true; - } -} - -template -bool AnyIntView::sub_any(const AnyIntView& yp) { - if (yp.size() <= size()) { - if (!yp.is_valid()) { - return invalidate_bool(); - } - for (int i = 0; i < yp.size(); i++) { - digits[i] -= yp.digits[i]; - } - return true; - } else { - if (!is_valid()) { - return false; - } - if (yp.size() > max_size()) { - return invalidate_bool(); - } - for (int i = 0; i < size(); i++) { - digits[i] -= yp.digits[i]; - } - for (int i = size(); i < yp.size(); i++) { - digits[i] = -yp.digits[i]; - } - set_size(yp.size()); - return true; - } -} - -template -template -bool AnyIntView::log_op_any(const AnyIntView& yp) { - word_t cx = 0, cy = 0, cz = 0; - int i = 0; - const int shift = Tr::word_shift; - if (size() == 1) { - if (LogOp::has_zero && digits[0] == LogOp::zero) { - return true; - } else if (digits[0] == LogOp::neutral) { - if (yp.size() <= max_size()) { - set_size(yp.size()); - std::memcpy(digits.data(), yp.digits.data(), size() * sizeof(word_t)); - return true; - } else { - return invalidate_bool(); - } - } - } - if (yp.size() == 1) { - if (LogOp::has_zero && yp.digits[0] == LogOp::zero) { - set_size(1); - digits[0] = LogOp::zero; - return true; - } else if (yp.digits[0] == LogOp::neutral) { - return true; - } - } - if (yp.size() <= size()) { - if (!yp.is_valid()) { - return invalidate_bool(); - } - for (; i < yp.size(); i++) { - cx += digits[i]; - cy += yp.digits[i]; - cz += (LogOp::op(cx, cy) & (Tr::Base - 1)) + Tr::Half; - cx >>= shift; - cy >>= shift; - digits[i] = (cz & (Tr::Base - 1)) - Tr::Half; - cz >>= shift; - } - for (; i < size(); i++) { - cx += digits[i]; - cz += (LogOp::op(cx, cy) & (Tr::Base - 1)) + Tr::Half; - cx >>= shift; - cy >>= shift; - digits[i] = (cz & (Tr::Base - 1)) - Tr::Half; - cz >>= shift; - } - cz += LogOp::op(cx, cy); - if (cz) { - if (size() >= max_size()) { - return invalidate_bool(); - } - digits[inc_size()] = cz; - } else { - while (size() > 1 && !digits[size() - 1]) { - dec_size(); - } - } - return true; - } else { - if (!is_valid()) { - return false; - } - for (; i < size(); i++) { - cx += digits[i]; - cy += yp.digits[i]; - cz += (LogOp::op(cx, cy) & (Tr::Base - 1)) + Tr::Half; - cx >>= shift; - cy >>= shift; - digits[i] = (cz & (Tr::Base - 1)) - Tr::Half; - cz >>= shift; - } - set_size(std::min(yp.size(), max_size())); - for (; i < size(); i++) { - cy += yp.digits[i]; - cz += (LogOp::op(cx, cy) & (Tr::Base - 1)) + Tr::Half; - cx >>= shift; - cy >>= shift; - digits[i] = (cz & (Tr::Base - 1)) - Tr::Half; - cz >>= shift; - } - if (yp.size() > size()) { - for (; i < yp.size(); i++) { - cy += yp.digits[i]; - cz += (LogOp::op(cx, cy) & (Tr::Base - 1)); - cx >>= shift; - cy >>= shift; - if ((cz & (Tr::Base - 1)) != 0) { - return invalidate_bool(); - } - cz >>= shift; - } - } - cz += LogOp::op(cx, cy); - if (cz) { - return invalidate_bool(); - } - while (size() > 1 && !digits[size() - 1]) { - dec_size(); - } - return true; - } -} - -template -bool AnyIntView::add_mul_any(const AnyIntView& yp, const AnyIntView& zp) { - int yn = yp.size(), zn = zp.size(), rn = yn + zn; - if (!yp.is_valid() || !zp.is_valid() || !is_valid()) { - return invalidate_bool(); - } - if (rn > max_size() + 1) { - return invalidate_bool(); - } else if (rn < max_size() + 1) { - while (size() < rn) { - digits[inc_size()] = 0; - } - for (int i = 0; i < yn; i++) { - word_t yv = yp.digits[i]; - for (int j = 0; j < zn; j++) { - Tr::add_mul(&digits[i + j + 1], &digits[i + j], yv, zp.digits[j]); - } - } - } else { - while (size() < rn - 1) { - digits[inc_size()] = 0; - } - int i; - for (i = 0; i < yn - 1; i++) { - word_t yv = yp.digits[i]; - for (int j = 0; j < zn; j++) { - Tr::add_mul(&digits[i + j + 1], &digits[i + j], yv, zp.digits[j]); - } - } - word_t yv = yp.digits[i]; - int j; - for (j = 0; j < zn - 1; j++) { - Tr::add_mul(&digits[i + j + 1], &digits[i + j], yv, zp.digits[j]); - } - word_t hi = 0; - Tr::add_mul(&hi, &digits[i + j], yv, zp.digits[j]); - if (hi && hi != -1) { - return invalidate_bool(); - } - digits[size() - 1] += (hi << word_shift); - } - return true; -} - -template -void AnyIntView::add_mul_trunc_any(const AnyIntView& yp, const AnyIntView& zp) { - int yn = yp.size(), zn = zp.size(); - if (!yp.is_valid() || !zp.is_valid() || !is_valid()) { - invalidate(); - return; - } - int xn = std::min(yn + zn, max_size()); - while (size() < xn) { - digits[inc_size()] = 0; - } - xn = size(); - for (int i = 0; i < yn && i < xn; i++) { - word_t yv = yp.digits[i]; - for (int j = 0; j < zn; j++) { - if (i + j + 1 < xn) { - Tr::add_mul(&digits[i + j + 1], &digits[i + j], yv, zp.digits[j]); - } else { - word_t hi = 0; - Tr::add_mul(&hi, &digits[i + j], yv, zp.digits[j]); - break; - } - } - } -} - -template -int AnyIntView::sgn_un_any() const { - if (!is_valid()) { - return 0; - } - word_t v = digits[size() - 1]; - if (size() >= 2) { - if (v >= Tr::MaxDenorm) { - return 1; - } else if (v <= -Tr::MaxDenorm) { - return -1; - } - int i = size() - 2; - do { - v <<= word_shift; - word_t w = digits[i]; - if (w >= -v + Tr::MaxDenorm) { - return 1; - } else if (w <= -v - Tr::MaxDenorm) { - return -1; - } - v += w; - } while (--i >= 0); - } - return (v > 0 ? 1 : (v < 0 ? -1 : 0)); -} - -template -bool AnyIntView::get_bit_any(unsigned bit) const { - if (!is_valid()) { - return 0; - } - if (bit >= (unsigned)size() * word_shift) { - return sgn() < 0; - } - if (bit < word_shift) { - return (digits[0] >> bit) & 1; - } - auto q = std::div(bit, word_shift); - int i = q.quot; - word_t x = digits[i]; - while (--i >= 0) { - if (digits[i] < 0) { - --x; - break; - } else if (digits[i] > 0) { - break; - } - } - return (x >> q.rem) & 1; -} - -template -typename Tr::word_t AnyIntView::to_long_any() const { - if (!is_valid()) { - return (~0ULL << 63); - } else if (size() == 1) { - return digits[0]; - } else { - word_t v = digits[0] + (digits[1] << word_shift); // approximation mod 2^64 - word_t w = (v & (Tr::Base - 1)) - digits[0]; - w >>= word_shift; - w += (v >> word_shift); // excess of approximation divided by Tr::Base - int n = size() - 1; - for (int i = 1; i < n; i++) { - w -= digits[i]; - if (w & (Tr::Base - 1)) { - return (~0ULL << 63); - } - w >>= word_shift; - } - return w != digits[n] ? (~0ULL << 63) : v; - } -} - -template -int AnyIntView::cmp_any(const AnyIntView& yp) const { - if (yp.size() < size()) { - return top_word() < 0 ? -1 : 1; - } else if (yp.size() > size()) { - return yp.top_word() > 0 ? -1 : 1; - } - for (int i = size() - 1; i >= 0; i--) { - if (digits[i] < yp.digits[i]) { - return -1; - } else if (digits[i] > yp.digits[i]) { - return 1; - } - } - return 0; -} - -template -int AnyIntView::cmp_any(word_t y) const { - if (size() > 1) { - return top_word() < 0 ? -1 : 1; - } else if (size() == 1) { - return digits[0] < y ? -1 : (digits[0] > y ? 1 : 0); - } else { - return 0x80000000; - } -} - -template -template -int AnyIntView::cmp_un_any(const AnyIntView& yp) const { - int xn = size(), yn = yp.size(); - word_t v; - if (yn < xn) { - v = T::eval(digits[--xn]); - if (v >= Tr::MaxDenorm) { - return 1; - } else if (v <= -Tr::MaxDenorm) { - return -1; - } - while (xn > yn) { - v <<= word_shift; - word_t w = T::eval(digits[--xn]); - if (w >= -v + Tr::MaxDenorm) { - return 1; - } else if (w <= -v + Tr::MaxDenorm) { - return -1; - } - v += w; - } - } else if (yn > xn) { - v = -yp.digits[--yn]; - if (v >= Tr::MaxDenorm) { - return 1; - } else if (v <= -Tr::MaxDenorm) { - return -1; - } - while (yn > xn) { - v <<= word_shift; - word_t w = yp.digits[--yn]; - if (w <= v - Tr::MaxDenorm) { - return 1; - } else if (w >= v + Tr::MaxDenorm) { - return -1; - } - v -= w; - } - } else { - v = 0; - } - while (--xn >= 0) { - v <<= word_shift; - word_t w = T::eval(digits[xn]) - yp.digits[xn]; - if (w >= -v + Tr::MaxDenorm) { - return 1; - } else if (w <= -v - Tr::MaxDenorm) { - return -1; - } - v += w; - } - return (v > 0 ? 1 : (v < 0 ? -1 : 0)); -} - -template -bool AnyIntView::eq_any(const AnyIntView& yp) const { - if (yp.size() != size()) { - return false; - } - return !std::memcmp(digits.data(), yp.digits.data(), size() * sizeof(word_t)); -} - -template -bool AnyIntView::eq_any(word_t y) const { - return (size() == 1 && digits[0] == y); -} - -template -void AnyIntView::negate_any() { - for (int i = 0; i < size(); i++) { - digits[i] = -digits[i]; - } -} - -template -void AnyIntView::mul_tiny_any(int y) { - for (int i = 0; i < size(); i++) { - digits[i] *= y; - } -} - -template -int AnyIntView::divmod_tiny_any(int y) { - if (!y) { - invalidate(); - return 0; - } - int rem = 0; - for (int i = size() - 1; i >= 0; i--) { - auto divmod = std::div(digits[i] + ((word_t)rem << word_shift), (word_t)y); - digits[i] = divmod.quot; - rem = (int)divmod.rem; - if ((rem ^ y) < 0 && rem) { - rem += y; - digits[i]--; - } - } - while (size() > 1 && !digits[size() - 1]) { - dec_size(); - } - return rem; -} - -template -typename Tr::word_t AnyIntView::divmod_short_any(word_t y) { - if (!y || !is_valid()) { - invalidate(); - throw IntOverflow{}; - } - word_t rem = 0; - int i = size() - 1; - if (!i) { - auto divmod = std::div(digits[0], y); - digits[0] = divmod.quot; - rem = divmod.rem; - if ((rem ^ y) < 0 && rem) { - rem += y; - digits[0]--; - } - return rem; - } - if (std::abs(digits[i]) * 2 < std::abs(y)) { - rem = digits[i--]; - dec_size(); - } - do { - Tr::dbl_divmod(&digits[i], &rem, rem, digits[i], y); - } while (--i >= 0); - if ((rem ^ y) < 0 && rem) { - rem += y; - digits[0]--; - } - while (size() > 1 && !digits[size() - 1]) { - dec_size(); - } - return rem; -} - -template -bool AnyIntView::mul_add_short_any(word_t y, word_t z) { - if (!is_valid()) { - return false; - } - for (int i = 0; i < size(); i++) { - word_t newc; - Tr::set_mul(&newc, digits.data() + i, y, digits[i]); - digits[i] += z; - z = newc; - } - if (!z) { - return true; - } - if (size() < max_size()) { - digits[inc_size()] = z; - return true; - } - z += (digits[size() - 1] >> word_shift); - digits[size() - 1] &= Tr::Base - 1; - if (!z || z == -1) { - digits[size() - 1] += (z << word_shift); - return true; - } else { - return false; - } -} - -template -bool AnyIntView::mod_div_any(const AnyIntView& yp, AnyIntView& quot, int round_mode) { - quot.invalidate(); - if (!is_valid()) { - return false; - } - if (yp.size() == 1) { - word_t yv = yp.digits[0]; - if (!yv) { - return false; - } - word_t rem = divmod_short_any(yv); - if (!round_mode) { - if ((yv > 0 && rem * 2 >= yv) || (yv < 0 && rem * 2 <= yv)) { - rem -= yv; - digits[0]++; - } - } else if (round_mode > 0 && rem) { - rem -= yv; - digits[0]++; - } - if (!normalize_bool_any()) { - return false; - } - if (size() > quot.max_size()) { - return false; - } - quot.set_size(size()); - std::memcpy(quot.digits.data(), digits.data(), size() * sizeof(word_t)); - *this = rem; - return true; - } - if (!yp.is_valid()) { - return invalidate_bool(); - } - - double y_top = yp.top_double(); - if (y_top == 0) { - // division by zero - return invalidate_bool(); - } - double y_inv = (double)Tr::Base / y_top; - - int k = size() - yp.size(); - if (k >= 0) { - if (std::abs(top_word()) * 2 <= std::abs(yp.top_word())) { - if (k > quot.max_size()) { - return invalidate_bool(); - } - quot.set_size(k); - } else { - if (k >= quot.max_size()) { - return invalidate_bool(); - } - quot.set_size(k + 1); - double x_top = top_double(); - word_t q = std::llrint(x_top * y_inv * Tr::InvBase); - quot.digits[k] = q; - int i = yp.size() - 1; - word_t hi = 0; - Tr::sub_mul(&hi, &digits[k + i], q, yp.digits[i]); - while (--i >= 0) { - Tr::sub_mul(&digits[k + i + 1], &digits[k + i], q, yp.digits[i]); - } - digits[size() - 1] += (hi << word_shift); - } - } else { - quot.set_size(1); - quot.digits[0] = 0; - } - while (--k >= 0) { - double x_top = top_double(); - word_t q = std::llrint(x_top * y_inv); - quot.digits[k] = q; - for (int i = yp.size() - 1; i >= 0; --i) { - Tr::sub_mul(&digits[k + i + 1], &digits[k + i], q, yp.digits[i]); - } - dec_size(); - digits[size() - 1] += (digits[size()] << word_shift); - } - if (size() >= yp.size()) { - assert(size() == yp.size()); - double x_top = top_double(); - double t = x_top * y_inv * Tr::InvBase; - if (round_mode >= 0) { - t += (round_mode ? 1 : 0.5); - } - word_t q = std::llrint(std::floor(t)); - if (q) { - for (int i = 0; i < size(); i++) { - digits[i] -= q * yp.digits[i]; - } - quot.digits[0] += q; - } - } - - int q_adj = 0, sy = (y_inv > 0 ? 1 : -1); - if (round_mode < 0) { - // floor: must have 0 <= rem < y or 0 >= rem > y - int sr = sgn_un_any(); - if (sr * sy < 0) { - q_adj = -1; - } else { - sr = cmp_un_any>(yp); - if (sr * sy >= 0) { - q_adj = 1; - } - } - } else if (round_mode > 0) { - // ceil: must have -y < rem <= 0 or -y > rem >= 0 - int sr = sgn_un_any(); - if (sr * sy > 0) { - q_adj = 1; - } else { - sr = cmp_un_any>(yp); // -rem ?? y - if (sr * sy >= 0) { - q_adj = -1; - } - } - } else { - // round: must have -y <= 2*rem < y or -y >= 2*rem > y - int sr = sgn_un_any(); - if (sr * sy > 0) { - // y and rem same sign, check 2*rem < y or 2*rem > y - sr = cmp_un_any>(yp); - if (sr * sy >= 0) { - q_adj = 1; - } - } else { - // y and rem different sign, check 2*rem >= -y or 2*rem <= -y - sr = cmp_un_any>(yp); - if (sr * sy > 0) { - q_adj = -1; - } - } - } - if (q_adj) { - quot.digits[0] += q_adj; - if (q_adj < 0 ? !add_any(yp) : !sub_any(yp)) { - return invalidate_bool(); - } - } - return normalize_bool_any(); -} - -template -bool AnyIntView::mod_pow2_any(int exponent) { - if (!is_valid()) { - return false; - } - if (exponent <= 0) { - *this = 0; - return true; - } - int q = exponent - (size() - 1) * word_shift; - if (q >= word_bits) { - if (sgn() >= 0) { - return true; - } - if (exponent >= max_size() * word_shift) { - return invalidate_bool(); - } - while (q >= word_shift) { - digits[inc_size()] = 0; - q -= word_shift; - } - if (q == word_shift - 1 && size() < max_size()) { - digits[size() - 1] = -Tr::Half; - digits[inc_size()] = 1; - } else { - digits[size() - 1] = ((word_t)1 << q); - } - return true; - } - while (q < 0) { - dec_size(); - q += word_shift; - } - word_t pow = ((word_t)1 << q); - word_t v = digits[size() - 1] & (pow - 1); - if (!v) { - int k = size() - 1; - while (k > 0 && !digits[k - 1]) { - --k; - } - if (!k) { - *this = 0; - return true; - } - if (digits[k - 1] > 0) { - set_size(k); - return true; - } - if (exponent >= max_size() * word_shift) { - return invalidate_bool(); - } - if (q - word_shift >= 0) { - digits[size() - 1] = 0; - digits[inc_size()] = ((word_t)1 << (q - word_shift)); - } - if (q - word_shift == -1 && size() < max_size() - 1) { - digits[size() - 1] = -Tr::Half; - digits[inc_size()] = 1; - } else { - digits[size() - 1] = pow; - } - return true; - } else if (v >= Tr::Half) { - if (size() == max_size() - 1) { - return invalidate_bool(); - } else { - digits[size() - 1] = v | -Tr::Half; - digits[inc_size()] = ((word_t)1 << (q - word_shift)); - return true; - } - } else { - digits[size() - 1] = v; - return true; - } -} - -template -bool AnyIntView::mod_pow2_any(int exponent, int round_mode) { - if (round_mode < 0) { - return mod_pow2_any(exponent); - } - if (!is_valid()) { - return false; - } - if (exponent <= 0) { - *this = 0; - return true; - } - if (round_mode > 0) { - negate_any(); - bool res = mod_pow2_any(exponent); - negate_any(); - return res; - } - if (signed_fits_bits_any(exponent)) { - return true; - } - if (!mod_pow2_any(exponent)) { - return false; - } - if (!unsigned_fits_bits_any(exponent - 1)) { - return add_pow2_any(exponent, -1); - } - return true; -} - -template -bool AnyIntView::rshift_any(int exponent, int round_mode) { - if (exponent < 0) { - return invalidate_bool(); - } - if (!exponent) { - return true; - } - if (exponent > size() * word_shift + word_bits - word_shift) { - if (!round_mode) { - *this = 0; - } else if (round_mode < 0) { - *this = (sgn() < 0 ? -1 : 0); - } else { - *this = (sgn() > 0 ? 1 : 0); - } - return true; - } - int q = exponent / word_shift, r = exponent % word_shift; - assert(q <= size()); - - if (!round_mode && !r) { - digits[q - 1] += Tr::Half; - round_mode = -1; - } - - word_t v = (round_mode > 0 ? -1 : 0); - for (int i = 0; i < q; i++) { - v += digits[i]; - v >>= word_shift; - } - - set_size(size() - q); - if (!size()) { - if (!round_mode) { - *this = (((v >> (r - 1)) + 1) >> 1); - } else { - *this = (v >> r) + (round_mode > 0); - } - return true; - } - - if (!r) { - std::memmove(digits.data(), digits.data() + q, size() * sizeof(word_t)); - digits[0] += v + (round_mode > 0); - return true; - } - - v += digits[q]; - if (!round_mode) { - v = (((v >> (r - 1)) + 1) >> 1); - } else { - v >>= r; - v += (round_mode > 0); - } - - word_t mask = ((word_t)1 << r) - 1; - for (int i = 1; i < size(); i++) { - word_t w = digits[q + i]; - v += ((w & mask) << (word_shift - r)); - digits[i - 1] = v; - v = (w >> r); - } - digits[size() - 1] = v; - return true; -} - -template -bool AnyIntView::lshift_any(int exponent) { - if (exponent < 0) { - return invalidate_bool(); - } - if (!exponent) { - return true; - } - int q = exponent / word_shift, r = exponent % word_shift; - if (size() + q > max_size()) { - return invalidate_bool(); - } - if (!r) { - std::memmove(digits.data() + q, digits.data(), size() * sizeof(word_t)); - std::memset(digits.data(), 0, q * sizeof(word_t)); - set_size(size() + q); - return true; - } - - word_t v = 0, mask = (Tr::Base >> r) - 1; - for (int i = 0; i < size(); i++) { - word_t w = digits[i]; - v += ((w & mask) << r); - digits[i] = v; - v = (w >> (word_shift - r)); - } - if (v) { - if (size() + q < max_size()) { - digits[inc_size()] = v; - } else if (v != -1) { - return invalidate_bool(); - } else { - digits[size() - 1] += (v << word_shift); - } - } - if (q) { - std::memmove(digits.data() + q, digits.data(), size() * sizeof(word_t)); - std::memset(digits.data(), 0, q * sizeof(word_t)); - set_size(size() + q); - } - return true; -} - -template -bool AnyIntView::unsigned_fits_bits_any(int nbits) const { - if (!is_valid()) { - return false; - } - if (sgn() < 0) { - return false; - } - if (!sgn()) { - return true; - } - if (nbits >= size() * word_shift) { - return true; - } - if (nbits < 0) { - return false; - } - auto dm = std::div(nbits, word_shift); - int k = dm.quot; - if (size() >= k + 2) { - if (!(size() == k + 2 && dm.rem == word_shift - 1)) { - return false; - } - if (digits[k + 1] != 1) { - return false; - } - if (digits[k] > -Tr::Half) { - return false; - } else if (digits[k] < -Tr::Half) { - return true; - } - } else { - if (size() <= k) { - return true; - } - word_t pow = ((word_t)1 << dm.rem); - if (digits[k] > pow) { - return false; - } else if (digits[k] < pow) { - return true; - } - } - while (--k >= 0) { - if (digits[k] < 0) { - return true; - } else if (digits[k] > 0) { - return false; - } - } - return false; -} - -template -bool AnyIntView::signed_fits_bits_any(int nbits) const { - if (!is_valid()) { - return false; - } - if (nbits > size() * word_shift) { - return true; - } - int s = sgn(); - if (!s) { - return true; - } - if (nbits <= 0) { - return false; - } - auto dm = std::div(nbits - 1, word_shift); - int k = dm.quot; - if (size() <= k) { - return true; - } - if (size() >= k + 2) { - if (!(size() == k + 2 && dm.rem == word_shift - 1)) { - return false; - } - if (digits[k + 1] != s) { - return false; - } - word_t val = (s > 0 ? digits[k] : -digits[k]); - if (val > -Tr::Half) { - return false; - } else if (val < -Tr::Half) { - return true; - } - } else { - word_t val = (s > 0 ? digits[k] : -digits[k]); - word_t pow = ((word_t)1 << dm.rem); - if (val > pow) { - return false; - } else if (val < pow) { - return true; - } - } - while (--k >= 0) { - if (digits[k] < 0) { - return s > 0; - } else if (digits[k] > 0) { - return s < 0; - } - } - return s < 0; -} - -template -int AnyIntView::bit_size_any(bool sgnd) const { - if (!is_valid()) { - return 0x7fffffff; - } - int sg = sgn(); - if (!sg) { - return 0; - } else if (sg >= 0) { - int k = size() - 1; - word_t q = digits[k]; - if (k > 0 && q < Tr::MaxDenorm / 2) { - q <<= word_shift; - q += digits[--k]; - } - if (!k) { - int s = 64 - td::count_leading_zeroes64(q); - return s + sgnd; - } - int s = 64 - td::count_leading_zeroes64(q - Tr::MaxDenorm / 4); - q -= (word_t)1 << s; - s += k * word_shift + sgnd; - while (k > 0) { - if (q >= Tr::MaxDenorm / 2) { - return s + 1; - } else if (q <= -Tr::MaxDenorm / 2) { - return s; - } - q <<= word_shift; - q += digits[--k]; - } - return q >= 0 ? s + 1 : s; - } else if (sgnd) { - int k = size() - 1; - word_t q = digits[k]; - if (k > 0 && q > -Tr::MaxDenorm / 2) { - q <<= word_shift; - q += digits[--k]; - } - if (!k) { - int s = 64 - td::count_leading_zeroes64(~q); - return s + 1; - } - int s = 64 - td::count_leading_zeroes64(-q - Tr::MaxDenorm / 4); - q += (word_t)1 << s; - s += k * word_shift + 1; - while (k > 0) { - if (q >= Tr::MaxDenorm / 2) { - return s; - } else if (q <= -Tr::MaxDenorm / 2) { - return s + 1; - } - q <<= word_shift; - q += digits[--k]; - } - return q >= 0 ? s : s + 1; - } else { - return 0x7fffffff; - } -} - -template -bool AnyIntView::export_bytes_any(unsigned char* buff, std::size_t buff_size, bool sgnd) const { - if (!is_valid()) { - return false; - } - if (!buff_size) { - return sgn_un_any() == 0; - } - int k = 0; - word_t v = 0; - unsigned char* ptr = buff + buff_size; - unsigned char s = (sgn_un_any() < 0 ? 0xff : 0); - if (s && !sgnd) { - return false; - } - for (int i = 0; i < size(); i++) { - if ((word_shift & 7) && word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) { - int k1 = 8 - k; - v += (digits[i] << k) & 0xff; - if (ptr > buff) { - *--ptr = (unsigned char)(v & 0xff); - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - v += (digits[i] >> k1); - k += word_shift - 8; - } else { - v += (digits[i] << k); - k += word_shift; - } - while (k >= 8) { - if (ptr > buff) { - *--ptr = (unsigned char)(v & 0xff); - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - k -= 8; - } - } - while (ptr > buff) { - *--ptr = (unsigned char)(v & 0xff); - v >>= 8; - } - if (v != -(s & 1)) { - return false; - } - return !sgnd ? true : !((*ptr ^ s) & 0x80); -} - -template -bool AnyIntView::export_bytes_lsb_any(unsigned char* buff, std::size_t buff_size, bool sgnd) const { - if (!is_valid()) { - return false; - } - if (!buff_size) { - return sgn_un_any() == 0; - } - int k = 0; - word_t v = 0; - unsigned char* end = buff + buff_size; - unsigned char s = (sgn_un_any() < 0 ? 0xff : 0); - if (s && !sgnd) { - return false; - } - for (int i = 0; i < size(); i++) { - if ((word_shift & 7) && word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) { - int k1 = 8 - k; - v += (digits[i] << k) & 0xff; - if (buff < end) { - *buff++ = (unsigned char)(v & 0xff); - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - v += (digits[i] >> k1); - k += word_shift - 8; - } else { - v += (digits[i] << k); - k += word_shift; - } - while (k >= 8) { - if (buff < end) { - *buff++ = (unsigned char)(v & 0xff); - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - k -= 8; - } - } - while (buff < end) { - *buff++ = (unsigned char)(v & 0xff); - v >>= 8; - } - if (v != -(s & 1)) { - return false; - } - return !sgnd ? true : !((buff[-1] ^ s) & 0x80); -} - -template -bool AnyIntView::export_bits_any(unsigned char* buff, int offs, unsigned bits, bool sgnd) const { - if (!is_valid()) { - return false; - } - if (!bits) { - return sgn_un_any() == 0; - } - if (size() == 1 || bits < 64) { - word_t v = to_long_any(); - if (bits < 64) { - if (!sgnd) { - if (v < 0 || (unsigned long long)v >= (1ULL << bits)) { - return false; - } - } else { - word_t pw = (1LL << (bits - 1)); - if (v < -pw || v >= pw) { - return false; - } - } - td::bitstring::bits_store_long_top(buff, offs, v << (64 - bits), bits); - } else { - if (!sgnd && v < 0) { - return false; - } - td::bitstring::bits_memset(buff, offs, v < 0, bits - 64); - td::bitstring::bits_store_long_top(buff, offs + bits - 64, v, 64); - } - return true; - } - buff += (offs >> 3); - offs &= 7; - unsigned char s = (sgn_un_any() < 0 ? 0xff : 0); - if (s && !sgnd) { - return false; - } - unsigned end_offs = offs + bits; - unsigned char* ptr = buff + (end_offs >> 3); - int k = td::bits_negate32(end_offs) & 7; - word_t v = k ? (*ptr++ & ((1 << k) - 1)) : 0; - for (int i = 0; i < size(); i++) { - if (word_shift + 8 >= word_bits && k >= word_bits - word_shift - 1) { - int k1 = 8 - k; - v += (digits[i] << k) & 0xff; - if (ptr > buff) { - if (--ptr > buff) { - *ptr = (unsigned char)(v & 0xff); - } else { - int mask = (0xff00 >> offs) & 0xff; - if (((unsigned char)v ^ s) & mask) { - return false; - } - *ptr = (unsigned char)((*ptr & mask) | ((int)v & ~mask)); - } - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - v += (digits[i] >> k1); - k += word_shift - 8; - } else { - v += (digits[i] << k); - k += word_shift; - } - while (k >= 8) { - if (ptr > buff) { - if (--ptr > buff) { - *ptr = (unsigned char)(v & 0xff); - } else { - int mask = (0xff00 >> offs) & 0xff; - if (((unsigned char)v ^ s) & mask) { - return false; - } - *ptr = (unsigned char)((*ptr & mask) | ((int)v & ~mask)); - } - } else if ((unsigned char)(v & 0xff) != s) { - return false; - } - v >>= 8; - k -= 8; - } - } - if (ptr > buff) { - while (--ptr > buff) { - *ptr = (unsigned char)(v & 0xff); - v >>= 8; - } - int mask = (0xff00 >> offs) & 0xff; - if (((unsigned char)v ^ s) & mask) { - return false; - } - *ptr = (unsigned char)((*ptr & mask) | ((int)v & ~mask)); - v >>= 8; - } - if (v != -(s & 1)) { - return false; - } - return !sgnd ? true : !((*ptr ^ s) & (0x80 >> offs)); -} - -template -bool AnyIntView::import_bytes_any(const unsigned char* buff, std::size_t buff_size, bool sgnd) { - if (!buff_size) { - *this = 0; - return true; - } - unsigned char s = (sgnd && (buff[0] & 0x80)) ? 0xff : 0; - const unsigned char* ptr = buff + buff_size; - while (buff < ptr && *buff == s) { - buff++; - } - int k = 0; - word_t v = 0; - set_size(1); - assert(word_bits - word_shift >= 8); - while (ptr > buff) { - if (k >= word_shift) { - if (size() < max_size()) { - digits[size() - 1] = v; - inc_size(); - v = 0; - k -= word_shift; - } else if (k >= word_bits - 8) { - return invalidate_bool(); - } - } - v |= (((word_t) * --ptr) << k); - k += 8; - } - if (s) { - v -= ((word_t)1 << k); - } - digits[size() - 1] = v; - return normalize_bool_any(); -} - -template -bool AnyIntView::import_bits_any(const unsigned char* buff, int offs, unsigned bits, bool sgnd) { - if (bits < word_shift) { - set_size(1); - unsigned long long val = td::bitstring::bits_load_long_top(buff, offs, bits); - if (sgnd) { - digits[0] = ((long long)val >> (64 - bits)); - } else { - digits[0] = (val >> (64 - bits)); - } - return true; - } - buff += (offs >> 3); - offs &= 7; - unsigned char s = (sgnd && (buff[0] & (0x80 >> offs))) ? 0xff : 0; - unsigned end_offs = (unsigned)offs + bits; - const unsigned char* ptr = buff + (end_offs >> 3); - if (buff < ptr && !((*buff ^ s) & (0xff >> offs))) { - buff++; - offs = 0; - while (buff < ptr && *buff == s) { - buff++; - } - } - int k = end_offs & 7; - word_t v = k ? (*ptr >> (8 - k)) : 0; - set_size(1); - assert(word_bits - word_shift >= 8); - while (ptr > buff) { - if (k >= word_shift) { - if (size() < max_size()) { - digits[size() - 1] = v; - inc_size(); - v = 0; - k -= word_shift; - } else if (k >= word_bits - 8) { - return invalidate_bool(); - } - } - v |= (((word_t) * --ptr) << k); - k += 8; - } - k -= offs; - word_t pw = ((word_t)1 << k); - v &= pw - 1; - if (s) { - v -= pw; - } - digits[size() - 1] = v; - return normalize_bool_any(); -} - -template -bool AnyIntView::import_bytes_lsb_any(const unsigned char* buff, std::size_t buff_size, bool sgnd) { - if (!buff_size) { - *this = 0; - return true; - } - const unsigned char* end = buff + buff_size; - unsigned char s = (sgnd && (end[-1] & 0x80)) ? 0xff : 0; - while (end > buff && end[-1] == s) { - --end; - } - int k = 0; - word_t v = 0; - set_size(1); - assert(word_bits - word_shift >= 8); - while (buff < end) { - if (k >= word_shift) { - if (size() < max_size()) { - digits[size() - 1] = v; - inc_size(); - v = 0; - k -= word_shift; - } else if (k >= word_bits - 8) { - return invalidate_bool(); - } - } - v |= (((word_t)*buff++) << k); - k += 8; - } - if (s) { - v -= ((word_t)1 << k); - } - digits[size() - 1] = v; - return normalize_bool_any(); -} - -template -int AnyIntView::parse_hex_any(const char* str, int str_len, int* frac) { - invalidate(); - bool sgn = (str[0] == '-'); - int i = sgn, j; - int p = (frac ? -1 : 0); - while (i < str_len && str[i] == '0') { - i++; - } - for (j = i; j < str_len; j++) { - int c = str[j]; - if (c == '.' && p < 0) { - p = j + 1; - continue; - } - if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) { - break; - } - } - if (j == sgn + (p > 0)) { - return 0; - } - if ((j - i - (p > 0)) * 4 > (max_size() - 1) * word_shift + word_bits - 2) { - return 0; - } - int j_len = j, k = 0; - word_t v = 0; - set_size(0); - while (j > i) { - if (j == p) { - --j; - continue; - } - if (k >= word_shift && size() < max_size() - 1) { - digits[inc_size()] = (sgn ? -v : v); - v = 0; - k -= word_shift; - } - int c = str[--j]; - if (c <= '9') { - c -= '0'; - } else { - c = (c | 0x20) - ('a' - 10); - } - v += ((word_t)c << k); - k += 4; - enforce(k < word_bits - 1); - } - digits[inc_size()] = (sgn ? -v : v); - if (!normalize_bool_any()) { - invalidate(); - return 0; - } - if (p) { - *frac = (p > 0 ? j_len - p : -1); - } - return j_len; -} - -template -int AnyIntView::parse_binary_any(const char* str, int str_len, int* frac) { - invalidate(); - bool sgn = (str[0] == '-'); - int i = sgn, j, p = (frac ? -1 : 0); - while (i < str_len && str[i] == '0') { - i++; - } - for (j = i; j < str_len; j++) { - int c = str[j]; - if (c != '0' && c != '1') { - if (c == '.' && p < 0) { - p = j + 1; - continue; - } - break; - } - } - if (j == sgn + (p > 0)) { - return 0; - } - if (j - i - (p > 0) > (max_size() - 1) * word_shift + word_bits - 2) { - return 0; - } - int j_len = j, k = 0; - word_t v = 0; - set_size(0); - while (j > i) { - if (j == p) { - --j; - continue; - } - if (k >= word_shift && size() < max_size() - 1) { - digits[inc_size()] = (sgn ? -v : v); - v = 0; - k -= word_shift; - } - v += ((word_t)(str[--j] & 1) << k); - k++; - enforce(k < word_bits - 1); - } - digits[inc_size()] = (sgn ? -v : v); - if (!normalize_bool_any()) { - invalidate(); - return 0; - } - if (p) { - *frac = (p > 0 ? j_len - p : -1); - } - return j_len; -} - -template -std::string AnyIntView::to_dec_string_slow_destroy_any() { - if (!is_valid()) { - return "NaN"; - } - std::string x; - x.reserve((size() * word_shift + word_bits) * 97879 / 325147 + 2); - int s = sgn(); - if (s < 0) { - negate_any(); - } - do { - x += (char)('0' + divmod_short_any(10)); - } while (sgn()); - if (s < 0) { - x += '-'; - } - std::reverse(x.begin(), x.end()); - return x; -} - -template -std::string AnyIntView::to_dec_string_destroy_any() { - if (!is_valid()) { - return "NaN"; - } - std::string s; - std::vector stack; - int l10 = (size() * word_shift + word_bits) * 97879 / 325147; - s.reserve(l10 + 2); - stack.reserve(l10 / Tr::max_pow10_exp + 1); - if (sgn() < 0) { - negate_any(); - s += '-'; - } - do { - stack.push_back(divmod_short_any(Tr::max_pow10)); - } while (sgn()); - char slice[word_bits * 97879 / 325147 + 2]; - std::sprintf(slice, "%lld", stack.back()); - s += slice; - stack.pop_back(); - while (stack.size()) { - std::sprintf(slice, "%018lld", stack.back()); - s += slice; - stack.pop_back(); - } - return s; -} - -static const char hex_digits[] = "0123456789abcdef"; -static const char HEX_digits[] = "0123456789ABCDEF"; - -template -std::string AnyIntView::to_hex_string_slow_destroy_any() { - if (!is_valid()) { - return "NaN"; - } - std::string x; - x.reserve(((size() * word_shift + word_bits) >> 2) + 2); - int s = sgn(); - if (s < 0) { - negate_any(); - } - do { - x += hex_digits[divmod_short_any(16)]; - } while (sgn()); - if (s < 0) { - x += '-'; - } - std::reverse(x.begin(), x.end()); - return x; -} - -template -std::string AnyIntView::to_hex_string_any(bool upcase, int zero_pad) const { - if (!is_valid()) { - return "NaN"; - } - int s = sgn(), k = 0; - if (!s) { - if (zero_pad > 0) { - return std::string(zero_pad, '0'); - } - return "0"; - } - std::string x; - x.reserve(2 + std::max((size() * word_shift + word_bits) >> 2, zero_pad)); - assert(word_shift < word_bits - 4); - const char* hex_digs = (upcase ? HEX_digits : hex_digits); - word_t v = 0; - for (int i = 0; i < size(); i++) { - v += ((s >= 0 ? digits[i] : -digits[i]) << k); - k += word_shift; - while (k >= 4 && (v || i < size() - 1)) { - x += hex_digs[v & 15]; - v >>= 4; - k -= 4; - } - } - assert(v >= 0); - while (v > 0) { - x += hex_digs[v & 15]; - v >>= 4; - } - if (zero_pad > 0) { - while (x.size() < (unsigned)zero_pad) { - x += '0'; - } - } - if (s < 0) { - x += '-'; - } - std::reverse(x.begin(), x.end()); - return x; -} - -template -std::string AnyIntView::to_binary_string_any() const { - if (!is_valid()) { - return "NaN"; - } - int s = sgn(); - if (!s) { - return "0"; - } - std::string x; - x.reserve(size() * word_shift + word_bits + 2); - assert(word_shift < word_bits - 1); - word_t v = 0; - for (int i = 0; i < size(); i++) { - v += (s >= 0 ? digits[i] : -digits[i]); - int k = word_shift; - while (--k >= 0 && (v || i < size() - 1)) { - x += (v & 1 ? '1' : '0'); - v >>= 1; - } - } - assert(v >= 0); - while (v > 0) { - x += (v & 1 ? '1' : '0'); - v >>= 1; - } - if (s < 0) { - x += '-'; - } - std::reverse(x.begin(), x.end()); - return x; -} - -template -BigIntG& BigIntG::denormalize() { - word_t val = 0; - for (int i = 0; i < n; i++) { - val += digits[i]; - digits[i] = (val & (Tr::Base - 1)); - val >>= word_shift; - } - while (n < word_cnt) { - digits[n++] = (val & (Tr::Base - 1)); - val >>= word_shift; - } - return *this; -} - -template -BigIntG& BigIntG::logical_not() { - digits[0] = ~digits[0]; - for (int i = 1; i < n; i++) { - digits[i] = -digits[i]; - } - return *this; -} - -template -std::ostream& BigIntG::dump(std::ostream& os, bool nl) const { - os << "{"; - //auto f = os.flags(); - //os.flags(std::ios::hex | std::ios::showbase); - //os.width(16); - for (int i = n - 1; i >= 0; i--) { - os << digits[i] << (i ? ' ' : '}'); - } - if (!n) { - os << "nan}"; - } - if (nl) { - os << std::endl; - } - //os.flags(f); - return os; -} - -template -std::string BigIntG::dump() const { - std::ostringstream os; - dump(os); - return os.str(); -} - -template -int BigIntG::parse_dec_slow(const char* str, int str_len) { - *this = 0; - int i; - bool sgn = (str[0] == '-'); - if (str_len <= static_cast(sgn)) { - return 0; - } - for (i = sgn; i < str_len; i++) { - if (str[i] < '0' || str[i] > '9') { - return i; - } - mul_tiny(10); - add_tiny(sgn ? '0' - str[i] : str[i] - '0'); - if (!normalize_bool()) { - *this = 0; - return 0; - } - } - return i; -} - -template -int BigIntG::parse_dec(const char* str, int str_len, int* frac) { - *this = 0; - int i; - int p = frac ? -1 : 0; - bool sgn = (str[0] == '-'), ok = false; - word_t q = 1, a = 0; - for (i = sgn; i < str_len; i++) { - if (str[i] == '.') { - if (p >= 0) { - break; - } - p = i + 1; - continue; - } - int digit = (int)str[i] - '0'; - if ((unsigned)digit >= 10) { - break; - } - ok = true; - if (q >= Tr::Half / 10) { - if (!mul_add_short_bool(q, a)) { - return 0; - } - q = 1; - a = 0; - } - q *= 10; - a *= 10; - a += (sgn ? -digit : digit); - } - if (!ok || !mul_add_short_bool(q, a) || !normalize_bool()) { - return 0; - } - if (frac) { - *frac = (p > 0 ? i - p : -1); - } - return i; -} - -template -std::string BigIntG::to_dec_string_slow() const { - BigIntG copy(*this); - copy.normalize_bool(); - return copy.as_any_int().to_dec_string_slow_destroy_any(); -} - -template -std::string BigIntG::to_dec_string() const { - BigIntG copy(*this); - copy.normalize_bool(); - //std::cout << "(tds " << (const void*)this << "->" << (void*)© << ")"; - return copy.as_any_int().to_dec_string_destroy_any(); -} - -template -std::string BigIntG::to_dec_string_destroy() { - normalize_bool(); - return as_any_int().to_dec_string_destroy_any(); -} - -template -std::string BigIntG::to_hex_string_slow() const { - BigIntG copy(*this); - copy.normalize_bool(); - return copy.as_any_int().to_hex_string_slow_destroy_any(); -} - -template -std::string BigIntG::to_hex_string(bool upcase, int zero_pad) const { - return as_any_int().to_hex_string_any(upcase, zero_pad); -} - -template -std::string BigIntG::to_binary_string() const { - return as_any_int().to_binary_string_any(); -} - -template -std::ostream& operator<<(std::ostream& os, const BigIntG& x) { - return os << x.to_dec_string(); -} - -template -std::ostream& operator<<(std::ostream& os, BigIntG&& x) { - return os << x.to_dec_string_destroy(); -} - -extern template class AnyIntView; -extern template class BigIntG<257, BigIntInfo>; -typedef BigIntG<257, BigIntInfo> BigInt256; - -template -BigIntG make_bigint(long long x) { - return BigIntG{Normalize(), x}; -} - -namespace literals { - -extern BigInt256 operator""_i256(const char* str, std::size_t str_len); -extern BigInt256 operator""_x256(const char* str, std::size_t str_len); - -} // namespace literals - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bitstring.cpp b/submodules/ton/tonlib-src/crypto/common/bitstring.cpp deleted file mode 100644 index 0a273949..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bitstring.cpp +++ /dev/null @@ -1,668 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "common/bitstring.h" -#include -#include -#include "td/utils/as.h" -#include "td/utils/bits.h" -#include "td/utils/misc.h" -#include "crypto/openssl/digest.hpp" - -namespace td { - -template class Ref; - -BitString::BitString(const BitSlice& bs, unsigned reserve_bits) { - if (!bs.size() && !reserve_bits) { - ptr = 0; - offs = len = bytes_alloc = 0; - } else { - offs = bs.get_offs(); - len = bs.size(); - bytes_alloc = (bs.get_offs() + bs.size() + reserve_bits + 7) >> 3; - ptr = static_cast(std::malloc(bytes_alloc)); - CHECK(ptr); - if (bs.size()) { - std::memcpy(ptr, bs.get_ptr(), bs.byte_size()); - } - } -} - -BitString::BitString(unsigned reserve_bits) { - if (!reserve_bits) { - ptr = 0; - offs = len = bytes_alloc = 0; - } else { - bytes_alloc = (reserve_bits + 7) >> 3; - ptr = static_cast(std::malloc(bytes_alloc)); - CHECK(ptr); - offs = len = 0; - } -} - -BitString::operator BitSlice() const { - return BitSlice(BitStringRef{this}, ptr, offs, len); -} - -BitString* BitString::make_copy() const { - if (!ptr) { - return new BitString(64); // reserve 64 bits - } else { - return new BitString(operator BitSlice(), 64); - } -} - -BitString& BitString::reserve_bits(unsigned req_bits) { - req_bits += offs + len; - if (req_bits > bytes_alloc * 8) { - bytes_alloc = (req_bits + 7) >> 3; - ptr = (unsigned char*)std::realloc(ptr, bytes_alloc); - CHECK(ptr); - } - return *this; -} - -BitSliceWrite BitString::reserve_bitslice(unsigned req_bits) { - reserve_bits(req_bits); - unsigned pos = offs + len; - len += req_bits; - return BitSliceWrite(Ref(this), ptr, pos, req_bits); -} - -BitString& BitString::append(const BitSlice& bs) { - reserve_bitslice(bs.size()) = bs; - return *this; -} - -BitSlice BitString::subslice(unsigned from, unsigned bits) const { - return BitSlice{BitStringRef{this}, ptr, static_cast(offs + from), bits}; -} - -BitSliceWrite BitString::subslice_write(unsigned from, unsigned bits) { - return BitSliceWrite{BitStringRef{this}, ptr, offs + from, bits}; -} - -const BitSliceWrite& BitSliceWrite::operator=(const BitSlice& bs) const { - if (size() != bs.size()) { - throw LengthMismatch(); - } - bitstring::bits_memcpy(get_ptr(), get_offs(), bs.get_ptr(), bs.get_offs(), size()); - return *this; -} - -const BitSliceWrite& BitSliceWrite::operator=(bool val) const { - bitstring::bits_memset(get_ptr(), get_offs(), val, size()); - return *this; -} - -std::ostream& operator<<(std::ostream& os, const BitString& bs) { - return os << bs.to_hex(); -} - -std::ostream& operator<<(std::ostream& os, Ref bs_ref) { - return os << (bs_ref.is_null() ? "(null-bs)" : bs_ref->to_hex()); -} - -namespace bitstring { - -void bits_memcpy(unsigned char* to, int to_offs, const unsigned char* from, int from_offs, std::size_t bit_count) { - if (bit_count <= 0) { - return; - } - from += (from_offs >> 3); - to += (to_offs >> 3); - from_offs &= 7; - to_offs &= 7; - //fprintf(stderr, "bits_memcpy: from=%p (%02x) to=%p (%02x) from_offs=%d to_offs=%d count=%lu\n", from, *from, to, *to, from_offs, to_offs, bit_count); - int sz = (int)bit_count; - bit_count += from_offs; - if (from_offs == to_offs) { - if (bit_count < 8) { - int mask = (-0x100 >> bit_count) & (0xff >> to_offs); - *to = (unsigned char)((*to & ~mask) | (*from & mask)); - return; - } - std::size_t l = (bit_count >> 3); - if (!to_offs) { - std::memcpy(to, from, l); - } else { - int mask = (0xff >> to_offs); - *to = (unsigned char)((*to & ~mask) | (*from & mask)); - std::memcpy(to + 1, from + 1, l - 1); - } - if ((bit_count &= 7) != 0) { - int mask = (-0x100 >> bit_count); - to[l] = (unsigned char)((to[l] & ~mask) | (from[l] & mask)); - } - } else { - int b = (int)to_offs; - unsigned long long acc = (b ? *to >> (8 - b) : 0); - if (bit_count < 8) { - acc <<= sz; - acc |= ((*from & (0xff >> from_offs)) >> (8 - bit_count)); - b += sz; - } else { - unsigned ld = 8 - from_offs; - acc <<= ld; - acc |= (*from++ & (0xff >> from_offs)); - b += ld; - bit_count -= 8; - // b <= 15 here - while (bit_count >= 32) { - acc <<= 32; - acc |= td::bswap32(as(from)); - from += 4; - as(to) = td::bswap32((unsigned)(acc >> b)); - to += 4; - bit_count -= 32; - } - // bit_count <= 31, b <= 15 - while (bit_count >= 8) { - acc <<= 8; - acc |= *from++; - bit_count -= 8; - b += 8; - } - // b + bit_count = const <= 46 - if (bit_count > 0) { - acc <<= bit_count; - acc |= (*from >> (8 - bit_count)); - b += (int)bit_count; - } - } - while (b >= 8) { - b -= 8; - *to++ = (unsigned char)(acc >> b); - } - if (b > 0) { - *to = (unsigned char)((*to & (0xff >> b)) | ((int)acc << (8 - b))); - } - } -} - -void bits_memcpy(BitPtr to, ConstBitPtr from, std::size_t bit_count) { - bits_memcpy(to.ptr, to.offs, from.ptr, from.offs, bit_count); -} - -void bits_memset(unsigned char* to, int to_offs, bool val, std::size_t bit_count) { - if (bit_count <= 0) { - return; - } - to += (to_offs >> 3); - to_offs &= 7; - int sz = (int)bit_count; - bit_count += to_offs; - int c = *to; - if (bit_count <= 8) { - int mask = (((-0x100 >> sz) & 0xff) >> to_offs); - if (val) { - *to = (unsigned char)(c | mask); - } else { - *to = (unsigned char)(c & ~mask); - } - return; - } - if (val) { - *to = (unsigned char)(c | (0xff >> to_offs)); - } else { - *to = (unsigned char)(c & (-0x100 >> to_offs)); - } - std::size_t l = (bit_count >> 3); - std::memset(to + 1, val ? 0xff : 0, l - 1); - if ((bit_count &= 7) != 0) { - if (val) { - to[l] = (unsigned char)(to[l] | (-0x100 >> bit_count)); - } else { - to[l] = (unsigned char)(to[l] & (0xff >> bit_count)); - } - } -} - -void bits_memset(BitPtr to, bool val, std::size_t bit_count) { - bits_memset(to.ptr, to.offs, val, bit_count); -} - -std::size_t bits_memscan_rev(const unsigned char* ptr, int offs, std::size_t bit_count, bool cmp_to) { - if (!bit_count) { - return 0; - } - int xor_val = (cmp_to ? -1 : 0); - ptr += ((offs + bit_count) >> 3); - offs = (int)((offs + bit_count) & 7); - std::size_t res = offs; - if (offs) { - unsigned v = (*ptr >> (8 - offs)) ^ xor_val; - unsigned c = td::count_trailing_zeroes32(v); - if (c < (unsigned)offs || res >= bit_count) { - return std::min(c, (unsigned)bit_count); - } - } - bit_count -= res; - while (bit_count >= 32) { - ptr -= 4; - unsigned v = td::bswap32(as(ptr)) ^ xor_val; - if (v) { - return td::count_trailing_zeroes_non_zero32(v) + res; - } - res += 32; - bit_count -= 32; - } - xor_val &= 0xff; - while (bit_count >= 8) { - unsigned v = *--ptr ^ xor_val; - if (v) { - return td::count_trailing_zeroes_non_zero32(v) + res; - } - res += 8; - bit_count -= 8; - } - if (bit_count > 0) { - unsigned v = *--ptr ^ xor_val; - return std::min((unsigned)td::count_trailing_zeroes32(v), (unsigned)bit_count) + res; - } else { - return res; - } -} - -std::size_t bits_memscan(const unsigned char* ptr, int offs, std::size_t bit_count, bool cmp_to) { - if (!bit_count) { - return 0; - } - int xor_val = -static_cast(cmp_to); - ptr += (offs >> 3); - offs &= 7; - std::size_t rem = bit_count; - unsigned v, c; - if (offs) { - v = ((unsigned)(ptr[0] ^ xor_val) << (24 + offs)); - // std::cerr << "[A] rem=" << rem << " ptr=" << (const void*)ptr << " v=" << std::hex << v << std::dec << std::endl; - c = td::count_leading_zeroes32(v); - unsigned l = (unsigned)(8 - offs); - if (c < l || bit_count <= l) { - return std::min(c, bit_count); - } - rem -= l; - ptr++; - } - while (rem >= 8 && !td::is_aligned_pointer<8>(ptr)) { - v = ((*ptr++ ^ xor_val) << 24); - // std::cerr << "[B] rem=" << rem << " ptr=" << (const void*)(ptr - 1) << " v=" << std::hex << v << std::dec << std::endl; - if (v) { - return bit_count - rem + td::count_leading_zeroes_non_zero32(v); - } - rem -= 8; - } - td::uint64 xor_val_l = (cmp_to ? ~0LL : 0LL); - while (rem >= 64) { - td::uint64 z = td::bswap64(as(ptr)) ^ xor_val_l; - // std::cerr << "[C] rem=" << rem << " ptr=" << (const void*)ptr << " z=" << std::hex << z << std::dec << std::endl; - if (z) { - return bit_count - rem + td::count_leading_zeroes_non_zero64(z); - } - ptr += 8; - rem -= 64; - } - while (rem >= 8) { - v = ((*ptr++ ^ xor_val) << 24); - // std::cerr << "[D] rem=" << rem << " ptr=" << (const void*)(ptr - 1) << " v=" << std::hex << v << std::dec << std::endl; - if (v) { - return bit_count - rem + td::count_leading_zeroes_non_zero32(v); - } - rem -= 8; - } - if (rem > 0) { - v = ((*ptr ^ xor_val) << 24); - // std::cerr << "[E] rem=" << rem << " ptr=" << (const void*)ptr << " v=" << std::hex << v << std::dec << std::endl; - c = td::count_leading_zeroes32(v); - return c < rem ? bit_count - rem + c : bit_count; - } else { - return bit_count; - } -} - -std::size_t bits_memscan(ConstBitPtr bs, std::size_t bit_count, bool cmp_to) { - return bits_memscan(bs.ptr, bs.offs, bit_count, cmp_to); -} - -std::size_t bits_memscan_rev(ConstBitPtr bs, std::size_t bit_count, bool cmp_to) { - return bits_memscan_rev(bs.ptr, bs.offs, bit_count, cmp_to); -} - -int bits_memcmp(const unsigned char* bs1, int bs1_offs, const unsigned char* bs2, int bs2_offs, std::size_t bit_count, - std::size_t* same_upto) { - if (!bit_count) { - return 0; - } - bs1 += (bs1_offs >> 3); - bs2 += (bs2_offs >> 3); - bs1_offs &= 7; - bs2_offs &= 7; - //fprintf(stderr, "bits_memcmp: bs1=%02x%02x offs=%d bs2=%02x%02x offs=%d cnt=%lu\n", bs1[0], bs1[1], bs1_offs, bs2[0], bs2[1], bs2_offs, bit_count); - unsigned long long acc1 = (((unsigned long long)*bs1++) << (56 + bs1_offs)); - int z1 = 8 - bs1_offs; - unsigned long long acc2 = (((unsigned long long)*bs2++) << (56 + bs2_offs)); - int z2 = 8 - bs2_offs; - std::size_t processed = 0; - while (bit_count >= 40) { - acc1 |= ((unsigned long long)td::bswap32(as(bs1)) << (32 - z1)); - bs1 += 4; - acc2 |= ((unsigned long long)td::bswap32(as(bs2)) << (32 - z2)); - bs2 += 4; - if ((acc1 ^ acc2) & (~0ULL << 32)) { - if (same_upto) { - *same_upto = processed + td::count_leading_zeroes64(acc1 ^ acc2); - } - return acc1 < acc2 ? -1 : 1; - } - acc1 <<= 32; - acc2 <<= 32; - processed += 32; - bit_count -= 32; - } - // now 0 <= bit_count <= 39 - - bs1_offs += (int)bit_count - 8; // = bit_count - z1, bits to load from bs1 - while (bs1_offs >= 8) { - acc1 |= ((unsigned long long)(*bs1++) << (56 - z1)); - z1 += 8; - bs1_offs -= 8; - } - if (bs1_offs > 0) { - acc1 |= ((unsigned long long)(*bs1) << (56 - z1)); - } - z1 += bs1_offs; // NB: bs1_offs may be negative - - bs2_offs += (int)bit_count - 8; // bits to load from bs2 - while (bs2_offs >= 8) { - acc2 |= ((unsigned long long)(*bs2++) << (56 - z2)); - z2 += 8; - bs2_offs -= 8; - } - if (bs2_offs > 0) { - acc2 |= ((unsigned long long)(*bs2) << (56 - z2)); - } - z2 += bs2_offs; - - CHECK(z1 == z2); - CHECK(z1 < 64); - //fprintf(stderr, "acc1=%016llx acc2=%016llx z1=z2=%d\n", acc1, acc2, z1); - if (z1) { - if ((acc1 ^ acc2) & (~0ULL << (64 - z1))) { - if (same_upto) { - *same_upto = processed + td::count_leading_zeroes64(acc1 ^ acc2); - } - return acc1 < acc2 ? -1 : 1; - } - } - if (same_upto) { - *same_upto = processed + bit_count; - } - return 0; -} - -int bits_memcmp(ConstBitPtr bs1, ConstBitPtr bs2, std::size_t bit_count, std::size_t* same_upto) { - return bits_memcmp(bs1.ptr, bs1.offs, bs2.ptr, bs2.offs, bit_count, same_upto); -} - -int bits_lexcmp(const unsigned char* bs1, int bs1_offs, std::size_t bs1_bit_count, const unsigned char* bs2, - int bs2_offs, std::size_t bs2_bit_count) { - int res = bits_memcmp(bs1, bs1_offs, bs2, bs2_offs, std::min(bs1_bit_count, bs2_bit_count), 0); - if (res || bs1_bit_count == bs2_bit_count) { - return res; - } - return bs1_bit_count < bs2_bit_count ? -1 : 1; -} - -int bits_lexcmp(ConstBitPtr bs1, std::size_t bs1_bit_count, ConstBitPtr bs2, std::size_t bs2_bit_count) { - return bits_lexcmp(bs1.ptr, bs1.offs, bs1_bit_count, bs2.ptr, bs2.offs, bs2_bit_count); -} - -void bits_store_long_top(unsigned char* to, int to_offs, unsigned long long val, unsigned top_bits) { - CHECK(top_bits <= 64); - if (top_bits <= 0) { - return; - } - to += (to_offs >> 3); - to_offs &= 7; - if (!to_offs && !(top_bits & 7)) { - // good only on little-endian machines! - unsigned long long tmp = td::bswap64(val); - std::memcpy(to, &tmp, top_bits >> 3); - return; - } - unsigned long long z = (unsigned long long)(*to & (-0x100 >> to_offs)) << 56; - z |= (val >> to_offs); - top_bits += to_offs; - if (top_bits > 64) { - as(to) = td::bswap64(z); - z = (val << (8 - to_offs)); - int mask = (0xff >> (top_bits - 64)); - to[8] = (unsigned char)((to[8] & mask) | ((int)z & ~mask)); - } else { - int p = 56, q = 64 - top_bits; - if (q <= 32) { - as(to) = td::bswap32((unsigned)(z >> 32)); - to += 4; - p -= 32; - } - while (p >= q) { - *to++ = (unsigned char)(z >> p); - p -= 8; - } - top_bits = p + 8 - q; - if (top_bits > 0) { - int mask = (0xff >> top_bits); - *to = (unsigned char)((*to & mask) | ((z >> p) & ~mask)); - } - } -} - -void bits_store_long_top(BitPtr to, unsigned long long val, unsigned top_bits) { - bits_store_long_top(to.ptr, to.offs, val, top_bits); -} - -void bits_store_long(BitPtr to, unsigned long long val, unsigned bits) { - bits_store_long_top(to, val << (64 - bits), bits); -} - -unsigned long long bits_load_long_top(const unsigned char* from, int from_offs, unsigned top_bits) { - CHECK(top_bits <= 64); - if (!top_bits) { - return 0; - } - from += (from_offs >> 3); - from_offs &= 7; - if ((unsigned)from_offs + top_bits <= 64) { - unsigned long long tmp; - std::memcpy(&tmp, from, (from_offs + top_bits + 7) >> 3); - return (td::bswap64(tmp) << from_offs) & (std::numeric_limits::max() << (64 - top_bits)); - } else { - unsigned long long z = td::bswap64(as(from)); - z <<= from_offs; - z |= (from[8] >> (8 - from_offs)); - return z & (std::numeric_limits::max() << (64 - top_bits)); - } -} - -unsigned long long bits_load_long_top(ConstBitPtr from, unsigned top_bits) { - return bits_load_long_top(from.ptr, from.offs, top_bits); -} - -unsigned long long bits_load_ulong(ConstBitPtr from, unsigned bits) { - return bits_load_long_top(from, bits) >> (64 - bits); -} - -long long bits_load_long(ConstBitPtr from, unsigned bits) { - return (long long)bits_load_long_top(from, bits) >> (64 - bits); -} - -std::string bits_to_binary(const unsigned char* ptr, int offs, std::size_t len) { - if (!len) { - return ""; - } - std::string s; - s.reserve(len); - ptr += (offs >> 3); - unsigned mask = (0x80 >> (offs & 7)); - unsigned value = *ptr++; - do { - s.push_back(value & mask ? '1' : '0'); - if (!(mask >>= 1)) { - value = *ptr++; - mask = 0x80; - } - } while (--len > 0); - return s; -} - -std::string bits_to_binary(ConstBitPtr bs, std::size_t len) { - return bits_to_binary(bs.ptr, bs.offs, len); -} - -static const char hex_digits[] = "0123456789ABCDEF"; - -std::string bits_to_hex(const unsigned char* ptr, int offs, std::size_t len) { - if (!len) { - return ""; - } - std::string s; - s.reserve((len + 7) >> 2); - ptr += (offs >> 3); - offs &= 7; - unsigned long long acc = *ptr++ & (0xff >> offs); - unsigned bits = 8 - offs; - if (bits > len) { - acc >>= bits - (unsigned)len; - bits = (unsigned)len; - } else { - len -= bits; - while (len >= 8) { - while (len >= 8 && bits <= 56) { - acc <<= 8; - acc |= *ptr++; - bits += 8; - len -= 8; - } - while (bits >= 4) { - bits -= 4; - s.push_back(hex_digits[(acc >> bits) & 15]); - } - } - if (len > 0) { - acc <<= len; - acc |= (*ptr >> (8 - len)); - bits += (unsigned)len; - } - } - int f = bits & 3; - if (f) { - acc = (2 * acc + 1) << (3 - f); - bits += 4 - f; - } - while (bits >= 4) { - bits -= 4; - s.push_back(hex_digits[(acc >> bits) & 15]); - } - CHECK(!bits); - if (f) { - s.push_back('_'); - } - return s; -} - -std::string bits_to_hex(ConstBitPtr bs, std::size_t len) { - return bits_to_hex(bs.ptr, bs.offs, len); -} - -long parse_bitstring_hex_literal(unsigned char* buff, std::size_t buff_size, const char* str, const char* str_end) { - std::size_t hex_digits_count = 0; - bool cmpl = false; - unsigned char* ptr = buff; - const char* rptr = str; - while (rptr < str_end) { - int c = *rptr++; - if (c == ' ' || c == '\t') { - continue; - } - if (cmpl) { - return td::narrow_cast(str - rptr); - } - if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { - int val = (c <= '9') ? c - '0' : ((c | 0x20) - 'a' + 10); - if (hex_digits_count >= 2 * buff_size) { - return td::narrow_cast(str - rptr); - } - if (!(hex_digits_count & 1)) { - *ptr = (unsigned char)(val << 4); - } else { - *ptr = (unsigned char)(*ptr | val); - ptr++; - } - hex_digits_count++; - continue; - } - if (c == '_') { - cmpl = true; - } else { - return td::narrow_cast(str - rptr); - } - } - std::size_t bits = 4 * hex_digits_count; - if (cmpl && bits) { - int t = (hex_digits_count & 1) ? (0x100 + *ptr) >> 4 : (0x100 + *--ptr); - while (bits > 0) { - --bits; - if (t & 1) { - break; - } - t >>= 1; - if (t == 1) { - t = 0x100 + *--ptr; - } - } - } - return bits; -} - -long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size, const char* str, const char* str_end) { - const char* ptr = str; - while (ptr < str_end && buff_size && (*ptr == '0' || *ptr == '1')) { - *buff++ = (bool)(*ptr++ & 1); - --buff_size; - } - return td::narrow_cast(ptr == str_end ? ptr - str : str - ptr - 1); -} - -void bits_sha256(BitPtr to, ConstBitPtr from, std::size_t size) { - if (from.byte_aligned() && !(size & 7)) { - if (to.byte_aligned()) { - digest::hash_str(to.get_byte_ptr(), from.get_byte_ptr(), size >> 3); - } else { - unsigned char buffer[32]; - digest::hash_str(buffer, from.get_byte_ptr(), size >> 3); - to.copy_from(BitPtr{buffer}, 256); - } - } else { - throw BitstringError{}; - } -} - -} // namespace bitstring - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/bitstring.h b/submodules/ton/tonlib-src/crypto/common/bitstring.h deleted file mode 100644 index dc3a2fa5..00000000 --- a/submodules/ton/tonlib-src/crypto/common/bitstring.h +++ /dev/null @@ -1,675 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include -#include -#include -#include -#include -#include "td/utils/bits.h" - -namespace td { -template -struct BitPtrGen; - -typedef BitPtrGen BitPtr; -typedef BitPtrGen ConstBitPtr; - -struct BitstringError {}; - -namespace bitstring { - -void bits_memcpy(unsigned char* to, int to_offs, const unsigned char* from, int from_offs, std::size_t bit_count); -void bits_memcpy(BitPtr to, ConstBitPtr from, std::size_t bit_count); -void bits_memset(unsigned char* to, int to_offs, bool val, std::size_t bit_count); -void bits_memset(BitPtr to, bool val, std::size_t bit_count); -int bits_memcmp(const unsigned char* bs1, int bs1_offs, const unsigned char* bs2, int bs2_offs, std::size_t bit_count, - std::size_t* same_upto = 0); -int bits_memcmp(ConstBitPtr bs1, ConstBitPtr bs2, std::size_t bit_count, std::size_t* same_upto = 0); -int bits_lexcmp(const unsigned char* bs1, int bs1_offs, std::size_t bs1_bit_count, const unsigned char* bs2, - int bs2_offs, std::size_t bs2_bit_count); -int bits_lexcmp(ConstBitPtr bs1, std::size_t bs1_bit_count, ConstBitPtr bs2, std::size_t bs2_bit_count); -std::size_t bits_memscan(const unsigned char* ptr, int offs, std::size_t bit_count, bool cmp_to); -std::size_t bits_memscan_rev(const unsigned char* ptr, int offs, std::size_t bit_count, bool cmp_to); -std::size_t bits_memscan(ConstBitPtr bs, std::size_t bit_count, bool cmp_to); -std::size_t bits_memscan_rev(ConstBitPtr bs, std::size_t bit_count, bool cmp_to); -void bits_store_long_top(unsigned char* to, int to_offs, unsigned long long val, unsigned top_bits); -void bits_store_long_top(BitPtr to, unsigned long long val, unsigned top_bits); -void bits_store_long(BitPtr to, unsigned long long val, unsigned bits); -unsigned long long bits_load_long_top(const unsigned char* from, int from_offs, unsigned top_bits); -unsigned long long bits_load_long_top(ConstBitPtr from, unsigned top_bits); -long long bits_load_long(ConstBitPtr from, unsigned bits); -unsigned long long bits_load_ulong(ConstBitPtr from, unsigned bits); -long parse_bitstring_hex_literal(unsigned char* buff, std::size_t buff_size, const char* str, const char* str_end); -long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size, const char* str, const char* str_end); - -void bits_sha256(BitPtr to, ConstBitPtr from, std::size_t size); - -std::string bits_to_binary(const unsigned char* ptr, int offs, std::size_t len); -std::string bits_to_binary(ConstBitPtr bs, std::size_t len); -std::string bits_to_hex(const unsigned char* ptr, int offs, std::size_t len); -std::string bits_to_hex(ConstBitPtr bs, std::size_t len); - -} // namespace bitstring - -template -struct BitPtrGen { - Pt* ptr; - int offs; - BitPtrGen(Pt* _ptr, int _offs = 0) : ptr(_ptr), offs(_offs) { - } - template - BitPtrGen(BitPtrGen val) : ptr(val.ptr), offs(val.offs) { - } - BitPtrGen& operator+=(int _offs) { - offs += _offs; - return *this; - } - BitPtrGen& operator-=(int _offs) { - offs -= _offs; - return *this; - } - void advance(int _offs) { - offs += _offs; - } - bool byte_aligned() const { - return !(offs & 7); - } - Pt* get_byte_ptr() const { - return ptr + (offs >> 3); - } - void copy_from(BitPtrGen from, unsigned size) const { - bitstring::bits_memcpy(*this, from, size); - } - BitPtrGen& concat(BitPtrGen from, unsigned size) { - bitstring::bits_memcpy(*this, from, size); - offs += size; - return *this; - } - template - void copy_from(const T& from) const { - copy_from(from.bits(), from.size()); - } - template - BitPtrGen& concat(const T& from) { - return concat(from.bits(), from.size()); - } - void fill(bool bit, unsigned size) { - bitstring::bits_memset(*this, bit, size); - } - BitPtrGen& concat_same(bool bit, unsigned size) { - bitstring::bits_memset(*this, bit, size); - offs += size; - return *this; - } - int compare(BitPtrGen other, std::size_t size, std::size_t* same_upto = nullptr) const { - return bitstring::bits_memcmp(*this, other, size, same_upto); - } - bool equals(BitPtrGen other, std::size_t size) const { - return !bitstring::bits_memcmp(*this, other, size); - } - std::size_t scan(bool value, std::size_t len) const { - return bitstring::bits_memscan(*this, len, value); - } - bool is_zero(std::size_t len) const { - return scan(false, len) == len; - } - long long get_int(unsigned bits) const { - return bitstring::bits_load_long(*this, bits); - } - unsigned long long get_uint(unsigned bits) const { - return bitstring::bits_load_ulong(*this, bits); - } - void store_uint(unsigned long long val, unsigned n) const { - bitstring::bits_store_long(*this, val, n); - } - void store_int(long long val, unsigned n) const { - bitstring::bits_store_long(*this, val, n); - } - BitPtrGen operator+(int _offs) const { - return BitPtrGen{ptr, offs + _offs}; - } - BitPtrGen operator-(int _offs) const { - return BitPtrGen{ptr, offs - _offs}; - } - BitPtrGen operator++() { - ++offs; - return *this; - } - BitPtrGen operator--() { - --offs; - return *this; - } - BitPtrGen operator++(int) { - return BitPtrGen{ptr, offs++}; - } - BitPtrGen operator--(int) { - return BitPtrGen{ptr, offs--}; - } - bool is_null() const { - return !ptr; - } - bool not_null() const { - return ptr; - } - class BitSelector { - Pt* ptr; - unsigned char mask; - - public: - BitSelector(Pt* _ptr, int offs) { - ptr = _ptr + (offs >> 3); - mask = (unsigned char)(0x80 >> (offs & 7)); - } - bool clear() { - *ptr = (unsigned char)(*ptr & ~mask); - return false; - } - bool set() { - *ptr = (unsigned char)(*ptr | mask); - return true; - } - bool operator=(bool val) { - return val ? set() : clear(); - } - operator bool() const { - return *ptr & mask; - } - }; - BitSelector operator*() const { - return BitSelector{ptr, offs}; - } - BitSelector operator[](int i) const { - return BitSelector{ptr, offs + i}; - } - std::string to_hex(std::size_t len) const { - return bitstring::bits_to_hex(*this, len); - } - std::string to_binary(std::size_t len) const { - return bitstring::bits_to_binary(*this, len); - } -}; - -template -class BitSliceGen { - Rf ref; - Pt* ptr; - unsigned offs, len; - - public: - struct BitSliceError {}; - BitSliceGen() : ref(), ptr(0), offs(0), len(0) { - } - BitSliceGen(Rf _ref, Pt* _ptr, int _offs, unsigned _len) - : ref(std::move(_ref)), ptr(_ptr + (_offs >> 3)), offs(_offs & 7), len(_len) { - } - BitSliceGen(const BitSliceGen& bs, unsigned _offs, unsigned _len); - BitSliceGen(BitSliceGen&& bs, unsigned _offs, unsigned _len); - BitSliceGen(Pt* _ptr, unsigned _len) : ref(), ptr(_ptr), offs(0), len(_len) { - } - explicit BitSliceGen(Slice slice) : BitSliceGen(slice.data(), slice.size() * 8) { - } - ~BitSliceGen() { - } - Pt* get_ptr() const { - return ptr; - } - BitPtrGen bits() const { - return BitPtrGen{ptr, (int)offs}; - } - bool is_valid() const { - return ptr != 0; - } - unsigned char cur_byte() const { - return *ptr; - } - unsigned get_offs() const { - return offs; - } - unsigned size() const { - return len; - } - unsigned byte_size() const { - return (offs + len + 7) >> 3; - } - void ensure_throw(bool cond) const { - if (!cond) { - throw BitSliceError{}; - } - } - BitSliceGen& assign(Rf _ref, Pt* _ptr, unsigned _offs, unsigned _len); - void forget() { - ref.clear(); - ptr = 0; - offs = len = 0; - } - bool operator[](unsigned i) const { - i += offs; - return ptr[i >> 3] & (0x80 >> (i & 7)); - } - bool at(unsigned i) const { - ensure_throw(i < len); - return operator[](i); - } - bool advance_bool(unsigned bits); - bool set_size_bool(unsigned bits) { - if (bits > len) { - return false; - } - len = bits; - return true; - } - BitSliceGen& advance(unsigned bits) { - ensure_throw(advance_bool(bits)); - return *this; - } - BitSliceGen& set_size(unsigned bits) { - ensure_throw(set_size_bool(bits)); - return *this; - } - BitSliceGen subslice(unsigned from, unsigned bits) const & { - return BitSliceGen(*this, from, bits); - } - BitSliceGen subslice(unsigned from, unsigned bits) && { - return BitSliceGen(*this, from, bits); - } - void copy_to(BitPtr to) const { - bitstring::bits_memcpy(to, bits(), size()); - } - int compare(ConstBitPtr other) const { - return bitstring::bits_memcmp(bits(), other, size()); - } - bool operator==(ConstBitPtr other) const { - return !compare(other); - } - bool operator!=(ConstBitPtr other) const { - return compare(other); - } - std::string to_binary() const { - return bitstring::bits_to_binary(ptr, offs, len); - } - std::string to_hex() const { - return bitstring::bits_to_hex(ptr, offs, len); - } - void dump(std::ostream& stream, bool nocr = false) const { - stream << "[" << offs << "," << len << "]"; - if (!nocr) { - stream << std::endl; - } - } - - protected: - inline Pt& cur_byte_w() const { - return *ptr; - } -}; - -template -BitSliceGen::BitSliceGen(const BitSliceGen& bs, unsigned from, unsigned bits) : ref() { - if (from >= bs.size() || bits > bs.size() - from) { - ptr = 0; - offs = len = 0; - return; - } - //bs.dump(std::cout, true); - //std::cout << ".subslice(" << from << "," << bits << ") = "; - ref = bs.ref; - offs = bs.offs + from; - ptr = bs.ptr + (offs >> 3); - offs &= 7; - len = bits; - //dump(std::cout); -} - -template -BitSliceGen::BitSliceGen(BitSliceGen&& bs, unsigned from, unsigned bits) : ref() { - if (from >= bs.size() || bits > bs.size() - from) { - ptr = 0; - offs = len = 0; - return; - } - ref = std::move(bs.ref); - offs = bs.offs + from; - ptr = bs.ptr + (offs >> 3); - offs &= 7; - len = bits; -} - -template -BitSliceGen& BitSliceGen::assign(Rf _ref, Pt* _ptr, unsigned _offs, unsigned _len) { - ref = std::move(_ref); - ptr = _ptr + (_offs >> 3); - offs = (_offs & 7); - len = _len; - return *this; -} - -template -inline bool BitSliceGen::advance_bool(unsigned bits) { - if (len < bits) { - return false; - } - len -= bits; - offs += bits; - ptr += (offs >> 3); - offs &= 7; - return true; -} - -typedef BitSliceGen BitSlice; - -static inline std::string to_hex(const BitSlice& bs) { - return bs.to_hex(); -} - -static inline std::string to_binary(const BitSlice& bs) { - return bs.to_binary(); -} - -class BitSliceWrite : public BitSliceGen { - public: - struct LengthMismatch {}; - BitSliceWrite(RefAny _ref, unsigned char* _ptr, unsigned _offs, unsigned _len) - : BitSliceGen(_ref, _ptr, _offs, _len) { - } - BitSliceWrite() : BitSliceGen() { - } - BitSliceWrite(unsigned char* _ptr, unsigned _len) : BitSliceGen(_ptr, _len) { - } - operator BitSlice&() { - return *reinterpret_cast(this); - } - operator const BitSlice&() const { - return *reinterpret_cast(this); - } - const BitSliceWrite& operator=(const BitSlice& bs) const; - const BitSliceWrite& operator=(bool val) const; -}; - -class BitString : public CntObject { - unsigned char* ptr; - unsigned offs, len, bytes_alloc; - - public: - BitString() : ptr(0), offs(0), len(0), bytes_alloc(0) { - } - explicit BitString(const BitSlice& bs, unsigned reserve_bits = 0); - explicit BitString(unsigned reserve_bits); - - BitString(const BitString&) = delete; - BitString& operator=(const BitString&) = delete; - BitString(BitString&&) = delete; - BitString& operator=(BitString&&) = delete; - ~BitString() { - if (ptr) { - std::free(ptr); - } - } - operator BitSlice() const; - BitString* make_copy() const override; - unsigned size() const { - return len; - } - unsigned byte_size() const { - return (offs + len + 7) >> 3; - } - ConstBitPtr cbits() const { - return ConstBitPtr{ptr, (int)offs}; - } - ConstBitPtr bits() const { - return ConstBitPtr{ptr, (int)offs}; - } - BitPtr bits() { - return BitPtr{ptr, (int)offs}; - } - BitString& reserve_bits(unsigned req_bits); - BitSliceWrite reserve_bitslice(unsigned req_bits); - BitString& append(const BitSlice& bs); - BitSlice subslice(unsigned from, unsigned bits) const; - BitSliceWrite subslice_write(unsigned from, unsigned bits); - std::string to_hex() const { - return bitstring::bits_to_hex(cbits(), size()); - } - std::string to_binary() const { - return bitstring::bits_to_binary(cbits(), size()); - } -}; - -extern std::ostream& operator<<(std::ostream& stream, const BitString& bs); -extern std::ostream& operator<<(std::ostream& stream, Ref bs_ref); - -extern template class Ref; -typedef Ref BitStringRef; - -template -class BitArray { - static constexpr unsigned m = (n + 7) >> 3; - typedef std::array byte_array_t; - typedef unsigned char raw_byte_array_t[m]; - byte_array_t bytes; - - public: - const unsigned char* data() const { - return bytes.data(); - } - unsigned char* data() { - return bytes.data(); - } - static unsigned size() { - return n; - } - const byte_array_t& as_array() const { - return bytes; - } - byte_array_t& as_array() { - return bytes; - } - Slice as_slice() const { - return Slice{data(), m}; - } - MutableSlice as_slice() { - return MutableSlice{data(), m}; - } - ConstBitPtr cbits() const { - return ConstBitPtr{data()}; - } - ConstBitPtr bits() const { - return ConstBitPtr{data()}; - } - BitPtr bits() { - return BitPtr{data()}; - } - BitArray() = default; - BitArray(const BitArray&) = default; - BitArray(const byte_array_t& init_bytes) : bytes(init_bytes) { - } - explicit BitArray(const raw_byte_array_t init_bytes) { - std::memcpy(data(), init_bytes, m); - } - BitArray(ConstBitPtr from) { - bitstring::bits_memcpy(bits(), from, n); - } - template > - explicit BitArray(long long val) { - bitstring::bits_store_long(bits(), val, n); - } - BitArray& operator=(const BitArray&) = default; - BitArray& operator=(const byte_array_t& set_bytes) { - bytes = set_bytes; - return *this; - } - BitArray& operator=(ConstBitPtr from) { - bitstring::bits_memcpy(bits(), from, n); - return *this; - } - BitArray& operator=(const raw_byte_array_t set_byte_array) { - std::memcpy(data(), set_byte_array, m); - return *this; - } - BitSliceWrite write_bitslice() { - return BitSliceWrite{data(), n}; - } - BitSlice as_bitslice() const { - return BitSlice{data(), n}; - } - //operator BitString() const { - //return BitString{as_bitslice()}; - //} - Ref make_bitstring_ref() const { - return td::make_ref(as_bitslice()); - } - unsigned long long to_ulong() const { - return bitstring::bits_load_ulong(bits(), n); - } - long long to_long() const { - return bitstring::bits_load_long(bits(), n); - } - void store_ulong(unsigned long long val) { - bitstring::bits_store_long(bits(), val, n); - } - void store_long(long long val) { - bitstring::bits_store_long(bits(), val, n); - } - void set_same(bool v) { - bytes.fill(static_cast(v ? -1 : 0)); - } - void set_zero() { - set_same(0); - } - void set_zero_s() { - volatile uint8* p = data(); - auto x = m; - while (x--) { - *p++ = 0; - } - } - void set_ones() { - set_same(1); - } - void clear() { - set_zero(); - } - bool is_zero() const { - return bitstring::bits_memscan(cbits(), n, 0) == n; - } - std::string to_hex() const { - return bitstring::bits_to_hex(cbits(), size()); - } - std::string to_binary() const { - return bitstring::bits_to_binary(cbits(), size()); - } - long from_hex(td::Slice hex_str, bool allow_partial = false) { - auto res = bitstring::parse_bitstring_hex_literal(data(), m, hex_str.begin(), hex_str.end()); - return allow_partial ? std::min(res, n) : (res == n ? res : -1); - } - long from_binary(td::Slice bin_str, bool allow_partial = false) { - auto res = bitstring::parse_bitstring_binary_literal(bits(), n, bin_str.begin(), bin_str.end()); - return allow_partial ? std::min(res, n) : (res == n ? res : -1); - } - int compare(const BitArray& other) const { - return (n % 8 == 0) ? std::memcmp(data(), other.data(), n / 8) : bitstring::bits_memcmp(bits(), other.bits(), n); - } - bool operator==(const BitArray& other) const { - return (n % 8 == 0) ? (bytes == other.bytes) : !bitstring::bits_memcmp(bits(), other.bits(), n); - } - bool operator!=(const BitArray& other) const { - return (n % 8 == 0) ? (bytes != other.bytes) : bitstring::bits_memcmp(bits(), other.bits(), n); - } - bool operator<(const BitArray& other) const { - return (n % 8 == 0) ? (bytes < other.bytes) : (bitstring::bits_memcmp(bits(), other.bits(), n) < 0); - } - int compare(ConstBitPtr other) const { - return bitstring::bits_memcmp(bits(), other, n); - } - bool operator==(ConstBitPtr other) const { - return !compare(other); - } - bool operator!=(ConstBitPtr other) const { - return compare(other); - } - BitPtr::BitSelector operator[](int i) { - return bits()[i]; - } - bool operator[](int i) const { - return cbits()[i]; - } - void compute_sha256(BitPtr to) const { - bitstring::bits_sha256(to, cbits(), n); - } - void compute_sha256(BitArray<256>& to) const { - bitstring::bits_sha256(to.bits(), cbits(), n); - } - static inline BitArray zero() { - BitArray x; - x.set_zero(); - return x; - } - static inline BitArray ones() { - BitArray x; - x.set_ones(); - return x; - } - BitArray operator^(const BitArray& with) const { - BitArray res; - for (unsigned i = 0; i < m; i++) { - res.bytes[i] = bytes[i] ^ with.bytes[i]; - } - return res; - } - unsigned scan(bool value) const { - return (unsigned)cbits().scan(value, n); - } - unsigned count_leading_zeroes() const { - return scan(false); - } - unsigned count_matching(ConstBitPtr other) const { - std::size_t cnt; - bitstring::bits_memcmp(cbits(), other, n, &cnt); - return (unsigned)cnt; - } - unsigned count_matching(const BitArray& other) const { - return count_matching(other.bits()); - } -}; - -using Bits256 = BitArray<256>; -using Bits128 = BitArray<128>; - -template -std::ostream& operator<<(std::ostream& stream, BitArray bits) { - return stream << bits.to_hex(); -} - -template -Slice as_slice(const BitArray& value) { - return value.as_slice(); -} - -template -MutableSlice as_slice(BitArray& value) { - return value.as_slice(); -} - -template -Ref make_bitstring_ref(const BitArray& value) { - return value.make_bitstring_ref(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/linalloc.hpp b/submodules/ton/tonlib-src/crypto/common/linalloc.hpp deleted file mode 100644 index da2ed05b..00000000 --- a/submodules/ton/tonlib-src/crypto/common/linalloc.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2020 Telegram Systems LLP -*/ -namespace td { - -class LinearAllocator { - std::size_t size; - char *ptr, *cur, *end; - - public: - LinearAllocator(std::size_t _size) : size(_size) { - cur = ptr = (char*)malloc(size); - if (!ptr) { - throw std::bad_alloc(); - } - end = ptr + size; - } - ~LinearAllocator() { - free(ptr); - } - void* allocate(std::size_t count) { - char* t = cur; - cur += (count + 7) & -8; - if (cur > end) { - throw std::bad_alloc(); - } - return (void*)t; - } -}; - -} // namespace td - -inline void* operator new(std::size_t count, td::LinearAllocator& alloc) { - return alloc.allocate(count); -} diff --git a/submodules/ton/tonlib-src/crypto/common/promiseop.hpp b/submodules/ton/tonlib-src/crypto/common/promiseop.hpp deleted file mode 100644 index 1e14bc7d..00000000 --- a/submodules/ton/tonlib-src/crypto/common/promiseop.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2020 Telegram Systems LLP -*/ -#pragma once -#include "refcnt.hpp" -#include "td/actor/PromiseFuture.h" - -namespace td { - -template -class BinaryPromiseMerger : public CntObject { - Result first_; - Result second_; - Promise> promise_; - std::atomic pending_; - - public: - BinaryPromiseMerger(Promise> promise) : promise_(std::move(promise)), pending_(2) { - } - static std::pair, Promise> split(Promise> promise) { - auto ref = make_ref(std::move(promise)); - auto& obj = ref.write(); - return std::make_pair(obj.left(), obj.right()); - } - - private: - Promise left() { - return [this, self = Ref(this)](Result res) { - first_ = std::move(res); - work(); - }; - } - Promise right() { - return [this, self = Ref(this)](Result res) { - second_ = std::move(res); - work(); - }; - } - void work() { - if (!--pending_) { - if (first_.is_error()) { - promise_.set_error(first_.move_as_error()); - } else if (second_.is_error()) { - promise_.set_error(second_.move_as_error()); - } else { - promise_.set_result(std::pair(first_.move_as_ok(), second_.move_as_ok())); - } - } - } -}; - -template -std::pair, Promise> split_promise(Promise> promise) { - return BinaryPromiseMerger::split(std::move(promise)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/refcnt.cpp b/submodules/ton/tonlib-src/crypto/common/refcnt.cpp deleted file mode 100644 index a90414f8..00000000 --- a/submodules/ton/tonlib-src/crypto/common/refcnt.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "refcnt.hpp" - -#include "td/utils/ScopeGuard.h" - -namespace td { -namespace detail { -struct SafeDeleter { - public: - void retire(const CntObject *ptr) { - if (is_active_) { - to_delete_.push_back(ptr); - return; - } - is_active_ = true; - SCOPE_EXIT { - is_active_ = false; - }; - delete ptr; - while (!to_delete_.empty()) { - auto *ptr = to_delete_.back(); - to_delete_.pop_back(); - delete ptr; - } - } - - private: - std::vector to_delete_; - bool is_active_{false}; -}; - -TD_THREAD_LOCAL SafeDeleter *deleter; -void safe_delete(const CntObject *ptr) { - init_thread_local(deleter); - deleter->retire(ptr); -} -} // namespace detail -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/refcnt.hpp b/submodules/ton/tonlib-src/crypto/common/refcnt.hpp deleted file mode 100644 index 7625ff7a..00000000 --- a/submodules/ton/tonlib-src/crypto/common/refcnt.hpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include -#include - -#include "td/utils/StringBuilder.h" -#include "td/utils/logging.h" - -namespace td { - -template -class Ref; - -class CntObject { - private: - mutable std::atomic cnt_; - template - friend class Ref; - - void inc() const { - cnt_.fetch_add(1, std::memory_order_relaxed); - } - bool dec() const { - return cnt_.fetch_sub(1, std::memory_order_acq_rel) == 1; - } - void inc(int cnt) const { - cnt_.fetch_add(cnt, std::memory_order_relaxed); - } - bool dec(int cnt) const { - return cnt_.fetch_sub(cnt, std::memory_order_acq_rel) == cnt; - } - - public: - struct WriteError {}; - CntObject() : cnt_(1) { - } - CntObject(const CntObject& other) : CntObject() { - } - CntObject(CntObject&& other) : CntObject() { - } - CntObject& operator=(const CntObject& other) { - return *this; - } - CntObject& operator=(CntObject&& other) { - return *this; - } - virtual ~CntObject() { - auto cnt = cnt_.load(std::memory_order_relaxed); - (void)cnt; - //TODO: assert(cnt == 0) will fail if object is allocated on stack - assert(cnt == 0 || cnt == 1); - } - virtual CntObject* make_copy() const { - throw WriteError(); - } - bool is_unique() const { - return cnt_.load(std::memory_order_acquire) == 1; - } - int get_refcnt() const { - // use std::memory_order_acquire - return cnt_.load(std::memory_order_acquire); - } - void assert_unique() const { - assert(is_unique()); - } -}; - -typedef Ref RefAny; - -template -class Cnt : public CntObject { - T value; - - public: - template - Cnt(Args&&... args) : value(std::forward(args)...) { - ///std::cout << "(N " << (void*)this << ")"; - } - Cnt(const Cnt& x) : CntObject(), value(x.value) { - ///std::cout << "(C)"; - } - virtual ~Cnt() { - ///std::cout << "(D " << (void*)this << ")"; - } - T* operator->() { - return &value; - } - const T* operator->() const { - return &value; - } - T& operator*() { - return value; - } - const T& operator*() const { - return value; - } - Cnt* make_copy() const override { - ///std::cout << "(c " << (const void*)this << ")"; - return new Cnt{value}; - } -}; - -template -struct RefValue { - using Type = T; - static Type& make_ref(T* ptr) { - return *ptr; - } - static const Type& make_const_ref(const T* ptr) { - return *ptr; - } - static Type* make_ptr(T* ptr) { - return ptr; - } - static const Type* make_const_ptr(const T* ptr) { - return ptr; - } -}; - -template -struct RefValue> { - using Type = T; - static Type& make_ref(Cnt* ptr) { - return **ptr; - } - static const Type& make_const_ref(const Cnt* ptr) { - return **ptr; - } - static Type* make_ptr(Cnt* ptr) { - return &(**ptr); - } - static const Type* make_const_ptr(const Cnt* ptr) { - return &(**ptr); - } -}; - -struct static_cast_ref {}; - -namespace detail { -void safe_delete(const CntObject* ptr); -} -template -class Ref { - T* ptr; - - template - friend class Ref; - - public: - struct NullRef {}; - Ref() : ptr(0) { - } - //explicit Ref(bool init) : ptr(init ? new T : 0) { - //} - template - explicit Ref(bool init, Args&&... args) : ptr(0) { - //assert(init); - ptr = new T(std::forward(args)...); - } - /* - explicit Ref(const T& c) : ptr(&c) { - ptr.inc(); - } - */ - explicit Ref(T* pc) : ptr(pc) { - if (ptr) { - acquire_shared(ptr); - } - } - explicit Ref(const T* pc) : ptr(const_cast(pc)) { - if (ptr) { - acquire_shared(ptr); - } - } - explicit Ref(const T& obj) : ptr(obj.make_copy()) { - } - Ref(const Ref& r) : ptr(r.ptr) { - if (ptr) { - acquire_shared(ptr); - ///std::cout << "(rc+ " << (const void*)ptr << ")"; - } - } - Ref(Ref&& r) noexcept : ptr(std::move(r.ptr)) { - r.ptr = 0; - } - - T* release() { - auto res = ptr; - ptr = nullptr; - return res; - } - struct acquire_t {}; - Ref(T* ptr, acquire_t) : ptr(ptr) { - } - - template - Ref(const Ref& r, std::enable_if_t::value, int> t = 0) : ptr(static_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid static Ref conversion"); - if (ptr) { - acquire_shared(ptr); - } - } - - template - explicit Ref(const Ref& r, - std::enable_if_t::value && std::is_base_of::value, int> t = 0) - : ptr(dynamic_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid dynamic Ref conversion"); - if (ptr) { - acquire_shared(ptr); - //std::cout << "(rv+ " << (const void*)ptr << ")"; - } else { - //std::cout << "(error converting " << (const void*)r.ptr << ")"; - } - } - - template - Ref(static_cast_ref, const Ref& r, std::enable_if_t::value, int> t = 0) - : ptr(static_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid static Ref downcast"); - if (r.ptr) { - acquire_shared(ptr); - } else { - ptr = nullptr; - } - } - - template - Ref(Ref&& r, std::enable_if_t::value, int> t = 0) : ptr(static_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid static Ref conversion"); - r.ptr = nullptr; - } - - template - explicit Ref(Ref&& r, std::enable_if_t::value && std::is_base_of::value, int> t = 0) - : ptr(dynamic_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid dynamic Ref conversion"); - if (!ptr && r.ptr) { - release_shared(r.ptr); - } - r.ptr = nullptr; - } - - template - Ref(static_cast_ref, Ref&& r, std::enable_if_t::value, int> t = 0) noexcept - : ptr(static_cast(r.ptr)) { - static_assert(std::is_base_of::value, "Invalid static Ref downcast"); - if (r.ptr) { - r.ptr = nullptr; - } else { - ptr = nullptr; - } - } - - ~Ref() { - clear(); - } - Ref& operator=(const Ref& r); - template - Ref& operator=(const Ref& r); - Ref& operator=(Ref&& r); - template - Ref& operator=(Ref&& r); - const typename RefValue::Type* operator->() const { - if (!ptr) { - CHECK(ptr && "deferencing null Ref"); - throw NullRef{}; - } - return RefValue::make_const_ptr(ptr); - } - const typename RefValue::Type& operator*() const { - if (!ptr) { - CHECK(ptr && "deferencing null Ref"); - throw NullRef{}; - } - return RefValue::make_const_ref(ptr); - } - const T* get() const { - return ptr; - } - bool is_null() const { - return ptr == 0; - } - bool not_null() const { - return ptr != 0; - } - bool is_unique() const { - if (!ptr) { - CHECK(ptr && "defererencing null Ref"); - throw NullRef{}; - } - return ptr->is_unique(); - } - void clear() { - if (ptr) { - ///std::cout << "(r- " << (const void*)ptr << ")"; - release_shared(ptr); - ptr = 0; - } - } - void swap(Ref& r) { - std::swap(ptr, r.ptr); - } - Ref& operator^=(const Ref& r); - Ref& operator^=(Ref&& r); - Ref& operator&=(bool retain); - bool operator==(const Ref& r) const; - bool operator!=(const Ref& r) const; - typename RefValue::Type& write(); - typename RefValue::Type& unique_write() const; - - public: - template - static void release_shared(S* obj, int cnt = 1) { - if (obj->dec(cnt)) { - detail::safe_delete(obj); - } - } - template - static void acquire_shared(S* obj, int cnt = 1) { - obj->inc(cnt); - } - - private: - void assign(T* p) { - ptr = p; - if (p) { - acquire_shared(p); - ///std::cout << "(r+ " << (const void*)ptr << ")"; - } - } -}; - -template -Ref make_ref(Args&&... args) { - return Ref{true, std::forward(args)...}; -} - -template -Ref> make_cnt_ref(Args&&... args) { - return Ref>{true, std::forward(args)...}; -} - -template -td::StringBuilder& operator<<(td::StringBuilder& sb, const Ref& ref) { - if (ref.is_null()) { - return sb << "nullptr"; - } - return sb << *ref; -} - -template -Ref& Ref::operator=(const Ref& r) { - if (ptr != r.ptr) { - clear(); - assign(r.ptr); - } - return *this; -} - -template -template -Ref& Ref::operator=(const Ref& r) { - if (ptr != static_cast(r.ptr)) { - clear(); - assign(r.ptr); - } - return *this; -} - -template -Ref& Ref::operator=(Ref&& r) { - clear(); - ptr = r.ptr; - r.ptr = 0; - return *this; -} - -template -template -Ref& Ref::operator=(Ref&& r) { - clear(); - ptr = r.ptr; - r.ptr = 0; - return *this; -} - -template -typename RefValue::Type& Ref::write() { - if (!ptr) { - throw CntObject::WriteError(); - } - if (!ptr->is_unique()) { - T* copy = dynamic_cast(ptr->make_copy()); - if (!copy) { - throw CntObject::WriteError(); - } - release_shared(ptr); - ptr = copy; - } - return RefValue::make_ref(ptr); -} - -template -typename RefValue::Type& Ref::unique_write() const { - if (!ptr || !ptr->is_unique()) { - throw CntObject::WriteError(); - } - return RefValue::make_ref(ptr); -} - -template -Ref& Ref::operator^=(const Ref& r) { - if (r.ptr && r.ptr != ptr) { - clear(); - assign(r.ptr); - } - return *this; -} - -template -Ref& Ref::operator^=(Ref&& r) { - if (r.ptr && r.ptr != ptr) { - clear(); - ptr = r.ptr; - r.ptr = 0; - } - return *this; -} - -template -Ref& Ref::operator&=(bool retain) { - if (!retain && ptr) { - clear(); - } - return *this; -} - -template -bool Ref::operator==(const Ref& r) const { - return ptr == r.ptr; -} - -template -bool Ref::operator!=(const Ref& r) const { - return ptr != r.ptr; -} - -template -void swap(Ref& r1, Ref& r2) { - r1.swap(r2); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/refint.cpp b/submodules/ton/tonlib-src/crypto/common/refint.cpp deleted file mode 100644 index b79750ce..00000000 --- a/submodules/ton/tonlib-src/crypto/common/refint.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "common/refint.h" -#include -#include - -#include "td/utils/StringBuilder.h" -#include "td/utils/Slice.h" - -namespace td { - -template class Cnt; -template class Ref>; - -RefInt256 operator+(RefInt256 x, RefInt256 y) { - (x.write() += *y).normalize(); - return x; -} - -RefInt256 operator+(RefInt256 x, long long y) { - x.write().add_tiny(y).normalize(); - return x; -} - -RefInt256 operator+(RefInt256 x, const BigInt256& y) { - (x.write() += y).normalize(); - return x; -} - -RefInt256 operator-(RefInt256 x, RefInt256 y) { - (x.write() -= *y).normalize(); - return x; -} - -RefInt256 operator-(RefInt256 x, long long y) { - x.write().add_tiny(-y).normalize(); - return x; -} - -RefInt256 operator-(RefInt256 x, const BigInt256& y) { - (x.write() -= y).normalize(); - return x; -} - -RefInt256 operator-(RefInt256 x) { - x.write().negate().normalize(); - return x; -} - -RefInt256 operator~(RefInt256 x) { - x.write().logical_not().normalize(); - return x; -} - -RefInt256 operator*(RefInt256 x, RefInt256 y) { - RefInt256 z{true, 0}; - z.write().add_mul(*x, *y).normalize(); - return z; -} - -RefInt256 operator*(RefInt256 x, long long y) { - x.write().mul_short_opt(y).normalize(); - return x; -} - -RefInt256 operator*(RefInt256 x, const BigInt256& y) { - RefInt256 z{true, 0}; - z.write().add_mul(*x, y).normalize(); - return z; -} - -RefInt256 operator/(RefInt256 x, RefInt256 y) { - RefInt256 quot{true}; - x.write().mod_div(*y, quot.write()); - quot.write().normalize(); - return quot; -} - -RefInt256 div(RefInt256 x, RefInt256 y, int round_mode) { - RefInt256 quot{true}; - x.write().mod_div(*y, quot.write(), round_mode); - quot.write().normalize(); - return quot; -} - -RefInt256 operator%(RefInt256 x, RefInt256 y) { - BigInt256 quot; - x.write().mod_div(*y, quot); - return x; -} - -RefInt256 mod(RefInt256 x, RefInt256 y, int round_mode) { - BigInt256 quot; - x.write().mod_div(*y, quot, round_mode); - return x; -} - -std::pair divmod(RefInt256 x, RefInt256 y, int round_mode) { - RefInt256 quot{true}; - x.write().mod_div(*y, quot.write(), round_mode); - quot.write().normalize(); - return std::make_pair(std::move(quot), std::move(x)); -} - -RefInt256 muldiv(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode) { - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y); - RefInt256 quot{true}; - tmp.mod_div(*z, quot.unique_write(), round_mode); - quot.write().normalize(); - return quot; -} - -std::pair muldivmod(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode) { - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y); - RefInt256 quot{true}; - tmp.mod_div(*z, quot.unique_write(), round_mode); - quot.write().normalize(); - return std::make_pair(std::move(quot), td::make_refint(tmp)); -} - -RefInt256 operator&(RefInt256 x, RefInt256 y) { - x.write() &= *y; - return x; -} - -RefInt256 operator|(RefInt256 x, RefInt256 y) { - x.write() |= *y; - return x; -} - -RefInt256 operator^(RefInt256 x, RefInt256 y) { - x.write() ^= *y; - return x; -} - -RefInt256 operator<<(RefInt256 x, int y) { - (x.write() <<= y).normalize(); - return x; -} - -RefInt256 operator>>(RefInt256 x, int y) { - (x.write() >>= y).normalize(); - return x; -} - -RefInt256 rshift(RefInt256 x, int y, int round_mode) { - x.write().rshift(y, round_mode).normalize(); - return x; -} - -RefInt256& operator+=(RefInt256& x, RefInt256 y) { - (x.write() += *y).normalize(); - return x; -} - -RefInt256& operator+=(RefInt256& x, long long y) { - x.write().add_tiny(y).normalize(); - return x; -} - -RefInt256& operator+=(RefInt256& x, const BigInt256& y) { - (x.write() += y).normalize(); - return x; -} - -RefInt256& operator-=(RefInt256& x, RefInt256 y) { - (x.write() -= *y).normalize(); - return x; -} - -RefInt256& operator-=(RefInt256& x, long long y) { - x.write().add_tiny(-y).normalize(); - return x; -} - -RefInt256& operator-=(RefInt256& x, const BigInt256& y) { - (x.write() -= y).normalize(); - return x; -} - -RefInt256& operator*=(RefInt256& x, RefInt256 y) { - RefInt256 z{true, 0}; - z.write().add_mul(*x, *y).normalize(); - return x = z; -} - -RefInt256& operator*=(RefInt256& x, long long y) { - x.write().mul_short_opt(y).normalize(); - return x; -} - -RefInt256& operator*=(RefInt256& x, const BigInt256& y) { - RefInt256 z{true, 0}; - z.write().add_mul(*x, y).normalize(); - return x = z; -} - -RefInt256& operator/=(RefInt256& x, RefInt256 y) { - RefInt256 quot{true}; - x.write().mod_div(*y, quot.write()); - quot.write().normalize(); - return x = quot; -} - -RefInt256& operator%=(RefInt256& x, RefInt256 y) { - BigInt256 quot; - x.write().mod_div(*y, quot); - return x; -} - -RefInt256& operator&=(RefInt256& x, RefInt256 y) { - x.write() &= *y; - return x; -} - -RefInt256& operator|=(RefInt256& x, RefInt256 y) { - x.write() |= *y; - return x; -} - -RefInt256& operator^=(RefInt256& x, RefInt256 y) { - x.write() ^= *y; - return x; -} - -RefInt256& operator<<=(RefInt256& x, int y) { - (x.write() <<= y).normalize(); - return x; -} - -RefInt256& operator>>=(RefInt256& x, int y) { - (x.write() >>= y).normalize(); - return x; -} - -int cmp(RefInt256 x, RefInt256 y) { - return x->cmp(*y); -} - -int cmp(RefInt256 x, long long y) { - return x->cmp(y); -} - -int sgn(RefInt256 x) { - return x->sgn(); -} - -RefInt256 make_refint(long long x) { - return td::RefInt256{true, td::Normalize(), x}; -} - -RefInt256 zero_refint() { - // static RefInt256 Zero = td::RefInt256{true, 0}; - // return Zero; - return td::RefInt256{true, 0}; -} - -RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd) { - td::RefInt256 x{true}; - x.unique_write().import_bits(bits, n, sgnd); - return x; -} - -std::string dec_string(RefInt256 x) { - return x.is_null() ? "(null)" : (x.is_unique() ? x.unique_write().to_dec_string_destroy() : x->to_dec_string()); -} - -std::string dec_string2(RefInt256&& x) { - return x.is_null() ? "(null)" : (x.is_unique() ? x.unique_write().to_dec_string_destroy() : x->to_dec_string()); -} - -std::string hex_string(RefInt256 x, bool upcase, int zero_pad) { - return x.is_null() ? "(null)" : x->to_hex_string(upcase, zero_pad); -} - -std::string binary_string(RefInt256 x) { - return x.is_null() ? "(null)" : x->to_binary_string(); -} - -std::ostream& operator<<(std::ostream& os, const RefInt256& x) { - //std::cout << ""; - //return os; -} - -std::ostream& operator<<(std::ostream& os, RefInt256&& x) { - //std::cout << ""; - //return os; -} - -StringBuilder& operator<<(StringBuilder& sb, const RefInt256& x) { - return sb << dec_string(x); -} - -RefInt256 dec_string_to_int256(const std::string& s) { - return dec_string_to_int256(td::Slice{s}); -} - -RefInt256 dec_string_to_int256(td::Slice s) { - if (s.size() > 255) { - return {}; - } - RefInt256 x{true}; - if (x.unique_write().parse_dec(s.begin(), (int)s.size()) == (int)s.size()) { - return x; - } else { - return {}; - } -} - -RefInt256 hex_string_to_int256(const std::string& s) { - return hex_string_to_int256(td::Slice{s}); -} - -RefInt256 hex_string_to_int256(td::Slice s) { - if (s.size() > 255) { - return {}; - } - RefInt256 x{true}; - if (x.unique_write().parse_hex(s.begin(), (int)s.size()) == (int)s.size()) { - return x; - } else { - return {}; - } -} - -RefInt256 string_to_int256(const std::string& s) { - return string_to_int256(td::Slice{s}); -} - -RefInt256 string_to_int256(td::Slice s) { - if (s.size() >= 3 && s[0] == '-' && s[1] == '0' && s[2] == 'x') { - auto x = hex_string_to_int256(td::Slice(s.begin() + 3, s.end())); - if (x.not_null()) { - x.write().negate(); - } - return x; - } else if (s.size() >= 2 && s[0] == '0' && s[1] == 'x') { - return hex_string_to_int256(td::Slice(s.begin() + 2, s.end())); - } else { - return dec_string_to_int256(s); - } -} - -namespace literals { - -RefInt256 operator""_ri256(const char* str, std::size_t str_len) { - RefInt256 x{true}; - x->enforce(x.unique_write().parse_dec(str, (int)str_len) == (int)str_len); - return x; -} - -RefInt256 operator""_rx256(const char* str, std::size_t str_len) { - RefInt256 x{true}; - x->enforce(x.unique_write().parse_hex(str, (int)str_len) == (int)str_len); - return x; -} - -} // namespace literals -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/refint.h b/submodules/ton/tonlib-src/crypto/common/refint.h deleted file mode 100644 index 488ae97f..00000000 --- a/submodules/ton/tonlib-src/crypto/common/refint.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include -#include - -namespace td { -class StringBuilder; - -extern template class Cnt; -extern template class Ref>; -typedef Cnt CntInt256; -typedef Ref RefInt256; - -extern RefInt256 operator+(RefInt256 x, RefInt256 y); -extern RefInt256 operator+(RefInt256 x, long long y); -extern RefInt256 operator+(RefInt256 x, const BigInt256& y); -extern RefInt256 operator-(RefInt256 x, RefInt256 y); -extern RefInt256 operator-(RefInt256 x, long long y); -extern RefInt256 operator-(RefInt256 x, const BigInt256& y); -extern RefInt256 operator*(RefInt256 x, RefInt256 y); -extern RefInt256 operator*(RefInt256 x, long long y); -extern RefInt256 operator*(RefInt256 x, const BigInt256& y); -extern RefInt256 operator/(RefInt256 x, RefInt256 y); -extern RefInt256 operator%(RefInt256 x, RefInt256 y); -extern RefInt256 div(RefInt256 x, RefInt256 y, int round_mode = -1); -extern RefInt256 mod(RefInt256 x, RefInt256 y, int round_mode = -1); -extern std::pair divmod(RefInt256 x, RefInt256 y, int round_mode = -1); -extern RefInt256 muldiv(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode = -1); -extern std::pair muldivmod(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode = -1); -extern RefInt256 operator-(RefInt256 x); -extern RefInt256 operator&(RefInt256 x, RefInt256 y); -extern RefInt256 operator|(RefInt256 x, RefInt256 y); -extern RefInt256 operator^(RefInt256 x, RefInt256 y); -extern RefInt256 operator~(RefInt256 x); -extern RefInt256 operator<<(RefInt256 x, int y); -extern RefInt256 operator>>(RefInt256 x, int y); -extern RefInt256 rshift(RefInt256 x, int y, int round_mode = -1); - -extern RefInt256& operator+=(RefInt256& x, RefInt256 y); -extern RefInt256& operator+=(RefInt256& x, long long y); -extern RefInt256& operator+=(RefInt256& x, const BigInt256& y); -extern RefInt256& operator-=(RefInt256& x, RefInt256 y); -extern RefInt256& operator-=(RefInt256& x, long long y); -extern RefInt256& operator-=(RefInt256& x, const BigInt256& y); -extern RefInt256& operator*=(RefInt256& x, RefInt256 y); -extern RefInt256& operator*=(RefInt256& x, long long y); -extern RefInt256& operator*=(RefInt256& x, const BigInt256& y); -extern RefInt256& operator/=(RefInt256& x, RefInt256 y); -extern RefInt256& operator%=(RefInt256& x, RefInt256 y); - -extern RefInt256& operator&=(RefInt256& x, RefInt256 y); -extern RefInt256& operator|=(RefInt256& x, RefInt256 y); -extern RefInt256& operator^=(RefInt256& x, RefInt256 y); -extern RefInt256& operator<<=(RefInt256& x, int y); -extern RefInt256& operator>>=(RefInt256& x, int y); - -template -bool operator==(RefInt256 x, T y) { - return cmp(x, y) == 0; -} - -template -bool operator!=(RefInt256 x, T y) { - return cmp(x, y) != 0; -} - -template -bool operator<(RefInt256 x, T y) { - return cmp(x, y) < 0; -} - -template -bool operator>(RefInt256 x, T y) { - return cmp(x, y) > 0; -} - -template -bool operator<=(RefInt256 x, T y) { - return cmp(x, y) <= 0; -} - -template -bool operator>=(RefInt256 x, T y) { - return cmp(x, y) >= 0; -} - -extern int cmp(RefInt256 x, RefInt256 y); -extern int cmp(RefInt256 x, long long y); -extern int sgn(RefInt256 x); - -template -RefInt256 make_refint(Args&&... args) { - return td::RefInt256{true, std::forward(args)...}; -} - -extern RefInt256 make_refint(long long x); - -extern RefInt256 zero_refint(); -extern RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd = false); - -extern std::string dec_string(RefInt256 x); -extern std::string dec_string2(RefInt256&& x); -extern std::string hex_string(RefInt256 x, bool upcase = false, int zero_pad = 0); -extern std::string binary_string(RefInt256 x); - -extern RefInt256 dec_string_to_int256(const std::string& s); -extern RefInt256 dec_string_to_int256(td::Slice s); -extern RefInt256 hex_string_to_int256(const std::string& s); -extern RefInt256 hex_string_to_int256(td::Slice s); -extern RefInt256 string_to_int256(const std::string& s); -extern RefInt256 string_to_int256(td::Slice s); - -extern std::ostream& operator<<(std::ostream& os, const RefInt256& x); -extern std::ostream& operator<<(std::ostream& os, RefInt256&& x); -extern td::StringBuilder& operator<<(td::StringBuilder& os, const RefInt256& x); - -namespace literals { - -extern RefInt256 operator""_ri256(const char* str, std::size_t str_len); -extern RefInt256 operator""_rx256(const char* str, std::size_t str_len); - -} // namespace literals -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/util.cpp b/submodules/ton/tonlib-src/crypto/common/util.cpp deleted file mode 100644 index d1b24a76..00000000 --- a/submodules/ton/tonlib-src/crypto/common/util.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "util.h" - -#include - -#include "td/utils/crypto.h" -#include "td/utils/base64.h" - -namespace td { - -std::size_t compute_base64_encoded_size(size_t bindata_size) { - return ((bindata_size + 2) / 3) << 2; -} - -const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -const char base64_url_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -const unsigned char base64_dec_table[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7e, 0, 0xbe, 0, 0x7f, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, - 0xfd, 0, 0, 0, 1, 0, 0, 0, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, - 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0, 0, 0, 0, - 0xbf, 0, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0, 0, 0, 0, 0}; - -std::size_t buff_base64_encode(td::MutableSlice buffer, td::Slice raw, bool base64_url) { - std::size_t orig_size = raw.size(), res_size = compute_base64_encoded_size(orig_size); - if (res_size > buffer.size()) { - return 0; - } - const char *table = base64_url ? base64_url_table : base64_table; - char *wptr = buffer.data(); - unsigned x; - std::size_t i; - for (i = 0; i < orig_size - 2; i += 3) { - x = (((unsigned)(unsigned char)raw[i]) << 16) | (((unsigned)(unsigned char)raw[i + 1]) << 8) | - ((unsigned)(unsigned char)raw[i + 2]); - *wptr++ = table[(x >> 18) & 0x3f]; - *wptr++ = table[(x >> 12) & 0x3f]; - *wptr++ = table[(x >> 6) & 0x3f]; - *wptr++ = table[x & 0x3f]; - } - switch (orig_size - i) { - case 1: - x = (((unsigned)(unsigned char)raw[i]) << 16); - *wptr++ = table[(x >> 18) & 0x3f]; - *wptr++ = table[(x >> 12) & 0x3f]; - *wptr++ = '='; - *wptr++ = '='; - break; - case 2: - x = (((unsigned)(unsigned char)raw[i]) << 16) | (((unsigned)(unsigned char)raw[i + 1]) << 8); - *wptr++ = table[(x >> 18) & 0x3f]; - *wptr++ = table[(x >> 12) & 0x3f]; - *wptr++ = table[(x >> 6) & 0x3f]; - *wptr++ = '='; - } - CHECK(wptr == buffer.data() + res_size); - return res_size; -} - -std::string str_base64_encode(td::Slice raw, bool base64_url) { - std::size_t res_size = compute_base64_encoded_size(raw.size()); - std::string s; - s.resize(res_size); - if (res_size) { - buff_base64_encode(td::MutableSlice{const_cast(s.data()), s.size()}, raw, base64_url); - } - return s; -} - -bool is_valid_base64(td::Slice encoded, bool allow_base64_url) { - const unsigned char *ptr = (const unsigned char *)encoded.data(), *end = ptr + encoded.size(); - if (encoded.size() & 3) { - return false; - } - unsigned mode = (allow_base64_url ? 0xc0 : 0x40); - while (ptr < end && (base64_dec_table[*ptr] & mode)) { - ptr++; - } - std::size_t d = end - ptr; - if (d > 2) { - return false; - } - while (ptr < end && *ptr == '=') { - ptr++; - } - return ptr == end; -} - -td::int32 decoded_base64_size(td::Slice encoded, bool allow_base64_url) { - const unsigned char *ptr = (const unsigned char *)encoded.data(), *end = ptr + encoded.size(); - if (encoded.size() & 3) { - return -1; - } - if (encoded.size() > static_cast(std::numeric_limits::max())) { - return -1; - } - if (end == ptr) { - return 0; - } - auto s = static_cast((encoded.size() >> 2) * 3); - if (end[-1] == '=') { - s--; - if (end[-2] == '=') { - s--; - } - } - return s; -} - -std::size_t buff_base64_decode(td::MutableSlice buffer, td::Slice encoded, bool allow_base64_url) { - if ((encoded.size() & 3) || !encoded.size()) { - return 0; - } - std::size_t n = (encoded.size() >> 2); - const unsigned char *ptr = (const unsigned char *)encoded.data(), *end = ptr + encoded.size(); - unsigned q = (end[-1] == '=' ? (end[-2] == '=' ? 2 : 1) : 0); - if (buffer.size() + q < n * 3) { - return 0; - } - unsigned char *wptr = (unsigned char *)buffer.data(), *wend = wptr + buffer.size(); - unsigned mode = (allow_base64_url ? 0xc0 : 0x40); - for (std::size_t i = 0; i < n; i++) { - unsigned x = 0; - for (std::size_t j = 0; j < 4; j++) { - unsigned z = base64_dec_table[ptr[4 * i + j]]; - if (!(z & mode) && z != 1 && (i < n - 1 || j + q < 4)) { - return 0; - } - x = (x << 6) | (z & 0x3f); - } - if (i < n - 1) { - *wptr++ = (unsigned char)(x >> 16); - *wptr++ = (unsigned char)(x >> 8); - *wptr++ = (unsigned char)x; - } else { - for (; q < 3; q++) { - *wptr++ = (unsigned char)(x >> 16); - x <<= 8; - } - break; - } - } - CHECK(wptr <= wend); - return wptr - (unsigned char *)buffer.data(); -} - -td::BufferSlice base64_decode(td::Slice encoded, bool allow_base64_url) { - auto s = decoded_base64_size(encoded, allow_base64_url); - if (s <= 0) { - return td::BufferSlice{}; - } - td::BufferSlice res{static_cast(s)}; - auto r = buff_base64_decode(res.as_slice(), encoded, allow_base64_url); - if (!r) { - return td::BufferSlice{}; - } - CHECK(r == static_cast(s)); - return res; -} - -std::string str_base64_decode(td::Slice encoded, bool allow_base64_url) { - auto s = decoded_base64_size(encoded, allow_base64_url); - if (s <= 0) { - return std::string{}; - } - std::string res; - res.resize(static_cast(s)); - auto r = buff_base64_decode(td::MutableSlice{const_cast(res.data()), res.size()}, encoded, allow_base64_url); - if (!r) { - return std::string{}; - } - CHECK(r == static_cast(s)); - return res; -} - -td::Result adnl_id_encode(td::Slice id, bool upper_case) { - if (id.size() != 32) { - return td::Status::Error("Wrong andl id size"); - } - td::uint8 buf[35]; - td::MutableSlice buf_slice(buf, 35); - buf_slice[0] = 0x2d; - buf_slice.substr(1).copy_from(id); - auto hash = td::crc16(buf_slice.substr(0, 33)); - buf[33] = static_cast((hash >> 8) & 255); - buf[34] = static_cast(hash & 255); - return td::base32_encode(buf_slice, upper_case).substr(1); -} - -std::string adnl_id_encode(td::Bits256 adnl_addr, bool upper_case) { - return adnl_id_encode(adnl_addr.as_slice(), upper_case).move_as_ok(); -} - -td::Result adnl_id_decode(td::Slice id) { - if (id.size() != 55) { - return td::Status::Error("Wrong length of adnl id"); - } - td::uint8 buf[56]; - buf[0] = 'f'; - td::MutableSlice buf_slice(buf, 56); - buf_slice.substr(1).copy_from(id); - TRY_RESULT(decoded_str, td::base32_decode(buf_slice)); - auto decoded = td::Slice(decoded_str); - if (decoded[0] != 0x2d) { - return td::Status::Error("Invalid first byte"); - } - auto got_hash = (decoded.ubegin()[33] << 8) | decoded.ubegin()[34]; - auto hash = td::crc16(decoded.substr(0, 33)); - if (hash != got_hash) { - return td::Status::Error("Hash mismatch"); - } - Bits256 res; - res.as_slice().copy_from(decoded.substr(1, 32)); - return res; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/common/util.h b/submodules/ton/tonlib-src/crypto/common/util.h deleted file mode 100644 index e6b8ec2e..00000000 --- a/submodules/ton/tonlib-src/crypto/common/util.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include "td/utils/Slice.h" -#include "td/utils/buffer.h" - -#include "bitstring.h" - -namespace td { - -std::size_t compute_base64_encoded_size(size_t bindata_size); -std::size_t buff_base64_encode(td::MutableSlice buffer, td::Slice raw, bool base64_url = false); -std::string str_base64_encode(td::Slice raw, bool base64_url = false); - -bool is_valid_base64(td::Slice encoded, bool allow_base64_url = true); -td::int32 decoded_base64_size(td::Slice encoded, bool allow_base64_url = true); - -std::size_t buff_base64_decode(td::MutableSlice buffer, td::Slice data, bool allow_base64_url = true); -td::BufferSlice base64_decode(td::Slice encoded, bool allow_base64_url = true); -std::string str_base64_decode(td::Slice encoded, bool allow_base64_url = true); - -//TODO: move it somewhere else -td::Result adnl_id_encode(td::Slice id, bool upper_case = false); -std::string adnl_id_encode(Bits256 adnl_addr, bool upper_case = false); -td::Result adnl_id_decode(td::Slice id); - -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.cpp b/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.cpp deleted file mode 100644 index a38eb079..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "Ed25519.h" - -#include "td/utils/Random.h" - -namespace crypto { -namespace Ed25519 { - -bool all_bytes_same(const unsigned char *str, std::size_t size) { - unsigned char c = str[0]; - for (std::size_t i = 0; i < size; i++) { - if (str[i] != c) { - return false; - } - } - return true; -} - -void PublicKey::clear(void) { - if (inited != pk_empty) { - std::memset(pubkey, 0, pubkey_bytes); - PubKey.zeroize(); - PubKey_xz.zeroize(); - } - inited = pk_empty; -} - -PublicKey::PublicKey(const unsigned char pub_key[pubkey_bytes]) - : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - import_public_key(pub_key); -} - -PublicKey::PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key) - : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - import_public_key(Pub_Key); -} - -bool PublicKey::import_public_key(const unsigned char pub_key[pubkey_bytes]) { - clear(); - if (all_bytes_same(pub_key, pubkey_bytes)) { - return false; - } - bool ok = false; - PubKey = ellcurve::Ed25519().import_point(pub_key, ok); - if (!ok) { - clear(); - return false; - } - std::memcpy(pubkey, pub_key, pubkey_bytes); - PubKey_xz.X = PubKey.Z + PubKey.Y; - PubKey_xz.Z = PubKey.Z - PubKey.Y; - inited = pk_init; - return true; -} - -bool PublicKey::import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key) { - clear(); - if (!Pub_Key.is_valid()) { - return false; - } - PubKey = Pub_Key; - PubKey_xz.X = PubKey.Z + PubKey.Y; - PubKey_xz.Z = PubKey.Z - PubKey.Y; - inited = pk_init; - - if (!PubKey.export_point(pubkey)) { - clear(); - return false; - } - return true; -} - -bool PublicKey::export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const { - if (inited != pk_init) { - std::memset(pubkey_buffer, 0, pubkey_bytes); - return false; - } else { - std::memcpy(pubkey_buffer, pubkey, pubkey_bytes); - return true; - } -} - -bool PublicKey::check_message_signature(const unsigned char signature[sign_bytes], const unsigned char *message, - std::size_t msg_size) { - if (inited != pk_init) { - return false; - } - unsigned char hash[64]; - { - digest::SHA512 hasher(signature, 32); - hasher.feed(pubkey, 32); - hasher.feed(message, msg_size); - hasher.extract(hash); - } - auto &E = ellcurve::Ed25519(); - const arith::Bignum &L = E.get_ell(); - arith::Bignum H, S; - S.import_lsb(signature + 32, 32); - H.import_lsb(hash, 64); - H %= L; - H = L - H; - auto sG = E.power_gen(S); - auto hA = E.power_point(PubKey, H); - auto pR1 = E.add_points(sG, hA); - unsigned char pR1_bytes[32]; - if (!pR1.export_point(pR1_bytes)) { - return false; - } - return !std::memcmp(pR1_bytes, signature, 32); -} - -// --------------------- -class PrivateKey; - -bool PrivateKey::random_private_key(bool strong) { - inited = false; - if (!prng::rand_gen().rand_bytes(privkey, privkey_bytes, strong)) { - clear(); - return false; - } - return process_private_key(); -} - -void PrivateKey::clear(void) { - std::memset(privkey, 0, privkey_bytes); - std::memset(priv_salt, 0, sizeof(priv_salt)); - priv_exp.clear(); - PubKey.clear(); - inited = false; -} - -bool PrivateKey::import_private_key(const unsigned char pk[privkey_bytes]) { - clear(); - if (all_bytes_same(pk, privkey_bytes)) { - return false; - } - std::memcpy(privkey, pk, privkey_bytes); - return process_private_key(); -} - -bool PrivateKey::export_private_key(unsigned char pk[privkey_bytes]) const { // careful! - if (!inited) { - std::memset(pk, 0, privkey_bytes); - return false; - } else { - std::memcpy(pk, privkey, privkey_bytes); - return true; - } -} - -bool PrivateKey::process_private_key() { - unsigned char buff[64]; - digest::hash_str(buff, privkey, privkey_bytes); - std::memcpy(priv_salt, buff + 32, 32); - buff[0] = (unsigned char)(buff[0] & -8); - buff[31] = (unsigned char)((buff[31] | 0x40) & ~0x80); - priv_exp.import_lsb(buff, 32); - PubKey = ellcurve::Ed25519().power_gen(priv_exp, true); // uniform - inited = PubKey.ok(); - if (!inited) { - clear(); - } - return inited; -} - -bool PrivateKey::compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey &Pub) { - if (!inited || !Pub.ok()) { - std::memset(secret, 0, shared_secret_bytes); - *(long *)secret = static_cast(td::Random::fast_uint64()); - return false; - } - // uniform power! - auto P = ellcurve::Curve25519().power_xz(Pub.get_point_xz(), priv_exp); - if (P.is_infty()) { - std::memset(secret, 0, shared_secret_bytes); - *(long *)secret = static_cast(td::Random::fast_uint64()); - return false; - } - P.export_point_u(secret); - return true; -} - -bool PrivateKey::compute_temp_shared_secret(unsigned char secret[shared_secret_bytes], - const unsigned char temp_pub_key[pubkey_bytes]) { - PublicKey tempPubkey(temp_pub_key); - if (!tempPubkey.ok()) { - return false; - } - return compute_shared_secret(secret, tempPubkey); -} - -bool PrivateKey::sign_message(unsigned char signature[sign_bytes], const unsigned char *message, std::size_t msg_size) { - if (!inited) { - std::memset(signature, 0, sign_bytes); - return false; - } - unsigned char r_bytes[64]; - digest::hash_two_str(r_bytes, priv_salt, 32, message, msg_size); - const arith::Bignum &L = ellcurve::Ed25519().get_ell(); - arith::Bignum eR; - eR.import_lsb(r_bytes, 64); - eR %= L; - std::memset(r_bytes, 0, sizeof(r_bytes)); - - // uniform power - auto pR = ellcurve::Ed25519().power_gen(eR, true); - - auto ok = pR.export_point(signature, true); - (void)ok; - assert(ok); - { - digest::SHA512 hasher(signature, 32); - hasher.feed(PubKey.get_pubkey_ptr(), 32); - hasher.feed(message, msg_size); - hasher.extract(r_bytes); - } - arith::Bignum S; - S.import_lsb(r_bytes, 64); - S %= L; - S *= priv_exp; - S += eR; - S %= L; - eR.clear(); - S.export_lsb(signature + 32, 32); - return true; -} - -// --------------------------------- -class TempKeyGenerator; - -unsigned char *TempKeyGenerator::get_temp_private_key(unsigned char *to, const unsigned char *message, std::size_t size, - const unsigned char *rand, - std::size_t rand_size) { // rand may be 0 - digest::SHA256 hasher(message, size); - hasher.feed(random_salt, salt_size); - if (rand && rand_size) { - hasher.feed(rand, rand_size); - } - if (!to) { - to = buffer; - } - hasher.extract(to); - //++ *((long *)random_salt); - return to; -} - -void TempKeyGenerator::create_temp_private_key(PrivateKey &pk, const unsigned char *message, std::size_t size, - const unsigned char *rand, std::size_t rand_size) { - pk.import_private_key(get_temp_private_key(buffer, message, size, rand, rand_size)); - std::memset(buffer, 0, privkey_bytes); -} - -bool TempKeyGenerator::create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes], - unsigned char shared_secret[shared_secret_bytes], - const PublicKey &recipientPubKey, const unsigned char *message, - std::size_t size, const unsigned char *rand, std::size_t rand_size) { - PrivateKey tmpPk; - create_temp_private_key(tmpPk, message, size, rand, rand_size); - return tmpPk.export_public_key(temp_pub_key) && tmpPk.compute_shared_secret(shared_secret, recipientPubKey); -} - -} // namespace Ed25519 -} // namespace crypto diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.h b/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.h deleted file mode 100644 index 4b9e6348..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Ed25519.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "ellcurve/Montgomery.h" -#include "ellcurve/TwEdwards.h" -#include "openssl/digest.hpp" -#include "openssl/rand.hpp" -#include -#include - -#include "td/utils/buffer.h" - -namespace crypto { -namespace Ed25519 { - -const int privkey_bytes = 32; -const int pubkey_bytes = 32; -const int sign_bytes = 64; -const int shared_secret_bytes = 32; - -class PublicKey { - enum { pk_empty, pk_xz, pk_init } inited; - unsigned char pubkey[pubkey_bytes]; - ellcurve::TwEdwardsCurve::SegrePoint PubKey; - ellcurve::MontgomeryCurve::PointXZ PubKey_xz; - - public: - PublicKey() : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - } - PublicKey(const unsigned char pub_key[pubkey_bytes]); - PublicKey(td::Slice pub_key) : PublicKey(pub_key.ubegin()) { - CHECK(pub_key.size() == pubkey_bytes); - } - PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key); - - bool import_public_key(const unsigned char pub_key[pubkey_bytes]); - bool import_public_key(td::Slice pub_key) { - CHECK(pub_key.size() == pubkey_bytes); - return import_public_key(pub_key.ubegin()); - } - bool import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key); - bool export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const; - bool export_public_key(td::MutableSlice pubk) const { - CHECK(pubk.size() == pubkey_bytes); - return export_public_key(pubk.ubegin()); - } - bool check_message_signature(const unsigned char signature[sign_bytes], const unsigned char *message, - std::size_t msg_size); - bool check_message_signature(td::Slice signature, td::Slice message) { - CHECK(signature.size() == sign_bytes); - return check_message_signature(signature.ubegin(), message.ubegin(), message.size()); - } - - void clear(); - bool ok() const { - return inited == pk_init; - } - - const unsigned char *get_pubkey_ptr() const { - return inited == pk_init ? pubkey : 0; - } - const ellcurve::TwEdwardsCurve::SegrePoint &get_point() const { - return PubKey; - } - const ellcurve::MontgomeryCurve::PointXZ &get_point_xz() const { - return PubKey_xz; - } -}; - -class PrivateKey { - public: - struct priv_key_no_copy {}; - PrivateKey() : inited(false) { - memset(privkey, 0, privkey_bytes); - } - PrivateKey(const unsigned char pk[privkey_bytes]) : inited(false) { - memset(privkey, 0, privkey_bytes); - import_private_key(pk); - } - PrivateKey(td::Slice pk) : inited(false) { - CHECK(pk.size() == privkey_bytes); - memset(privkey, 0, privkey_bytes); - import_private_key(pk.ubegin()); - } - ~PrivateKey() { - clear(); - } - bool random_private_key(bool strong = false); - bool import_private_key(const unsigned char pk[privkey_bytes]); - bool import_private_key(td::Slice pk) { - CHECK(pk.size() == privkey_bytes); - return import_private_key(pk.ubegin()); - } - bool export_private_key(unsigned char pk[privkey_bytes]) const; // careful! - bool export_private_key(td::MutableSlice pk) const { // careful! - return export_private_key(pk.ubegin()); - } - bool export_public_key(unsigned char pubk[pubkey_bytes]) const { - return PubKey.export_public_key(pubk); - } - bool export_public_key(td::MutableSlice pubk) const { - return PubKey.export_public_key(pubk); - } - void clear(); - bool ok() const { - return inited; - } - - // used for EdDSA (sign) - bool sign_message(unsigned char signature[sign_bytes], const unsigned char *message, std::size_t msg_size); - bool sign_message(td::MutableSlice signature, td::Slice message) { - CHECK(signature.size() == sign_bytes); - return sign_message(signature.ubegin(), message.ubegin(), message.size()); - } - // used for ECDH (encrypt / decrypt) - bool compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey &Pub); - bool compute_shared_secret(td::MutableSlice secret, const PublicKey &Pub) { - CHECK(secret.size() == shared_secret_bytes); - return compute_shared_secret(secret.ubegin(), Pub); - } - // used for EC asymmetric decryption - bool compute_temp_shared_secret(unsigned char secret[shared_secret_bytes], - const unsigned char temp_pub_key[pubkey_bytes]); - - const PublicKey &get_public_key() const { - return PubKey; - } - - private: - bool inited; - unsigned char privkey[privkey_bytes]; - unsigned char priv_salt[32]; - arith::Bignum priv_exp; - PublicKey PubKey; - - bool process_private_key(); - PrivateKey(const PrivateKey &) { - throw priv_key_no_copy(); - } - PrivateKey &operator=(const PrivateKey &) { - throw priv_key_no_copy(); - } -}; - -// use one TempKeyGenerator object a lot of times -class TempKeyGenerator { - enum { salt_size = 64 }; - unsigned char random_salt[salt_size]; - unsigned char buffer[privkey_bytes]; - - public: - TempKeyGenerator() { - prng::rand_gen().strong_rand_bytes(random_salt, salt_size); - } - ~TempKeyGenerator() { - memset(random_salt, 0, salt_size); - memset(buffer, 0, privkey_bytes); - } - - unsigned char *get_temp_private_key(unsigned char *to, const unsigned char *message, std::size_t size, - const unsigned char *rand = 0, std::size_t rand_size = 0); // rand may be 0 - void create_temp_private_key(PrivateKey &pk, const unsigned char *message, std::size_t size, - const unsigned char *rand = 0, std::size_t rand_size = 0); - - // sets temp_pub_key and shared_secret for one-time asymmetric encryption of message - bool create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes], unsigned char secret[shared_secret_bytes], - const PublicKey &recipientPubKey, const unsigned char *message, std::size_t size, - const unsigned char *rand = 0, std::size_t rand_size = 0); -}; - -} // namespace Ed25519 -} // namespace crypto diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.cpp b/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.cpp deleted file mode 100644 index 7b248f64..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "ellcurve/Fp25519.h" - -namespace ellcurve { -using namespace arith; - -const Bignum& P25519() { - static const Bignum P25519 = (Bignum(1) << 255) - 19; - return P25519; -} - -td::Ref Fp25519() { - static const td::Ref Fp25519(true, P25519()); - return Fp25519; -} -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.h b/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.h deleted file mode 100644 index b6b63be5..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Fp25519.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "openssl/residue.h" - -namespace ellcurve { -using namespace arith; - -// returns 2^255-19 -const Bignum& P25519(); - -// residue ring modulo P25519 -td::Ref Fp25519(); - -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.cpp b/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.cpp deleted file mode 100644 index ed71910d..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "ellcurve/Montgomery.h" - -#include -#include - -namespace ellcurve { -using namespace arith; - -class MontgomeryCurve; - -void MontgomeryCurve::init() { - assert(!((a_short + 2) & 3) && a_short >= 0); -} - -void MontgomeryCurve::set_order_cofactor(const Bignum& order, int cof) { - assert(order > 0); - assert(cof >= 0); - assert(cof == 0 || (order % cof) == 0); - Order = order; - cofactor = cofactor_short = cof; - if (cof > 0) { - L = order / cof; - assert(is_prime(L)); - } - assert(!power_gen_xz(1).is_infty()); - assert(power_gen_xz(Order).is_infty()); -} - -// computes u(P+Q)*u(P-Q) as X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::add_xz(const MontgomeryCurve::PointXZ& P, - const MontgomeryCurve::PointXZ& Q) const { - Residue u = (P.X + P.Z) * (Q.X - Q.Z); - Residue v = (P.X - P.Z) * (Q.X + Q.Z); - return MontgomeryCurve::PointXZ(sqr(u + v), sqr(u - v)); -} - -// computes u(2P) as X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::double_xz(const MontgomeryCurve::PointXZ& P) const { - Residue u = sqr(P.X + P.Z); - Residue v = sqr(P.X - P.Z); - Residue w = u - v; - return PointXZ(u * v, w * (v + Residue(a_short, ring) * w)); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::power_gen_xz(const Bignum& n) const { - return power_xz(Gu, n); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const Residue& u, const Bignum& n) const { - return power_xz(PointXZ(u), n); -} - -// computes u([n]P) in form X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const PointXZ& A, const Bignum& n) const { - assert(n >= 0); - if (n == 0) { - return PointXZ(ring); - } - - int k = n.num_bits(); - PointXZ P(A); - PointXZ Q(double_xz(P)); - for (int i = k - 2; i >= 0; --i) { - PointXZ PQ(add_xz(P, Q)); - PQ.X *= A.Z; - PQ.Z *= A.X; - if (n[i]) { - P = PQ; - Q = double_xz(Q); - } else { - Q = PQ; - P = double_xz(P); - } - } - return P; -} - -bool MontgomeryCurve::PointXZ::export_point_y(unsigned char buffer[32]) const { - if ((X + Z).is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } else { - get_y().extract().export_lsb(buffer, 32); - return true; - } -} - -bool MontgomeryCurve::PointXZ::export_point_u(unsigned char buffer[32]) const { - if (Z.is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } else { - get_u().extract().export_lsb(buffer, 32); - return true; - } -} - -MontgomeryCurve::PointXZ MontgomeryCurve::import_point_u(const unsigned char point[32]) const { - Bignum u; - u.import_lsb(point, 32); - u[255] = 0; - return PointXZ(Residue(u, ring)); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::import_point_y(const unsigned char point[32]) const { - Bignum y; - y.import_lsb(point, 32); - y[255] = 0; - return PointXZ(Residue(y, ring), true); -} - -const MontgomeryCurve& Curve25519() { - static const MontgomeryCurve Curve25519 = [] { - MontgomeryCurve res(486662, 9, Fp25519()); - res.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8); - return res; - }(); - return Curve25519; -} -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.h b/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.h deleted file mode 100644 index 94d852c0..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/Montgomery.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include - -#include "openssl/bignum.h" -#include "openssl/residue.h" -#include "ellcurve/Fp25519.h" - -namespace ellcurve { -using namespace arith; - -class MontgomeryCurve { - td::Ref ring; - int A_short; // v^2 = u^2 + Au + 1 - int Gu_short; // u(G) - int a_short; // (A+2)/4 - Residue A_; - Residue Gu; - Bignum P_; - Bignum L; - Bignum Order; - Bignum cofactor; - int cofactor_short; - - void init(); - - public: - MontgomeryCurve(int _A, int _Gu, td::Ref _R) - : ring(_R) - , A_short(_A) - , Gu_short(_Gu) - , a_short((_A + 2) / 4) - , A_(_A, _R) - , Gu(_Gu, _R) - , P_(_R->get_modulus()) - , cofactor_short(0) { - init(); - } - - const Residue& get_gen_u() const { - return Gu; - } - const Bignum& get_ell() const { - return L; - } - const Bignum& get_order() const { - return Order; - } - td::Ref get_base_ring() const { - return ring; - } - const Bignum& get_p() const { - return P_; - } - - void set_order_cofactor(const Bignum& order, int cof); - - struct PointXZ { - Residue X, Z; - PointXZ(Residue x, Residue z) : X(x), Z(z) { - x.same_ring(z); - } - PointXZ(td::Ref r) : X(r->one()), Z(r->zero()) { - } - explicit PointXZ(Residue u) : X(u), Z(u.ring_of().one()) { - } - explicit PointXZ(Residue y, bool) : X(y.ring_of().one() + y), Z(y.ring_of().one() - y) { - } - PointXZ(const PointXZ& P) : X(P.X), Z(P.Z) { - } - PointXZ& operator=(const PointXZ& P) { - X = P.X; - Z = P.Z; - return *this; - } - Residue get_u() const { - return X * inverse(Z); - } - Residue get_v(bool sign_v = false) const; - bool is_infty() const { - return Z.is_zero(); - } - Residue get_y() const { - return (X - Z) * inverse(X + Z); - } - bool export_point_y(unsigned char buffer[32]) const; - bool export_point_u(unsigned char buffer[32]) const; - void zeroize() { - X = Z = Z.ring_of().zero(); - } - }; - - PointXZ power_gen_xz(const Bignum& n) const; - PointXZ power_xz(const Residue& u, const Bignum& n) const; - PointXZ power_xz(const PointXZ& P, const Bignum& n) const; - PointXZ add_xz(const PointXZ& P, const PointXZ& Q) const; - PointXZ double_xz(const PointXZ& P) const; - - PointXZ import_point_u(const unsigned char point[32]) const; - PointXZ import_point_y(const unsigned char point[32]) const; -}; - -const MontgomeryCurve& Curve25519(); - -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.cpp b/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.cpp deleted file mode 100644 index eb131f70..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "ellcurve/TwEdwards.h" -#include -#include - -namespace ellcurve { -using namespace arith; - -class TwEdwardsCurve; - -TwEdwardsCurve::TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref _R) - : ring(_R) - , D(_D) - , D2(_D + _D) - , Gy(_Gy) - , P_(_R->get_modulus()) - , cofactor_short(0) - , G(_R) - , O(_R) - , table_lines(0) - , table() { - init(); -} - -TwEdwardsCurve::~TwEdwardsCurve() { -} - -void TwEdwardsCurve::init() { - assert(D != ring->zero() && D != ring->convert(-1)); - O.X = O.Z = ring->one(); - G = SegrePoint(*this, Gy, 0); - assert(!G.XY.is_zero()); -} - -void TwEdwardsCurve::set_order_cofactor(const Bignum& order, int cof) { - assert(order > 0); - assert(cof >= 0); - assert(cof == 0 || (order % cof) == 0); - Order = order; - cofactor = cofactor_short = cof; - if (cof > 0) { - L = order / cof; - assert(is_prime(L)); - assert(!power_gen(1).is_zero()); - assert(power_gen(L).is_zero()); - } -} - -TwEdwardsCurve::SegrePoint::SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign) - : XY(y), X(E.get_base_ring()), Y(y), Z(E.get_base_ring()->one()) { - Residue x(y.ring_ref()); - if (E.recover_x(x, y, x_sign)) { - XY *= x; - X = x; - } else { - XY = Y = Z = E.get_base_ring()->zero(); - } -} - -bool TwEdwardsCurve::recover_x(Residue& x, const Residue& y, bool x_sign) const { - // recovers x from equation -x^2+y^2 = 1+d*x^2*y^2 - Residue z = inverse(ring->one() + D * sqr(y)); - if (z.is_zero()) { - return false; - } - z *= sqr(y) - ring->one(); - Residue t = sqrt(z); - if (sqr(t) == z) { - x = (t.extract().odd() == x_sign) ? t : -t; - //std::cout << "x=" << x << ", y=" << y << std::endl; - return true; - } else { - return false; - } -} - -void TwEdwardsCurve::add_points(SegrePoint& Res, const SegrePoint& P, const SegrePoint& Q) const { - Residue a((P.X + P.Y) * (Q.X + Q.Y)); - Residue b((P.X - P.Y) * (Q.X - Q.Y)); - Residue c(P.Z * Q.Z * ring->convert(2)); - Residue d(P.XY * Q.XY * D2); - Residue x_num(a - b); // 2(x1y2+x2y1) - Residue y_num(a + b); // 2(x1x2+y1y2) - Residue x_den(c + d); // 2(1+dx1x2y1y2) - Residue y_den(c - d); // 2(1-dx1x2y1y2) - Res.X = x_num * y_den; // x = x_num/x_den, y = y_num/y_den - Res.Y = y_num * x_den; - Res.XY = x_num * y_num; - Res.Z = x_den * y_den; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::add_points(const SegrePoint& P, const SegrePoint& Q) const { - SegrePoint Res(ring); - add_points(Res, P, Q); - return Res; -} - -void TwEdwardsCurve::double_point(SegrePoint& Res, const SegrePoint& P) const { - add_points(Res, P, P); -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::double_point(const SegrePoint& P) const { - SegrePoint Res(ring); - double_point(Res, P); - return Res; -} - -// computes u([n]P) in form (xy,x,y,1)*Z -TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_point(const SegrePoint& A, const Bignum& n, bool uniform) const { - assert(n >= 0); - if (n == 0) { - return O; - } - - int k = n.num_bits(); - SegrePoint P(A); - - if (uniform) { - SegrePoint Q(double_point(A)); - - for (int i = k - 2; i >= 0; --i) { - if (n[i]) { - add_points(P, P, Q); - double_point(Q, Q); - } else { - // we do more operations than necessary for uniformicity - add_points(Q, P, Q); - double_point(P, P); - } - } - } else { - for (int i = k - 2; i >= 0; --i) { - double_point(P, P); - if (n[i]) { - add_points(P, P, A); // may optimize further if A.z = 1 - } - } - } - return P; -} - -int TwEdwardsCurve::build_table() { - if (table.size()) { - return -1; - } - table_lines = (P_.num_bits() >> 2) + 2; - table.reserve(table_lines * 15 + 1); - table.emplace_back(get_base_point()); - for (int i = 0; i < table_lines; i++) { - for (int j = 0; j < 15; j++) { - table.emplace_back(add_points(table[15 * i + j], table[15 * i])); - } - } - return 1; -} - -int get_nibble(const Bignum& n, int idx) { - return n[idx * 4 + 3] * 8 + n[idx * 4 + 2] * 4 + n[idx * 4 + 1] * 2 + n[idx * 4]; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_gen(const Bignum& n, bool uniform) const { - if (uniform || n.num_bits() > table_lines * 4) { - return power_point(G, n, uniform); - } else if (n.is_zero()) { - return O; - } else { - int k = (n.num_bits() + 3) >> 2; - assert(k > 0 && k <= table_lines); - int x = get_nibble(n, k - 1); - assert(x > 0 && x < 16); - SegrePoint P(table[15 * (k - 1) + x - 1]); - for (int i = k - 2; i >= 0; i--) { - x = get_nibble(n, i); - assert(x >= 0 && x < 16); - if (x > 0) { - add_points(P, P, table[15 * i + x - 1]); - } - } - return P; - } -} - -bool TwEdwardsCurve::SegrePoint::export_point(unsigned char buffer[32], bool need_x) const { - if (!is_normalized()) { - if (Z.is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } - Residue f(inverse(Z)); - Bignum y((Y * f).extract()); - assert(!y[255]); - if (need_x) { - y[255] = (X * f).extract().odd(); - } - y.export_lsb(buffer, 32); - } else { - Bignum y(Y.extract()); - assert(!y[255]); - if (need_x) { - y[255] = X.extract().odd(); - } - y.export_lsb(buffer, 32); - } - return true; -} - -bool TwEdwardsCurve::SegrePoint::export_point_u(unsigned char buffer[32]) const { - if (Z == Y) { - std::memset(buffer, 0xff, 32); - return false; - } - Residue f(inverse(Z - Y)); - ((Z + Y) * f).extract().export_lsb(buffer, 32); - assert(!(buffer[31] & 0x80)); - return true; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::import_point(const unsigned char point[32], bool& ok) const { - Bignum y; - y.import_lsb(point, 32); - bool x_sign = y[255]; - y[255] = 0; - Residue yr(y, ring); - Residue xr(ring); - ok = recover_x(xr, yr, x_sign); - return ok ? SegrePoint(xr, yr) : SegrePoint(ring); -} - -const TwEdwardsCurve& Ed25519() { - static const TwEdwardsCurve Ed25519 = [] { - TwEdwardsCurve res(Fp25519()->frac(-121665, 121666), Fp25519()->frac(4, 5), Fp25519()); - res.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8); - res.build_table(); - return res; - }(); - return Ed25519; -} -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.h b/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.h deleted file mode 100644 index c720ecca..00000000 --- a/submodules/ton/tonlib-src/crypto/ellcurve/TwEdwards.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include "common/refcnt.hpp" -#include "openssl/residue.h" -#include "ellcurve/Fp25519.h" - -namespace ellcurve { -using namespace arith; - -class TwEdwardsCurve { - public: - struct SegrePoint { - Residue XY, X, Y, Z; // if x=X/Z and y=Y/T, stores (xy,x,y,1)*Z*T - SegrePoint(td::Ref R) : XY(R), X(R), Y(R), Z(R) { - } - SegrePoint(const Residue& x, const Residue& y) : XY(x * y), X(x), Y(y), Z(y.ring_of().one()) { - } - SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign); - SegrePoint(const SegrePoint& P) : XY(P.XY), X(P.X), Y(P.Y), Z(P.Z) { - } - SegrePoint& operator=(const SegrePoint& P) { - XY = P.XY; - X = P.X; - Y = P.Y; - Z = P.Z; - return *this; - } - bool is_zero() const { - return X.is_zero() && (Y == Z); - } - bool is_valid() const { - return (XY * Z == X * Y) && !(XY.is_zero() && X.is_zero() && Y.is_zero() && Z.is_zero()); - } - bool is_finite() const { - return !Z.is_zero(); - } - bool is_normalized() const { - return Z == Z.ring_of().one(); - } - SegrePoint& normalize() { - auto f = inverse(Z); - XY *= f; - X *= f; - Y *= f; - Z = Z.ring_of().one(); - return *this; - } - SegrePoint& zeroize() { - XY = X = Y = Z = Z.ring_of().zero(); - return *this; - } - bool export_point(unsigned char buffer[32], bool need_x = true) const; - bool export_point_y(unsigned char buffer[32]) const { - return export_point(buffer, false); - } - bool export_point_u(unsigned char buffer[32]) const; - Residue get_y() const { - return Y * inverse(Z); - } - Residue get_x() const { - return X * inverse(Z); - } - Residue get_u() const { - return (Z + Y) * inverse(Z - Y); - } - void negate() { - XY.negate(); - X.negate(); - } - }; - - private: - td::Ref ring; - Residue D; - Residue D2; - Residue Gy; - Bignum P_; - Bignum L; - Bignum Order; - Bignum cofactor; - int cofactor_short; - SegrePoint G; - SegrePoint O; - int table_lines; - std::vector table; - - void init(); - - public: - TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref _R); - ~TwEdwardsCurve(); - const Residue& get_gen_y() const { - return Gy; - } - const Bignum& get_ell() const { - return L; - } - const Bignum& get_order() const { - return Order; - } - td::Ref get_base_ring() const { - return ring; - } - const Bignum& get_p() const { - return P_; - } - const SegrePoint& get_base_point() const { - return G; - } - - void set_order_cofactor(const Bignum& order, int cof); - bool recover_x(Residue& x, const Residue& y, bool x_sign) const; - - void add_points(SegrePoint& R, const SegrePoint& P, const SegrePoint& Q) const; - SegrePoint add_points(const SegrePoint& P, const SegrePoint& Q) const; - void double_point(SegrePoint& R, const SegrePoint& P) const; - SegrePoint double_point(const SegrePoint& P) const; - SegrePoint power_point(const SegrePoint& A, const Bignum& n, bool uniform = false) const; - SegrePoint power_gen(const Bignum& n, bool uniform = false) const; - int build_table(); - - SegrePoint import_point(const unsigned char point[32], bool& ok) const; -}; - -std::ostream& operator<<(std::ostream& os, const TwEdwardsCurve::SegrePoint& P); -const TwEdwardsCurve& Ed25519(); -} // namespace ellcurve diff --git a/submodules/ton/tonlib-src/crypto/fift/Dictionary.cpp b/submodules/ton/tonlib-src/crypto/fift/Dictionary.cpp deleted file mode 100644 index 34a4b246..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/Dictionary.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "Dictionary.h" - -namespace fift { - -// -// WordDef -// -void WordDef::run(IntCtx& ctx) const { - auto next = run_tail(ctx); - while (next.not_null()) { - next = next->run_tail(ctx); - } -} - -// -// StackWord -// -Ref StackWord::run_tail(IntCtx& ctx) const { - f(ctx.stack); - return {}; -} - -// -// CtxWord -// -Ref CtxWord::run_tail(IntCtx& ctx) const { - f(ctx); - return {}; -} - -// -// CtxTailWord -// -Ref CtxTailWord::run_tail(IntCtx& ctx) const { - return f(ctx); -} - -// -// WordList -// -WordList::WordList(std::vector>&& _list) : list(std::move(_list)) { -} - -WordList::WordList(const std::vector>& _list) : list(_list) { -} - -WordList& WordList::push_back(Ref word_def) { - list.push_back(std::move(word_def)); - return *this; -} - -WordList& WordList::push_back(WordDef& wd) { - list.emplace_back(&wd); - return *this; -} - -Ref WordList::run_tail(IntCtx& ctx) const { - if (list.empty()) { - return {}; - } - auto it = list.cbegin(), it2 = list.cend() - 1; - while (it < it2) { - (*it)->run(ctx); - ++it; - } - return *it; -} - -void WordList::close() { - list.shrink_to_fit(); -} - -WordList& WordList::append(const std::vector>& other) { - list.insert(list.end(), other.begin(), other.end()); - return *this; -} - -// -// WordRef -// - -WordRef::WordRef(Ref _def, bool _act) : def(std::move(_def)), active(_act) { -} - -WordRef::WordRef(StackWordFunc func) : def(Ref{true, std::move(func)}), active(false) { -} - -WordRef::WordRef(CtxWordFunc func, bool _act) : def(Ref{true, std::move(func)}), active(_act) { -} - -WordRef::WordRef(CtxTailWordFunc func, bool _act) : def(Ref{true, std::move(func)}), active(_act) { -} - -Ref WordRef::get_def() const & { - return def; -} - -Ref WordRef::get_def() && { - return std::move(def); -} - -void WordRef::operator()(IntCtx& ctx) const { - def->run(ctx); -} - -bool WordRef::is_active() const { - return active; -} - -// -// Dictionary -// -WordRef* Dictionary::lookup(td::Slice name) { - auto it = words_.find(name); - if (it == words_.end()) { - return nullptr; - } - return &it->second; -} - -void Dictionary::def_ctx_word(std::string name, CtxWordFunc func) { - def_word(std::move(name), std::move(func)); -} - -void Dictionary::def_active_word(std::string name, CtxWordFunc func) { - Ref wdef = Ref{true, std::move(func)}; - def_word(std::move(name), {std::move(wdef), true}); -} - -void Dictionary::def_stack_word(std::string name, StackWordFunc func) { - def_word(std::move(name), std::move(func)); -} - -void Dictionary::def_ctx_tail_word(std::string name, CtxTailWordFunc func) { - def_word(std::move(name), std::move(func)); -} - -void Dictionary::def_word(std::string name, WordRef word) { - auto res = words_.emplace(name, std::move(word)); - LOG_IF(FATAL, !res.second) << "Cannot redefine word: " << name; -} - -void Dictionary::undef_word(td::Slice name) { - auto it = words_.find(name); - if (it == words_.end()) { - return; - } - words_.erase(it); -} - -void interpret_nop(vm::Stack& stack) { -} - -Ref Dictionary::nop_word_def = Ref{true, interpret_nop}; - -// -// functions for wordef -// -Ref pop_exec_token(vm::Stack& stack) { - stack.check_underflow(1); - auto wd_ref = stack.pop().as_object(); - if (wd_ref.is_null()) { - throw IntError{"execution token expected"}; - } - return wd_ref; -} - -Ref pop_word_list(vm::Stack& stack) { - stack.check_underflow(1); - auto wl_ref = stack.pop().as_object(); - if (wl_ref.is_null()) { - throw IntError{"word list expected"}; - } - return wl_ref; -} - -void push_argcount(vm::Stack& stack, int args) { - stack.push_smallint(args); - stack.push({vm::from_object, Dictionary::nop_word_def}); -} - -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/Dictionary.h b/submodules/ton/tonlib-src/crypto/fift/Dictionary.h deleted file mode 100644 index 4da390ca..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/Dictionary.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include - -#include "IntCtx.h" - -namespace fift { -using td::Ref; -/* - * - * WORD CLASSES - * - */ - -typedef std::function StackWordFunc; -typedef std::function CtxWordFunc; - -class WordDef : public td::CntObject { - public: - WordDef() = default; - virtual ~WordDef() override = default; - virtual Ref run_tail(IntCtx& ctx) const = 0; - void run(IntCtx& ctx) const; - virtual bool is_list() const { - return false; - } - virtual long long list_size() const { - return -1; - } - virtual const std::vector>* get_list() const { - return nullptr; - } -}; - -class StackWord : public WordDef { - StackWordFunc f; - - public: - StackWord(StackWordFunc _f) : f(std::move(_f)) { - } - ~StackWord() override = default; - Ref run_tail(IntCtx& ctx) const override; -}; - -class CtxWord : public WordDef { - CtxWordFunc f; - - public: - CtxWord(CtxWordFunc _f) : f(std::move(_f)) { - } - ~CtxWord() override = default; - Ref run_tail(IntCtx& ctx) const override; -}; - -typedef std::function(IntCtx&)> CtxTailWordFunc; - -class CtxTailWord : public WordDef { - CtxTailWordFunc f; - - public: - CtxTailWord(CtxTailWordFunc _f) : f(std::move(_f)) { - } - ~CtxTailWord() override = default; - Ref run_tail(IntCtx& ctx) const override; -}; - -class WordList : public WordDef { - std::vector> list; - - public: - ~WordList() override = default; - WordList() = default; - WordList(std::vector>&& _list); - WordList(const std::vector>& _list); - WordList& push_back(Ref word_def); - WordList& push_back(WordDef& wd); - Ref run_tail(IntCtx& ctx) const override; - void close(); - bool is_list() const override { - return true; - } - long long list_size() const override { - return (long long)list.size(); - } - const std::vector>* get_list() const override { - return &list; - } - WordList& append(const std::vector>& other); - WordList* make_copy() const override { - return new WordList(list); - } -}; - -class WordRef { - Ref def; - bool active; - - public: - WordRef() = delete; - WordRef(const WordRef& ref) = default; - WordRef(WordRef&& ref) = default; - WordRef(Ref _def, bool _act = false); - WordRef(StackWordFunc func); - WordRef(CtxWordFunc func, bool _act = false); - WordRef(CtxTailWordFunc func, bool _act = false); - //WordRef(const std::vector>& word_list); - //WordRef(std::vector>&& word_list); - WordRef& operator=(const WordRef&) = default; - WordRef& operator=(WordRef&&) = default; - Ref get_def() const &; - Ref get_def() &&; - void operator()(IntCtx& ctx) const; - bool is_active() const; - ~WordRef() = default; -}; - -/* -WordRef::WordRef(const std::vector>& word_list) : def(Ref{true, word_list}) { -} - -WordRef::WordRef(std::vector>&& word_list) : def(Ref{true, std::move(word_list)}) { -} -*/ - -/* - * - * DICTIONARIES - * - */ - -class Dictionary { - public: - WordRef* lookup(td::Slice name); - void def_ctx_word(std::string name, CtxWordFunc func); - void def_ctx_tail_word(std::string name, CtxTailWordFunc func); - void def_active_word(std::string name, CtxWordFunc func); - void def_stack_word(std::string name, StackWordFunc func); - void def_word(std::string name, WordRef word); - void undef_word(td::Slice name); - - auto begin() const { - return words_.begin(); - } - auto end() const { - return words_.end(); - } - - static Ref nop_word_def; - - private: - std::map> words_; -}; - -/* - * - * AUX FUNCTIONS FOR WORD DEFS - * - */ - -Ref pop_exec_token(vm::Stack& stack); -Ref pop_word_list(vm::Stack& stack); -void push_argcount(vm::Stack& stack, int args); -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/Fift.cpp b/submodules/ton/tonlib-src/crypto/fift/Fift.cpp deleted file mode 100644 index a2feee59..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/Fift.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "Fift.h" - -#include "words.h" - -#include "td/utils/PathView.h" - -namespace fift { - -Fift::Fift(Config config) : config_(std::move(config)) { -} - -Fift::Config& Fift::config() { - return config_; -} - -td::Result Fift::interpret_file(std::string fname, std::string current_dir, bool is_interactive) { - auto r_file = config_.source_lookup.lookup_source(fname, current_dir); - if (r_file.is_error()) { - return td::Status::Error("cannot locate file `" + fname + "`"); - } - auto file = r_file.move_as_ok(); - IntCtx ctx; - std::stringstream ss(file.data); - ctx.input_stream = &ss; - ctx.filename = td::PathView(file.path).file_name().str(); - ctx.currentd_dir = td::PathView(file.path).parent_dir().str(); - ctx.include_depth = is_interactive ? 0 : 1; - return do_interpret(ctx); -} - -td::Result Fift::interpret_istream(std::istream& stream, std::string current_dir, bool is_interactive) { - IntCtx ctx; - ctx.input_stream = &stream; - ctx.filename = "stdin"; - ctx.currentd_dir = current_dir; - ctx.include_depth = is_interactive ? 0 : 1; - return do_interpret(ctx); -} - -td::Result Fift::do_interpret(IntCtx& ctx) { - ctx.ton_db = &config_.ton_db; - ctx.source_lookup = &config_.source_lookup; - ctx.dictionary = &config_.dictionary; - ctx.output_stream = config_.output_stream; - ctx.error_stream = config_.error_stream; - if (!ctx.output_stream) { - return td::Status::Error("Cannot run interpreter without output_stream"); - } - try { - return funny_interpret_loop(ctx); - } catch (fift::IntError ab) { - return td::Status::Error(ab.msg); - } catch (fift::Quit q) { - return q.res; - } - return 0; -} -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/Fift.h b/submodules/ton/tonlib-src/crypto/fift/Fift.h deleted file mode 100644 index a57eef0e..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/Fift.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "SourceLookup.h" -#include "vm/db/TonDb.h" -#include "Dictionary.h" - -#include "td/utils/Status.h" - -namespace fift { -struct IntCtx; -int funny_interpret_loop(IntCtx& ctx); - -struct Fift { - public: - struct Config { - fift::SourceLookup source_lookup; - vm::TonDb ton_db; - fift::Dictionary dictionary; - std::ostream* output_stream{&std::cout}; - std::ostream* error_stream{&std::cerr}; - }; - // Fift must own ton_db and dictionary, no concurrent access is allowed - explicit Fift(Config config); - - td::Result interpret_file(std::string fname, std::string current_dir, bool interactive = false); - td::Result interpret_istream(std::istream& stream, std::string current_dir, bool interactive = true); - - Config& config(); - - private: - Config config_; - - td::Result do_interpret(IntCtx& ctx); -}; -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/IntCtx.cpp b/submodules/ton/tonlib-src/crypto/fift/IntCtx.cpp deleted file mode 100644 index d77a14a2..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/IntCtx.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "IntCtx.h" - -namespace fift { - -td::StringBuilder& operator<<(td::StringBuilder& os, const IntCtx& ctx) { - if (ctx.include_depth) { - return os << ctx.filename << ":" << ctx.line_no << ": "; - } else { - return os; - } -} - -std::ostream& operator<<(std::ostream& os, const IntCtx& ctx) { - return os << (PSLICE() << ctx).c_str(); -} - -void CharClassifier::import_from_string(td::Slice str, int space_cls) { - set_char_class(' ', space_cls); - set_char_class('\t', space_cls); - int cls = 3; - for (char c : str) { - if (c == ' ') { - cls--; - } else { - set_char_class(c, cls); - } - } -} - -void CharClassifier::import_from_string(std::string str, int space_cls) { - import_from_string(td::Slice{str}, space_cls); -} - -void CharClassifier::import_from_string(const char* str, int space_cls) { - import_from_string(td::Slice{str}, space_cls); -} - -CharClassifier CharClassifier::from_string(td::Slice str, int space_cls) { - return CharClassifier{str, space_cls}; -} - -void CharClassifier::set_char_class(int c, int cl) { - c &= 0xff; - cl &= 3; - int offs = (c & 3) * 2; - int mask = (3 << offs); - cl <<= offs; - unsigned char* p = data_ + (c >> 2); - *p = static_cast((*p & ~mask) | cl); -} - -IntCtx::Savepoint::Savepoint(IntCtx& _ctx, std::string new_filename, std::string new_current_dir, - std::istream* new_input_stream) - : ctx(_ctx) - , old_line_no(_ctx.line_no) - , old_need_line(_ctx.need_line) - , old_filename(_ctx.filename) - , old_current_dir(_ctx.currentd_dir) - , old_input_stream(_ctx.input_stream) - , old_curline(_ctx.str) - , old_curpos(_ctx.input_ptr - _ctx.str.c_str()) { - ctx.line_no = 0; - ctx.filename = new_filename; - ctx.currentd_dir = new_current_dir; - ctx.input_stream = new_input_stream; - ctx.str = ""; - ctx.input_ptr = 0; - ++(ctx.include_depth); -} - -IntCtx::Savepoint::~Savepoint() { - ctx.line_no = old_line_no; - ctx.need_line = old_need_line; - ctx.filename = old_filename; - ctx.currentd_dir = old_current_dir; - ctx.input_stream = old_input_stream; - ctx.str = old_curline; - ctx.input_ptr = ctx.str.c_str() + old_curpos; - --(ctx.include_depth); -} - -bool IntCtx::load_next_line() { - if (!std::getline(*input_stream, str)) { - return false; - } - need_line = false; - if (!str.empty() && str.back() == '\r') { - str.pop_back(); - } - set_input(str); - return true; -} - -bool IntCtx::is_sb() const { - return !eof() && line_no == 1 && *input_ptr == '#' && input_ptr[1] == '!'; -} - -td::Slice IntCtx::scan_word_to(char delim, bool err_endl) { - load_next_line_ifreq(); - auto ptr = input_ptr; - while (*ptr && *ptr != delim) { - ptr++; - } - if (*ptr) { - std::swap(ptr, input_ptr); - return td::Slice{ptr, input_ptr++}; - } else if (err_endl && delim) { - throw IntError{std::string{"end delimiter `"} + delim + "` not found"}; - } else { - need_line = true; - std::swap(ptr, input_ptr); - return td::Slice{ptr, input_ptr}; - } -} - -td::Slice IntCtx::scan_word() { - skipspc(true); - auto ptr = input_ptr; - while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\r') { - ptr++; - } - auto ptr2 = ptr; - std::swap(ptr, input_ptr); - skipspc(); - return td::Slice{ptr, ptr2}; -} - -td::Slice IntCtx::scan_word_ext(const CharClassifier& classifier) { - skipspc(true); - auto ptr = input_ptr; - while (*ptr && *ptr != '\r' && *ptr != '\n') { - int c = classifier.classify(*ptr); - if ((c & 1) && ptr != input_ptr) { - break; - } - ptr++; - if (c & 2) { - break; - } - } - std::swap(ptr, input_ptr); - return td::Slice{ptr, input_ptr}; -} - -void IntCtx::skipspc(bool skip_eol) { - do { - while (*input_ptr == ' ' || *input_ptr == '\t' || *input_ptr == '\r') { - ++input_ptr; - } - if (!skip_eol || *input_ptr) { - break; - } - } while (load_next_line()); -} - -void check_compile(const IntCtx& ctx) { - if (ctx.state <= 0) { - throw IntError{"compilation mode only"}; - } -} - -void check_execute(const IntCtx& ctx) { - if (ctx.state != 0) { - throw IntError{"interpret mode only"}; - } -} - -void check_not_int_exec(const IntCtx& ctx) { - if (ctx.state < 0) { - throw IntError{"not allowed in internal interpret mode"}; - } -} - -void check_int_exec(const IntCtx& ctx) { - if (ctx.state >= 0) { - throw IntError{"internal interpret mode only"}; - } -} -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/IntCtx.h b/submodules/ton/tonlib-src/crypto/fift/IntCtx.h deleted file mode 100644 index 7d2e0967..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/IntCtx.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "crypto/vm/db/TonDb.h" // FIXME -#include "crypto/vm/stack.hpp" -#include "crypto/common/bitstring.h" - -#include -#include -#include -#include - -namespace fift { -class Dictionary; -class SourceLookup; - -struct IntError { - std::string msg; - IntError(std::string _msg) : msg(_msg) { - } -}; - -class CharClassifier { - unsigned char data_[64]; - - public: - CharClassifier() { - std::memset(data_, 0, sizeof(data_)); - } - CharClassifier(td::Slice str, int space_cls = 3) : CharClassifier() { - import_from_string(str, space_cls); - } - CharClassifier(std::string str, int space_cls = 3) : CharClassifier(td::Slice{str}, space_cls) { - } - CharClassifier(const char* str, int space_cls = 3) : CharClassifier(td::Slice{str}, space_cls) { - } - void import_from_string(td::Slice str, int space_cls = 3); - void import_from_string(std::string str, int space_cls = 3); - void import_from_string(const char* str, int space_cls = 3); - static CharClassifier from_string(td::Slice str, int space_cls = 3); - void set_char_class(int c, int cl); - int classify(int c) const { - c &= 0xff; - int offs = (c & 3) * 2; - return (data_[(unsigned)c >> 2] >> offs) & 3; - } -}; - -struct IntCtx { - vm::Stack stack; - int state{0}; - int include_depth{0}; - int line_no{0}; - bool need_line{true}; - std::string filename; - std::string currentd_dir; - std::istream* input_stream{nullptr}; - std::ostream* output_stream{nullptr}; - std::ostream* error_stream{nullptr}; - - vm::TonDb* ton_db{nullptr}; - Dictionary* dictionary{nullptr}; - SourceLookup* source_lookup{nullptr}; - int* now{nullptr}; - - private: - std::string str; - const char* input_ptr; - - public: - IntCtx() = default; - - operator vm::Stack&() { - return stack; - } - - td::Slice scan_word_to(char delim, bool err_endl = true); - td::Slice scan_word(); - td::Slice scan_word_ext(const CharClassifier& classifier); - void skipspc(bool skip_eol = false); - - bool eof() const { - return !*input_stream; - } - - bool not_eof() const { - return !eof(); - } - - void set_input(std::string input_str) { - str = input_str; - input_ptr = str.c_str(); - ++line_no; - } - void set_input(const char* ptr) { - input_ptr = ptr; - } - const char* get_input() const { - return input_ptr; - } - - bool load_next_line(); - bool load_next_line_ifreq() { - return need_line && load_next_line(); - } - - bool is_sb() const; - - void clear() { - state = 0; - stack.clear(); - } - class Savepoint { - IntCtx& ctx; - int old_line_no; - bool old_need_line; - std::string old_filename; - std::string old_current_dir; - std::istream* old_input_stream; - std::string old_curline; - std::ptrdiff_t old_curpos; - - public: - Savepoint(IntCtx& _ctx, std::string new_filename, std::string new_current_dir, std::istream* new_input_stream); - ~Savepoint(); - }; -}; - -void check_compile(const IntCtx& ctx); -void check_execute(const IntCtx& ctx); -void check_not_int_exec(const IntCtx& ctx); -void check_int_exec(const IntCtx& ctx); - -td::StringBuilder& operator<<(td::StringBuilder& os, const IntCtx& ctx); -std::ostream& operator<<(std::ostream& os, const IntCtx& ctx); -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.cpp b/submodules/ton/tonlib-src/crypto/fift/SourceLookup.cpp deleted file mode 100644 index cd80e314..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "SourceLookup.h" - -#include "td/utils/PathView.h" -#include "td/utils/PathView.h" -#include "td/utils/port/path.h" -#include "td/utils/filesystem.h" - -#include - -namespace fift { -td::Result OsFileLoader::read_file(td::CSlice filename) { - File res; - TRY_RESULT(data, td::read_file_str(filename)); - res.data = std::move(data); - TRY_RESULT(path, td::realpath(filename)); - res.path = std::move(path); - return std::move(res); -} - -td::Status OsFileLoader::write_file(td::CSlice filename, td::Slice data) { - return td::write_file(filename, data); -} - -td::Result OsFileLoader::read_file_part(td::CSlice filename, td::int64 size, td::int64 offset) { - File res; - TRY_RESULT(data, td::read_file_str(filename, size, offset)); - res.data = std::move(data); - TRY_RESULT(path, td::realpath(filename)); - res.path = std::move(path); - return std::move(res); -} - -bool OsFileLoader::is_file_exists(td::CSlice filename) { - return td::stat(filename).is_ok(); -} - -void SourceLookup::add_include_path(td::string path) { - if (path.empty()) { - return; - } - if (!td::PathView(path).is_dir()) { - path += TD_DIR_SLASH; - } - - source_include_path_.push_back(std::move(path)); -} - -td::Result SourceLookup::lookup_source(std::string filename, std::string current_dir) { - CHECK(file_loader_); - if (!current_dir.empty() && !td::PathView(current_dir).is_dir()) { - current_dir += TD_DIR_SLASH; - } - if (td::PathView(filename).is_absolute()) { - return read_file(filename); - } - if (!current_dir.empty()) { - auto res = read_file(current_dir + filename); - if (res.is_ok()) { - return res; - } - } - for (auto& dir : source_include_path_) { - auto res = read_file(dir + filename); - if (res.is_ok()) { - return res; - } - } - - return td::Status::Error(PSLICE() << "failed to lookup file: " << filename); -} -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h b/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h deleted file mode 100644 index 816ad667..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include - -#include "td/utils/Status.h" -#include "td/utils/Time.h" - -namespace fift { -class FileLoader { - public: - virtual ~FileLoader() = default; - struct File { - std::string data; - std::string path; - }; - virtual td::Result read_file(td::CSlice filename) = 0; - virtual td::Status write_file(td::CSlice filename, td::Slice data) = 0; - virtual td::Result read_file_part(td::CSlice filename, td::int64 size, td::int64 offset) = 0; - virtual bool is_file_exists(td::CSlice filename) = 0; -}; - -class OsFileLoader : public FileLoader { - public: - td::Result read_file(td::CSlice filename) override; - td::Status write_file(td::CSlice filename, td::Slice data) override; - td::Result read_file_part(td::CSlice filename, td::int64 size, td::int64 offset) override; - bool is_file_exists(td::CSlice filename) override; -}; - -class OsTime { - public: - virtual ~OsTime() = default; - virtual td::uint32 now() = 0; -}; - -//TODO: rename SourceLookup -class SourceLookup { - public: - SourceLookup() = default; - explicit SourceLookup(std::unique_ptr file_loader, std::unique_ptr os_time = {}) - : file_loader_(std::move(file_loader)), os_time_(std::move(os_time)) { - } - void set_os_time(std::unique_ptr os_time) { - os_time_ = std::move(os_time); - } - void add_include_path(td::string path); - td::Result lookup_source(std::string filename, std::string current_dir); - - td::Result read_file(td::CSlice path) { - return file_loader_->read_file(path); - } - td::Status write_file(td::CSlice path, td::Slice data) { - return file_loader_->write_file(path, data); - } - td::Result read_file_part(td::CSlice filename, td::int64 size, td::int64 offset) { - return file_loader_->read_file_part(filename, size, offset); - } - bool is_file_exists(td::CSlice filename) { - return file_loader_->is_file_exists(filename); - } - td::uint32 now() { - if (os_time_) { - return os_time_->now(); - } - return static_cast(td::Clocks::system()); - } - - protected: - std::unique_ptr file_loader_; - std::unique_ptr os_time_; - std::vector source_include_path_; -}; -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/fift-main.cpp b/submodules/ton/tonlib-src/crypto/fift/fift-main.cpp deleted file mode 100644 index 077cdecc..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/fift-main.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/stack.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Fift.h" -#include "Dictionary.h" -#include "SourceLookup.h" -#include "words.h" - -#include "vm/db/TonDb.h" - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Parser.h" -#include "td/utils/port/path.h" - -void usage(const char* progname) { - std::cerr << "A simple Fift interpreter. Type `bye` to quit, or `words` to get a list of all commands\n"; - std::cerr - << "usage: " << progname - << " [-i] [-n] [-I ] {-L } ...\n"; - std::cerr << "\t-n\tDo not preload standard preamble file `Fift.fif`\n" - "\t-i\tForce interactive mode even if explicit source file names are indicated\n" - "\t-I\tSets colon-separated library source include path. If not indicated, " - "$FIFTPATH is used instead.\n" - "\t-L\tPre-loads a library source file\n" - "\t-d\tUse a ton database\n" - "\t-s\tScript mode: use first argument as a fift source file and import remaining arguments as $n)\n" - "\t-v\tSet verbosity level\n"; - std::exit(2); -} - -void parse_include_path_set(std::string include_path_set, std::vector& res) { - td::Parser parser(include_path_set); - while (!parser.empty()) { - auto path = parser.read_till_nofail(':'); - if (!path.empty()) { - res.push_back(path.str()); - } - parser.skip_nofail(':'); - } -} - -int main(int argc, char* const argv[]) { - bool interactive = false; - bool fift_preload = true, no_env = false; - bool script_mode = false; - std::vector library_source_files, source_list; - std::vector source_include_path; - std::string ton_db_path; - - fift::Fift::Config config; - - int i; - int new_verbosity_level = VERBOSITY_NAME(INFO); - while (!script_mode && (i = getopt(argc, argv, "hinI:L:d:sv:")) != -1) { - switch (i) { - case 'i': - interactive = true; - break; - case 'n': - fift_preload = false; - break; - case 'I': - parse_include_path_set(optarg, source_include_path); - no_env = true; - break; - case 'L': - library_source_files.emplace_back(optarg); - break; - case 'd': - ton_db_path = optarg; - break; - case 's': - script_mode = true; - break; - case 'v': - new_verbosity_level = VERBOSITY_NAME(FATAL) + td::to_integer(td::Slice(optarg)); - break; - case 'h': - default: - usage(argv[0]); - } - } - SET_VERBOSITY_LEVEL(new_verbosity_level); - - while (optind < argc) { - source_list.emplace_back(argv[optind++]); - if (script_mode) { - break; - } - } - - if (!no_env) { - const char* path = std::getenv("FIFTPATH"); - parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path); - } - std::string current_dir; - auto r_current_dir = td::realpath("."); - if (r_current_dir.is_ok()) { - current_dir = r_current_dir.move_as_ok(); - source_include_path.push_back(current_dir); - } - config.source_lookup = fift::SourceLookup(std::make_unique()); - for (auto& path : source_include_path) { - config.source_lookup.add_include_path(path); - } - - if (!ton_db_path.empty()) { - auto r_ton_db = vm::TonDbImpl::open(ton_db_path); - if (r_ton_db.is_error()) { - LOG(ERROR) << "Error opening ton database: " << r_ton_db.error().to_string(); - std::exit(2); - } - config.ton_db = r_ton_db.move_as_ok(); - // FIXME //std::atexit([&] { config.ton_db.reset(); }); - } - - fift::init_words_common(config.dictionary); - fift::init_words_vm(config.dictionary, true); // enable vm debug - fift::init_words_ton(config.dictionary); - - if (script_mode) { - fift::import_cmdline_args(config.dictionary, source_list.empty() ? "" : source_list[0], argc - optind, - argv + optind); - } - - fift::Fift fift(std::move(config)); - - if (fift_preload) { - auto status = fift.interpret_file("Fift.fif", ""); - if (status.is_error()) { - LOG(ERROR) << "Error interpreting standard preamble file `Fift.fif`: " << status.error().message() - << "\nCheck that correct include path is set by -I or by FIFTPATH environment variable, or disable " - "standard preamble by -n.\n"; - std::exit(2); - } - } - - for (auto source : library_source_files) { - auto status = fift.interpret_file(source, ""); - if (status.is_error()) { - LOG(ERROR) << "Error interpreting preloaded file `" << source << "`: " << status.error().message(); - std::exit(2); - } - } - - if (source_list.empty()) { - interactive = true; - } - for (const auto& source : source_list) { - bool is_stdin = (source.empty() || source == "-"); - auto status = - !is_stdin ? fift.interpret_file(source, current_dir) : fift.interpret_istream(std::cin, current_dir, false); - if (status.is_error()) { - if (!is_stdin) { - LOG(ERROR) << "Error interpreting file `" << source << "`: " << status.error().message(); - } else { - LOG(ERROR) << "Error interpreting stdin: " << status.error().message(); - } - std::exit(2); - } - auto res = status.move_as_ok(); - if (res) { - std::exit(~res); - } - } - if (interactive) { - auto status = fift.interpret_istream(std::cin, current_dir); - if (status.is_error()) { - LOG(ERROR) << status.error().message(); - std::exit(2); - } else { - int res = status.move_as_ok(); - if (res) { - std::exit(~res); - } - } - } -} diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif deleted file mode 100644 index a2d22af2..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif +++ /dev/null @@ -1,1290 +0,0 @@ -library TVM_Asm -// simple TVM Assembler -variable @atend -{ "not in asm context" abort } @atend ! -{ `normal eq? not abort"must be terminated by }>" } : @normal? -{ @atend @ 1 { @atend ! @normal? } does @atend ! } : @pushatend -{ @pushatend -{ }> b> } : }>c -{ }>c s -{ @atend @ 2 { @atend ! rot b> ref, swap @endblk } does @atend ! = -rot <= and } : 2x<= -{ 2 pick brembitrefs 1- 2x<= } : @havebitrefs -{ @havebits ' @| ifnot } : @ensurebits -{ @havebitrefs ' @| ifnot } : @ensurebitrefs -{ rot over @ensurebits -rot u, } : @simpleuop -{ tuck sbitrefs @ensurebitrefs swap s, } : @addop -{ tuck bbitrefs @ensurebitrefs swap b+ } : @addopb -' @addopb : @inline -{ 1 ' @addop does create } : @Defop -{ 1 { } : si() -// x mi ma -- ? -{ rot tuck >= -rot <= and } : @range -{ rot tuck < -rot > or } : @-range -{ @-range abort"Out of range" } : @rangechk -{ dup 0 < over 255 > or abort"Invalid stack register number" si() } : s() -{ si() constant } : @Sreg --2 @Sreg s(-2) --1 @Sreg s(-1) -0 @Sreg s0 -1 @Sreg s1 -2 @Sreg s2 -3 @Sreg s3 -4 @Sreg s4 -5 @Sreg s5 -6 @Sreg s6 -7 @Sreg s7 -8 @Sreg s8 -9 @Sreg s9 -10 @Sreg s10 -11 @Sreg s11 -12 @Sreg s12 -13 @Sreg s13 -14 @Sreg s14 -15 @Sreg s15 -{ dup 0 < over 7 > or abort"Invalid control register number" } : c() -{ c() constant } : @Creg -0 @Creg c0 -1 @Creg c1 -2 @Creg c2 -3 @Creg c3 -4 @Creg c4 -5 @Creg c5 -7 @Creg c7 -{ abort"not a stack register" 12 i@+ s> } : @bigsridx -{ @bigsridx dup 16 >= over 0< or abort"stack register s0..s15 expected" } : @sridx -{ rot @bigsridx tuck < -rot tuck > rot or abort"stack register out of range" } : @sridxrange -{ swap @bigsridx + dup 16 >= over 0< or abort"stack register out of range" } : @sridx+ -{ swap 0xcc <> over 7 > or over 6 = or abort"not a control register c0..c5 or c7" } : @cridx -{ = - { tuck 16 >= - { = and - { 15 and abort"integer too large" 8 + 2dup fits } until - > 2- 5 u, -rot i, - } cond - } cond - } cond - @addopb } dup : PUSHINT : INT -{ = or abort"invalid slice padding" - swap 1 1 u, 0 rot u, } : @scomplete -{ tuck sbitrefs swap 17 + swap @havebitrefs not - { PUSHREFSLICE } - { over sbitrefs 2dup 123 0 2x<= - { drop tuck 4 + 3 >> swap x{8B} s, over 4 u, 3 roll s, - -rot 3 << 4 + swap - @scomplete } - { 2dup 1 >= swap 248 <= and - { rot x{8C} s, swap 1- 2 u, over 7 + 3 >> tuck 5 u, 3 roll s, - -rot 3 << 1 + swap - @scomplete } - { rot x{8D} s, swap 3 u, over 2 + 3 >> tuck 7 u, 3 roll s, - -rot 3 << 6 + swap - @scomplete - } cond - } cond - } cond -} dup : PUSHSLICE : SLICE -// ( b' -- ? ) -{ bbitrefs or 0= } : @cont-empty? -{ bbits 7 and 0= } : @cont-aligned? -// ( b b' -- ? ) -{ bbitrefs over 7 and { 2drop drop false } { - swap 16 + swap @havebitrefs nip - } cond -} : @cont-fits? -// ( b b' -- ? ) -{ bbitrefs over 7 and { 2drop drop false } { - 32 1 pair+ @havebitrefs nip - } cond -} : @cont-ref-fit? -// ( b b' b'' -- ? ) -{ over @cont-aligned? over @cont-aligned? and not { 2drop drop false } { - bbitrefs rot bbitrefs pair+ swap 32 + swap @havebitrefs nip - } cond -} : @two-cont-fit? -{ 2dup @cont-fits? not - { b> PUSHREFCONT } - { swap over bbitrefs 2dup 120 0 2x<= - { drop swap x{9} s, swap 3 >> 4 u, swap b+ } - { rot x{8F_} s, swap 2 u, swap 3 >> 7 u, swap b+ } cond - } cond -} dup : PUSHCONT : CONT -{ }> PUSHCONT } : }>CONT -{ { @normal? PUSHCONT } @doafter<{ } : CONT:<{ - -// arithmetic operations -{ 2 { rot dup 8 fits - { nip > tuck 3 u, 3 roll s, - -rot 3 << 2 + swap - @scomplete } - { 2drop swap PUSHSLICE STSLICER } cond - } cond -} : STSLICECONST -x{CF81} @Defop STZERO -x{CF83} @Defop STONE - -// cell deserialization (CellSlice primitives) -x{D0} @Defop CTOS -x{D1} @Defop ENDS -x{D2} @Defop(8u+1) LDI -x{D3} @Defop(8u+1) LDU -x{D4} @Defop LDREF -x{D5} @Defop LDREFRTOS -x{D6} @Defop(8u+1) LDSLICE -x{D700} @Defop LDIX -x{D701} @Defop LDUX -x{D702} @Defop PLDIX -x{D703} @Defop PLDUX -x{D704} @Defop LDIXQ -x{D705} @Defop LDUXQ -x{D706} @Defop PLDIXQ -x{D707} @Defop PLDUXQ -x{D708} @Defop(8u+1) LDI_l -x{D709} @Defop(8u+1) LDU_l -x{D70A} @Defop(8u+1) PLDI -x{D70B} @Defop(8u+1) PLDU -x{D70C} @Defop(8u+1) LDIQ -x{D70D} @Defop(8u+1) LDUQ -x{D70E} @Defop(8u+1) PLDIQ -x{D70F} @Defop(8u+1) PLDUQ -{ dup 31 and abort"argument must be a multiple of 32" 5 >> 1- - > swap x{D72A_} s, over 7 u, 3 roll s, - -rot 3 << 3 + swap - @scomplete } : SDBEGINS:imm -{ tuck sbitrefs abort"no references allowed in slice" dup 26 <= - { drop > swap x{D72E_} s, over 7 u, 3 roll s, - -rot 3 << 3 + swap - @scomplete } : SDBEGINSQ:imm -{ tuck sbitrefs abort"no references allowed in slice" dup 26 <= - { drop rot 2 } { - swap @| swap 2dup @cont-fits? { rot 1 } { - b> rot 2 - } cond } cond } cond } cond - [] execute -} : @run-cont-op -{ triple 1 ' @run-cont-op does create } : @def-cont-op -{ } { PUSHCONT IF } { IFREF } @def-cont-op IF-cont -{ IFRET } { PUSHCONT IFJMP } { IFJMPREF } @def-cont-op IFJMP-cont -{ } { PUSHCONT IFNOT } { IFNOTREF } @def-cont-op IFNOT-cont -{ IFNOTRET } { PUSHCONT IFNOTJMP } { IFNOTJMPREF } @def-cont-op IFNOTJMP-cont -{ dup 2over rot } : 3dup - -recursive IFELSE-cont2 { - dup @cont-empty? { drop IF-cont } { - over @cont-empty? { nip IFNOT-cont } { - 3dup @two-cont-fit? { -rot PUSHCONT swap PUSHCONT IFELSE } { - 3dup nip @cont-ref-fit? { rot swap PUSHCONT swap b> IFREFELSE } { - 3dup drop @cont-ref-fit? { -rot PUSHCONT swap b> IFELSEREF } { - rot 32 2 @havebitrefs { rot b> rot b> IFREFELSEREF } { - @| -rot IFELSE-cont2 - } cond } cond } cond } cond } cond } cond -} swap ! - -{ }> IF-cont } : }>IF -{ }> IFNOT-cont } : }>IFNOT -{ }> IFJMP-cont } : }>IFJMP -{ }> IFNOTJMP-cont } : }>IFNOTJMP -{ { @normal? IFJMP-cont } @doafter<{ } : IFJMP:<{ -{ { @normal? IFNOTJMP-cont } @doafter<{ } : IFNOTJMP:<{ -{ `else @endblk } : }>ELSE<{ -{ `else: @endblk } : }>ELSE: -{ 1 { swap @normal? swap IFELSE-cont2 } does @doafter<{ } : @doifelse -{ 1 { swap @normal? IFELSE-cont2 } does @doafter<{ } : @doifnotelse -{ - { dup `else eq? - { drop @doifelse } - { dup `else: eq? - { drop IFJMP-cont } - { @normal? IF-cont - } cond - } cond - } @doafter<{ -} : IF:<{ -{ - { dup `else eq? - { drop @doifnotelse } - { dup `else: eq? - { drop IFNOTJMP-cont } - { @normal? IFNOT-cont - } cond - } cond - } @doafter<{ -} : IFNOT:<{ - -x{E304} @Defop CONDSEL -x{E305} @Defop CONDSELCHK -x{E308} @Defop IFRETALT -x{E309} @Defop IFNOTRETALT -{ DO<{ -{ `do: @endblk } : }>DO: -{ }> PUSHCONT REPEAT } : }>REPEAT -{ { @normal? PUSHCONT REPEAT } @doafter<{ } : REPEAT:<{ -{ }> PUSHCONT UNTIL } : }>UNTIL -{ { @normal? PUSHCONT UNTIL } @doafter<{ } : UNTIL:<{ -{ PUSHCONT { @normal? PUSHCONT WHILE } @doafter<{ } : @dowhile -{ - { dup `do eq? - { drop @dowhile } - { `do: eq? not abort"`}>DO<{` expected" PUSHCONT WHILEEND - } cond - } @doafter<{ -} : WHILE:<{ -{ }> PUSHCONT AGAIN } : }>AGAIN -{ { @normal? PUSHCONT AGAIN } @doafter<{ } : AGAIN:<{ - -x{E314} @Defop REPEATBRK -x{E315} @Defop REPEATENDBRK -x{E316} @Defop UNTILBRK -x{E317} dup @Defop UNTILENDBRK @Defop UNTILBRK: -x{E318} @Defop WHILEBRK -x{E319} @Defop WHILEENDBRK -x{E31A} @Defop AGAINBRK -x{E31B} dup @Defop AGAINENDBRK @Defop AGAINBRK: - -{ }> PUSHCONT REPEATBRK } : }>REPEATBRK -{ { @normal? PUSHCONT REPEATBRK } @doafter<{ } : REPEATBRK:<{ -{ }> PUSHCONT UNTILBRK } : }>UNTILBRK -{ { @normal? PUSHCONT UNTILBRK } @doafter<{ } : UNTILBRK:<{ -{ PUSHCONT { @normal? PUSHCONT WHILEBRK } @doafter<{ } : @dowhile -{ - { dup `do eq? - { drop @dowhile } - { `do: eq? not abort"`}>DO<{` expected" PUSHCONT WHILEENDBRK - } cond - } @doafter<{ -} : WHILEBRK:<{ -{ }> PUSHCONT AGAINBRK } : }>AGAINBRK -{ { @normal? PUSHCONT AGAINBRK } @doafter<{ } : AGAINBRK:<{ - - -// -// continuation stack manipulation and continuation creation -// -{ PUSHCONT ATEXIT } : }>ATEXIT -{ { @normal? PUSHCONT ATEXIT } @doafter<{ } : ATEXIT:<{ -x{EDF4} @Defop ATEXITALT -{ }> PUSHCONT ATEXITALT } : }>ATEXITALT -{ { @normal? PUSHCONT ATEXITALT } @doafter<{ } : ATEXITALT:<{ -x{EDF5} @Defop SETEXITALT -{ }> PUSHCONT SETEXITALT } : }>SETEXITALT -{ { @normal? PUSHCONT SETEXITALT } @doafter<{ } : SETEXITALT:<{ -x{EDF6} @Defop THENRET -x{EDF7} @Defop THENRETALT -x{EDF8} @Defop INVERT -x{EDF9} @Defop BOOLEVAL -x{EDFA} @Defop SAMEALT -x{EDFB} @Defop SAMEALTSAVE -// x{EE} is BLESSARGS -// -// dictionary subroutine call/jump primitives -{ c3 PUSH EXECUTE } : CALLVAR -{ c3 PUSH JMPX } : JMPVAR -{ c3 PUSH } : PREPAREVAR -{ dup 14 ufits { - dup 8 ufits { - CATCH<{ -{ PUSHCONT { @normal? PUSHCONT TRY } @doafter<{ } : @trycatch -{ - { `catch eq? not abort"`}>CATCH<{` expected" @trycatch - } @doafter<{ -} : TRY:<{ -// -// dictionary manipulation -' NULL : NEWDICT -' ISNULL : DICTEMPTY -' STSLICE : STDICTS -x{F400} dup @Defop STDICT @Defop STOPTREF -x{F401} dup @Defop SKIPDICT @Defop SKIPOPTREF -x{F402} @Defop LDDICTS -x{F403} @Defop PLDDICTS -x{F404} dup @Defop LDDICT @Defop LDOPTREF -x{F405} dup @Defop PLDDICT @Defop PLDOPTREF -x{F406} @Defop LDDICTQ -x{F407} @Defop PLDDICTQ - -x{F40A} @Defop DICTGET -x{F40B} @Defop DICTGETREF -x{F40C} @Defop DICTIGET -x{F40D} @Defop DICTIGETREF -x{F40E} @Defop DICTUGET -x{F40F} @Defop DICTUGETREF - -x{F412} @Defop DICTSET -x{F413} @Defop DICTSETREF -x{F414} @Defop DICTISET -x{F415} @Defop DICTISETREF -x{F416} @Defop DICTUSET -x{F417} @Defop DICTUSETREF -x{F41A} @Defop DICTSETGET -x{F41B} @Defop DICTSETGETREF -x{F41C} @Defop DICTISETGET -x{F41D} @Defop DICTISETGETREF -x{F41E} @Defop DICTUSETGET -x{F41F} @Defop DICTUSETGETREF - -x{F422} @Defop DICTREPLACE -x{F423} @Defop DICTREPLACEREF -x{F424} @Defop DICTIREPLACE -x{F425} @Defop DICTIREPLACEREF -x{F426} @Defop DICTUREPLACE -x{F427} @Defop DICTUREPLACEREF -x{F42A} @Defop DICTREPLACEGET -x{F42B} @Defop DICTREPLACEGETREF -x{F42C} @Defop DICTIREPLACEGET -x{F42D} @Defop DICTIREPLACEGETREF -x{F42E} @Defop DICTUREPLACEGET -x{F42F} @Defop DICTUREPLACEGETREF - -x{F432} @Defop DICTADD -x{F433} @Defop DICTADDREF -x{F434} @Defop DICTIADD -x{F435} @Defop DICTIADDREF -x{F436} @Defop DICTUADD -x{F437} @Defop DICTUADDREF -x{F43A} @Defop DICTADDGET -x{F43B} @Defop DICTADDGETREF -x{F43C} @Defop DICTIADDGET -x{F43D} @Defop DICTIADDGETREF -x{F43E} @Defop DICTUADDGET -x{F43F} @Defop DICTUADDGETREF - -x{F441} @Defop DICTSETB -x{F442} @Defop DICTISETB -x{F443} @Defop DICTUSETB -x{F445} @Defop DICTSETGETB -x{F446} @Defop DICTISETGETB -x{F447} @Defop DICTUSETGETB - -x{F449} @Defop DICTREPLACEB -x{F44A} @Defop DICTIREPLACEB -x{F44B} @Defop DICTUREPLACEB -x{F44D} @Defop DICTREPLACEGETB -x{F44E} @Defop DICTIREPLACEGETB -x{F44F} @Defop DICTUREPLACEGETB - -x{F451} @Defop DICTADDB -x{F452} @Defop DICTIADDB -x{F453} @Defop DICTUADDB -x{F455} @Defop DICTADDGETB -x{F456} @Defop DICTIADDGETB -x{F457} @Defop DICTUADDGETB - -x{F459} @Defop DICTDEL -x{F45A} @Defop DICTIDEL -x{F45B} @Defop DICTUDEL - -x{F462} @Defop DICTDELGET -x{F463} @Defop DICTDELGETREF -x{F464} @Defop DICTIDELGET -x{F465} @Defop DICTIDELGETREF -x{F466} @Defop DICTUDELGET -x{F467} @Defop DICTUDELGETREF - -x{F469} @Defop DICTGETOPTREF -x{F46A} @Defop DICTIGETOPTREF -x{F46B} @Defop DICTUGETOPTREF -x{F46D} @Defop DICTSETGETOPTREF -x{F46E} @Defop DICTISETGETOPTREF -x{F46F} @Defop DICTUSETGETOPTREF - -x{F470} @Defop PFXDICTSET -x{F471} @Defop PFXDICTREPLACE -x{F472} @Defop PFXDICTADD -x{F473} @Defop PFXDICTDEL - -x{F474} @Defop DICTGETNEXT -x{F475} @Defop DICTGETNEXTEQ -x{F476} @Defop DICTGETPREV -x{F477} @Defop DICTGETPREVEQ -x{F478} @Defop DICTIGETNEXT -x{F479} @Defop DICTIGETNEXTEQ -x{F47A} @Defop DICTIGETPREV -x{F47B} @Defop DICTIGETPREVEQ -x{F47C} @Defop DICTUGETNEXT -x{F47D} @Defop DICTUGETNEXTEQ -x{F47E} @Defop DICTUGETPREV -x{F47F} @Defop DICTUGETPREVEQ - -x{F482} @Defop DICTMIN -x{F483} @Defop DICTMINREF -x{F484} @Defop DICTIMIN -x{F485} @Defop DICTIMINREF -x{F486} @Defop DICTUMIN -x{F487} @Defop DICTUMINREF -x{F48A} @Defop DICTMAX -x{F48B} @Defop DICTMAXREF -x{F48C} @Defop DICTIMAX -x{F48D} @Defop DICTIMAXREF -x{F48E} @Defop DICTUMAX -x{F48F} @Defop DICTUMAXREF - -x{F492} @Defop DICTREMMIN -x{F493} @Defop DICTREMMINREF -x{F494} @Defop DICTIREMMIN -x{F495} @Defop DICTIREMMINREF -x{F496} @Defop DICTUREMMIN -x{F497} @Defop DICTUREMMINREF -x{F49A} @Defop DICTREMMAX -x{F49B} @Defop DICTREMMAXREF -x{F49C} @Defop DICTIREMMAX -x{F49D} @Defop DICTIREMMAXREF -x{F49E} @Defop DICTUREMMAX -x{F49F} @Defop DICTUREMMAXREF - -x{F4A0} @Defop DICTIGETJMP -x{F4A1} @Defop DICTUGETJMP -x{F4A2} @Defop DICTIGETEXEC -x{F4A3} @Defop DICTUGETEXEC -{ dup sbitrefs tuck 1 > swap 1 <> or abort"not a dictionary" swap 1 u@ over <> abort"not a dictionary" } : @chkdicts -{ dup null? tuck { idict! - not abort"cannot add key to procedure info dictionary" - @procinfo ! -} : @procinfo! -// ( x v1 v2 -- ) -{ not 2 pick @procinfo@ and xor swap @procinfo! } : @procinfo~! -// ( s i f -- ) -{ over @procdictkeylen fits not abort"procedure index out of range" - over swap dup @procinfo~! 2dup @proclistadd - 1 'nop does swap 0 (create) -} : @declproc -{ 1 'nop does swap 0 (create) } : @declglobvar -{ @proccnt @ 1+ dup @proccnt ! 1 @declproc } : @newproc -{ @gvarcnt @ 1+ dup @gvarcnt ! @declglobvar } : @newglobvar -{ 0 =: main @proclist null! @proccnt 0! @gvarcnt 0! - { bl word @newproc } : NEWPROC - { bl word dup (def?) ' drop ' @newproc cond } : DECLPROC - { bl word dup find - { nip execute <> abort"method redefined with different id" } - { swap 17 @declproc } - cond } : DECLMETHOD - { bl word @newglobvar } : DECLGLOBVAR - "main" 0 @proclistadd - dictnew dup @procdict ! - @procinfo ! 16 0 @procinfo! -} : PROGRAM{ -{ over sbits < { s>c } : }END> -{ }END> b> } : }END>c -{ }END>c s - -0 constant recv_internal --1 constant recv_external --2 constant run_ticktock --3 constant split_prepare --4 constant split_install - -{ asm-mode 0 3 ~! } : asm-no-remove-unused -{ asm-mode 1 1 ~! } : asm-remove-unused // enabled by default -{ asm-mode 3 3 ~! } : asm-warn-remove-unused -{ asm-mode 4 4 ~! } : asm-warn-inline-mix -{ asm-mode 0 4 ~! } : asm-no-warn-inline-mix // disabled by default -{ asm-mode 8 8 ~! } : asm-warn-unused -{ asm-mode 0 8 ~! } : asm-no-warn-unused // disabled by default - -// ( c -- ) add vm library for later use with runvmcode -{ spec } : hash>libref -// ( c -- c' ) -{ hash hash>libref } : >libref diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Color.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Color.fif deleted file mode 100644 index bd8ed7af..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Color.fif +++ /dev/null @@ -1,21 +0,0 @@ -library Color -{ 27 emit } : esc - { char " word 27 chr swap $+ 1 ' type does create } :_ make-esc" - make-esc"[0m" ^reset - make-esc"[30m" ^black - make-esc"[31m" ^red - make-esc"[32m" ^green -make-esc"[33m" ^yellow -make-esc"[34m" ^blue -make-esc"[35m" ^magenta -make-esc"[36m" ^cyan -make-esc"[37m" ^white - // bold -make-esc"[30;1m" ^Black -make-esc"[31;1m" ^Red -make-esc"[32;1m" ^Green -make-esc"[33;1m" ^Yellow -make-esc"[34;1m" ^Blue -make-esc"[35;1m" ^Magenta -make-esc"[36;1m" ^Cyan -make-esc"[37;1m" ^White diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif deleted file mode 100644 index 6c83001a..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif +++ /dev/null @@ -1,140 +0,0 @@ -{ 0 word drop 0 'nop } :: // -{ char " word 1 { swap { abort } if drop } } ::_ abort" -{ { bl word dup "" $= abort"comment extends after end of file" "*/" $= } until 0 'nop } :: /* -// { bl word 1 2 ' (create) } "::" 1 (create) -// { bl word 0 2 ' (create) } :: : -// { bl word 2 2 ' (create) } :: :_ -// { bl word 3 2 ' (create) } :: ::_ -// { bl word 0 (create) } : create -// { bl word (forget) } : forget -{ bl word 1 ' (forget) } :: [forget] -{ char " word 1 ' type } ::_ ." -{ char } word x>B 1 'nop } ::_ B{ -{ swap ({) over 2+ -roll swap (compile) (}) } : does -{ 1 'nop does create } : constant -{ 2 'nop does create } : 2constant -{ hole constant } : variable -10 constant ten -{ bl word 1 { find 0= abort"word not found" } } :: (') -{ bl word find not abort"-?" 0 swap } :: [compile] -{ bl word 1 { - dup find { " -?" $+ abort } ifnot nip execute -} } :: @' -{ bl word 1 { swap 1 'nop does swap 0 (create) } -} :: =: -{ bl word 1 { -rot 2 'nop does swap 0 (create) } -} :: 2=: -{ } : s>c -{ s>c hashB } : shash -// to be more efficiently re-implemented in C++ in the future -{ dup 0< ' negate if } : abs -{ 2dup > ' swap if } : minmax -{ minmax drop } : min -{ minmax nip } : max -"" constant <# -' $reverse : #> -{ swap 10 /mod char 0 + rot swap hold } : # -{ { # over 0<= } until } : #s -{ 0< { char - hold } if } : sign -// { dup abs <# #s rot sign #> nip } : (.) -// { (.) type } : ._ -// { ._ space } : . -{ dup 10 < { 48 } { 55 } cond + } : Digit -{ dup 10 < { 48 } { 87 } cond + } : digit -// x s b -- x' s' -{ rot swap /mod Digit rot swap hold } : B# -{ rot swap /mod digit rot swap hold } : b# -{ 16 B# } : X# -{ 16 b# } : x# -// x s b -- 0 s' -{ -rot { 2 pick B# over 0<= } until rot drop } : B#s -{ -rot { 2 pick b# over 0<= } until rot drop } : b#s -{ 16 B#s } : X#s -{ 16 b#s } : x#s -variable base -{ 10 base ! } : decimal -{ 16 base ! } : hex -{ 8 base ! } : octal -{ 2 base ! } : binary -{ base @ B# } : Base# -{ base @ b# } : base# -{ base @ B#s } : Base#s -{ base @ b#s } : base#s -// x w -- s -{ over abs <# rot 1- ' X# swap times X#s rot sign #> nip } : (0X.) -{ over abs <# rot 1- ' x# swap times x#s rot sign #> nip } : (0x.) -{ (0X.) type } : 0X._ -{ 0X._ space } : 0X. -{ (0x.) type } : 0x._ -{ 0x._ space } : 0x. -{ bl (-trailing) } : -trailing -{ char 0 (-trailing) } : -trailing0 -{ char " word 1 ' $+ } ::_ +" -{ find 0<> dup ' nip if } : (def?) -{ bl word 1 ' (def?) } :: def? -{ bl word 1 { (def?) not } } :: undef? -{ def? ' skip-to-eof if } : skip-ifdef -{ bl word dup (def?) { drop skip-to-eof } { 'nop swap 0 (create) } cond } : library -{ bl word dup (def?) { 2drop skip-to-eof } { swap 1 'nop does swap 0 (create) } cond } : library-version -{ char ) word "$" swap $+ 1 { find 0= abort"undefined parameter" execute } } ::_ $( -// b s -- ? -{ sbitrefs rot brembitrefs rot >= -rot <= and } : s-fits? -// b s x -- ? -{ swap sbitrefs -rot + rot brembitrefs -rot <= -rot <= and } : s-fits-with? -{ 0 swap ! } : 0! -{ tuck @ + swap ! } : +! -{ tuck @ swap - swap ! } : -! -{ 1 swap +! } : 1+! -{ -1 swap +! } : 1-! -{ null swap ! } : null! -{ not 2 pick @ and xor swap ! } : ~! -0 tuple constant nil -{ 1 tuple } : single -{ 2 tuple } : pair -{ 3 tuple } : triple -{ 1 untuple } : unsingle -{ 2 untuple } : unpair -{ 3 untuple } : untriple -{ over tuple? { swap count = } { 2drop false } cond } : tuple-len? -{ 0 tuple-len? } : nil? -{ 1 tuple-len? } : single? -{ 2 tuple-len? } : pair? -{ 3 tuple-len? } : triple? -{ 0 [] } : first -{ 1 [] } : second -{ 2 [] } : third -' pair : cons -' unpair : uncons -{ 0 [] } : car -{ 1 [] } : cdr -{ cdr car } : cadr -{ cdr cdr } : cddr -{ cdr cdr car } : caddr -{ null ' cons rot times } : list -{ -rot pair swap ! } : 2! -{ @ unpair } : 2@ -{ true (atom) drop } : atom -{ bl word atom 1 'nop } ::_ ` -{ hole dup 1 { @ execute } does create } : recursive -{ 0 { 1+ dup 1 ' $() does over (.) "$" swap $+ 0 (create) } rot times drop } : :$1..n -{ 10 hold } : +cr -{ 9 hold } : +tab -{ "" swap { 0 word 2dup $cmp } { rot swap $+ +cr swap } while 2drop } : scan-until-word -{ 0 word -trailing scan-until-word 1 'nop } ::_ $<< -{ 0x40 runvmx } : runvmcode -{ 0x48 runvmx } : gasrunvmcode -{ 0xc8 runvmx } : gas2runvmcode -{ 0x43 runvmx } : runvmdict -{ 0x4b runvmx } : gasrunvmdict -{ 0xcb runvmx } : gas2runvmdict -{ 0x45 runvmx } : runvm -{ 0x4d runvmx } : gasrunvm -{ 0xcd runvmx } : gas2runvm -{ 0x55 runvmx } : runvmctx -{ 0x5d runvmx } : gasrunvmctx -{ 0xdd runvmx } : gas2runvmctx -{ 0x75 runvmx } : runvmctxact -{ 0x7d runvmx } : gasrunvmctxact -{ 0xfd runvmx } : gas2runvmctxact -{ 0x35 runvmx } : runvmctxactq -{ 0x3d runvmx } : gasrunvmctxactq diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/GetOpt.fif b/submodules/ton/tonlib-src/crypto/fift/lib/GetOpt.fif deleted file mode 100644 index 442552b6..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/GetOpt.fif +++ /dev/null @@ -1,131 +0,0 @@ -library GetOpt // Simple command-line options parser -"Lists.fif" include - -// May be used as follows: -// begin-options -// "h" { ."Help Message" 0 halt } short-option -// "v" { parse-int =: verbosity } short-option-arg -// "i" "--interactive" { true =: interactive } short-long-option -// parse-options - -// ( l -- l') computes tail of list l if non-empty; else () -{ dup null? ' cdr ifnot } : safe-cdr -// ( l c -- l') deletes first c elements from list l -{ ' safe-cdr swap times } : list-delete-first -// ( l n c -- l' ) deletes c elements starting from n-th in list l -recursive list-delete-range { - dup 0<= { 2drop } { - over 0<= { nip list-delete-first } { - swap 1- swap rot uncons 2swap list-delete-range cons - } cond } cond -} swap ! -// ( n c -- ) deletes $n .. $(n+c-1) from the argument list $* -{ swap 1- $* @ swap rot list-delete-range $* ! } : $*del.. -// ( s s' -- ? ) checks whether s' is a prefix of s -{ tuck $len over $len over >= { $| drop $= } { 2drop drop false } cond -} : $pfx? -// ( s -- ? ) checks whether s is an option (a string beginning with '-') -{ dup $len 1 > { "-" $pfx? } { drop false } cond } : is-opt? -// ( s -- ? ) checks whether s is a digit option -{ 2 $| drop 1 $| nip $>B 8 B>u@ dup 57 <= swap 48 >= and } : is-digit-opt? -0 box constant disable-digit-opts -// ( l -- s i or 0 ) finds first string in l beginning with '-' -{ 0 { 1+ over null? { 2drop 0 true } { - swap uncons over is-opt? - { disable-digit-opts @ { over is-digit-opt? not } { true } cond } { false } cond - { drop swap true } { nip swap false } cond - } cond } until -} : list-find-opt -// ( -- s i or 0 ) finds first option in cmdline args -{ $* @ list-find-opt } : first-opt -' second : get-opt-flags -' first : get-opt-exec -// ( s t -- ? ) checks whether short/long option s matches description t -{ third $= } : short-option-matches -{ dup get-opt-flags 4 and 0= 3 + [] $= -} : long-option-matches -// ( t -- s -1 or 0 ) extracts help message from description -{ dup get-opt-flags 4 and 0= 4 + over count over > - { [] true } { 2drop false } cond -} : get-opt-help -// ( s l -- t -1 or 0 ) finds short/long option s in list l -{ swap 1 { swap short-option-matches } does assoc-gen -} : lookup-short-option -{ swap 1 { swap long-option-matches } does assoc-gen -} : lookup-long-option -// ( s -- s' null or s' s'' ) Splits long option --opt=arg at '=' -{ dup "=" $pos 1+ ?dup { tuck $| swap rot 1- $| drop swap } { null } cond -} : split-longopt -// ( l -- f or 0 ) Extracts global option flags from first entry of l -{ dup null? { drop 0 } { car get-opt-flags -256 and } cond -} : get-global-option-flags -variable options-list -// ( l -- i or 0 ) -// parses command line arguments according to option description list l -// and returns index i of first incorrect option -{ dup options-list ! get-global-option-flags - 256 and disable-digit-opts ! - { first-opt dup 0= { true } { - swap dup "--" $pfx? { // i s - dup $len 2 = { drop dup 1 $*del.. 0 true } { - split-longopt swap options-list @ - lookup-long-option not { drop true } { // i s' t f - dup get-opt-exec swap get-opt-flags 3 and // i s' e f' - 2 pick null? { dup 1 = } { dup 0= negate } cond // i s' e f' f'' - dup 1 = { 2drop 2drop true } { - { drop nip over 1+ $() swap execute 2 $*del.. false } { - ' nip ifnot execute 1 $*del.. false - } cond } cond } cond } cond } { // i s - 1 $| nip { - dup $len 0= { drop 1 $*del.. false true } { - 1 $| swap options-list @ // i s' s l - lookup-short-option not { drop true true } { // i s' t - dup get-opt-exec swap get-opt-flags 3 and // i s' e f' - ?dup 0= { execute false } { - 2 pick $len { drop execute "" false } { - 2 = { nip null swap execute "" false } { // i e - nip over 1+ $() swap execute 2 $*del.. false true - } cond } cond } cond } cond } cond } until - } cond - } cond } until -} : getopt -// ( t -- ) Displays help message for one option -{ dup get-opt-flags dup 4 and 2 pick third swap { - ."-" type ."/" over 3 [] type } { - dup $len { dup "--" $pfx? { ."-" } ifnot type } { - drop ."usage: " $0 type - } cond } cond - dup 3 and ?dup { - 2 = { ."[=]" } { ."=" } cond - } if - 8 and { 9 emit } ifnot - get-opt-help { type } { ."No help available" } cond cr -} : show-opt-help -// ( -- ) Displays options help message according to options-list -{ options-list @ { dup null? not } { - uncons swap show-opt-help - } while drop -} : show-options-help -// ( l -- ) Parses options and throws an error on failure -{ getopt ?dup { - $() "cannot parse command line options near `" swap $+ +"`" - show-options-help abort } if -} : run-getopt -anon constant opt-list-marker -' opt-list-marker : begin-options -{ opt-list-marker list-until-marker } : end-options -{ end-options run-getopt } : parse-options -// ( s e -- o ) Creates short/long option s with execution token e -{ 0 rot triple } dup : short-option : long-option -// ( s s' e -- o ) Creates a combined short option s and long option s' with execution token e -{ 4 2swap 4 tuple } : short-long-option -{ 1 rot triple } dup : short-option-arg : long-option-arg -{ 2 rot triple } dup : short-option-?arg : long-option-?arg -{ 5 2swap 4 tuple } : short-long-option-arg -{ 6 2swap 4 tuple } : short-long-option-?arg -// ( o s -- s' ) Adds help message to option -' , : option-help -// ( s f -- o ) Creates a generic help message -{ swap 'nop rot "" 3 roll 4 tuple } : generic-help-setopt -{ 0 generic-help-setopt } : generic-help -256 constant disable-digit-options diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Lisp.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Lisp.fif deleted file mode 100644 index fb91408d..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Lisp.fif +++ /dev/null @@ -1,436 +0,0 @@ -library Lisp // tiny Lisp (or rather Scheme) interpreter -"Lists.fif" include -variable lisp-dict -{ hole dup 1 { @ execute } does create } : recursive -{ atom>$ +" undefined" abort } : report-not-found -// a l -- d -1 or a 0 Look up definition d of atom a in dictionary l -{ { dup null? { drop false true } - { uncons -rot unpair -rot over eq? - { drop nip true true } { nip swap false } cond - } cond - } until -} : lookup-in -// a dict -- def -{ lookup-in ' report-not-found ifnot } : lookup-or-fail -{ lisp-dict @ lookup-or-fail } : lisp-dict-lookup -// a d -- Defines a with definition d in dictionary lisp-dict -{ pair lisp-dict @ cons lisp-dict ! } : lisp-dict-int-define -{ box lisp-dict-int-define } : lisp-dict-define -// a d -- Defines new a with defininition d -{ over lisp-dict @ lookup-in { 2drop atom>$ +" already defined" abort } - { drop lisp-dict-int-define } cond -} : lisp-dict-int-define-new -{ box lisp-dict-int-define-new } : lisp-dict-define-new -// a e -- Defines a with executable definition given by e -{ single lisp-dict-define-new } : lisp-dict-define-exec -// expr ctx def -- val -{ dup first execute } : run-definition -// expr ctx -- val -recursive lisp-ctx-eval { - over tuple? - { over first over lisp-ctx-eval run-definition } - { over atom? { lookup-or-fail @ } { drop } cond } - cond -} swap ! -// exp -- value -{ lisp-dict @ lisp-ctx-eval } : lisp-eval -// (exprs) ctx -- (vals) -recursive lisp-ctx-eval-list -{ over null? { drop } { - swap uncons -rot over lisp-ctx-eval -rot lisp-ctx-eval-list cons - } cond -} swap ! -// (exprs) ctx -- val -{ null rot { - dup null? { drop nip true } { - nip uncons swap 2 pick lisp-ctx-eval swap false - } cond } until -} : lisp-ctx-eval-list-last -// l c -- (args) -{ swap uncons nip swap lisp-ctx-eval-list } : extract-eval-arg-list -{ drop uncons nip } : extract-arg-list -// (x1 .. xn) e n -- x1 .. xn e -{ { swap uncons rot } swap times - swap null? not abort"invalid number of arguments" -} : unpack-list -// l c n e -- v -{ swap 2swap extract-eval-arg-list // e n (args) - -rot unpack-list execute -} : eval-exec-fixed -// l c n e -- v -{ 2 pick pair - swap 2swap extract-arg-list // [e c] n (args) - -rot unpack-list unpair swap execute -} : exec-fixed -// l c e -- v -{ -rot extract-eval-arg-list // e (args) - swap execute -} : eval-exec-list -{ -rot tuck extract-arg-list // e c (args) - swap rot execute -} : exec-list -// e a n -- -{ rot 2 { // expr ctx def n e - rot drop eval-exec-fixed } does - lisp-dict-define-exec -} : lisp-fixed-primitive -{ rot 2 { rot drop exec-fixed } does lisp-dict-define-exec -} : lisp-fixed-lazy-primitive -// e a -- -{ swap 1 { nip eval-exec-list } does lisp-dict-define-exec -} : lisp-primitive -{ swap 1 { nip exec-list } does lisp-dict-define-exec -} : lisp-lazy-primitive - -// Uncomment next line for Fift booleans -// false constant #f true constant #t null constant no-answer -// Uncomment next line for Scheme booleans -`#f constant #f `#t constant #t #f constant no-answer -{ #f eq? } : lisp-false? -{ lisp-false? 0= } : lisp-true? -{ ' #t ' #f cond } : lisp-bool - -// temp for defining a lot of primitives -{ bl word atom lisp-primitive } : L: -{ bl word atom swap lisp-dict-define } : L=: -{ bl word atom swap lisp-fixed-primitive } : #L: -{ 0 #L: } : 0L: -{ 1 #L: } : 1L: -{ 2 #L: } : 2L: - -// basic primitives -{ sum-list } L: + -{ - } 2L: - -{ dup null? { drop 1 } { ' * foldl-ne } cond } L: * -{ / } 2L: / -{ mod } 2L: modulo -{ abs } 1L: abs -{ ' min foldl-ne } L: min -{ ' max foldl-ne } L: max -{ true ' and foldl } L: integer-and -{ false ' or foldl } L: integer-or -{ 0 ' xor foldl } L: integer-xor -{ not } 1L: integer-not -{ = lisp-bool } 2L: = -{ <> lisp-bool } 2L: <> -{ < lisp-bool } 2L: < -{ <= lisp-bool } 2L: <= -{ > lisp-bool } 2L: > -{ >= lisp-bool } 2L: >= -{ eq? lisp-bool } 2L: eq? -{ eqv? lisp-bool } 2L: eqv? -{ equal? lisp-bool } 2L: equal? -{ cons } 2L: cons -{ car } 1L: car -{ cdr } 1L: cdr -{ cadr } 1L: cadr -{ cddr } 1L: cddr -{ caddr } 1L: caddr -{ cdr cddr } 1L: cdddr -{ concat-list-lists } L: append -{ list-reverse } 1L: reverse -{ list-tail } 2L: list-tail -{ list-ref } 2L: list-ref -{ list-member-eq } 2L: memq -{ list-member-eqv } 2L: memv -{ list-member-equal } 2L: member -{ assq ' #f ifnot } 2L: assq -{ assv ' #f ifnot } 2L: assv -{ assoc ' #f ifnot } 2L: assoc -{ list? lisp-bool } 1L: list? -{ pair? lisp-bool } 1L: pair? -{ tuple? lisp-bool } 1L: tuple? -{ string? lisp-bool } 1L: string? -{ integer? lisp-bool } 1L: integer? -{ integer? lisp-bool } 1L: number? -{ count } 1L: width -{ list-length } 1L: length -{ [] } 2L: tuple-ref -{ first } 1L: first -{ second } 1L: second -{ third } 1L: third -{ 3 [] } 1L: fourth -{ list>tuple } 1L: list->tuple -{ explode list } 1L: tuple->list -null L=: null -{ atom? lisp-bool } 1L: symbol? -{ atom } 1L: string->symbol -{ atom>$ } 1L: symbol->string -{ dup #f eq? swap #t eq? or lisp-bool } 1L: boolean? -#t L=: else -#f L=: #f -#t L=: #t -{ null? lisp-bool } 1L: null? -{ 0= lisp-bool } 1L: zero? -{ 0> lisp-bool } 1L: positive? -{ 0< lisp-bool } 1L: negative? -{ 1 and 0= lisp-bool } 1L: even? -{ 1 and 0<> lisp-bool } 1L: odd? -{ bye } 0L: exit -{ .l null } 1L: write -{ lisp-eval } 1L: eval -{ drop } `quote 1 lisp-fixed-lazy-primitive -'nop L: list -{ list>tuple } L: tuple -{ list-last } L: begin -{ $len } 1L: string-length -{ concat-string-list } L: string-append -{ $= lisp-bool } 2L: string=? -{ $cmp 0< lisp-bool } 2L: string lisp-bool } 2L: string>? -{ $cmp 0>= lisp-bool } 2L: string>=? -{ (number) dup 1 = { drop } { ' 2drop if no-answer } cond -} 1L: string->number -{ (.) } 1L: number->string -{ box? lisp-bool } 1L: box? -{ box } 1L: box -{ hole } 0L: new-box -{ @ } 1L: unbox -{ tuck swap ! } 2L: set-box! -{ abort } 1L: error -{ dup find { nip execute } { +" -?" abort } cond } : find-execute -{ explode-list 1- roll find-execute } L: fift-exec -{ explode-list dup 1- swap roll find-execute } L: fift-exec-cnt -{ uncons swap find-execute } L: fift-exec-list -// end of basic primitives -forget L: forget #L: forget L=: -forget 0L: forget 1L: forget 2L: - -{ { dup tuple? ' do-quote if } list-map } : map-quote -{ uncons ' cons foldr-ne map-quote - null swap cons lisp-dict @ rot run-definition -} `apply lisp-primitive // bad: should have preserved original context -// e1 e2 e3 ctx -{ 3 exch 3 pick lisp-ctx-eval lisp-true? ' swap if nip swap lisp-ctx-eval } -`if 3 lisp-fixed-lazy-primitive -// (e) ctx -{ #t -rot - { over null? { 2drop true } { - swap uncons swap 2 pick lisp-ctx-eval dup lisp-true? // v' c t v ? - { swap 2swap nip false } { -rot 2drop nip true } cond - } cond } until -} `and lisp-lazy-primitive -{ #f -rot - { over null? { 2drop true } { - swap uncons swap 2 pick lisp-ctx-eval dup lisp-false? // v' c t v ? - { swap 2swap nip false } { -rot 2drop nip true } cond - } cond } until -} `or lisp-lazy-primitive -{ lisp-false? lisp-bool } `not 1 lisp-fixed-primitive -// cond-clause ctx -- v -1 or 0 -{ swap uncons -rot dup `else eq? { - drop lisp-ctx-eval-list-last true } { - over lisp-ctx-eval lisp-true? { - lisp-ctx-eval-list-last true } { - 2drop false - } cond } cond -} : eval-cond-clause -// (clauses) ctx -- v -{ { over null? { no-answer true } { - swap uncons -rot over eval-cond-clause } cond - } until -rot 2drop -} `cond lisp-lazy-primitive -{ lisp-dict @ lookup-in { hole tuck lisp-dict-int-define } ifnot -} : lisp-create-global-var -// a e ctx -- old (simple) define -{ drop over atom? not abort"only a variable can be define'd" - over lisp-create-global-var swap lisp-eval swap ! -} drop // `define 2 lisp-fixed-lazy-primitive -{ tuck lisp-ctx-eval rot dup atom? not abort"only a variable can be set" - rot lookup-or-fail dup @ -rot ! -} `set! 2 lisp-fixed-lazy-primitive -// define lambda -{ { dup null? { drop true true } - { uncons swap atom? { false } { drop false true } cond } cond - } until -} : var-list? -{ { dup null? over atom? or { drop true true } - { uncons swap atom? { false } { drop false true } cond } cond - } until -} : lambda-var-list? -// (quote x) -- x -1 ; else 0 -{ dup pair? { uncons swap `quote eq? { car true } { drop false } cond } - { drop false } cond -} : is-quote? -recursive match-arg-list-acc -// l (vars) (args) -- ((var . arg) ...)+l -1 or ? 0 -{ over atom? { over `_ eq? { 2drop } { pair swap cons } cond true } { - over null? { nip null? } { // (vars) (args) - over tuple? not { 2drop false } { - over is-quote? { eq? nip } { // (v) (a) - dup tuple? not { 2drop false } { - over count over count over <> { drop 2drop false } { // l [v] [a] n - 3 roll 0 rot { // [v] [a] l i - dup 0< { - 3 pick over [] swap // [v] [a] l vi i - 3 pick over [] 2swap rot // [v] [a] i l vi ai - match-arg-list-acc { // [v] [a] i l' - swap 1+ } { nip -1 } cond - } ifnot - } swap times - 2swap 2drop 0>= - } cond } cond } cond } cond } cond } cond -} swap ! -{ null -rot match-arg-list-acc } : match-arg-list -// ((var . arg)...) ctx -- ctx' -{ { over null? not } - { swap uncons swap unpair box pair rot cons } while - nip -} : extend-ctx-by-list -// ((vars) body) ctx -{ swap uncons -rot - dup lambda-var-list? not abort"invalid formal parameter list" - { // l-expr ctx' [_ body ctx (vars)] - -rot 2 pick 3 [] swap rot // [_ body ...] (vars) ctx' l-expr - uncons nip swap lisp-ctx-eval-list // [_ body ...] (vars) (arg-vals) - match-arg-list not abort"invalid arguments to lambda" // [_ body ...] ((var arg)...) - over third extend-ctx-by-list // [_ body ctx (vars)] ctx'' - swap second swap lisp-ctx-eval-list-last - } 3 -roll 4 tuple -} : make-lambda -{ make-lambda } `lambda lisp-lazy-primitive -// (a e) ctx -- more sophisticated (define a e) -{ drop uncons swap dup atom? { // (e) a - tuck lisp-create-global-var - swap lisp-dict @ lisp-ctx-eval-list-last swap ! - } { // (e) (a v..) - uncons over atom? not abort"only variables can be define'd" // (e) a (v..) - rot cons over lisp-create-global-var // a ((v..) (e)) h - swap lisp-dict @ make-lambda swap ! - } cond -} `define lisp-lazy-primitive -// ((x e) ..) ctx -- ((x.v) ..) -recursive eval-assign-list -{ over null? { drop } { - swap uncons swap uncons // ctx t x (e) - over atom? not abort"invalid variable name in assignment list" - 3 pick lisp-ctx-eval-list-last // ctx t x v - pair swap rot eval-assign-list cons - } cond -} swap ! -// (((x v) ..) body) ctx -- let construct -{ swap uncons swap 2 pick eval-assign-list // ctx body ((x v)...) - rot extend-ctx-by-list lisp-ctx-eval-list-last -} `let lisp-lazy-primitive -// ((x e) ..) ctx -- ctx' -{ swap { - dup null? { drop true } { - uncons swap uncons // ctx t x (e) - over atom? not abort"invalid variable name in assignment list" - 3 pick lisp-ctx-eval-list-last // ctx t x v - box pair rot cons swap false - } cond } until -} : compute-let*-ctx -// (((x v) ..) body) ctx -- let* construct -{ swap uncons swap rot compute-let*-ctx lisp-ctx-eval-list-last -} `let* lisp-lazy-primitive -// ((x e) ..) ctx -- ((h e) ..) ctx' , with x bound to h in ctx' -recursive prepare-letrec-ctx { - over null? { - swap uncons swap uncons swap // ctx t (e) x - hole tuck pair swap rot cons // ctx t (x.h) (h e) - 3 -roll rot cons prepare-letrec-ctx // (h e) t ctx' - -rot cons swap - } ifnot -} swap ! -// (((x v) ..) body) ctx -- letrec construct -{ swap uncons swap rot prepare-letrec-ctx swap { // body ctx' ((h e)..) - dup null? { drop true } { - uncons -rot uncons 2 pick lisp-ctx-eval-list-last // body t ctx' h v - swap ! swap false - } cond } until - lisp-ctx-eval-list-last -} `letrec lisp-lazy-primitive -// (e (p e)...) ctx -- match construct -{ swap uncons swap 2 pick lisp-ctx-eval swap { // ctx v ((p e)..) - dup null? { drop 2drop no-answer true } { - uncons swap uncons swap 3 pick // ctx v t e p v - match-arg-list { // ctx v t e ((x' . v')...) - 2swap 2drop rot extend-ctx-by-list lisp-ctx-eval-list-last true } { - 2drop false - } cond } cond } until -} `match lisp-lazy-primitive -// -lisp-dict @ constant original-lisp-dict -{ original-lisp-dict lisp-dict ! } : reset-lisp -{ ' drop { lisp-eval .l cr } List-generic( } :_ LISP-EVAL-PRINT( -// LISP-EVAL-PRINT((+ 3 4) (* 5 6)) computes and prints 12 and 30 -{ hole dup 1 { @ nip } does swap - 1 { swap lisp-eval swap ! } does - List-generic( -} :_ LISP-EVAL( -// LISP-EVAL((+ 3 4) (* 5 6)) computes 12 and 30, returns only 30 -// /* -LISP-EVAL-PRINT( - (define succ (lambda (x) (+ x 1))) - (define (twice f) (lambda (x) (f (f x)))) - (define (fact n) (if (= n 0) 1 (* n (fact (- n 1))))) - (fact ((twice succ) 5)) - (define compare (lambda (x y) (cond ((< x y) 'less) ((= x y) 'equal) (else 'greater)))) - (compare 2 3) - (compare 7 (+ 2 3)) - (define next (let ((cnt 0)) (lambda () (set! cnt (+ cnt 1)) cnt))) - (list (next) (next)) - (define new-counter (lambda () (let ((x 0)) (lambda () (set! x (+ x 1)) x)))) - (define c1 (new-counter)) - (define c2 (new-counter)) - (list (c1) (c1) (c2) (c1) (c2) (c1) (c1) (c2) (c2)) - (let* ((x (+ 2 3)) (y (* x x)) (z (+ x y))) (list x y z)) - (letrec ((even? (lambda (n) (if (= n 0) #t (odd? (- n 1))))) - (odd? (lambda (n) (if (= n 0) #f (even? (- n 1)))))) - (even? 88)) - (define (len l) (if (null? l) 0 (+ 1 (len (cdr l))))) - (len '(2 3 9)) - (define (len2 l) (match l (() 0) ((x . t) (+ 1 (len2 t))))) - (len2 '(2 3 9)) - (define (foo x) (match x - (('zero) 0) - (('succ x) (+ (foo x) 1)) - (('plus x y) (+ (foo x) (foo y))) - (('minus x y) (- (foo x) (foo y))) - (x x))) - (foo '(plus (succ (zero)) (minus (succ (succ 5)) 3))) - (define (bar x) (match x - (['zero] 0) - (['succ x] (+ (bar x) 1)) - (['plus x y] (+ (bar x) (bar y))) - (['minus x y] (- (bar x) (bar y))) - (['const x] x))) - (bar '[plus [succ [zero]] [minus [succ [succ [const 5]]] [const 3]]]) - (define (map f l) (letrec - ((map-f (lambda (l) (match l - (() ()) - ((h . t) (cons (f h) (map-f t))))))) - (map-f l))) - (map (lambda (x) (* x (+ 2 x))) '(2 3 9)) - (define (make-promise proc) (let ((result-ready? #f) (result #f)) - (lambda () - (if result-ready? result - (let ((x (proc))) - (if result-ready? result - (begin (set! result x) (set! result-ready? #t) result))))))) - (define (force promise) (promise)) -) -// */ -// words for invoking Lisp definitions from Fift -// (args) def -- val -{ null rot map-quote cons lisp-dict @ rot run-definition -} : invoke-lisp-definition -{ atom lisp-dict-lookup 1 { @ invoke-lisp-definition } -} : (invoke-lisp) -{ bl word (invoke-lisp) } :: invoke-lisp -// ( 2 3 ) invoke-lisp compare .l -{ atom lisp-dict-lookup 2 { @ mklist-1 invoke-lisp-definition } -} : (invoke-lisp-fixed) -{ bl word (invoke-lisp-fixed) } :: invoke-lisp-fixed -// 9 8 2 invoke-lisp-fixed compare .l -{ bl word (invoke-lisp) does } : make-lisp-invoker -{ bl word (invoke-lisp-fixed) does } : make-lisp-fixed-invoker -// 2 make-lisp-fixed-invoker compare : compare -// 3 9 compare -// import Lisp definitions as Fift words -{ bl word dup (invoke-lisp) does swap 0 (create) } : import-lisp -{ bl word tuck (invoke-lisp-fixed) does swap 0 (create) } : import-lisp-fixed -// 1 import-lisp-fixed fact -// 7 fact . diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Lists.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Lists.fif deleted file mode 100644 index b59e40a0..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Lists.fif +++ /dev/null @@ -1,220 +0,0 @@ -library Lists // List utilities -// -{ hole dup 1 { @ execute } does create } : recursive -// x x' -- ? recursively compares two S-expressions -recursive equal? { - dup tuple? { - over tuple? { - over count over count over = { // t t' l ? - 0 { dup 0>= { 2dup [] 3 pick 2 pick [] equal? { 1+ } { drop -1 } cond - } if } rot times - nip nip 0>= - } { drop 2drop false } cond - } { 2drop false } cond - } { eqv? } cond -} swap ! -// (a1 .. an) -- (an .. a1) -{ null swap { dup null? not } { uncons swap rot cons swap } while drop } : list-reverse -// (a1 .. an) -- an Computes last element of non-empty list l -{ { uncons dup null? { drop true } { nip false } cond } until } : list-last -// l l' -- l++l' Concatenates two lists -recursive list+ { - over null? { nip } { swap uncons rot list+ cons } cond -} swap ! -// l l' -- l'' -1 or 0, where l = l' ++ l'' -// Removes prefix from list -{ { dup null? { drop true true } { - swap dup null? { 2drop false true } { // l' l - uncons swap rot uncons -rot equal? { false } { - 2drop false true - } cond } cond } cond } until -} : list- -// (a1 .. an) -- a1 .. an n Explodes a list -{ 0 { over null? not } { swap uncons rot 1+ } while nip } : explode-list -// (a1 .. an) x -- a1 .. an n x Explodes a list under the topmost element -{ swap explode-list dup 1+ roll } : explode-list-1 -// l -- t Transforms a list into a tuple with the same elements -{ explode-list tuple } : list>tuple -// a1 ... an n x -- (a1 .. an) x -{ null swap rot { -rot cons swap } swap times } : mklist-1 -// (s1 ... sn) -- s1+...+sn Concatenates a list of strings -{ "" { over null? not } { swap uncons -rot $+ } while nip -} : concat-string-list -// (x1 ... xn) -- x1+...+xn Sums a list of integers -{ 0 { over null? not } { swap uncons -rot + } while nip -} : sum-list -// (a1 ... an) a e -- e(...e(e(a,a1),a2),...),an) -{ -rot { over null? not } { swap uncons -rot 3 pick execute } while nip nip -} : foldl -// (a1 ... an) e -- e(...e(e(a1,a2),a3),...),an) -{ swap uncons swap rot foldl } : foldl-ne -// (a1 ... an) a e -- e(a1,e(a2,...,e(an,a)...)) -recursive foldr { - rot dup null? { 2drop } { - uncons -rot 2swap swap 3 pick foldr rot execute - } cond -} swap ! -// (a1 ... an) e -- e(a1,e(a2,...,e(a[n-1],an)...)) -recursive foldr-ne { - over cdr null? { drop car } { - swap uncons 2 pick foldr-ne rot execute - } cond -} swap ! -// (l1 ... ln) -- l1++...++ln Concatenates a list of lists -{ dup null? { ' list+ foldr-ne } ifnot } : concat-list-lists -// (a1 .. an . t) n -- t Computes the n-th tail of a list -{ ' cdr swap times } : list-tail -// (a0 .. an ..) n -- an Computes the n-th element of a list -{ list-tail car } : list-ref -// l -- ? -{ { dup null? { drop true true } { - dup pair? { cdr false } { - drop false true - } cond } cond } until -} : list? -// l -- n -{ 0 { over null? not } { 1+ swap uncons nip swap } while nip -} : list-length -// l e -- t // returns tail of l after first member that satisfies e -{ swap { - dup null? { nip true } { - tuck car over execute { drop true } { - swap cdr false - } cond } cond } until -} : list-tail-from -// a l -- t // tail of l after first occurence of a using eq? -{ swap 1 ' eq? does list-tail-from } : list-member-eq -{ swap 1 ' eqv? does list-tail-from } : list-member-eqv -{ swap 1 ' equal? does list-tail-from } : list-member-equal -// a l -- ? -{ list-member-eq null? not } : list-member? -{ list-member-eqv null? not } : list-member-eqv? -// l -- a -1 or 0 // returns car l if l is non-empty -{ dup null? { drop false } { car true } cond -} : safe-car -{ dup null? { drop false } { car second true } cond -} : get-first-value -// l e -- v -1 or 0 -{ list-tail-from safe-car } : assoc-gen -{ list-tail-from get-first-value } : assoc-gen-x -// a l -- (a.v) -1 or 0 -- returns first entry (a . v) in l -{ swap 1 { swap first eq? } does assoc-gen } : assq -{ swap 1 { swap first eqv? } does assoc-gen } : assv -{ swap 1 { swap first equal? } does assoc-gen } : assoc -// a l -- v -1 or 0 -- returns v from first entry (a . v) in l -{ swap 1 { swap first eq? } does assoc-gen-x } : assq-val -{ swap 1 { swap first eqv? } does assoc-gen-x } : assv-val -{ swap 1 { swap first equal? } does assoc-gen-x } : assoc-val -// (a1 .. an) e -- (e(a1) .. e(an)) -recursive list-map { - over null? { drop } { - swap uncons -rot over execute -rot list-map cons - } cond -} swap ! - -variable ctxdump variable curctx -// (a1 .. an) e -- executes e for a1, ..., an -{ ctxdump @ curctx @ ctxdump 2! curctx 2! - { curctx 2@ over null? not } { swap uncons rot tuck curctx 2! execute } - while 2drop ctxdump 2@ curctx ! ctxdump ! -} : list-foreach -forget ctxdump forget curctx - -// -// Experimental implementation of `for` loops with index -// -variable loopdump variable curloop -{ curloop @ loopdump @ loopdump 2! } : push-loop-ctx -{ loopdump 2@ loopdump ! curloop ! } : pop-loop-ctx -// ilast i0 e -- executes e for i=i0,i0+1,...,ilast-1 -{ -rot 2dup > { - push-loop-ctx { - triple dup curloop ! first execute curloop @ untriple 1+ 2dup <= - } until pop-loop-ctx - } if 2drop drop -} : for -// ilast i0 e -- same as 'for', but pushes current index i before executing e -{ -rot 2dup > { - push-loop-ctx { - triple dup curloop ! untriple nip swap execute curloop @ untriple 1+ 2dup <= - } until pop-loop-ctx - } if 2drop drop -} : for-i -// ( -- i ) Returns innermost loop index -{ curloop @ third } : i -// ( -- j ) Returns outer loop index -{ loopdump @ car third } : j -{ loopdump @ cadr third } : k -forget curloop forget loopdump - -// -// create Lisp-style lists using words "(" and ")" -// -variable ') -'nop box constant ', -{ ") without (" abort } ') ! -{ ') @ execute } : ) -anon constant dot-marker -// m x1 ... xn t m -- (x1 ... xn . t) -{ swap - { -rot 2dup eq? not } - { over dot-marker eq? abort"invalid dotted list" - swap rot cons } while 2drop -} : list-tail-until-marker -// m x1 ... xn m -- (x1 ... xn) -{ null swap list-tail-until-marker } : list-until-marker -{ over dot-marker eq? { nip 2dup eq? abort"invalid dotted list" } - { null swap } cond - list-tail-until-marker -} : list-until-marker-ext -{ ') @ ', @ } : ops-get -{ ', ! ') ! } : ops-set -{ anon dup ops-get 3 { ops-set list-until-marker-ext } does ') ! 'nop ', ! -} : ( -// test of Lisp-style lists -// ( 42 ( `+ 9 ( `* 3 4 ) ) "test" ) .l cr -// ( `eq? ( `* 3 4 ) 3 4 * ) .l cr -// `alpha ( `beta `gamma `delta ) cons .l cr -// { ( `eq? ( `* 3 5 pick ) 3 4 roll * ) } : 3*sample -// 17 3*sample .l cr - -// similar syntax _( x1 .. xn ) for tuples -{ 2 { 1+ 2dup pick eq? } until 3 - nip } : count-to-marker -{ count-to-marker tuple nip } : tuple-until-marker -{ anon dup ops-get 3 { ops-set tuple-until-marker } does ') ! 'nop ', ! } : _( -// test of tuples -// _( _( 2 "two" ) _( 3 "three" ) _( 4 "four" ) ) .dump cr - -// pseudo-Lisp tokenizer -"()[]'" 34 hold constant lisp-delims -{ lisp-delims 11 (word) } : lisp-token -{ null cons `quote swap cons } : do-quote -{ 1 { ', @ 2 { 2 { ', ! execute ', @ execute } does ', ! } - does ', ! } does -} : postpone-prefix -{ ', @ 1 { ', ! } does ', ! } : postpone-', -( `( ' ( pair - `) ' ) pair - `[ ' _( pair - `] ' ) pair - `' ' do-quote postpone-prefix pair - `. ' dot-marker postpone-prefix pair - `" { char " word } pair - `;; { 0 word drop postpone-', } pair -) constant lisp-token-dict -variable eol -{ eol @ eol 0! anon dup ') @ 'nop 3 - { ops-set list-until-marker-ext true eol ! } does ') ! rot ', ! - { lisp-token dup (number) dup { roll drop } { - drop atom dup lisp-token-dict assq { nip second execute } if - } cond - ', @ execute - eol @ - } until - -rot eol ! execute -} :_ List-generic( -{ 'nop 'nop List-generic( } :_ LIST( -// LIST((lambda (x) (+ x 1)) (* 3 4)) -// LIST('(+ 3 4)) -// LIST(2 3 "test" . 9) -// LIST((process '[plus 3 4])) diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Stack.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Stack.fif deleted file mode 100644 index c7ef6f8e..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Stack.fif +++ /dev/null @@ -1,266 +0,0 @@ -library Stack // advanced stack manupulation library -"Lists.fif" include -// S(a b c - a c 2 a b) would compile to code performing the requested stack manipulation - -// interface to low-level stack manipulation primitives -{ (number) 1- abort"index expected" dup 0 < over 255 > or - abort"index 0..255 expected" -} : (idx) -// push(n) : a0 .. an - a0 .. an a0 equivalent to "n pick" -// push(0) = dup, push(1) = over -{ 0 char ) word (idx) } ::_ push( -// pop(n) : a0 a1 .. a(n-1) an - an a1 .. a(n-1) -// pop(0) = drop, pop(1) = nip -{ 0 char ) word (idx) } ::_ pop( -// xchg(i,j) : equivalent to "i j exch2" -{ 0 char , word (idx) char ) word (idx) } ::_ xchg( -// xchg0(i) : equivalent to "i exch" or "xchg(0,i)" -// xchg0(1) = swap -{ 0 char ) word (idx) 0 } ::_ xchg0( -forget (idx) - -// parser for stack notation expressions -")" 34 hold +" -" constant stk-delims -anon constant stk-start -anon constant stk-to -variable stk-mode -{ stk-delims 11 (word) } : stk-token -'nop : mk-lit -// stk-start vn ... v0 -- stk-start ... v0 i where v[i]=v0 -{ 0 { - 1+ 2dup 2+ pick dup stk-start eq? { 2drop drop 0 true } { eqv? } cond - } until -} : stk-lookup -// stk-start a1 .. an stk-to b1 .. bm -- [a1 .. an] [b1 .. bm] -{ stk-mode @ 0= abort"identifier expected" } : chk-lit -{ stk-to list-until-marker stk-mode ! - stk-start list-until-marker stk-mode @ - stk-mode 0! -} : build-stk-effect -{ stk-start stk-mode 0! { - stk-token dup ")" $= { drop true } { - dup "-" $= { - drop stk-mode @ abort"duplicate -" true stk-mode ! stk-to false } { - dup 34 chr $= { chk-lit drop char " word mk-lit false } { - dup (number) ?dup { chk-lit 1- { swap mk-lit -rot } if mk-lit nip false } { - atom dup `_ eq? { stk-mode @ abort"identifier expected" false } { - stk-lookup 0= stk-mode @ = { - stk-mode @ { atom>$ +" -?" } { atom>$ +" redefined" } cond abort } { - false - } cond } cond } cond } cond } cond } cond } until - stk-mode @ 0= abort"'-' expected" - build-stk-effect -} :_ parse-stk-list( - -// stack operation list construction -variable op-rlist -{ op-rlist null! } : clear-op-list -{ op-rlist @ list-reverse } : get-op-list -{ op-rlist @ cons op-rlist ! } : issue-op -{ minmax `xchg -rot triple } : op-xchg -{ `push swap pair } : op-push -{ `lit swap pair } : op-lit -{ `pop swap pair } : op-pop -0 op-pop constant op-drop -{ 2dup <> { op-xchg issue-op } if } : issue-xchg -{ op-push issue-op } : issue-push -{ op-lit issue-op } : issue-lit -{ op-pop issue-op } : issue-pop -{ op-drop issue-op } : issue-drop -{ ' issue-drop swap times } : issue-drop-# - -// emulated stack contents -variable emul-stk -{ emul-stk @ count } : emul-depth -{ emul-depth 1- swap - } : adj-i -{ emul-depth 1- tuck swap - swap rot - swap } : adj-ij -// i j -- -{ adj-ij 2dup emul-stk @ tuck swap [] swap rot [] rot // i sj si j - emul-stk @ -rot []= swap rot []= emul-stk ! -} : emul-xchg -{ emul-stk @ tpop drop emul-stk ! } : emul-drop -// i -- -{ 0 emul-xchg emul-drop } : emul-pop -// i -- s[i] -{ emul-stk @ swap [] } : emul-stk[] -// i -- si -{ adj-i emul-stk[] } : emul-get -{ 0 emul-get } : emul-tos -// v i -- ? Check whether s[i]=v -{ dup emul-depth < { emul-stk[] eqv? } { 2drop false } cond } : emul[]-eq? -// v -- i or -1 Returns maximum i with s[i]=v -{ emul-stk @ dup count { // v s i - ?dup 0= { -1 true } { 1- 2dup [] 3 pick eqv? } cond // v s i' ? - } until nip nip -} : emul-stk-lookup-rev -// i -- -{ emul-get emul-stk @ swap , emul-stk ! } : emul-push -{ emul-stk @ swap , emul-stk ! } : emul-lit -// show emulated stack contents similarly to .s -{ emul-stk @ explode dup 1 reverse ' .l swap times cr } : .e - -// both issue an operation and emulate it -{ 2dup issue-xchg emul-xchg } : issue-emul-xchg -{ dup issue-push emul-push } : issue-emul-push -{ dup issue-lit emul-lit } : issue-emul-lit -{ dup issue-pop emul-pop } : issue-emul-pop -{ issue-drop emul-drop } : issue-emul-drop -{ ' issue-emul-drop swap times } : issue-emul-drop-# - -// b.. s -- b.. s moves tos value to stk[s] -{ dup emul-stk[] 2 pick cdr list-member-eqv? { - dup adj-i 0 issue-emul-xchg } { dup adj-i issue-emul-pop } cond -} : move-tos-to - -// new s -- ops registered -{ { over null? not } { - // .sl .e get-op-list .l cr - // get-op-list list-length 100 > abort"too long" - emul-depth over > - { over emul-tos swap list-member-eqv? not } { false } cond { - // b.. s tos unneeded - issue-emul-drop } { - over car // b.. s b1 - 2dup swap emul[]-eq? { drop swap cdr swap 1+ } { - dup emul-stk-lookup-rev // b.. s b1 i - dup 0< { // b.. s b1 i not found, must be a literal - drop dup atom? abort"unavailable value" - issue-emul-lit } { - dup 3 pick < { // b.. s b1 i found in bottom s stack values - nip adj-i issue-emul-push // b.. s - dup emul-depth 1- < { move-tos-to } if - } { - emul-depth 1- over = { // b.. s b1 i found in tos - 2drop move-tos-to - } { // b.. s b1 i - nip over adj-ij issue-emul-xchg - } cond } cond } cond } cond } cond } while - nip emul-depth swap - issue-emul-drop-# -} : generate-reorder-ops - -// old new -- op-list -{ emul-stk @ op-rlist @ 2swap - swap list>tuple emul-stk ! clear-op-list - 0 generate-reorder-ops get-op-list - -rot op-rlist ! emul-stk ! -} : generate-reorder -{ parse-stk-list( generate-reorder } :_ SG( - -// op-list rewriting according to a ruleset -// l f l1 l2 -- l' -1 or l f with l' = l2 + (l - l1) -{ push(3) rot list- { list+ nip nip true } { drop } cond -} : try-rule -// l f ll -- l' -1 or l f -{ { dup null? not } { uncons 3 -roll unpair try-rule rot } while drop -} : try-ruleset -// l ll -- l' -{ swap { over false swap try-ruleset 0= } until nip -} : try-ruleset* -// l ruleset -- l' -recursive try-ruleset*-everywhere { - tuck try-ruleset* dup null? { nip } { - uncons rot try-ruleset*-everywhere cons } cond -} swap ! -LIST( - [([xchg 0 1] [xchg 0 2]) ([rot])] - [([xchg 0 1] [xchg 1 2]) ([-rot])] - [([xchg 0 2] [xchg 1 2]) ([rot])] - [([xchg 0 2] [xchg 0 1]) ([-rot])] - [([xchg 1 2] [xchg 0 1]) ([rot])] - [([xchg 1 2] [xchg 0 2]) ([-rot])] - [([xchg 0 1] [rot]) ([xchg 0 2])] - [([-rot] [xchg 0 1]) ([xchg 0 2])] - [([xchg 0 2] [xchg 1 3]) ([2swap])] - [([xchg 1 3] [xchg 0 2]) ([2swap])] - [([push 1] [push 1]) ([2dup])] - [([push 3] [push 3]) ([2over])] - [([pop 0] [pop 0]) ([2drop])] - [([pop 1] [pop 0]) ([2drop])] - [([xchg 0 1] [push 1]) ([tuck])] - [([rot] [-rot]) ()] - [([-rot] [rot]) ()] -) constant fift-stack-ruleset -{ fift-stack-ruleset try-ruleset*-everywhere } : fift-ops-rewrite -{ SG( fift-ops-rewrite } :_ SGF( - -// helpers for creating Fift source strings for one fift-op -// i j -- s -{ minmax over { "xchg(" rot (.) $+ +"," swap (.) $+ +")" } - { nip dup 1 = { drop "swap" } { - ?dup { "xchg0(" swap (.) $+ +")" } { "" } cond - } cond } cond -} : source- -// i -- s -{ dup 1 = { drop "over" } { - ?dup { "push(" swap (.) $+ +")" } { "dup" } cond - } cond -} : source- -// i -- s -{ dup 1 = { drop "nip" } { - ?dup { "pop(" swap (.) $+ +")" } { "drop" } cond - } cond -} : source- -// lit -- s -{ dup string? { char " chr swap $+ char " hold } { (.) } cond -} : source- - -// dictionary with all fift op compilation/source creation -{ 0 swap (compile) } : fop-compile -( _( `xchg 2 { fop-compile } { source- swap cons } ) - _( `push 1 { fop-compile } { source- swap cons } ) - _( `pop 1 { fop-compile } { source- swap cons } ) - _( `lit 1 { 1 'nop (compile) } { source- swap cons } ) - _( `rot 0 { ' rot fop-compile } { "rot" swap cons } ) - _( `-rot 0 { ' -rot fop-compile } { "-rot" swap cons } ) - _( `tuck 0 { ' tuck fop-compile } { "tuck" swap cons } ) - _( `2swap 0 { ' 2swap fop-compile } { "2swap" swap cons } ) - _( `2drop 0 { ' 2drop fop-compile } { "2drop" swap cons } ) - _( `2dup 0 { ' 2dup fop-compile } { "2dup" swap cons } ) - _( `2over 0 { ' 2over fop-compile } { "2over" swap cons } ) -) box constant fift-op-dict - -{ dup atom? { atom>$ } { drop "" } cond - "unknown operation " swap $+ abort -} : report-unknown-op -variable 'fop-entry-exec -// process fift-op according to 'fop-entry-exec -// ... op - ... -{ dup first dup fift-op-dict @ assq { report-unknown-op } ifnot - dup second 1+ push(3) count <> abort"incorrect param count" - nip swap explode dup roll drop 1- roll // o2 .. on entry - 'fop-entry-exec @ execute -} : process-fift-op - -// compile op-list into Fift wordlist -// wl op-list -- wl' -{ { third execute } 'fop-entry-exec ! - swap ' process-fift-op foldl } : compile-fift-op* -// op-list -- e -{ fift-ops-rewrite ({) swap compile-fift-op* (}) } : ops>wdef - -// S( - ) compiles a "word" performing required action -{ SG( ops>wdef 0 swap } ::_ S( -// 1 2 3 S(a b c - c a b a) .s would print 3 1 2 1 - -// transform op-list into Fift source -// ls op -- ls' -{ fift-ops-rewrite - { 3 [] execute } 'fop-entry-exec ! - null ' process-fift-op foldl - dup null? { drop "" } { { +" " swap $+ } foldr-ne } cond -} : ops>$ -{ SG( ops>$ 1 'nop } ::_ $S( -{ SG( ops>$ type } :_ .$S( -// $S(a b c - b c a c a c) => string "rot 2dup over" -// S(a b c - b c a c a c) => compile/execute block { rot 2dup over } -// $S(_ x y _ - y x) => string "drop pop(2)" -// .$S(x1 x2 - 17 x1) => print string "drop 17 swap" - -// simplify/transform sequences of stack manipulation operations -LIST(. [a b c d e f g h i j]) constant std-stack -{ stk-start std-stack explode drop stk-to std-stack explode drop -} : simplify<{ -{ build-stk-effect generate-reorder ops>$ } : }>stack -// simplify<{ drop drop over over -13 }>stack => string "2drop 2dup -13" -// simplify<{ 17 rot }>stack => string "swap 17 swap" -// simplify<{ 5 1 reverse }>stack => string "xchg(1,5) xchg(2,4)" diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif b/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif deleted file mode 100644 index 1b978a28..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif +++ /dev/null @@ -1,270 +0,0 @@ -library TonUtil // TON Blockchain Fift Library -"Lists.fif" include - --1 constant Masterchain -0 constant Basechain - -// parse workchain id -// ( S -- workchain ) -{ (number) 1- abort"workchain id must be an integer" - dup 32 fits not abort"workchain id must fit in 32 bits" -} : parse-workchain-id - -{ (number) 1- abort"integer expected" } : parse-int - -{ over null? ' swap if drop } : replace-if-null - -// Private key load/generate -// ( fname -- pubkey privkey ) -{ dup ."Loading private key from file " type cr - file>B dup Blen 32 <> abort"Private key must be exactly 32 bytes long" - dup priv>pub swap -} : load-keypair -// ( fname -- pubkey privkey ) -{ dup file-exists? - { load-keypair } - { dup newkeypair swap rot over swap B>file - rot ."Saved new private key to file " type cr - } cond -} : load-generate-keypair - -// Parse smart-contract address -// ( S -- workchain addr bounce? ) -{ $>smca not abort"invalid smart-contract address" - 1 and 0= -} : parse-smc-addr - -// ( x -- ) Displays a 64-digit hex number -{ 64 0x. } : 64x. -{ 64 0X. } : 64X. -// ( wc addr -- ) Show address in : form -{ swap ._ .":" 64x. } : .addr -// ( wc addr flags -- ) Show address in base64url form -{ smca>$ type } : .Addr -// ( wc addr fname -- ) Save address to file in 36-byte format -{ -rot 256 u>B swap 32 i>B B+ swap B>file } : save-address -// ( wc addr fname -- ) Save address and print message -{ dup ."(Saving address to file " type .")" cr save-address -} : save-address-verbose - -// ( fname -- wc addr ) Load address from file -{ file>B 32 B| - dup Blen { 32 B>i@ } { drop Basechain } cond - swap 256 B>u@ -} : load-address -// ( fname -- wc addr ) Load address from file and print message -{ dup ."(Loading address from file " type .")" cr load-address -} : load-address-verbose -// Parse string as address or load address from file (if string is prefixed by @) -// ( S default-bounce -- workchain addr bounce? ) -{ over $len 0= abort"empty smart-contract address" - swap dup 1 $| swap "@" $= - { nip load-address rot } { drop nip parse-smc-addr } cond -} : parse-load-address - -// ( hex-str -- addr ) Parses ADNL address -{ dup $len 64 <> abort"ADNL address must consist of exactly 64 hexadecimal characters" - (hex-number) 1 <> abort"ADNL address must consist of 64 hexadecimal characters" - dup 256 ufits not abort"invalid ADNL address" -} : parse-adnl-address - -// ( b wc addr -- b' ) Serializes address into Builder b -{ -rot 8 i, swap 256 u, } : addr, -{ over 8 fits { rot b{100} s, -rot addr, } { - rot b{110} s, 256 9 u, rot 32 i, swap 256 u, } cond -} : Addr, - -// Gram utilities -1000000000 constant Gram -{ Gram swap */r } : Gram*/ -{ Gram * } : Gram* -{ (number) dup { 1- ' Gram*/ ' Gram* cond true } if -} : $>GR? -// ( S -- nanograms ) -{ $>GR? not abort"not a valid Gram amount" -} : $>GR -{ bl word $>GR 1 'nop } ::_ GR$ -// ( nanograms -- S ) -{ dup abs <# ' # 9 times char . hold #s rot sign #> -nip -trailing0 } : (.GR) -{ (.GR) ."GR$" type } : .GR_ -{ .GR_ space } : .GR - -// b x -- b' ( serializes a Gram amount ) -{ -1 { 1+ 2dup 8 * ufits } until - rot over 4 u, -rot 8 * u, } : Gram, -// s -- x s' ( deserializes a Gram amount ) -{ 4 u@+ swap 8 * u@+ } : Gram@+ -// s -- x -{ 4 u@+ swap 8 * u@ } : Gram@ - -// currency collections -// b x --> b' ( serializes a VarUInteger32 ) -{ -1 { 1+ 2dup 8 * ufits } until - rot over 5 u, -rot 8 * u, } : VarUInt32, -// s --> x ( deserializes a VarUInteger32 ) -{ 5 u@+ swap 8 * u@ } : VarUInt32@ -32 constant cc-key-bits -' VarUInt32, : val, -' VarUInt32@ : val@ -// d k v -- d' -{ cc -{ dup null? { ."(null)" drop } { val@ ._ } cond } dup : .maybeVarUInt32 : .val -{ swap cc-key-bits { rot { ."+" } if .val ."*$" ._ true true } idictforeach drop } : (.cc) -{ false (.cc) { ."0" } ifnot } : .cc_ -{ .cc_ space } : .cc -{ true (.cc) drop } : .+cc_ -{ .+cc_ space } : .+cc -{ cc-key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-cc-diff -{ cc-key-bits { val@ swap val@ + val, true } dictmerge } : cc+ -{ null swap cc-key-bits { val@ pair swap cons true } idictforeach drop } : cc>list-rev -{ cc>list-rev list-reverse } : cc>list -forget val, forget val@ forget .val - -// ( S -- x -1 or 0 ) -{ (number) dup 2 = { -rot 2drop } if 1 = } : int? -{ int? dup { drop dup 0< { drop false } { true } cond } if } : pos-int? -// ( S -- k v -1 or 0 ) Parses expression * or *$ -{ dup "*" $pos dup 0< { 2drop false } { - $| dup $len 2 < { 2drop false } { - 1 $| nip dup 1 $| swap "$" $= { swap } if drop - int? dup { over 32 fits { 2drop false } ifnot } if - not { drop false } { - swap pos-int? not { drop false } { - true - } cond } cond } cond } cond -} : cc-key-value? -// ( S -- D -1 or 0 ) Parses an extra currency collection -// e.g. "10000*$3+7777*$-11" means "10000 units of currency #3 and 7777 units of currency #-11" -{ dictnew { // S D - swap dup "+" $pos dup 0< { drop null -rot } { $| 1 $| nip -rot } cond - cc-key-value? { +ccpair over null? dup { rot drop true } if } { 2drop false true } cond - } until -} : $>xcc? -{ $>xcc? not abort"invalid extra currency collection" } : $>xcc -{ char } word dup $len { $>xcc } { drop dictnew } cond 1 'nop } ::_ CX{ - -// complete currency collections -{ $>xcc? { true } { drop false } cond } : end-parse-cc -// ( S -- x D -1 or 0 ) Parses a currency collection -// e.g. "1.2+300*$2" means "1200000000ng plus 300 units of currency #2" -{ 0 swap dup "+" $pos dup 0< { drop dup - $>GR? { nip nip dictnew true } { end-parse-cc } cond - } { over swap $| swap $>GR? { 2swap 2drop swap 1 $| nip } { drop - } cond end-parse-cc } cond -} : $>cc? -{ $>cc? not abort"invalid currency collection" } : $>cc -{ char } word dup $len { $>cc } { drop 0 dictnew } cond 2 'nop } ::_ CC{ -// ( x D -- ) -{ swap ?dup { .GR_ .+cc_ } { .cc_ } cond } : .GR+cc_ -{ .GR+cc_ space } : .GR+cc -{ -rot Gram, swap dict, } : Gram+cc, - -// Libraries -// ( -- D ) New empty library collection -' dictnew : Libs{ -// ( D -- D ) Return library collection as dictionary -'nop : }Libs -// ( D c x -- D' ) Add a public/private library c to collection D -{ -rot B, swap ref, - } cond -} swap ! -// b S n -- b' -{ swap $>B swap append-long-bytes } : append-long-string -// S -- c -{ -} : simple-transfer-body - -// ( S -- x ) parse public key -{ dup $len 48 <> abort"public key must be 48 characters long" - base64url>B dup Blen 36 <> abort"public key must be 48 characters long" - 34 B| 16 B>u@ over crc16 <> abort"crc16 mismatch in public key" - 16 B>u@+ 0x3ee6 <> abort"invalid tag in public key" - 256 B>u@ -} : parse-pubkey -{ bl word parse-pubkey 1 'nop } ::_ PK' -// ( x -- S ) serialize public key -{ 256 u>B B{3ee6} swap B+ dup crc16 16 u>B B+ B>base64 } : pubkey>$ -{ pubkey>$ type } : .pubkey - -// ( S -- x ) parse validator-encoded public key -{ base64>B dup Blen 36 <> abort"public key with magic must be 36 bytes long" - 4 B| swap 32 B>u@ 0xC6B41348 <> abort"unknown magic for public key (not Ed25519)" -} : parse-val-pubkey -{ bl word parse-val-pubkey 1 'nop } ::_ VPK' -{ char } word base64>B 1 'nop } ::_ B64{ - -// adnl address parser -{ 256 u>B B{2D} swap B+ dup crc16 16 u>B B+ } : adnl-preconv -{ swap 32 /mod dup 26 < { 65 } { 24 } cond + rot swap hold } : Base32# -{ <# ' Base32# 8 times #> } : Base32#*8 -{ "" over Blen 5 / { swap 40 B>u@+ Base32#*8 nip rot swap $+ } swap times nip } : B>Base32 - -// ( x -- S ) Converts an adnl-address from a 256-bit integer to a string -{ adnl-preconv B>Base32 1 $| nip } : adnl>$ - -{ 65 - dup 0>= { -33 and dup 26 < } { 41 + dup 25 > over 32 < and } cond ?dup nip } : Base32-digit? -{ Base32-digit? not abort"not a Base32 digit" } : Base32-digit -{ 0 { over $len } { swap 1 $| -rot (char) Base32-digit swap 5 << + } while nip } : Base32-number -{ B{} { over $len } { swap 8 $| -rot Base32-number 40 u>B B+ } while nip } : Base32>B - -// ( S -- x ) Converts an adnl address from a string to 256-bit integer -{ dup $len 55 <> abort"not 55 alphanumeric characters" "F" swap $+ Base32>B - 33 B| 16 B>u@ over crc16 <> abort"crc16 checksum mismatch" - 8 B>u@+ 0x2D <> abort"not a valid adnl address" 256 B>u@ } : $>adnl - -{ 65 - dup 0>= { -33 and 10 + dup 16 < } { 17 + dup 0>= over 10 < and } cond ?dup nip } : hex-digit? -// ( S -- x -1 or 0 ) Parses a hexadecimal integer -{ dup $len { - 0 { - 4 << swap 1 $| -rot (char) hex-digit? // S a d -1 or S a 0 - { + over $len 0= } { drop -1 true } cond - } until - dup 0< { 2drop false } { nip true } cond - } { drop false } cond -} : hex$>u? -// ( S -- x ) -{ hex$>u? not abort"not a hexadecimal number" } : hex$>u - -{ dup $len 64 = { hex$>u } { - dup $len 55 = { $>adnl } { - true abort"invalid adnl address" - } cond } cond -} : parse-adnl-addr -{ adnl>$ type } : .adnl -{ bl word parse-adnl-addr 1 'nop } ::_ adnl: - -// ( x a b -- a<=x<=b ) -{ 2 pick >= -rot >= and } : in-range? - -// ( c i -- ? ) Checks whether c is a valid value for config param #i -def? config-valid? { - { nip 0>= { ."warning: cannot check validity of configuration parameter value, use create-state instead of fift to check validity" cr } if - true } : config-valid? -} ifnot - -{ dup -1000 = { drop . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "utils.h" -#include "words.h" -#include "td/utils/PathView.h" -#include "td/utils/filesystem.h" -#include "td/utils/port/path.h" - -namespace fift { -namespace { - -std::string fift_dir(std::string dir) { - return dir.size() > 0 ? dir : td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str() + "lib/"; -} -td::Result load_source(std::string name, std::string dir = "") { - return td::read_file_str(fift_dir(dir) + name); -} -td::Result load_Fift_fif(std::string dir = "") { - return load_source("Fift.fif", dir); -} -td::Result load_Asm_fif(std::string dir = "") { - return load_source("Asm.fif", dir); -} -td::Result load_TonUtil_fif(std::string dir = "") { - return load_source("TonUtil.fif", dir); -} -td::Result load_Lists_fif(std::string dir = "") { - return load_source("Lists.fif", dir); -} -td::Result load_Lisp_fif(std::string dir = "") { - return load_source("Lisp.fif", dir); -} -td::Result load_GetOpt_fif(std::string dir = "") { - return load_source("GetOpt.fif", dir); -} - -class MemoryFileLoader : public fift::FileLoader { - public: - td::Result read_file(td::CSlice filename) override { - auto it = files_.find(filename); - if (it == files_.end()) { - return td::Status::Error("File not found"); - } - fift::FileLoader::File res; - res.data = it->second; - res.path = it->first; - return std::move(res); - } - - td::Status write_file(td::CSlice filename, td::Slice data) override { - files_[filename.str()] = data.str(); - return td::Status::OK(); - } - - void add_file(std::string path, std::string data) { - files_[path] = std::move(data); - } - td::Result read_file_part(td::CSlice filename, td::int64 size, td::int64 offset) override { - auto it = files_.find(filename); - if (it == files_.end()) { - return td::Status::Error("File not found"); - } - fift::FileLoader::File res; - if (static_cast(it->second.size()) < offset) { - return td::Status::Error("Offset too large"); - } - if (size > static_cast(it->second.size())) { - size = static_cast(it->second.size()); - } - res.data = td::Slice(it->second).substr(td::narrow_cast(offset), td::narrow_cast(size)).str(); - res.path = it->first; - return std::move(res); - } - - bool is_file_exists(td::CSlice filename) override { - return files_.count(filename) != 0; - } - - private: - std::map> files_; -}; - -td::Result create_source_lookup(std::string main, bool need_preamble = true, bool need_asm = true, - bool need_ton_util = true, bool need_lisp = true, - std::string dir = "") { - auto loader = std::make_unique(); - loader->add_file("/main.fif", std::move(main)); - if (need_preamble) { - TRY_RESULT(f, load_Fift_fif(dir)); - loader->add_file("/Fift.fif", std::move(f)); - } - if (need_asm) { - TRY_RESULT(f, load_Asm_fif(dir)); - loader->add_file("/Asm.fif", std::move(f)); - } - if (need_ton_util) { - { - TRY_RESULT(f, load_Lists_fif(dir)); - loader->add_file("/Lists.fif", std::move(f)); - } - { - TRY_RESULT(f, load_TonUtil_fif(dir)); - loader->add_file("/TonUtil.fif", std::move(f)); - } - { - TRY_RESULT(f, load_GetOpt_fif(dir)); - loader->add_file("/GetOpt.fif", std::move(f)); - } - } - if (need_lisp) { - TRY_RESULT(f, load_Lisp_fif(dir)); - loader->add_file("/Lisp.fif", std::move(f)); - } - auto res = fift::SourceLookup(std::move(loader)); - res.add_include_path("/"); - return std::move(res); -} - -td::Result run_fift(fift::SourceLookup source_lookup, std::ostream *stream, - bool preload_fift = true, std::vector args = {}) { - fift::Fift::Config config; - config.source_lookup = std::move(source_lookup); - fift::init_words_common(config.dictionary); - fift::init_words_vm(config.dictionary); - fift::init_words_ton(config.dictionary); - config.error_stream = stream; - config.output_stream = stream; - if (args.size() != 0) { - std::vector argv; - for (auto &arg : args) { - argv.push_back(arg.c_str()); - } - fift::import_cmdline_args(config.dictionary, argv[0], td::narrow_cast(argv.size() - 1), argv.data() + 1); - } - fift::Fift fift{std::move(config)}; - if (preload_fift) { - TRY_STATUS(fift.interpret_file("Fift.fif", "")); - } - TRY_STATUS(fift.interpret_file("main.fif", "")); - return std::move(fift.config().source_lookup); -} -} // namespace -td::Result mem_run_fift(std::string source, std::vector args, std::string fift_dir) { - std::stringstream ss; - TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, true, fift_dir)); - TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args))); - FiftOutput res; - res.source_lookup = std::move(source_lookup); - res.output = ss.str(); - return std::move(res); -} -td::Result mem_run_fift(SourceLookup source_lookup, std::vector args) { - std::stringstream ss; - TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args))); - FiftOutput res; - res.source_lookup = std::move(source_lookup); - res.output = ss.str(); - return std::move(res); -} -td::Result create_mem_source_lookup(std::string main, std::string fift_dir, bool need_preamble, - bool need_asm, bool need_ton_util, bool need_lisp) { - return create_source_lookup(main, need_preamble, need_asm, need_ton_util, need_lisp, fift_dir); -} - -td::Result> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) { - std::stringstream ss; - TRY_RESULT(source_lookup, - create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n" - << (is_raw ? "}>c" : "") << " boc>B \"res\" B>file", - true, true, true, false, fift_dir)); - TRY_RESULT(res, run_fift(std::move(source_lookup), &ss)); - TRY_RESULT(boc, res.read_file("res")); - return vm::std_boc_deserialize(std::move(boc.data)); -} - -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/utils.h b/submodules/ton/tonlib-src/crypto/fift/utils.h deleted file mode 100644 index 11f1e4a3..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "Fift.h" -#include - -namespace fift { -struct FiftOutput { - SourceLookup source_lookup; - std::string output; -}; -td::Result create_mem_source_lookup(std::string main, std::string fift_dir = "", - bool need_preamble = true, bool need_asm = true, - bool need_ton_util = true, bool need_lisp = true); -td::Result mem_run_fift(std::string source, std::vector args = {}, std::string fift_dir = ""); -td::Result mem_run_fift(SourceLookup source_lookup, std::vector args); -td::Result> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true); -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/words.cpp b/submodules/ton/tonlib-src/crypto/fift/words.cpp deleted file mode 100644 index 3c9e01dd..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/words.cpp +++ /dev/null @@ -1,3081 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "words.h" - -#include "Dictionary.h" -#include "IntCtx.h" -#include "SourceLookup.h" - -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "common/bitstring.h" -#include "common/util.h" - -#include "openssl/digest.hpp" - -#include "Ed25519.h" - -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/vm.h" -#include "vm/cp0.h" -#include "vm/dict.h" -#include "vm/boc.h" - -#include "vm/box.hpp" -#include "vm/atom.h" - -#include "block/block.h" - -#include "td/utils/filesystem.h" -#include "td/utils/misc.h" -#include "td/utils/optional.h" -#include "td/utils/PathView.h" -#include "td/utils/port/thread.h" -#include "td/utils/port/Stat.h" -#include "td/utils/Timer.h" -#include "td/utils/tl_helpers.h" -#include "td/utils/crypto.h" - -#include - -namespace fift { - -void show_total_cells(std::ostream& stream) { - stream << "total cells = " << vm::DataCell::get_total_data_cells() << std::endl; -} - -void do_compile(vm::Stack& stack, Ref word_def); -void do_compile_literals(vm::Stack& stack, int count); - -void interpret_dot(IntCtx& ctx, bool space_after) { - *ctx.output_stream << dec_string2(ctx.stack.pop_int()) << (space_after ? " " : ""); -} - -void interpret_dothex(IntCtx& ctx, bool upcase, bool space_after) { - *ctx.output_stream << hex_string(ctx.stack.pop_int(), upcase) << (space_after ? " " : ""); -} - -void interpret_dotbinary(IntCtx& ctx, bool space_after) { - *ctx.output_stream << binary_string(ctx.stack.pop_int()) << (space_after ? " " : ""); -} - -void interpret_dot_cellslice_rec(IntCtx& ctx) { - auto cs = ctx.stack.pop_cellslice(); - cs->print_rec(*ctx.output_stream); -} - -void interpret_dotstack(IntCtx& ctx) { - for (int i = ctx.stack.depth(); i > 0; i--) { - ctx.stack[i - 1].dump(*ctx.output_stream); - *ctx.output_stream << ' '; - } - *ctx.output_stream << std::endl; -} - -void interpret_dotstack_list(IntCtx& ctx) { - for (int i = ctx.stack.depth(); i > 0; i--) { - ctx.stack[i - 1].print_list(*ctx.output_stream); - *ctx.output_stream << ' '; - } - *ctx.output_stream << std::endl; -} - -void interpret_dotstack_list_dump(IntCtx& ctx) { - ctx.stack.dump(*ctx.output_stream, 3); -} - -void interpret_dump(IntCtx& ctx) { - ctx.stack.pop_chk().dump(*ctx.output_stream); - *ctx.output_stream << ' '; -} - -void interpret_dump_internal(vm::Stack& stack) { - stack.push_string(stack.pop_chk().to_string()); -} - -void interpret_list_dump_internal(vm::Stack& stack) { - stack.push_string(stack.pop_chk().to_lisp_string()); -} - -void interpret_print_list(IntCtx& ctx) { - ctx.stack.pop_chk().print_list(*ctx.output_stream); - *ctx.output_stream << ' '; -} - -void interpret_dottc(IntCtx& ctx) { - show_total_cells(*ctx.output_stream); -} - -void interpret_dot_internal(vm::Stack& stack) { - stack.push_string(dec_string2(stack.pop_int())); -} - -void interpret_dothex_internal(vm::Stack& stack, bool upcase) { - stack.push_string(hex_string(stack.pop_int(), upcase)); -} - -void interpret_dotbinary_internal(vm::Stack& stack) { - stack.push_string(binary_string(stack.pop_int())); -} - -void interpret_plus(vm::Stack& stack) { - stack.push_int(stack.pop_int() + stack.pop_int()); -} - -void interpret_cond_dup(vm::Stack& stack) { - auto x = stack.pop_int(); - if (x->sgn()) { - stack.push_int(x); - } - stack.push_int(std::move(x)); -} - -void interpret_plus_tiny(vm::Stack& stack, long long y) { - stack.push_int(stack.pop_int() + y); -} - -void interpret_minus(vm::Stack& stack) { - auto y = stack.pop_int(); - stack.push_int(stack.pop_int() - y); -} - -void interpret_times(vm::Stack& stack) { - stack.push_int(stack.pop_int() * stack.pop_int()); -} - -void interpret_div(vm::Stack& stack, int round_mode) { - auto y = stack.pop_int(); - stack.push_int(td::div(stack.pop_int(), y, round_mode)); -} - -void interpret_mod(vm::Stack& stack, int round_mode) { - auto y = stack.pop_int(); - stack.push_int(td::mod(stack.pop_int(), y, round_mode)); -} - -void interpret_divmod(vm::Stack& stack, int round_mode) { - auto y = stack.pop_int(); - auto dm = td::divmod(stack.pop_int(), std::move(y), round_mode); - stack.push_int(std::move(dm.first)); - stack.push_int(std::move(dm.second)); -} - -void interpret_times_div(vm::Stack& stack, int round_mode) { - auto z = stack.pop_int(), y = stack.pop_int(), x = stack.pop_int(); - stack.push_int(muldiv(std::move(x), std::move(y), std::move(z), round_mode)); -} - -void interpret_times_divmod(vm::Stack& stack, int round_mode) { - auto z = stack.pop_int(), y = stack.pop_int(), x = stack.pop_int(); - auto dm = muldivmod(std::move(x), std::move(y), std::move(z)); - stack.push_int(std::move(dm.first)); - stack.push_int(std::move(dm.second)); -} - -void interpret_times_mod(vm::Stack& stack, int round_mode) { - auto z = stack.pop_int(); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{0}, q; - tmp.add_mul(*x, *y); - tmp.mod_div(*z, q, round_mode); - stack.push_int(td::make_refint(tmp)); -} - -void interpret_negate(vm::Stack& stack) { - stack.push_int(-stack.pop_int()); -} - -void interpret_const(vm::Stack& stack, long long val) { - stack.push_smallint(val); -} - -void interpret_big_const(vm::Stack& stack, td::RefInt256 val) { - stack.push_int(std::move(val)); -} - -void interpret_literal(vm::Stack& stack, vm::StackEntry se) { - stack.push(std::move(se)); -} - -void interpret_cmp(vm::Stack& stack, const char opt[3]) { - auto y = stack.pop_int(); - auto x = stack.pop_int(); - int r = x->cmp(*y); - assert((unsigned)(r + 1) <= 2); - stack.push_smallint(((const signed char*)opt)[r + 1]); -} - -void interpret_sgn(vm::Stack& stack, const char opt[3]) { - auto x = stack.pop_int(); - int r = x->sgn(); - assert((unsigned)(r + 1) <= 2); - stack.push_smallint(((const signed char*)opt)[r + 1]); -} - -void interpret_fits(vm::Stack& stack, bool sgnd) { - int n = stack.pop_smallint_range(1023); - auto x = stack.pop_int(); - stack.push_bool(x->fits_bits(n, sgnd)); -} - -void interpret_pow2(vm::Stack& stack) { - int x = stack.pop_smallint_range(255); - auto r = td::make_refint(); - r.unique_write().set_pow2(x); - stack.push_int(r); -} - -void interpret_neg_pow2(vm::Stack& stack) { - int x = stack.pop_smallint_range(256); - auto r = td::make_refint(); - r.unique_write().set_pow2(x).negate().normalize(); - stack.push_int(r); -} - -void interpret_pow2_minus1(vm::Stack& stack) { - int x = stack.pop_smallint_range(256); - auto r = td::make_refint(); - r.unique_write().set_pow2(x).add_tiny(-1).normalize(); - stack.push_int(r); -} - -void interpret_mod_pow2(vm::Stack& stack) { - int y = stack.pop_smallint_range(256); - auto x = stack.pop_int(); - x.write().mod_pow2(y).normalize(); - stack.push_int(x); -} - -void interpret_lshift(vm::Stack& stack) { - int y = stack.pop_smallint_range(256); - stack.push_int(stack.pop_int() << y); -} - -void interpret_rshift(vm::Stack& stack, int round_mode) { - int y = stack.pop_smallint_range(256); - stack.push_int(rshift(stack.pop_int(), y, round_mode)); -} - -void interpret_lshift_const(vm::Stack& stack, int y) { - stack.push_int(stack.pop_int() << y); -} - -void interpret_rshift_const(vm::Stack& stack, int y) { - stack.push_int(stack.pop_int() >> y); -} - -void interpret_times_rshift(vm::Stack& stack, int round_mode) { - int z = stack.pop_smallint_range(256); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y).rshift(z, round_mode).normalize(); - stack.push_int(td::make_refint(tmp)); -} - -void interpret_lshift_div(vm::Stack& stack, int round_mode) { - int z = stack.pop_smallint_range(256); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{*x}; - tmp <<= z; - auto q = td::make_refint(); - tmp.mod_div(*y, q.unique_write(), round_mode); - q.unique_write().normalize(); - stack.push_int(std::move(q)); -} - -void interpret_not(vm::Stack& stack) { - stack.push_int(~stack.pop_int()); -} - -void interpret_and(vm::Stack& stack) { - stack.push_int(stack.pop_int() & stack.pop_int()); -} - -void interpret_or(vm::Stack& stack) { - stack.push_int(stack.pop_int() | stack.pop_int()); -} - -void interpret_xor(vm::Stack& stack) { - stack.push_int(stack.pop_int() ^ stack.pop_int()); -} - -void interpret_has_type(vm::Stack& stack, int t) { - stack.push_bool(stack.pop_chk().type() == t); -} - -void interpret_drop(vm::Stack& stack) { - stack.check_underflow(1); - stack.pop(); -} - -void interpret_2drop(vm::Stack& stack) { - stack.check_underflow(2); - stack.pop(); - stack.pop(); -} - -void interpret_dup(vm::Stack& stack) { - stack.check_underflow(1); - stack.push(stack.fetch(0)); -} - -void interpret_2dup(vm::Stack& stack) { - stack.check_underflow(2); - stack.push(stack.fetch(1)); - stack.push(stack.fetch(1)); -} - -void interpret_over(vm::Stack& stack) { - stack.check_underflow(2); - stack.push(stack.fetch(1)); -} - -void interpret_2over(vm::Stack& stack) { - stack.check_underflow(4); - stack.push(stack.fetch(3)); - stack.push(stack.fetch(3)); -} - -void interpret_swap(vm::Stack& stack) { - stack.check_underflow(2); - swap(stack[0], stack[1]); -} - -void interpret_2swap(vm::Stack& stack) { - stack.check_underflow(4); - swap(stack[0], stack[2]); - swap(stack[1], stack[3]); -} - -void interpret_tuck(vm::Stack& stack) { - stack.check_underflow(2); - swap(stack[0], stack[1]); - stack.push(stack.fetch(1)); -} - -void interpret_nip(vm::Stack& stack) { - stack.check_underflow(2); - stack.pop(stack[1]); -} - -void interpret_rot(vm::Stack& stack) { - stack.check_underflow(3); - swap(stack[1], stack[2]); - swap(stack[0], stack[1]); -} - -void interpret_rot_rev(vm::Stack& stack) { - stack.check_underflow(3); - swap(stack[0], stack[1]); - swap(stack[1], stack[2]); -} - -void interpret_pick(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - stack.check_underflow(n + 1); - stack.push(stack.fetch(n)); -} - -void interpret_roll(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - stack.check_underflow(n + 1); - for (int i = n; i > 0; i--) { - swap(stack[i], stack[i - 1]); - } -} - -void interpret_roll_rev(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - stack.check_underflow(n + 1); - for (int i = 0; i < n; i++) { - swap(stack[i], stack[i + 1]); - } -} - -void interpret_reverse(vm::Stack& stack) { - int m = stack.pop_smallint_range(255); - int n = stack.pop_smallint_range(255); - stack.check_underflow(n + m); - int s = 2 * m + n - 1; - for (int i = ((s - 1) >> 1); i >= m; i--) { - swap(stack[i], stack[s - i]); - } -} - -void interpret_exch(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - stack.check_underflow(n + 1); - swap(stack[0], stack[n]); -} - -void interpret_exch2(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - int m = stack.pop_smallint_range(255); - stack.check_underflow(std::max(m, n) + 1); - swap(stack[n], stack[m]); -} - -void interpret_depth(vm::Stack& stack) { - stack.push_smallint(stack.depth()); -} - -void interpret_xchg0(vm::Stack& stack, int x) { - stack.check_underflow_p(x); - std::swap(stack.tos(), stack.at(x)); -} - -void interpret_xchg(vm::Stack& stack, int x, int y) { - stack.check_underflow_p(x, y); - std::swap(stack.at(x), stack.at(y)); -} - -void interpret_push(vm::Stack& stack, int x) { - stack.check_underflow_p(x); - stack.push(stack.fetch(x)); -} - -void interpret_pop(vm::Stack& stack, int x) { - stack.check_underflow_p(x); - std::swap(stack.tos(), stack.at(x)); - stack.pop(); -} - -Ref dup_word_def{true, interpret_dup}, over_word_def{true, interpret_over}, - drop_word_def{true, interpret_drop}, nip_word_def{true, interpret_nip}, swap_word_def{true, interpret_swap}; - -void interpret_make_xchg(vm::Stack& stack) { - using namespace std::placeholders; - int y = stack.pop_smallint_range(255), x = stack.pop_smallint_range(255); - if (x > y) { - std::swap(x, y); - } - if (x) { - stack.push_object(td::Ref{true, std::bind(interpret_xchg, _1, x, y)}); - } else if (y <= 1) { - stack.push_object(y ? swap_word_def : Dictionary::nop_word_def); - } else { - stack.push_object(td::Ref{true, std::bind(interpret_xchg0, _1, y)}); - } -} - -void interpret_make_push(vm::Stack& stack) { - int x = stack.pop_smallint_range(255); - if (x <= 1) { - stack.push_object(x ? over_word_def : dup_word_def); - } else { - stack.push_object(td::Ref{true, std::bind(interpret_push, std::placeholders::_1, x)}); - } -} - -void interpret_make_pop(vm::Stack& stack) { - int x = stack.pop_smallint_range(255); - if (x <= 1) { - stack.push_object(x ? nip_word_def : drop_word_def); - } else { - stack.push_object(td::Ref{true, std::bind(interpret_pop, std::placeholders::_1, x)}); - } -} - -void interpret_is_string(vm::Stack& stack) { - stack.push_bool(stack.pop().type() == vm::StackEntry::t_string); -} - -int make_utf8_char(char buffer[4], int x) { - if (x < -0x80) { - return 0; - } else if (x < 0x80) { - buffer[0] = (char)x; - return 1; - } else if (x < 0x800) { - buffer[0] = (char)(0xc0 + (x >> 6)); - buffer[1] = (char)(0x80 + (x & 0x3f)); - return 2; - } else if (x < 0x10000) { - buffer[0] = (char)(0xe0 + (x >> 12)); - buffer[1] = (char)(0x80 + ((x >> 6) & 0x3f)); - buffer[2] = (char)(0x80 + (x & 0x3f)); - return 3; - } else if (x < 0x200000) { - buffer[0] = (char)(0xf0 + (x >> 18)); - buffer[1] = (char)(0x80 + ((x >> 12) & 0x3f)); - buffer[2] = (char)(0x80 + ((x >> 6) & 0x3f)); - buffer[3] = (char)(0x80 + (x & 0x3f)); - return 4; - } else { - return 0; - } -} - -void interpret_chr(vm::Stack& stack) { - char buffer[8]; - unsigned len = make_utf8_char(buffer, stack.pop_smallint_range(0x10ffff, -128)); - stack.push_string(std::string{buffer, len}); -} - -void interpret_hold(vm::Stack& stack) { - stack.check_underflow(2); - char buffer[8]; - unsigned len = make_utf8_char(buffer, stack.pop_smallint_range(0x10ffff, -128)); - std::string s = stack.pop_string() + std::string{buffer, len}; - stack.push_string(std::move(s)); -} - -void interpret_emit(IntCtx& ctx) { - char buffer[8]; - buffer[make_utf8_char(buffer, ctx.stack.pop_smallint_range(0x10ffff, -128))] = 0; - *ctx.output_stream << buffer; -} - -void interpret_emit_const(IntCtx& ctx, char c) { - *ctx.output_stream << c; -} - -void interpret_type(IntCtx& ctx) { - std::string s = ctx.stack.pop_string(); - *ctx.output_stream << s; -} - -void interpret_str_concat(vm::Stack& stack) { - std::string t = stack.pop_string(); - stack.push_string(stack.pop_string() + t); -} - -void interpret_str_equal(vm::Stack& stack) { - stack.check_underflow(2); - std::string t = stack.pop_string(), s = stack.pop_string(); - stack.push_bool(s == t); -} - -void interpret_str_cmp(vm::Stack& stack) { - stack.check_underflow(2); - std::string t = stack.pop_string(), s = stack.pop_string(); - int res = s.compare(std::move(t)); - stack.push_smallint((res > 0) - (res < 0)); -} - -void interpret_str_len(vm::Stack& stack) { - stack.push_smallint((long long)stack.pop_string().size()); -} - -void interpret_str_split(vm::Stack& stack) { - stack.check_underflow(2); - unsigned sz = stack.pop_smallint_range(0x7fffffff); - std::string str = stack.pop_string(); - if (sz > str.size()) { - throw IntError{"not enough bytes for cutting"}; - } - stack.push_string(std::string{str, 0, sz}); - stack.push_string(std::string{str, sz}); -} - -void interpret_str_pos(vm::Stack& stack) { - auto s2 = stack.pop_string(), s1 = stack.pop_string(); - auto pos = s1.find(s2); - stack.push_smallint(pos == std::string::npos ? -1 : static_cast(pos)); -} - -void interpret_str_reverse(vm::Stack& stack) { - std::string s = stack.pop_string(); - auto it = s.begin(); - while (it < s.end()) { - if ((*it & 0xc0) != 0xc0) { - ++it; - } else { - auto it0 = it++; - while (it < s.end() && (*it & 0xc0) == 0x80) { - ++it; - } - std::reverse(it0, it); - } - } - std::reverse(s.begin(), s.end()); - stack.push_string(std::move(s)); -} - -void interpret_utf8_str_len(vm::Stack& stack) { - std::string s = stack.pop_string(); - long long cnt = 0; - for (char c : s) { - if ((c & 0xc0) != 0x80) { - cnt++; - } - } - stack.push_smallint(cnt); -} - -void interpret_utf8_str_split(vm::Stack& stack) { - stack.check_underflow(2); - unsigned c = stack.pop_smallint_range(0xffff); - std::string s = stack.pop_string(); - if (c > s.size()) { - throw IntError{"not enough utf8 characters for cutting"}; - } - auto it = s.begin(); - for (; it < s.end(); ++it) { - if ((*it & 0xc0) != 0x80) { - if (!c) { - stack.push_string(std::string{s.begin(), it}); - stack.push_string(std::string{it, s.end()}); - return; - } - --c; - } - } - if (!c) { - stack.push_string(std::move(s)); - stack.push_string(std::string{}); - } else { - throw IntError{"not enough utf8 characters for cutting"}; - } -} - -void interpret_utf8_str_pos(vm::Stack& stack) { - auto s2 = stack.pop_string(), s1 = stack.pop_string(); - auto pos = s1.find(s2); - if (pos == std::string::npos) { - stack.push_smallint(-1); - return; - } - int cnt = 0; - for (std::size_t i = 0; i < pos; i++) { - cnt += ((s1[i] & 0xc0) != 0x80); - } - stack.push_smallint(cnt); -} - -void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) { - char x = (char)(arg ? arg : stack.pop_long_range(127)); - std::string s = stack.pop_string(); - s.resize(s.find_last_not_of(x) + 1); // if not found, this expression will be 0 - stack.push_string(std::move(s)); -} - -void interpret_bytes_len(vm::Stack& stack) { - stack.push_smallint((long long)stack.pop_bytes().size()); -} - -const char hex_digits[] = "0123456789abcdef"; -const char HEX_digits[] = "0123456789ABCDEF"; - -static inline const char* hex_digits_table(bool upcase) { - return upcase ? HEX_digits : hex_digits; -} - -void interpret_bytes_hex_print_raw(IntCtx& ctx, bool upcase) { - auto hex_digits = hex_digits_table(upcase); - std::string str = ctx.stack.pop_bytes(); - for (unsigned c : str) { - *ctx.output_stream << hex_digits[(c >> 4) & 15] << hex_digits[c & 15]; - } -} - -void interpret_bytes_to_hex(vm::Stack& stack, bool upcase) { - auto hex_digits = hex_digits_table(upcase); - std::string str = stack.pop_bytes(); - std::string t(str.size() * 2, 0); - for (std::size_t i = 0; i < str.size(); i++) { - unsigned c = str[i]; - t[2 * i] = hex_digits[(c >> 4) & 15]; - t[2 * i + 1] = hex_digits[c & 15]; - } - stack.push_string(std::move(t)); -} - -void interpret_hex_to_bytes(vm::Stack& stack, bool partial) { - std::string str = stack.pop_string(), t; - if (!partial) { - if (str.size() & 1) { - throw IntError{"not a hex string"}; - } - t.reserve(str.size() >> 1); - } - std::size_t i; - unsigned f = 0; - for (i = 0; i < str.size(); i++) { - int c = str[i]; - if (c >= '0' && c <= '9') { - c -= '0'; - } else { - c |= 0x20; - if (c >= 'a' && c <= 'f') { - c -= 'a' - 10; - } else { - if (!partial) { - throw IntError{"not a hex string"}; - } - break; - } - } - f = (f << 4) + c; - if (i & 1) { - t += (char)(f & 0xff); - } - } - stack.push_bytes(t); - if (partial) { - stack.push_smallint(i & -2); - } -} - -void interpret_bytes_split(vm::Stack& stack) { - stack.check_underflow(2); - unsigned sz = stack.pop_smallint_range(0x7fffffff); - std::string str = stack.pop_bytes(); - if (sz > str.size()) { - throw IntError{"not enough bytes for cutting"}; - } - stack.push_bytes(std::string{str, 0, sz}); - stack.push_bytes(std::string{str, sz}); -} - -void interpret_bytes_concat(vm::Stack& stack) { - std::string t = stack.pop_bytes(); - stack.push_bytes(stack.pop_bytes() + t); -} - -void interpret_bytes_equal(vm::Stack& stack) { - stack.check_underflow(2); - std::string t = stack.pop_bytes(), s = stack.pop_bytes(); - stack.push_bool(s == t); -} - -void interpret_bytes_cmp(vm::Stack& stack) { - stack.check_underflow(2); - std::string t = stack.pop_bytes(), s = stack.pop_bytes(); - int res = s.compare(std::move(t)); - stack.push_smallint((res > 0) - (res < 0)); -} - -void interpret_bytes_fetch_int(vm::Stack& stack, int mode) { - stack.check_underflow(2); - unsigned bits = (unsigned)stack.pop_smallint_range(256 + (mode & 1)); - std::string str = stack.pop_bytes(); - if ((bits & 7)) { - throw IntError{"can load only an integer number of bytes"}; - } - unsigned sz = bits >> 3; - if (str.size() < sz) { - throw IntError{"not enough bytes in the source"}; - } - td::RefInt256 x{true}; - bool ok; - const unsigned char* ptr = (const unsigned char*)(str.data()); - if (!(mode & 0x10)) { - ok = x.write().import_bytes(ptr, sz, mode & 1); - } else { - ok = x.write().import_bytes_lsb(ptr, sz, mode & 1); - } - if (!ok) { - throw IntError{"cannot load integer"}; - } - if (mode & 2) { - stack.push_bytes(std::string{str, sz}); - } - stack.push_int(std::move(x)); -} - -void interpret_int_to_bytes(vm::Stack& stack, bool sgnd, bool lsb) { - stack.check_underflow(2); - unsigned bits = (unsigned)stack.pop_smallint_range(sgnd ? 264 : 256, 1); - td::RefInt256 x = stack.pop_int(); - if ((bits & 7)) { - throw IntError{"can store only an integer number of bytes"}; - } - unsigned sz = bits >> 3; - unsigned char buffer[33]; - if (!(lsb ? x->export_bytes_lsb(buffer, sz, sgnd) : x->export_bytes(buffer, sz, sgnd))) { - throw IntError{"cannot store integer"}; - } - stack.push_bytes(std::string{(char*)buffer, sz}); -} - -void interpret_string_to_bytes(vm::Stack& stack) { - stack.push_bytes(stack.pop_string()); -} - -void interpret_bytes_to_string(vm::Stack& stack) { - stack.push_string(stack.pop_bytes()); -} - -void interpret_bytes_hash(vm::Stack& stack, bool as_uint) { - std::string str = stack.pop_bytes(); - unsigned char buffer[32]; - digest::hash_str(buffer, str.c_str(), str.size()); - if (as_uint) { - td::RefInt256 x{true}; - x.write().import_bytes(buffer, 32, false); - stack.push_int(std::move(x)); - } else { - stack.push_bytes(std::string{(char*)buffer, 32}); - } -} - -void interpret_empty(vm::Stack& stack) { - stack.push(td::Ref{true}); -} - -void interpret_store(vm::Stack& stack, bool sgnd) { - stack.check_underflow(3); - int bits = stack.pop_smallint_range(1023); - auto x = stack.pop_int(); - auto cell = stack.pop_builder(); - if (!cell.write().store_int256_bool(*x, bits, sgnd)) { - throw IntError{"integer does not fit into cell"}; - } - stack.push(cell); -} - -void interpret_store_str(vm::Stack& stack) { - stack.check_underflow(2); - auto str = stack.pop_string(); - auto cell = stack.pop_builder(); - if (!cell.write().store_bytes_bool(str)) { - throw IntError{"string does not fit into cell"}; - } - stack.push(cell); -} - -void interpret_store_bytes(vm::Stack& stack) { - stack.check_underflow(2); - auto str = stack.pop_bytes(); - auto cell = stack.pop_builder(); - if (!cell.write().store_bytes_bool(str)) { - throw IntError{"byte string does not fit into cell"}; - } - stack.push(cell); -} - -void interpret_string_to_cellslice(vm::Stack& stack) { - auto str = stack.pop_string(); - vm::CellBuilder cb; - if (!cb.store_bytes_bool(str)) { - throw IntError{"string does not fit into cell"}; - } - stack.push_cellslice(td::Ref{true, cb.finalize()}); -} - -void interpret_store_cellslice(vm::Stack& stack) { - stack.check_underflow(2); - auto cs = stack.pop_cellslice(); - auto cb = stack.pop_builder(); - if (!vm::cell_builder_add_slice_bool(cb.write(), *cs)) { - throw IntError{"slice does not fit into cell"}; - } - stack.push(std::move(cb)); -} - -void interpret_store_cellslice_ref(vm::Stack& stack) { - stack.check_underflow(2); - auto cs = stack.pop_cellslice(); - vm::CellBuilder cs_cell_builder; - vm::cell_builder_add_slice(cs_cell_builder, *cs); - auto cb = stack.pop_builder(); - if (!cb.write().store_ref_bool(cs_cell_builder.finalize())) { - throw IntError{"cell reference list overflow"}; - } - stack.push(std::move(cb)); -} - -void interpret_concat_cellslice(vm::Stack& stack) { - stack.check_underflow(2); - auto cs2 = stack.pop_cellslice(); - auto cs1 = stack.pop_cellslice(); - vm::CellBuilder cb; - if (vm::cell_builder_add_slice_bool(cb, *cs1) && vm::cell_builder_add_slice_bool(cb, *cs2)) { - stack.push_cellslice(td::Ref{true, cb.finalize()}); - } else { - throw IntError{"concatenation of two slices does not fit into a cell"}; - } -} - -void interpret_concat_cellslice_ref(vm::Stack& stack) { - stack.check_underflow(2); - auto cs2 = stack.pop_cellslice(); - auto cs1 = stack.pop_cellslice(); - vm::CellBuilder builder1, builder2; - vm::cell_builder_add_slice(builder1, *cs1); - vm::cell_builder_add_slice(builder2, *cs2); - if (!builder1.store_ref_bool(builder2.finalize())) { - throw IntError{"cell reference list overflow"}; - } - stack.push_cellslice(td::Ref{true, builder1.finalize()}); -} - -void interpret_concat_builders(vm::Stack& stack) { - stack.check_underflow(2); - auto cb2 = stack.pop_builder(); - auto cb1 = stack.pop_builder(); - if (!cb1.write().append_builder_bool(std::move(cb2))) { - throw IntError{"cannot concatenate two builders"}; - } - stack.push_builder(std::move(cb1)); -} - -void interpret_cell_datasize(vm::Stack& stack, int mode) { - auto bound = (mode & 4 ? stack.pop_int() : td::make_refint(1 << 22)); - Ref cell; - Ref cs; - if (mode & 2) { - cs = stack.pop_cellslice(); - } else { - cell = stack.pop_maybe_cell(); - } - if (!bound->is_valid() || bound->sgn() < 0) { - throw IntError{"finite non-negative integer expected"}; - } - vm::VmStorageStat stat{bound->unsigned_fits_bits(63) ? bound->to_long() : (1ULL << 63) - 1}; - bool ok = (mode & 2 ? stat.add_storage(cs.write()) : stat.add_storage(std::move(cell))); - if (ok) { - stack.push_smallint(stat.cells); - stack.push_smallint(stat.bits); - stack.push_smallint(stat.refs); - } else if (!(mode & 1)) { - throw IntError{"scanned too many cells"}; - } - if (mode & 1) { - stack.push_bool(ok); - } -} - -void interpret_slice_bitrefs(vm::Stack& stack, int mode) { - auto cs = stack.pop_cellslice(); - if (mode & 1) { - stack.push_smallint(cs->size()); - } - if (mode & 2) { - stack.push_smallint(cs->size_refs()); - } -} - -void interpret_builder_bitrefs(vm::Stack& stack, int mode) { - auto cb = stack.pop_builder(); - if (mode & 1) { - stack.push_smallint(cb->size()); - } - if (mode & 2) { - stack.push_smallint(cb->size_refs()); - } -} - -void interpret_builder_remaining_bitrefs(vm::Stack& stack, int mode) { - auto cb = stack.pop_builder(); - if (mode & 1) { - stack.push_smallint(cb->remaining_bits()); - } - if (mode & 2) { - stack.push_smallint(cb->remaining_refs()); - } -} - -void interpret_cell_hash(vm::Stack& stack, bool as_uint) { - auto cell = stack.pop_cell(); - if (as_uint) { - td::RefInt256 hash{true}; - hash.write().import_bytes(cell->get_hash().as_slice().ubegin(), 32, false); - stack.push_int(std::move(hash)); - } else { - stack.push_bytes(cell->get_hash().as_slice().str()); - } -} - -void interpret_store_ref(vm::Stack& stack) { - auto ref = stack.pop_cell(); - auto cb = stack.pop_builder(); - if (!cb.write().store_ref_bool(ref)) { - throw IntError{"cell reference list overflow"}; - } - stack.push(std::move(cb)); -} - -void interpret_store_end(vm::Stack& stack, bool special) { - auto cell = stack.pop_builder()->finalize_copy(special); - if (cell.is_null()) { - throw IntError{"invalid special cell constructed"}; - } - stack.push_cell(std::move(cell)); -} - -void interpret_from_cell(vm::Stack& stack) { - auto cell = stack.pop_cell(); - Ref cs{true, vm::NoVmOrd(), std::move(cell)}; - if (!cs->is_valid()) { - throw IntError{"deserializing a special cell as ordinary"}; - } - stack.push(cs); -} - -// cs n -- cs' x -// cs n -- cs' x -1 OR cs' 0 -// mode & 1 : signed -// mode & 2 : advance position -// mode & 4 : return error on stack -void interpret_fetch(vm::Stack& stack, int mode) { - auto n = stack.pop_smallint_range(256 + (mode & 1)); - auto cs = stack.pop_cellslice(); - if (!cs->have(n)) { - if (mode & 2) { - stack.push(std::move(cs)); - } - stack.push_bool(false); - if (!(mode & 4)) { - throw IntError{"end of data while reading integer from cell"}; - } - } else { - if (mode & 2) { - stack.push_int(cs.write().fetch_int256(n, mode & 1)); - stack.push(std::move(cs)); - } else { - stack.push_int(cs->prefetch_int256(n, mode & 1)); - } - if (mode & 4) { - stack.push_bool(true); - } - } -} - -// mode & 1 : return result as bytes (instead of string) -// mode & 2 : advance position -// mode & 4 : return error on stack -void interpret_fetch_bytes(vm::Stack& stack, int mode) { - unsigned n = stack.pop_smallint_range(127); - auto cs = stack.pop_cellslice(); - if (!cs->have(n * 8)) { - if (mode & 2) { - stack.push(std::move(cs)); - } - stack.push_bool(false); - if (!(mode & 4)) { - throw IntError{"end of data while reading byte string from cell"}; - } - } else { - // unfortunately, std::string's data() is writeable only in C++17 - unsigned char tmp[128]; - if (mode & 2) { - cs.write().fetch_bytes(tmp, n); - } else { - cs->prefetch_bytes(tmp, n); - } - std::string s{tmp, tmp + n}; - if (mode & 1) { - stack.push_bytes(std::move(s)); - } else { - stack.push_string(std::move(s)); - } - if (mode & 2) { - stack.push(std::move(cs)); - } - if (mode & 4) { - stack.push_bool(true); - } - } -} - -void interpret_cell_empty(vm::Stack& stack) { - auto cs = stack.pop_cellslice(); - stack.push_bool(cs->empty_ext()); -} - -void interpret_cell_check_empty(vm::Stack& stack) { - auto cs = stack.pop_cellslice(); - if (!cs->empty_ext()) { - throw IntError{"cell slice not empty"}; - } -} - -void interpret_cell_remaining(vm::Stack& stack) { - auto cs = stack.pop_cellslice(); - stack.push_smallint(cs->size()); - stack.push_smallint(cs->size_refs()); -} - -// mode & 1 : return result as slice (instead of cell) -// mode & 2 : advance position -// mode & 4 : return error on stack -void interpret_fetch_ref(vm::Stack& stack, int mode) { - auto cs = stack.pop_cellslice(); - if (!cs->have_refs(1)) { - if (mode & 2) { - stack.push(std::move(cs)); - } - stack.push_bool(false); - if (!(mode & 4)) { - throw IntError{"end of data while reading reference from cell"}; - } - } else { - auto cell = (mode & 2) ? cs.write().fetch_ref() : cs->prefetch_ref(); - if (mode & 2) { - stack.push(std::move(cs)); - } - if (mode & 1) { - Ref new_cs{true, vm::NoVmOrd(), std::move(cell)}; - if (!new_cs->is_valid()) { - throw IntError{"cannot load ordinary cell"}; - } - stack.push(std::move(new_cs)); - } else { - stack.push_cell(std::move(cell)); - } - if (mode & 4) { - stack.push_bool(true); - } - } -} - -// Box create/fetch/store operations - -void interpret_hole(vm::Stack& stack) { - stack.push_box(Ref{true}); -} - -void interpret_box(vm::Stack& stack) { - stack.push_box(Ref{true, stack.pop_chk()}); -} - -void interpret_box_fetch(vm::Stack& stack) { - stack.push(stack.pop_box()->get()); -} - -void interpret_box_store(vm::Stack& stack) { - stack.check_underflow(2); - auto box = stack.pop_box(); - box->set(stack.pop()); -} - -void interpret_push_null(vm::Stack& stack) { - stack.push({}); -} - -void interpret_is_null(vm::Stack& stack) { - stack.push_bool(stack.pop_chk().empty()); -} - -// Tuple/array operations - -void interpret_empty_tuple(vm::Stack& stack) { - stack.push_tuple(Ref{true}); -} - -void interpret_is_tuple(vm::Stack& stack) { - stack.push_bool(stack.pop_chk().type() == vm::StackEntry::t_tuple); -} - -void interpret_tuple_push(vm::Stack& stack) { - stack.check_underflow(2); - auto val = stack.pop(); - auto tuple = stack.pop_tuple(); - tuple.write().emplace_back(std::move(val)); - stack.push_tuple(std::move(tuple)); -} - -void interpret_tuple_pop(vm::Stack& stack) { - auto tuple = stack.pop_tuple(); - if (tuple->empty()) { - throw IntError{"empty tuple"}; - } - auto val = tuple->back(); - tuple.write().pop_back(); - stack.push_tuple(std::move(tuple)); - stack.push(std::move(val)); -} - -void interpret_tuple_len(vm::Stack& stack) { - stack.push_smallint(stack.pop_tuple()->size()); -} - -void interpret_tuple_index(vm::Stack& stack) { - auto idx = stack.pop_long_range(std::numeric_limits::max()); - auto tuple = stack.pop_tuple(); - if ((td::uint64)idx >= tuple->size()) { - throw vm::VmError{vm::Excno::range_chk, "array index out of range"}; - } - stack.push((*tuple)[td::narrow_cast(idx)]); -} - -void interpret_tuple_set(vm::Stack& stack) { - auto idx = stack.pop_long_range(std::numeric_limits::max()); - auto val = stack.pop_chk(); - auto tuple = stack.pop_tuple(); - if ((td::uint64)idx >= tuple->size()) { - throw vm::VmError{vm::Excno::range_chk, "array index out of range"}; - } - tuple.write()[td::narrow_cast(idx)] = std::move(val); - stack.push_tuple(std::move(tuple)); -} - -void interpret_make_tuple(vm::Stack& stack) { - int n = stack.pop_smallint_range(255); - stack.check_underflow(n); - Ref ref{true}; - auto& tuple = ref.unique_write(); - tuple.reserve(n); - for (int i = n - 1; i >= 0; i--) { - tuple.push_back(std::move(stack[i])); - } - stack.pop_many(n); - stack.push_tuple(std::move(ref)); -} - -void interpret_tuple_explode(vm::Stack& stack, bool pop_count) { - std::size_t n = pop_count ? (unsigned)stack.pop_smallint_range(255) : 0; - auto ref = stack.pop_tuple(); - const auto& tuple = *ref; - if (!pop_count) { - n = tuple.size(); - if (n > 255) { - throw IntError{"tuple too large to be exploded"}; - } - } else if (tuple.size() != n) { - throw IntError{"tuple size mismatch"}; - } - if (ref.is_unique()) { - auto& tuplew = ref.unique_write(); - for (auto& entry : tuplew) { - stack.push(std::move(entry)); - } - } else { - for (const auto& entry : tuple) { - stack.push(entry); - } - } - if (!pop_count) { - stack.push_smallint((td::int32)n); - } -} - -void interpret_allot(vm::Stack& stack) { - auto n = stack.pop_long_range(0xffffffff); - Ref ref{true}; - auto& tuple = ref.unique_write(); - tuple.reserve(td::narrow_cast(n)); - while (n-- > 0) { - tuple.emplace_back(Ref{true}); - } - stack.push(std::move(ref)); -} - -// Atoms - -void interpret_atom(vm::Stack& stack) { - bool create = stack.pop_bool(); - auto atom = vm::Atom::find(stack.pop_string(), create); - if (atom.is_null()) { - stack.push_bool(false); - } else { - stack.push_atom(std::move(atom)); - stack.push_bool(true); - } -} - -void interpret_atom_name(vm::Stack& stack) { - stack.push_string(stack.pop_atom()->name_ext()); -} - -void interpret_atom_anon(vm::Stack& stack) { - stack.push_atom(vm::Atom::anon()); -} - -void interpret_is_atom(vm::Stack& stack) { - stack.push_bool(stack.pop().is_atom()); -} - -bool are_eqv(vm::StackEntry x, vm::StackEntry y) { - if (x.type() != y.type()) { - return false; - } - switch (x.type()) { - case vm::StackEntry::t_null: - return true; - case vm::StackEntry::t_atom: - return std::move(x).as_atom() == std::move(y).as_atom(); - case vm::StackEntry::t_int: - return !td::cmp(std::move(x).as_int(), std::move(y).as_int()); - case vm::StackEntry::t_string: - return std::move(x).as_string() == std::move(y).as_string(); - default: - return false; - } -} - -void interpret_is_eqv(vm::Stack& stack) { - auto y = stack.pop(), x = stack.pop(); - stack.push_bool(are_eqv(std::move(x), std::move(y))); -} - -void interpret_is_eq(vm::Stack& stack) { - auto y = stack.pop(), x = stack.pop(); - stack.push_bool(x == y); -} - -// BoC (de)serialization - -void interpret_boc_serialize(vm::Stack& stack) { - vm::BagOfCells boc; - boc.add_root(stack.pop_cell()); - auto res = boc.import_cells(); - if (res.is_error()) { - throw IntError{(PSLICE() << "cannot serialize bag-of-cells " << res.error()).c_str()}; - } - stack.push_bytes(boc.serialize_to_string()); -} - -void interpret_boc_serialize_ext(vm::Stack& stack) { - int mode = stack.pop_smallint_range(vm::BagOfCells::Mode::max); - vm::BagOfCells boc; - boc.add_root(stack.pop_cell()); - auto res = boc.import_cells(); - if (res.is_error()) { - throw IntError{(PSLICE() << "cannot serialize bag-of-cells " << res.error()).c_str()}; - } - stack.push_bytes(boc.serialize_to_string(mode)); -} - -void interpret_boc_deserialize(vm::Stack& stack) { - std::string bytes = stack.pop_bytes(); - vm::BagOfCells boc; - auto res = boc.deserialize(td::Slice{bytes}); - if (res.is_error()) { - throw IntError{(PSLICE() << "cannot deserialize bag-of-cells " << res.error()).c_str()}; - } - if (res.ok() <= 0 || boc.get_root_cell().is_null()) { - throw IntError{"cannot deserialize bag-of-cells "}; - } - stack.push_cell(boc.get_root_cell()); -} - -void interpret_read_file(IntCtx& ctx) { - std::string filename = ctx.stack.pop_string(); - auto r_data = ctx.source_lookup->read_file(filename); - if (r_data.is_error()) { - throw IntError{PSTRING() << "error reading file `" << filename << "`: " << r_data.error()}; - } - ctx.stack.push_bytes(r_data.move_as_ok().data); -} - -void interpret_read_file_part(IntCtx& ctx) { - auto size = ctx.stack.pop_long_range(std::numeric_limits::max()); - auto offset = ctx.stack.pop_long_range(std::numeric_limits::max()); - std::string filename = ctx.stack.pop_string(); - auto r_data = ctx.source_lookup->read_file_part(filename, size, offset); - if (r_data.is_error()) { - throw IntError{PSTRING() << "error reading file `" << filename << "`: " << r_data.error()}; - } - ctx.stack.push_bytes(r_data.move_as_ok().data); -} - -void interpret_write_file(IntCtx& ctx) { - std::string filename = ctx.stack.pop_string(); - std::string str = ctx.stack.pop_bytes(); - auto status = ctx.source_lookup->write_file(filename, str); - if (status.is_error()) { - throw IntError{PSTRING() << "error writing file `" << filename << "`: " << status.error()}; - } -} - -void interpret_file_exists(IntCtx& ctx) { - std::string filename = ctx.stack.pop_string(); - auto res = ctx.source_lookup->is_file_exists(filename); - ctx.stack.push_bool(res); -} - -// custom and crypto - -void interpret_now(IntCtx& ctx) { - ctx.stack.push_smallint(ctx.source_lookup->now()); -} - -void interpret_new_keypair(vm::Stack& stack) { - auto priv_key = td::Ed25519::generate_private_key(); - if (!priv_key.is_ok()) { - throw fift::IntError{priv_key.error().to_string()}; - } - auto pub_key = priv_key.ok().get_public_key(); - if (!pub_key.is_ok()) { - throw fift::IntError{pub_key.error().to_string()}; - } - stack.push_bytes(priv_key.ok().as_octet_string()); - stack.push_bytes(pub_key.ok().as_octet_string()); -} - -void interpret_priv_key_to_pub(vm::Stack& stack) { - std::string str = stack.pop_bytes(); - if (str.size() != 32) { - throw IntError{"Ed25519 private key must be exactly 32 bytes long"}; - } - td::Ed25519::PrivateKey priv_key{td::SecureString{str}}; - auto pub_key = priv_key.get_public_key(); - if (!pub_key.is_ok()) { - throw fift::IntError{pub_key.error().to_string()}; - } - stack.push_bytes(pub_key.ok().as_octet_string()); -} - -void interpret_ed25519_sign(vm::Stack& stack) { - stack.check_underflow(2); - std::string key = stack.pop_bytes(), data = stack.pop_bytes(); - if (key.size() != 32) { - throw IntError{"Ed25519 private key must be exactly 32 bytes long"}; - } - td::Ed25519::PrivateKey priv_key{td::SecureString{key}}; - auto signature = priv_key.sign(td::Slice{data}); - if (!signature.is_ok()) { - throw fift::IntError{signature.error().to_string()}; - } - stack.push_bytes(signature.move_as_ok()); -} - -void interpret_ed25519_sign_uint(vm::Stack& stack) { - stack.check_underflow(2); - std::string key = stack.pop_bytes(); - td::RefInt256 data_int = stack.pop_int(); - if (key.size() != 32) { - throw IntError{"Ed25519 private key must be exactly 32 bytes long"}; - } - unsigned char data[32]; - if (!data_int->export_bytes(data, 32, false)) { - throw IntError{"Ed25519 data to be signed must fit into 256 bits"}; - } - td::Ed25519::PrivateKey priv_key{td::SecureString{key}}; - auto signature = priv_key.sign(td::Slice{data, 32}); - if (!signature.is_ok()) { - throw fift::IntError{signature.error().to_string()}; - } - stack.push_bytes(signature.move_as_ok()); -} - -void interpret_ed25519_chksign(vm::Stack& stack) { - stack.check_underflow(3); - std::string key = stack.pop_bytes(), signature = stack.pop_bytes(), data = stack.pop_bytes(); - if (key.size() != 32) { - throw IntError{"Ed25519 public key must be exactly 32 bytes long"}; - } - if (signature.size() != 64) { - throw IntError{"Ed25519 signature must be exactly 64 bytes long"}; - } - td::Ed25519::PublicKey pub_key{td::SecureString{key}}; - auto res = pub_key.verify_signature(td::Slice{data}, td::Slice{signature}); - stack.push_bool(res.is_ok()); -} - -void interpret_crc16(vm::Stack& stack) { - std::string str = stack.pop_bytes(); - stack.push_smallint(td::crc16(td::Slice{str})); -} - -void interpret_crc32(vm::Stack& stack) { - std::string str = stack.pop_bytes(); - stack.push_smallint(td::crc32(td::Slice{str})); -} - -void interpret_crc32c(vm::Stack& stack) { - std::string str = stack.pop_bytes(); - stack.push_smallint(td::crc32c(td::Slice{str})); -} - -// vm dictionaries -void interpret_dict_new(vm::Stack& stack) { - stack.push({}); -} - -void interpret_dict_to_slice(vm::Stack& stack) { - vm::CellBuilder cb; - cb.store_maybe_ref(stack.pop_maybe_cell()); - stack.push_cellslice(vm::load_cell_slice_ref(cb.finalize())); -} - -void interpret_load_dict(vm::Stack& stack, bool fetch) { - auto cs = stack.pop_cellslice(); - Ref dict; - bool non_empty; - if (!(cs.write().fetch_bool_to(non_empty) && (!non_empty || cs.write().fetch_ref_to(dict)))) { - throw IntError{"cell underflow"}; - } - stack.push_maybe_cell(std::move(dict)); - if (fetch) { - stack.push_cellslice(std::move(cs)); - } -} - -void interpret_store_dict(vm::Stack& stack) { - auto cell = stack.pop_maybe_cell(); - auto cb = stack.pop_builder(); - if (!cb.write().store_maybe_ref(std::move(cell))) { - throw IntError{"cell overflow"}; - } - stack.push_builder(std::move(cb)); -} - -// val key dict keylen -- dict' ? -void interpret_dict_add(vm::Stack& stack, vm::Dictionary::SetMode mode, bool add_builder, int sgnd) { - int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict{stack.pop_maybe_cell(), n}; - unsigned char buffer[vm::Dictionary::max_key_bytes]; - vm::BitSlice key = - (sgnd >= 0) ? dict.integer_key(stack.pop_int(), n, sgnd, buffer) : stack.pop_cellslice()->prefetch_bits(n); - if (!key.is_valid()) { - throw IntError{"not enough bits for a dictionary key"}; - } - bool res; - if (add_builder) { - res = dict.set_builder(std::move(key), stack.pop_builder(), mode); - } else { - res = dict.set(std::move(key), stack.pop_cellslice(), mode); - } - stack.push_maybe_cell(std::move(dict).extract_root_cell()); - stack.push_bool(res); -} - -void interpret_dict_get(vm::Stack& stack, int sgnd, int mode) { - int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict{stack.pop_maybe_cell(), n}; - unsigned char buffer[vm::Dictionary::max_key_bytes]; - vm::BitSlice key = - (sgnd >= 0) ? dict.integer_key(stack.pop_int(), n, sgnd, buffer) : stack.pop_cellslice()->prefetch_bits(n); - if (!key.is_valid()) { - throw IntError{"not enough bits for a dictionary key"}; - } - auto res = (mode & 4 ? dict.lookup_delete(std::move(key)) : dict.lookup(std::move(key))); - if (mode & 4) { - stack.push_maybe_cell(std::move(dict).extract_root_cell()); - } - bool found = res.not_null(); - if (found && (mode & 2)) { - stack.push_cellslice(std::move(res)); - } - if (mode & 1) { - stack.push_bool(found); - } -} - -void interpret_dict_map(IntCtx& ctx, bool ext, bool sgnd) { - auto func = pop_exec_token(ctx); - int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n}, dict2{n}; - for (auto entry : dict.range(false, sgnd)) { - ctx.stack.push_builder(Ref{true}); - if (ext) { - ctx.stack.push_int(dict.key_as_integer(entry.first, sgnd)); - } - ctx.stack.push_cellslice(std::move(entry.second)); - func->run(ctx); - if (ctx.stack.pop_bool()) { - if (!dict2.set_builder(entry.first, n, ctx.stack.pop_builder())) { - throw IntError{"cannot insert value into dictionary"}; - } - } - }; - ctx.stack.push_maybe_cell(std::move(dict2).extract_root_cell()); -} - -void interpret_dict_foreach(IntCtx& ctx, bool reverse, bool sgnd) { - auto func = pop_exec_token(ctx); - int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n}; - for (auto entry : dict.range(reverse, sgnd)) { - ctx.stack.push_int(dict.key_as_integer(entry.first, sgnd)); - ctx.stack.push_cellslice(std::move(entry.second)); - func->run(ctx); - if (!ctx.stack.pop_bool()) { - ctx.stack.push_bool(false); - return; - } - }; - ctx.stack.push_bool(true); -} - -// mode: +1 = reverse, +2 = signed, +4 = strict, +8 = lookup backwards, +16 = with hint -void interpret_dict_foreach_from(IntCtx& ctx, int mode) { - if (mode < 0) { - mode = ctx.stack.pop_smallint_range(31); - } - auto func = pop_exec_token(ctx); - int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n}; - vm::DictIterator it{dict, mode & 3}; - unsigned char buffer[vm::Dictionary::max_key_bytes]; - for (int s = (mode >> 4) & 1; s >= 0; --s) { - auto key = dict.integer_key(ctx.stack.pop_int(), n, mode & 2, buffer); - if (!key.is_valid()) { - throw IntError{"not enough bits for a dictionary key"}; - } - it.lookup(key, mode & 4, mode & 8); - } - for (; !it.eof(); ++it) { - ctx.stack.push_int(dict.key_as_integer(it.cur_pos(), mode & 2)); - ctx.stack.push_cellslice(it.cur_value()); - func->run(ctx); - if (!ctx.stack.pop_bool()) { - ctx.stack.push_bool(false); - return; - } - }; - ctx.stack.push_bool(true); -} - -void interpret_dict_merge(IntCtx& ctx) { - auto func = pop_exec_token(ctx); - int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict2{ctx.stack.pop_maybe_cell(), n}; - vm::Dictionary dict1{ctx.stack.pop_maybe_cell(), n}; - vm::Dictionary dict3{n}; - auto it1 = dict1.begin(), it2 = dict2.begin(); - while (!it1.eof() || !it2.eof()) { - int c = it1.eof() ? 1 : (it2.eof() ? -1 : it1.cur_pos().compare(it2.cur_pos(), n)); - bool ok = true; - if (c < 0) { - ok = dict3.set(it1.cur_pos(), n, it1.cur_value()); - ++it1; - } else if (c > 0) { - ok = dict3.set(it2.cur_pos(), n, it2.cur_value()); - ++it2; - } else { - ctx.stack.push_builder(Ref{true}); - ctx.stack.push_cellslice(it1.cur_value()); - ctx.stack.push_cellslice(it2.cur_value()); - func->run(ctx); - if (ctx.stack.pop_bool()) { - ok = dict3.set_builder(it1.cur_pos(), n, ctx.stack.pop_builder()); - } - ++it1; - ++it2; - } - if (!ok) { - throw IntError{"cannot insert value into dictionary"}; - } - } - ctx.stack.push_maybe_cell(std::move(dict3).extract_root_cell()); -} - -void interpret_dict_diff(IntCtx& ctx) { - auto func = pop_exec_token(ctx); - int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::Dictionary dict2{ctx.stack.pop_maybe_cell(), n}; - vm::Dictionary dict1{ctx.stack.pop_maybe_cell(), n}; - auto it1 = dict1.begin(), it2 = dict2.begin(); - while (!it1.eof() || !it2.eof()) { - int c = it1.eof() ? 1 : (it2.eof() ? -1 : it1.cur_pos().compare(it2.cur_pos(), n)); - bool run = true; - if (c < 0) { - ctx.stack.push_int(dict1.key_as_integer(it1.cur_pos())); - ctx.stack.push_cellslice(it1.cur_value()); - ctx.stack.push_null(); - ++it1; - } else if (c > 0) { - ctx.stack.push_int(dict2.key_as_integer(it2.cur_pos())); - ctx.stack.push_null(); - ctx.stack.push_cellslice(it2.cur_value()); - ++it2; - } else { - if (!it1.cur_value()->contents_equal(*it2.cur_value())) { - ctx.stack.push_int(dict1.key_as_integer(it1.cur_pos())); - ctx.stack.push_cellslice(it1.cur_value()); - ctx.stack.push_cellslice(it2.cur_value()); - } else { - run = false; - } - ++it1; - ++it2; - } - if (run) { - func->run(ctx); - if (!ctx.stack.pop_bool()) { - ctx.stack.push_bool(false); - return; - } - } - } - ctx.stack.push_bool(true); -} - -void interpret_pfx_dict_add(vm::Stack& stack, vm::Dictionary::SetMode mode, bool add_builder) { - int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::PrefixDictionary dict{stack.pop_maybe_cell(), n}; - auto cs = stack.pop_cellslice(); - bool res; - if (add_builder) { - res = dict.set_builder(cs->data_bits(), cs->size(), stack.pop_builder(), mode); - } else { - res = dict.set(cs->data_bits(), cs->size(), stack.pop_cellslice(), mode); - } - stack.push_maybe_cell(std::move(dict).extract_root_cell()); - stack.push_bool(res); -} - -void interpret_pfx_dict_get(vm::Stack& stack) { - int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits); - vm::PrefixDictionary dict{stack.pop_maybe_cell(), n}; - auto cs = stack.pop_cellslice(); - auto res = dict.lookup(cs->data_bits(), cs->size()); - if (res.not_null()) { - stack.push_cellslice(std::move(res)); - stack.push_bool(true); - } else { - stack.push_bool(false); - } -} - -void interpret_bitstring_hex_literal(IntCtx& ctx) { - auto s = ctx.scan_word_to('}'); - unsigned char buff[128]; - int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), s.begin(), s.end()); - if (bits < 0) { - throw IntError{"Invalid hex bitstring constant"}; - } - auto cs = Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}; - ctx.stack.push(std::move(cs)); - push_argcount(ctx.stack, 1); -} - -void interpret_bitstring_binary_literal(IntCtx& ctx) { - auto s = ctx.scan_word_to('}'); - unsigned char buff[128]; - int bits = (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), s.begin(), s.end()); - if (bits < 0) { - throw IntError{"Invalid binary bitstring constant"}; - } - auto cs = Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}; - ctx.stack.push(std::move(cs)); - push_argcount(ctx.stack, 1); -} - -void interpret_word(IntCtx& ctx) { - char sep = (char)ctx.stack.pop_smallint_range(127); - auto word = (sep != ' ' ? ctx.scan_word_to(sep, true) : ctx.scan_word()); - ctx.stack.push_string(word); -} - -void interpret_word_ext(IntCtx& ctx) { - int mode = ctx.stack.pop_smallint_range(11); - auto delims = ctx.stack.pop_string(); - if (mode & 8) { - ctx.skipspc(mode & 4); - } - ctx.stack.push_string(ctx.scan_word_ext(CharClassifier{delims, mode & 3})); -} - -void interpret_skipspc(IntCtx& ctx) { - ctx.skipspc(); -} - -void interpret_wordlist_begin_aux(vm::Stack& stack) { - stack.push({vm::from_object, Ref{true}}); -} - -void interpret_wordlist_begin(IntCtx& ctx) { - check_not_int_exec(ctx); - interpret_wordlist_begin_aux(ctx.stack); - push_argcount(ctx, 0); - ++(ctx.state); -} - -void interpret_wordlist_end_aux(vm::Stack& stack) { - Ref wordlist_ref = pop_word_list(stack); - wordlist_ref.write().close(); - stack.push({vm::from_object, Ref{wordlist_ref}}); -} - -void interpret_wordlist_end(IntCtx& ctx) { - check_compile(ctx); - interpret_wordlist_end_aux(ctx.stack); - push_argcount(ctx, 1); - --(ctx.state); -} - -void interpret_internal_interpret_begin(IntCtx& ctx) { - check_compile(ctx); - push_argcount(ctx, 0); - ctx.state = -ctx.state; -} - -void interpret_internal_interpret_end(IntCtx& ctx) { - check_int_exec(ctx); - ctx.state = -ctx.state; - ctx.stack.push({vm::from_object, Dictionary::nop_word_def}); -} - -// (create) -// maybe need an extra argument to identify the vocabulary (namespace) to be edited -void interpret_create_aux(IntCtx& ctx, int mode) { - if (mode < 0) { - mode = ctx.stack.pop_smallint_range(3); - } - std::string word = ctx.stack.pop_string(); - if (!word.size()) { - throw IntError{"non-empty word name expected"}; - } - auto wd_ref = pop_exec_token(ctx.stack); - if (!(mode & 2)) { - word += ' '; - } - bool active = (mode & 1); - auto entry = ctx.dictionary->lookup(word); - if (entry) { - *entry = WordRef{wd_ref, active}; // redefine word - } else { - ctx.dictionary->def_word(std::move(word), {wd_ref, active}); - } -} - -// { bl word 0 (create) } : create -void interpret_create(IntCtx& ctx) { - auto word = ctx.scan_word(); - if (!word.size()) { - throw IntError{"non-empty word name expected"}; - } - ctx.stack.push_string(word); - interpret_create_aux(ctx, 0); -} - -Ref create_aux_wd{Ref{true, std::bind(interpret_create_aux, std::placeholders::_1, -1)}}; - -// { bl word 2 ' (create) } :: : -void interpret_colon(IntCtx& ctx, int mode) { - ctx.stack.push_string(ctx.scan_word()); - ctx.stack.push_smallint(mode); - ctx.stack.push_smallint(2); - ctx.stack.push({vm::from_object, create_aux_wd}); - //push_argcount(ctx, 2, create_wd); -} - -// (forget) -void interpret_forget_aux(IntCtx& ctx) { - std::string s = ctx.stack.pop_string(); - auto s_copy = s; - auto entry = ctx.dictionary->lookup(s); - if (!entry) { - s += " "; - entry = ctx.dictionary->lookup(s); - } - if (!entry) { - throw IntError{"`" + s_copy + "` not found"}; - } else { - ctx.dictionary->undef_word(s); - } -} - -// { bl word (forget) } : forget -void interpret_forget(IntCtx& ctx) { - ctx.stack.push_string(ctx.scan_word()); - interpret_forget_aux(ctx); -} - -void interpret_quote_str(IntCtx& ctx) { - ctx.stack.push_string(ctx.scan_word_to('"')); - push_argcount(ctx.stack, 1); -} - -int str_utf8_code(const char* str, int& len) { - if (len <= 0) { - return -1; - } - if (len >= 1 && (unsigned char)str[0] < 0x80) { - len = 1; - return str[0]; - } - if (len >= 2 && (str[0] & 0xe0) == 0xc0 && (str[1] & 0xc0) == 0x80) { - len = 2; - return ((str[0] & 0x1f) << 6) | (str[1] & 0x3f); - } - if (len >= 3 && (str[0] & 0xf0) == 0xe0 && (str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) { - len = 3; - return ((str[0] & 0x0f) << 12) | ((str[1] & 0x3f) << 6) | (str[2] & 0x3f); - } - if (len >= 4 && (str[0] & 0xf8) == 0xf0 && (str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 && - (str[3] & 0xc0) == 0x80) { - len = 4; - return ((str[0] & 7) << 18) | ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) | (str[3] & 0x3f); - } - return -1; -} - -void interpret_char(IntCtx& ctx) { - auto s = ctx.scan_word(); - int len = (s.size() < 10 ? (int)s.size() : 10); - int code = str_utf8_code(s.data(), len); - if (code < 0 || s.size() != (unsigned)len) { - throw IntError{"exactly one character expected"}; - } - ctx.stack.push_smallint(code); - push_argcount(ctx, 1); -} - -void interpret_char_internal(vm::Stack& stack) { - auto s = stack.pop_string(); - int len = (s.size() < 10 ? (int)s.size() : 10); - int code = str_utf8_code(s.c_str(), len); - if (code < 0 || s.size() != (unsigned)len) { - throw IntError{"exactly one character expected"}; - } - stack.push_smallint(code); -} - -int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool allow_frac = true, - bool throw_error = false) { - if (allow_frac) { - auto pos = s.find('/'); - if (pos != std::string::npos) { - return parse_number(std::string{s, 0, pos}, num, denom, false, throw_error) > 0 && - parse_number(std::string{s, pos + 1}, denom, num, false, throw_error) > 0 - ? 2 - : 0; - } - } - const char* str = s.c_str(); - int len = (int)s.size(); - int frac = -1, base, *frac_ptr = allow_frac ? &frac : nullptr; - num = td::make_refint(); - auto& x = num.unique_write(); - if (len >= 4 && str[0] == '-' && str[1] == '0' && (str[2] == 'x' || str[2] == 'b')) { - if (str[2] == 'x') { - base = 16; - if (x.parse_hex(str + 3, len - 3, frac_ptr) != len - 3) { - return 0; - } - } else { - base = 2; - if (x.parse_binary(str + 3, len - 3, frac_ptr) != len - 3) { - return 0; - } - } - x.negate().normalize(); - } else if (len >= 3 && str[0] == '0' && (str[1] == 'x' || str[1] == 'b')) { - if (str[1] == 'x') { - base = 16; - if (x.parse_hex(str + 2, len - 2, frac_ptr) != len - 2) { - return 0; - } - } else { - base = 2; - if (x.parse_binary(str + 2, len - 2, frac_ptr) != len - 2) { - return 0; - } - } - } else { - base = 10; - if (!len || x.parse_dec(str, len, frac_ptr) != len) { - return 0; - } - } - if (!x.signed_fits_bits(257)) { - if (throw_error) { - throw IntError{"integer constant too large"}; - } - return 0; - } - if (frac < 0) { - return 1; - } else { - denom = td::make_refint(1); - while (frac-- > 0) { - if (!denom.unique_write().mul_tiny(base).normalize_bool()) { - if (throw_error) { - throw IntError{"denominator in constant too large"}; - } - return 0; - } - } - if (!denom.unique_write().unsigned_fits_bits(256)) { - if (throw_error) { - throw IntError{"denominator in constant too large"}; - } - return 0; - } - return 2; - } -} - -void interpret_parse_number(vm::Stack& stack) { - td::RefInt256 num, denom; - int res = parse_number(stack.pop_string(), num, denom, true, false); - if (res >= 1) { - stack.push_int(std::move(num)); - } - if (res == 2) { - stack.push_int(std::move(denom)); - } - stack.push_smallint(res); -} - -void interpret_parse_hex_number(vm::Stack& stack) { - td::RefInt256 x{true}; - auto str = stack.pop_string(); - bool ok = (str.size() <= 65535) && x.unique_write().parse_hex(str.data(), (int)str.size()) == (int)str.size(); - if (ok) { - stack.push_int(std::move(x)); - } - stack.push_smallint(ok); -} - -void interpret_quit(IntCtx& ctx) { - throw Quit{0}; -} - -void interpret_bye(IntCtx& ctx) { - throw Quit{-1}; -} - -void interpret_halt(vm::Stack& stack) { - int code = stack.pop_smallint_range(255); - throw Quit{~code}; -} - -void interpret_abort(IntCtx& ctx) { - throw IntError{ctx.stack.pop_string()}; -} - -Ref interpret_execute(IntCtx& ctx) { - return pop_exec_token(ctx); -} - -Ref interpret_execute_times(IntCtx& ctx) { - int count = ctx.stack.pop_smallint_range(1000000000); - auto wd_ref = pop_exec_token(ctx); - if (!count) { - return {}; - } - while (--count > 0) { - wd_ref->run(ctx); - } - return wd_ref; -} - -Ref interpret_if(IntCtx& ctx) { - auto true_ref = pop_exec_token(ctx); - if (ctx.stack.pop_bool()) { - return true_ref; - } else { - return {}; - } -} - -Ref interpret_ifnot(IntCtx& ctx) { - auto false_ref = pop_exec_token(ctx); - if (ctx.stack.pop_bool()) { - return {}; - } else { - return false_ref; - } -} - -Ref interpret_cond(IntCtx& ctx) { - auto false_ref = pop_exec_token(ctx); - auto true_ref = pop_exec_token(ctx); - if (ctx.stack.pop_bool()) { - return true_ref; - } else { - return false_ref; - } -} - -void interpret_while(IntCtx& ctx) { - auto body_ref = pop_exec_token(ctx); - auto cond_ref = pop_exec_token(ctx); - while (true) { - cond_ref->run(ctx); - if (!ctx.stack.pop_bool()) { - break; - } - body_ref->run(ctx); - } -} - -void interpret_until(IntCtx& ctx) { - auto body_ref = pop_exec_token(ctx); - do { - body_ref->run(ctx); - } while (!ctx.stack.pop_bool()); -} - -void interpret_tick(IntCtx& ctx) { - std::string word = ctx.scan_word().str(); - auto entry = ctx.dictionary->lookup(word); - if (!entry) { - entry = ctx.dictionary->lookup(word + ' '); - if (!entry) { - throw IntError{"word `" + word + "` undefined"}; - } - } - ctx.stack.push({vm::from_object, entry->get_def()}); - push_argcount(ctx, 1); -} - -void interpret_find(IntCtx& ctx) { - std::string word = ctx.stack.pop_string(); - auto entry = ctx.dictionary->lookup(word); - if (!entry) { - entry = ctx.dictionary->lookup(word + ' '); - } - if (!entry) { - ctx.stack.push_bool(false); - } else { - ctx.stack.push({vm::from_object, entry->get_def()}); - ctx.stack.push_bool(true); - } -} - -void interpret_tick_nop(vm::Stack& stack) { - stack.push({vm::from_object, Dictionary::nop_word_def}); -} - -void interpret_include(IntCtx& ctx) { - auto fname = ctx.stack.pop_string(); - auto r_file = ctx.source_lookup->lookup_source(fname, ctx.currentd_dir); - if (r_file.is_error()) { - throw IntError{"cannot locate file `" + fname + "`"}; - } - auto file = r_file.move_as_ok(); - std::stringstream ss(std::move(file.data)); - IntCtx::Savepoint save{ctx, td::PathView(file.path).file_name().str(), td::PathView(file.path).parent_dir().str(), - &ss}; - funny_interpret_loop(ctx); -} - -void interpret_skip_source(vm::Stack& stack) { - throw SkipToEof(); -} - -void interpret_words(IntCtx& ctx) { - for (const auto& x : *ctx.dictionary) { - *ctx.output_stream << x.first << " "; - } - *ctx.output_stream << std::endl; -} - -void interpret_pack_std_smc_addr(vm::Stack& stack) { - block::StdAddress a; - stack.check_underflow(3); - int mode = stack.pop_smallint_range(7); - td::RefInt256 x = stack.pop_int_finite(); - if (td::sgn(x) < 0) { - throw IntError{"non-negative integer expected"}; - } - CHECK(x->export_bytes(a.addr.data(), 32, false)); - a.workchain = stack.pop_smallint_range(0x7f, -0x80); - a.testnet = mode & 2; - a.bounceable = !(mode & 1); - stack.push_string(a.rserialize(mode & 4)); -} - -void interpret_unpack_std_smc_addr(vm::Stack& stack) { - block::StdAddress a; - if (!a.parse_addr(stack.pop_string())) { - stack.push_bool(false); - } else { - stack.push_smallint(a.workchain); - td::RefInt256 x{true}; - CHECK(x.write().import_bytes(a.addr.data(), 32, false)); - stack.push_int(std::move(x)); - stack.push_smallint(a.testnet * 2 + 1 - a.bounceable); - stack.push_bool(true); - } -} - -void interpret_bytes_to_base64(vm::Stack& stack, bool base64_url) { - stack.push_string(td::str_base64_encode(stack.pop_bytes(), base64_url)); -} - -void interpret_base64_to_bytes(vm::Stack& stack, bool allow_base64_url, bool quiet) { - auto s = stack.pop_string(); - if (!td::is_valid_base64(s, allow_base64_url)) { - stack.push_bool(false); - if (!quiet) { - throw IntError{"invalid base64"}; - } - } else { - stack.push_bytes(td::str_base64_decode(s, allow_base64_url)); - if (quiet) { - stack.push_bool(true); - } - } -} - -vm::VmLog create_vm_log(td::LogInterface* logger) { - if (!logger) { - return {}; - } - auto options = td::LogOptions::plain(); - options.level = 4; - options.fix_newlines = true; - return {logger, options}; -} - -class StringLogger : public td::LogInterface { - public: - void append(td::CSlice slice) override { - res.append(slice.data(), slice.size()); - } - std::string res; -}; - -class OstreamLogger : public td::LogInterface { - public: - explicit OstreamLogger(std::ostream* stream) : stream_(stream) { - } - void append(td::CSlice slice) override { - stream_->write(slice.data(), slice.size()); - } - - private: - std::ostream* stream_{nullptr}; -}; - -td::Ref vm_libraries{true}; - -std::vector> get_vm_libraries() { - if (vm_libraries->get().type() == vm::StackEntry::t_cell) { - return {vm_libraries->get().as_cell()}; - } else { - return {}; - } -} - -// mode: -1 = pop from stack -// +1 = same_c3 (set c3 to code) -// +2 = push_0 (push an implicit 0 before running the code) -// +4 = load c4 (persistent data) from stack and return its final value -// +8 = load gas limit from stack and return consumed gas -// +16 = load c7 (smart-contract context) -// +32 = return c5 (actions) -// +64 = log vm ops to stderr -// +128 = pop hard gas limit (enabled by ACCEPT) from stack as well -// +256 = enable stack trace -// +512 = enable debug instructions -void interpret_run_vm(IntCtx& ctx, int mode) { - if (mode < 0) { - mode = ctx.stack.pop_smallint_range(0x3ff); - } - bool with_data = mode & 4; - Ref c7; - Ref data, actions; - long long gas_max = (mode & 128) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty; - long long gas_limit = (mode & 8) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty; - if (!(mode & 128)) { - gas_max = gas_limit; - } else { - gas_max = std::max(gas_max, gas_limit); - } - if (mode & 16) { - c7 = ctx.stack.pop_tuple(); - } - if (with_data) { - data = ctx.stack.pop_cell(); - } - auto cs = ctx.stack.pop_cellslice(); - OstreamLogger ostream_logger(ctx.error_stream); - auto log = create_vm_log((mode & 64) && ctx.error_stream ? &ostream_logger : nullptr); - vm::GasLimits gas{gas_limit, gas_max}; - int res = vm::run_vm_code(cs, ctx.stack, (mode & 3) | ((mode & 0x300) >> 6), &data, log, nullptr, &gas, - get_vm_libraries(), std::move(c7), &actions); - ctx.stack.push_smallint(res); - if (with_data) { - ctx.stack.push_cell(std::move(data)); - } - if (mode & 32) { - ctx.stack.push_cell(std::move(actions)); - } - if (mode & 8) { - ctx.stack.push_smallint(gas.gas_consumed()); - } -} - -void do_interpret_db_run_vm_parallel(std::ostream* stream, vm::Stack& stack, vm::TonDb* ton_db_ptr, int threads_n, - int tasks_n) { - if (!ton_db_ptr || !*ton_db_ptr) { - throw vm::VmError{vm::Excno::fatal, "Ton database is not available"}; - } - auto& ton_db = *ton_db_ptr; - auto txn = ton_db->begin_transaction(); - auto txn_abort = td::ScopeExit() + [&] { ton_db->abort_transaction(std::move(txn)); }; - - struct Task { - vm::Ref code; - vm::SmartContractDb smart; - td::optional diff; - td::unique_ptr guard; - Ref stack; - int res{0}; - Ref data; - std::string log; - }; - std::vector tasks(tasks_n); - std::vector threads(threads_n); - - for (auto& task : tasks) { - task.code = stack.pop_cellslice(); - auto smart_hash = td::serialize(stack.pop_smallint_range(1000000000)); - task.smart = txn->begin_smartcontract(smart_hash); - task.guard = td::create_lambda_guard([&] { txn->abort_smartcontract(std::move(task.smart)); }); - auto argsn = stack.pop_smallint_range(100); - task.stack = stack.split_top(argsn); - } - - std::atomic next_task_i{0}; - auto run_tasks = [&] { - while (true) { - auto task_i = next_task_i++; - if (task_i >= tasks_n) { - break; - } - auto& task = tasks[task_i]; - auto data = task.smart->get_root(); - - StringLogger logger; - vm::VmLog log = create_vm_log(stream ? &logger : nullptr); - - task.res = vm::run_vm_code(task.code, task.stack, 3, &data, std::move(log)); - task.smart->set_root(data); - task.diff = vm::SmartContractDiff(std::move(task.smart)); - task.data = std::move(data); - task.log = std::move(logger.res); - } - }; - - td::Timer timer; - for (auto& thread : threads) { - thread = td::thread(run_tasks); - } - run_tasks(); - for (auto& thread : threads) { - thread.join(); - } - - if (stream) { - int id = 0; - for (auto& task : tasks) { - id++; - *stream << "Task #" << id << " vm_log begin" << std::endl; - *stream << task.log; - *stream << "Task #" << id << " vm_log end" << std::endl; - } - } - - LOG(ERROR) << timer; - timer = {}; - - for (auto& task : tasks) { - auto retn = task.stack.write().pop_smallint_range(100, -1); - if (retn == -1) { - retn = task.stack->depth(); - } - stack.push_from_stack(std::move(*task.stack), retn); - stack.push_smallint(task.res); - stack.push_cell(std::move(task.data)); - task.guard->dismiss(); - if (task.diff) { - txn->commit_smartcontract(std::move(task.diff.value())); - } else { - txn->commit_smartcontract(std::move(task.smart)); - } - } - LOG(ERROR) << timer; - timer = {}; - - txn_abort.dismiss(); - ton_db->commit_transaction(std::move(txn)); - timer = {}; - LOG(INFO) << "TonDB stats: \n" << ton_db->stats(); -} - -void interpret_db_run_vm(IntCtx& ctx) { - do_interpret_db_run_vm_parallel(ctx.error_stream, ctx.stack, ctx.ton_db, 0, 1); -} - -void interpret_db_run_vm_parallel(IntCtx& ctx) { - auto threads_n = ctx.stack.pop_smallint_range(32, 0); - auto tasks_n = ctx.stack.pop_smallint_range(1000000000); - do_interpret_db_run_vm_parallel(ctx.error_stream, ctx.stack, ctx.ton_db, threads_n, tasks_n); -} - -void interpret_store_vm_cont(vm::Stack& stack) { - auto vmcont = stack.pop_cont(); - auto cb = stack.pop_builder(); - if (!vmcont->serialize(cb.write())) { - throw IntError{"cannot serialize vm continuation"}; - } - stack.push_builder(std::move(cb)); -} - -void interpret_fetch_vm_cont(vm::Stack& stack) { - auto cs = stack.pop_cellslice(); - auto vmcont = vm::Continuation::deserialize(cs.write()); - if (vmcont.is_null()) { - throw IntError{"cannot deserialize vm continuation"}; - } - stack.push_cellslice(std::move(cs)); - stack.push_cont(std::move(vmcont)); -} - -Ref cmdline_args{true}; - -void interpret_get_fixed_cmdline_arg(vm::Stack& stack, int n) { - if (!n) { - return; - } - auto v = cmdline_args->get(); - while (true) { - if (v.empty()) { - stack.push(vm::StackEntry{}); - return; - } - auto t = v.as_tuple_range(2, 2); - if (t.is_null()) { - throw IntError{"invalid cmdline arg list"}; - } - if (!--n) { - stack.push(t->at(0)); - return; - } - v = t->at(1); - } -} - -// n -- executes $n -void interpret_get_cmdline_arg(IntCtx& ctx) { - int n = ctx.stack.pop_smallint_range(999999); - if (n) { - interpret_get_fixed_cmdline_arg(ctx.stack, n); - return; - } - auto entry = ctx.dictionary->lookup("$0 "); - if (!entry) { - throw IntError{"-?"}; - } else { - (*entry)(ctx); - } -} - -void interpret_get_cmdline_arg_count(vm::Stack& stack) { - auto v = cmdline_args->get(); - int cnt; - for (cnt = 0; !v.empty(); cnt++) { - auto t = v.as_tuple_range(2, 2); - if (t.is_null()) { - throw IntError{"invalid cmdline arg list"}; - } - v = t->at(1); - } - stack.push_smallint(cnt); -} - -void interpret_getenv(vm::Stack& stack) { - auto str = stack.pop_string(); - auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr; - stack.push_string(value ? std::string{value} : ""); -} - -void interpret_getenv_exists(vm::Stack& stack) { - auto str = stack.pop_string(); - auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr; - if (value) { - stack.push_string(std::string{value}); - } - stack.push_bool((bool)value); -} - -// x1 .. xn n 'w --> -void interpret_execute_internal(IntCtx& ctx) { - Ref word_def = pop_exec_token(ctx); - int count = ctx.stack.pop_smallint_range(255); - ctx.stack.check_underflow(count); - word_def->run(ctx); -} - -// wl x1 .. xn n 'w --> wl' -void interpret_compile_internal(vm::Stack& stack) { - Ref word_def = pop_exec_token(stack); - int count = stack.pop_smallint_range(255); - do_compile_literals(stack, count); - if (word_def != Dictionary::nop_word_def) { - do_compile(stack, word_def); - } -} - -void do_compile(vm::Stack& stack, Ref word_def) { - Ref wl_ref = pop_word_list(stack); - if (word_def != Dictionary::nop_word_def) { - if ((td::uint64)word_def->list_size() <= 1) { - // inline short definitions - wl_ref.write().append(*(word_def->get_list())); - } else { - wl_ref.write().push_back(word_def); - } - } - stack.push({vm::from_object, wl_ref}); -} - -void compile_one_literal(WordList& wlist, vm::StackEntry val) { - using namespace std::placeholders; - if (val.type() == vm::StackEntry::t_int) { - auto x = std::move(val).as_int(); - if (!x->signed_fits_bits(257)) { - throw IntError{"invalid numeric literal"}; - } else if (x->signed_fits_bits(td::BigIntInfo::word_shift)) { - wlist.push_back(Ref{true, std::bind(interpret_const, _1, x->to_long())}); - } else { - wlist.push_back(Ref{true, std::bind(interpret_big_const, _1, std::move(x))}); - } - } else { - wlist.push_back(Ref{true, std::bind(interpret_literal, _1, std::move(val))}); - } -} - -void do_compile_literals(vm::Stack& stack, int count) { - if (count < 0) { - throw IntError{"cannot compile a negative number of literals"}; - } - stack.check_underflow(count + 1); - Ref wl_ref = std::move(stack[count]).as_object(); - if (wl_ref.is_null()) { - throw IntError{"list of words expected"}; - } - for (int i = count - 1; i >= 0; i--) { - compile_one_literal(wl_ref.write(), std::move(stack[i])); - } - stack.pop_many(count + 1); - stack.push({vm::from_object, wl_ref}); -} - -void init_words_common(Dictionary& d) { - using namespace std::placeholders; - d.def_word("nop ", Dictionary::nop_word_def); - // stack print/dump words - d.def_ctx_word(". ", std::bind(interpret_dot, _1, true)); - d.def_ctx_word("._ ", std::bind(interpret_dot, _1, false)); - d.def_ctx_word("x. ", std::bind(interpret_dothex, _1, false, true)); - d.def_ctx_word("x._ ", std::bind(interpret_dothex, _1, false, false)); - d.def_ctx_word("X. ", std::bind(interpret_dothex, _1, true, true)); - d.def_ctx_word("X._ ", std::bind(interpret_dothex, _1, true, false)); - d.def_ctx_word("b. ", std::bind(interpret_dotbinary, _1, true)); - d.def_ctx_word("b._ ", std::bind(interpret_dotbinary, _1, false)); - d.def_ctx_word("csr. ", interpret_dot_cellslice_rec); - d.def_ctx_word(".s ", interpret_dotstack); - d.def_ctx_word(".sl ", interpret_dotstack_list); - d.def_ctx_word(".sL ", interpret_dotstack_list_dump); // TMP - d.def_ctx_word(".dump ", interpret_dump); - d.def_ctx_word(".l ", interpret_print_list); - d.def_ctx_word(".tc ", interpret_dottc); - d.def_stack_word("(dump) ", interpret_dump_internal); - d.def_stack_word("(ldump) ", interpret_list_dump_internal); - d.def_stack_word("(.) ", interpret_dot_internal); - d.def_stack_word("(x.) ", std::bind(interpret_dothex_internal, _1, false)); - d.def_stack_word("(X.) ", std::bind(interpret_dothex_internal, _1, true)); - d.def_stack_word("(b.) ", interpret_dotbinary_internal); - // stack manipulation - d.def_stack_word("drop ", interpret_drop); - d.def_stack_word("2drop ", interpret_2drop); - d.def_stack_word("dup ", interpret_dup); - d.def_stack_word("over ", interpret_over); - d.def_stack_word("2dup ", interpret_2dup); - d.def_stack_word("2over ", interpret_2over); - d.def_stack_word("swap ", interpret_swap); - d.def_stack_word("2swap ", interpret_2swap); - d.def_stack_word("tuck ", interpret_tuck); - d.def_stack_word("nip ", interpret_nip); - d.def_stack_word("rot ", interpret_rot); - d.def_stack_word("-rot ", interpret_rot_rev); - d.def_stack_word("pick ", interpret_pick); - d.def_stack_word("roll ", interpret_roll); - d.def_stack_word("-roll ", interpret_roll_rev); - d.def_stack_word("reverse ", interpret_reverse); - d.def_stack_word("exch ", interpret_exch); - d.def_stack_word("exch2 ", interpret_exch2); - d.def_stack_word("depth ", interpret_depth); - d.def_stack_word("?dup ", interpret_cond_dup); - // low-level stack manipulation - d.def_stack_word(" ", interpret_make_xchg); - d.def_stack_word(" ", interpret_make_push); - d.def_stack_word(" ", interpret_make_pop); - // arithmetic - d.def_stack_word("+ ", interpret_plus); - d.def_stack_word("- ", interpret_minus); - d.def_stack_word("negate ", interpret_negate); - d.def_stack_word("1+ ", std::bind(interpret_plus_tiny, _1, 1)); - d.def_stack_word("1- ", std::bind(interpret_plus_tiny, _1, -1)); - d.def_stack_word("2+ ", std::bind(interpret_plus_tiny, _1, 2)); - d.def_stack_word("2- ", std::bind(interpret_plus_tiny, _1, -2)); - d.def_stack_word("* ", interpret_times); - d.def_stack_word("/ ", std::bind(interpret_div, _1, -1)); - d.def_stack_word("/c ", std::bind(interpret_div, _1, 1)); - d.def_stack_word("/r ", std::bind(interpret_div, _1, 0)); - d.def_stack_word("mod ", std::bind(interpret_mod, _1, -1)); - d.def_stack_word("rmod ", std::bind(interpret_mod, _1, 0)); - d.def_stack_word("cmod ", std::bind(interpret_mod, _1, 1)); - d.def_stack_word("/mod ", std::bind(interpret_divmod, _1, -1)); - d.def_stack_word("/cmod ", std::bind(interpret_divmod, _1, 1)); - d.def_stack_word("/rmod ", std::bind(interpret_divmod, _1, 0)); - d.def_stack_word("*/ ", std::bind(interpret_times_div, _1, -1)); - d.def_stack_word("*/c ", std::bind(interpret_times_div, _1, 1)); - d.def_stack_word("*/r ", std::bind(interpret_times_div, _1, 0)); - d.def_stack_word("*/mod ", std::bind(interpret_times_divmod, _1, -1)); - d.def_stack_word("*/cmod ", std::bind(interpret_times_divmod, _1, 1)); - d.def_stack_word("*/rmod ", std::bind(interpret_times_divmod, _1, 0)); - d.def_stack_word("*mod ", std::bind(interpret_times_mod, _1, -1)); - d.def_stack_word("1<< ", interpret_pow2); - d.def_stack_word("-1<< ", interpret_neg_pow2); - d.def_stack_word("1<<1- ", interpret_pow2_minus1); - d.def_stack_word("%1<< ", interpret_mod_pow2); - d.def_stack_word("<< ", interpret_lshift); - d.def_stack_word(">> ", std::bind(interpret_rshift, _1, -1)); - d.def_stack_word(">>c ", std::bind(interpret_rshift, _1, 1)); - d.def_stack_word(">>r ", std::bind(interpret_rshift, _1, 0)); - d.def_stack_word("2* ", std::bind(interpret_lshift_const, _1, 1)); - d.def_stack_word("2/ ", std::bind(interpret_rshift_const, _1, 1)); - d.def_stack_word("*>> ", std::bind(interpret_times_rshift, _1, -1)); - d.def_stack_word("*>>c ", std::bind(interpret_times_rshift, _1, 1)); - d.def_stack_word("*>>r ", std::bind(interpret_times_rshift, _1, 0)); - d.def_stack_word("< ", std::bind(interpret_cmp, _1, "\xff\x00\xff")); - d.def_stack_word("<= ", std::bind(interpret_cmp, _1, "\xff\xff\x00")); - d.def_stack_word(">= ", std::bind(interpret_cmp, _1, "\x00\xff\xff")); - d.def_stack_word("< ", std::bind(interpret_cmp, _1, "\xff\x00\x00")); - d.def_stack_word("> ", std::bind(interpret_cmp, _1, "\x00\x00\xff")); - d.def_stack_word("sgn ", std::bind(interpret_sgn, _1, "\xff\x00\x01")); - d.def_stack_word("0= ", std::bind(interpret_sgn, _1, "\x00\xff\x00")); - d.def_stack_word("0<> ", std::bind(interpret_sgn, _1, "\xff\x00\xff")); - d.def_stack_word("0<= ", std::bind(interpret_sgn, _1, "\xff\xff\x00")); - d.def_stack_word("0>= ", std::bind(interpret_sgn, _1, "\x00\xff\xff")); - d.def_stack_word("0< ", std::bind(interpret_sgn, _1, "\xff\x00\x00")); - d.def_stack_word("0> ", std::bind(interpret_sgn, _1, "\x00\x00\xff")); - d.def_stack_word("fits ", std::bind(interpret_fits, _1, true)); - d.def_stack_word("ufits ", std::bind(interpret_fits, _1, false)); - // char/string manipulation - d.def_active_word("\"", interpret_quote_str); - d.def_active_word("char ", interpret_char); - d.def_stack_word("(char) ", interpret_char_internal); - d.def_ctx_word("emit ", interpret_emit); - d.def_ctx_word("space ", std::bind(interpret_emit_const, _1, ' ')); - d.def_ctx_word("cr ", std::bind(interpret_emit_const, _1, '\n')); - d.def_ctx_word("type ", interpret_type); - d.def_stack_word("string? ", interpret_is_string); - d.def_stack_word("chr ", interpret_chr); - d.def_stack_word("hold ", interpret_hold); - d.def_stack_word("(number) ", interpret_parse_number); - d.def_stack_word("(hex-number) ", interpret_parse_hex_number); - d.def_stack_word("$| ", interpret_str_split); - d.def_stack_word("$+ ", interpret_str_concat); - d.def_stack_word("$= ", interpret_str_equal); - d.def_stack_word("$cmp ", interpret_str_cmp); - d.def_stack_word("$reverse ", interpret_str_reverse); - d.def_stack_word("$pos ", interpret_str_pos); - d.def_stack_word("(-trailing) ", std::bind(interpret_str_remove_trailing_int, _1, 0)); - d.def_stack_word("-trailing ", std::bind(interpret_str_remove_trailing_int, _1, ' ')); - d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0')); - d.def_stack_word("$len ", interpret_str_len); - d.def_stack_word("Blen ", interpret_bytes_len); - d.def_stack_word("$Len ", interpret_utf8_str_len); - d.def_stack_word("$Split ", interpret_utf8_str_split); - d.def_stack_word("$Pos ", interpret_utf8_str_pos); - d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true)); - d.def_stack_word("B>X ", std::bind(interpret_bytes_to_hex, _1, true)); - d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false)); - d.def_stack_word("x>B ", std::bind(interpret_hex_to_bytes, _1, false)); - d.def_stack_word("x>B? ", std::bind(interpret_hex_to_bytes, _1, true)); - d.def_stack_word("B| ", interpret_bytes_split); - d.def_stack_word("B+ ", interpret_bytes_concat); - d.def_stack_word("B= ", interpret_bytes_equal); - d.def_stack_word("Bcmp ", interpret_bytes_cmp); - d.def_stack_word("u>B ", std::bind(interpret_int_to_bytes, _1, false, false)); - d.def_stack_word("i>B ", std::bind(interpret_int_to_bytes, _1, true, false)); - d.def_stack_word("Lu>B ", std::bind(interpret_int_to_bytes, _1, false, true)); - d.def_stack_word("Li>B ", std::bind(interpret_int_to_bytes, _1, true, true)); - d.def_stack_word("B>u@ ", std::bind(interpret_bytes_fetch_int, _1, 0)); - d.def_stack_word("B>i@ ", std::bind(interpret_bytes_fetch_int, _1, 1)); - d.def_stack_word("B>u@+ ", std::bind(interpret_bytes_fetch_int, _1, 2)); - d.def_stack_word("B>i@+ ", std::bind(interpret_bytes_fetch_int, _1, 3)); - d.def_stack_word("B>Lu@ ", std::bind(interpret_bytes_fetch_int, _1, 0x10)); - d.def_stack_word("B>Li@ ", std::bind(interpret_bytes_fetch_int, _1, 0x11)); - d.def_stack_word("B>Lu@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x12)); - d.def_stack_word("B>Li@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x13)); - d.def_stack_word("$>B ", interpret_string_to_bytes); - d.def_stack_word("B>$ ", interpret_bytes_to_string); - d.def_stack_word("Bhash ", std::bind(interpret_bytes_hash, _1, true)); - d.def_stack_word("Bhashu ", std::bind(interpret_bytes_hash, _1, true)); - d.def_stack_word("BhashB ", std::bind(interpret_bytes_hash, _1, false)); - // cell manipulation (create, write and modify cells) - d.def_stack_word(" ", std::bind(interpret_store_end, _1, false)); - d.def_stack_word("b>spec ", std::bind(interpret_store_end, _1, true)); - d.def_stack_word("$>s ", interpret_string_to_cellslice); - d.def_stack_word("|+ ", interpret_concat_cellslice); - d.def_stack_word("|_ ", interpret_concat_cellslice_ref); - d.def_stack_word("b+ ", interpret_concat_builders); - d.def_stack_word("bbits ", std::bind(interpret_builder_bitrefs, _1, 1)); - d.def_stack_word("brefs ", std::bind(interpret_builder_bitrefs, _1, 2)); - d.def_stack_word("bbitrefs ", std::bind(interpret_builder_bitrefs, _1, 3)); - d.def_stack_word("brembits ", std::bind(interpret_builder_remaining_bitrefs, _1, 1)); - d.def_stack_word("bremrefs ", std::bind(interpret_builder_remaining_bitrefs, _1, 2)); - d.def_stack_word("brembitrefs ", std::bind(interpret_builder_remaining_bitrefs, _1, 3)); - d.def_stack_word("hash ", std::bind(interpret_cell_hash, _1, true)); - d.def_stack_word("hashu ", std::bind(interpret_cell_hash, _1, true)); - d.def_stack_word("hashB ", std::bind(interpret_cell_hash, _1, false)); - // cellslice manipulation (read from cells) - d.def_stack_word(" ", interpret_cell_check_empty); - d.def_stack_word("empty? ", interpret_cell_empty); - d.def_stack_word("remaining ", interpret_cell_remaining); - d.def_stack_word("sbits ", std::bind(interpret_slice_bitrefs, _1, 1)); - d.def_stack_word("srefs ", std::bind(interpret_slice_bitrefs, _1, 2)); - d.def_stack_word("sbitrefs ", std::bind(interpret_slice_bitrefs, _1, 3)); - d.def_stack_word("totalcsize ", std::bind(interpret_cell_datasize, _1, 0)); - d.def_stack_word("totalssize ", std::bind(interpret_cell_datasize, _1, 2)); - // boc manipulation - d.def_stack_word("B>boc ", interpret_boc_deserialize); - d.def_stack_word("boc>B ", interpret_boc_serialize); - d.def_stack_word("boc+>B ", interpret_boc_serialize_ext); - d.def_ctx_word("file>B ", interpret_read_file); - d.def_ctx_word("filepart>B ", interpret_read_file_part); - d.def_ctx_word("B>file ", interpret_write_file); - d.def_ctx_word("file-exists? ", interpret_file_exists); - // custom & crypto - d.def_ctx_word("now ", interpret_now); - d.def_stack_word("getenv ", interpret_getenv); - d.def_stack_word("getenv? ", interpret_getenv_exists); - d.def_stack_word("newkeypair ", interpret_new_keypair); - d.def_stack_word("priv>pub ", interpret_priv_key_to_pub); - d.def_stack_word("ed25519_sign ", interpret_ed25519_sign); - d.def_stack_word("ed25519_chksign ", interpret_ed25519_chksign); - d.def_stack_word("ed25519_sign_uint ", interpret_ed25519_sign_uint); - d.def_stack_word("crc16 ", interpret_crc16); - d.def_stack_word("crc32 ", interpret_crc32); - d.def_stack_word("crc32c ", interpret_crc32c); - // vm dictionaries - d.def_stack_word("dictnew ", interpret_dict_new); - d.def_stack_word("dict>s ", interpret_dict_to_slice); - d.def_stack_word("dict, ", interpret_store_dict); - d.def_stack_word("dict@ ", std::bind(interpret_load_dict, _1, false)); - d.def_stack_word("dict@+ ", std::bind(interpret_load_dict, _1, true)); - d.def_stack_word("sdict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, -1)); - d.def_stack_word("sdict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, -1)); - d.def_stack_word("b>sdict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, -1)); - d.def_stack_word("b>sdict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, -1)); - d.def_stack_word("sdict@ ", std::bind(interpret_dict_get, _1, -1, 3)); - d.def_stack_word("sdict@- ", std::bind(interpret_dict_get, _1, -1, 7)); - d.def_stack_word("sdict- ", std::bind(interpret_dict_get, _1, -1, 5)); - d.def_stack_word("udict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, 0)); - d.def_stack_word("udict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, 0)); - d.def_stack_word("b>udict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, 0)); - d.def_stack_word("b>udict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, 0)); - d.def_stack_word("udict@ ", std::bind(interpret_dict_get, _1, 0, 3)); - d.def_stack_word("udict@- ", std::bind(interpret_dict_get, _1, 0, 7)); - d.def_stack_word("udict- ", std::bind(interpret_dict_get, _1, 0, 5)); - d.def_stack_word("idict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, 1)); - d.def_stack_word("idict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, 1)); - d.def_stack_word("b>idict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, 1)); - d.def_stack_word("b>idict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, 1)); - d.def_stack_word("idict@ ", std::bind(interpret_dict_get, _1, 1, 3)); - d.def_stack_word("idict@- ", std::bind(interpret_dict_get, _1, 1, 7)); - d.def_stack_word("idict- ", std::bind(interpret_dict_get, _1, 1, 5)); - d.def_stack_word("pfxdict!+ ", std::bind(interpret_pfx_dict_add, _1, vm::Dictionary::SetMode::Add, false)); - d.def_stack_word("pfxdict! ", std::bind(interpret_pfx_dict_add, _1, vm::Dictionary::SetMode::Set, false)); - d.def_stack_word("pfxdict@ ", interpret_pfx_dict_get); - d.def_ctx_word("dictmap ", std::bind(interpret_dict_map, _1, false, false)); - d.def_ctx_word("dictmapext ", std::bind(interpret_dict_map, _1, true, false)); - d.def_ctx_word("idictmapext ", std::bind(interpret_dict_map, _1, true, true)); - d.def_ctx_word("dictforeach ", std::bind(interpret_dict_foreach, _1, false, false)); - d.def_ctx_word("idictforeach ", std::bind(interpret_dict_foreach, _1, false, true)); - d.def_ctx_word("dictforeachrev ", std::bind(interpret_dict_foreach, _1, true, false)); - d.def_ctx_word("idictforeachrev ", std::bind(interpret_dict_foreach, _1, true, true)); - d.def_ctx_word("dictforeachfromx ", std::bind(interpret_dict_foreach_from, _1, -1)); - d.def_ctx_word("dictmerge ", interpret_dict_merge); - d.def_ctx_word("dictdiff ", interpret_dict_diff); - // slice/bitstring constants - d.def_active_word("x{", interpret_bitstring_hex_literal); - d.def_active_word("b{", interpret_bitstring_binary_literal); - // boxes/holes/variables - d.def_stack_word("hole ", interpret_hole); - d.def_stack_word("box ", interpret_box); - d.def_stack_word("@ ", interpret_box_fetch); - d.def_stack_word("! ", interpret_box_store); - d.def_stack_word("null ", interpret_push_null); - d.def_stack_word("null? ", interpret_is_null); - // tuples/arrays - d.def_stack_word("| ", interpret_empty_tuple); - d.def_stack_word(", ", interpret_tuple_push); - d.def_stack_word("tpop ", interpret_tuple_pop); - d.def_stack_word("[] ", interpret_tuple_index); - d.def_stack_word("[]= ", interpret_tuple_set); - d.def_stack_word("count ", interpret_tuple_len); - d.def_stack_word("tuple? ", interpret_is_tuple); - d.def_stack_word("tuple ", interpret_make_tuple); - d.def_stack_word("untuple ", std::bind(interpret_tuple_explode, _1, true)); - d.def_stack_word("explode ", std::bind(interpret_tuple_explode, _1, false)); - d.def_stack_word("allot ", interpret_allot); - // atoms - d.def_stack_word("anon ", interpret_atom_anon); - d.def_stack_word("(atom) ", interpret_atom); - d.def_stack_word("atom>$ ", interpret_atom_name); - d.def_stack_word("eq? ", interpret_is_eq); - d.def_stack_word("eqv? ", interpret_is_eqv); - d.def_stack_word("atom? ", interpret_is_atom); - // execution control - d.def_ctx_tail_word("execute ", interpret_execute); - d.def_ctx_tail_word("times ", interpret_execute_times); - d.def_ctx_tail_word("if ", interpret_if); - d.def_ctx_tail_word("ifnot ", interpret_ifnot); - d.def_ctx_tail_word("cond ", interpret_cond); - d.def_ctx_word("while ", interpret_while); - d.def_ctx_word("until ", interpret_until); - // compiler control - d.def_active_word("[ ", interpret_internal_interpret_begin); - d.def_active_word("] ", interpret_internal_interpret_end); - d.def_active_word("{ ", interpret_wordlist_begin); - d.def_active_word("} ", interpret_wordlist_end); - d.def_stack_word("({) ", interpret_wordlist_begin_aux); - d.def_stack_word("(}) ", interpret_wordlist_end_aux); - d.def_stack_word("(compile) ", interpret_compile_internal); - d.def_ctx_word("(execute) ", interpret_execute_internal); - d.def_active_word("' ", interpret_tick); - d.def_stack_word("'nop ", interpret_tick_nop); - // dictionary manipulation - d.def_ctx_word("find ", interpret_find); - d.def_ctx_word("create ", interpret_create); - d.def_ctx_word("(create) ", std::bind(interpret_create_aux, _1, -1)); - d.def_active_word(": ", std::bind(interpret_colon, _1, 0)); - d.def_active_word(":: ", std::bind(interpret_colon, _1, 1)); - d.def_active_word(":_ ", std::bind(interpret_colon, _1, 2)); - d.def_active_word("::_ ", std::bind(interpret_colon, _1, 3)); - d.def_ctx_word("(forget) ", interpret_forget_aux); - d.def_ctx_word("forget ", interpret_forget); - d.def_ctx_word("words ", interpret_words); - // input parse - d.def_ctx_word("word ", interpret_word); - d.def_ctx_word("(word) ", interpret_word_ext); - d.def_ctx_word("skipspc ", interpret_skipspc); - d.def_ctx_word("include ", interpret_include); - d.def_stack_word("skip-to-eof ", interpret_skip_source); - d.def_ctx_word("abort ", interpret_abort); - d.def_ctx_word("quit ", interpret_quit); - d.def_ctx_word("bye ", interpret_bye); - d.def_stack_word("halt ", interpret_halt); - // cmdline args - d.def_stack_word("$* ", std::bind(interpret_literal, _1, vm::StackEntry{cmdline_args})); - d.def_stack_word("$# ", interpret_get_cmdline_arg_count); - d.def_ctx_word("$() ", interpret_get_cmdline_arg); -} - -void init_words_ton(Dictionary& d) { - using namespace std::placeholders; - d.def_stack_word("smca>$ ", interpret_pack_std_smc_addr); - d.def_stack_word("$>smca ", interpret_unpack_std_smc_addr); - d.def_stack_word("B>base64 ", std::bind(interpret_bytes_to_base64, _1, false)); - d.def_stack_word("B>base64url ", std::bind(interpret_bytes_to_base64, _1, true)); - d.def_stack_word("base64>B ", std::bind(interpret_base64_to_bytes, _1, false, false)); - d.def_stack_word("base64url>B ", std::bind(interpret_base64_to_bytes, _1, true, false)); -} - -void init_words_vm(Dictionary& d, bool enable_debug) { - using namespace std::placeholders; - vm::init_op_cp0(enable_debug); - // vm run - d.def_stack_word("vmlibs ", std::bind(interpret_literal, _1, vm::StackEntry{vm_libraries})); - // d.def_ctx_word("runvmcode ", std::bind(interpret_run_vm, _1, 0x40)); - // d.def_ctx_word("runvm ", std::bind(interpret_run_vm, _1, 0x45)); - d.def_ctx_word("runvmx ", std::bind(interpret_run_vm, _1, -1)); - d.def_ctx_word("dbrunvm ", interpret_db_run_vm); - d.def_ctx_word("dbrunvm-parallel ", interpret_db_run_vm_parallel); - d.def_stack_word("vmcont, ", interpret_store_vm_cont); - d.def_stack_word("vmcont@ ", interpret_fetch_vm_cont); -} - -void import_cmdline_args(Dictionary& d, std::string arg0, int n, const char* const argv[]) { - using namespace std::placeholders; - LOG(DEBUG) << "import_cmdlist_args(" << arg0 << "," << n << ")"; - d.def_stack_word("$0 ", std::bind(interpret_literal, _1, vm::StackEntry{arg0})); - vm::StackEntry list; - for (int i = n - 1; i >= 0; i--) { - list = vm::StackEntry::cons(vm::StackEntry{argv[i]}, list); - } - cmdline_args->set(std::move(list)); - for (int i = 1; i <= n; i++) { - char buffer[14]; - sprintf(buffer, "$%d ", i); - d.def_stack_word(buffer, std::bind(interpret_get_fixed_cmdline_arg, _1, i)); - } -} - -std::pair numeric_value_ext(std::string s, bool allow_frac = true) { - td::RefInt256 num, denom; - int res = parse_number(s, num, denom, allow_frac); - if (res <= 0) { - throw IntError{"-?"}; - } - return std::make_pair(std::move(num), res == 2 ? std::move(denom) : td::RefInt256{}); -} - -td::RefInt256 numeric_value(std::string s) { - td::RefInt256 num, denom; - int res = parse_number(s, num, denom, false); - if (res != 1) { - throw IntError{"-?"}; - } - return num; -} - -int funny_interpret_loop(IntCtx& ctx) { - while (ctx.load_next_line()) { - if (ctx.is_sb()) { - continue; - } - std::ostringstream errs; - bool ok = true; - while (ok) { - ctx.skipspc(); - const char* ptr = ctx.get_input(); - if (!*ptr) { - break; - } - std::string Word; - Word.reserve(128); - auto entry = ctx.dictionary->lookup(""); - std::string entry_word; - const char* ptr_end = ptr; - while (*ptr && *ptr != ' ' && *ptr != '\t') { - Word += *ptr++; - auto cur = ctx.dictionary->lookup(Word); - if (cur) { - entry = cur; - entry_word = Word; - ptr_end = ptr; - } - } - auto cur = ctx.dictionary->lookup(Word + " "); - if (cur || !entry) { - entry = std::move(cur); - ctx.set_input(ptr); - ctx.skipspc(); - } else { - Word = entry_word; - ctx.set_input(ptr_end); - } - try { - if (entry) { - if (entry->is_active()) { - (*entry)(ctx); - } else { - ctx.stack.push_smallint(0); - ctx.stack.push({vm::from_object, entry->get_def()}); - } - } else { - auto res = numeric_value_ext(Word); - ctx.stack.push(std::move(res.first)); - if (res.second.not_null()) { - ctx.stack.push(std::move(res.second)); - push_argcount(ctx, 2); - } else { - push_argcount(ctx, 1); - } - } - if (ctx.state > 0) { - interpret_compile_internal(ctx.stack); - } else { - interpret_execute_internal(ctx); - } - } catch (IntError& ab) { - errs << ctx << Word << ": " << ab.msg; - ok = false; - } catch (vm::VmError& ab) { - errs << ctx << Word << ": " << ab.get_msg(); - ok = false; - } catch (vm::CellBuilder::CellWriteError) { - errs << ctx << Word << ": Cell builder write error"; - ok = false; - } catch (vm::VmFatal) { - errs << ctx << Word << ": fatal vm error"; - ok = false; - } catch (Quit& q) { - if (ctx.include_depth) { - throw; - } - if (!q.res) { - ok = false; - } else { - return q.res; - } - } catch (SkipToEof) { - return 0; - } - }; - if (!ok) { - auto err_msg = errs.str(); - if (!err_msg.empty()) { - LOG(ERROR) << err_msg; - } - ctx.clear(); - if (ctx.include_depth) { - throw IntError{"error interpreting included file `" + ctx.filename + "` : " + err_msg}; - } - } else if (!ctx.state && !ctx.include_depth) { - *ctx.output_stream << " ok" << std::endl; - } - } - return 0; -} - -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/words.h b/submodules/ton/tonlib-src/crypto/fift/words.h deleted file mode 100644 index de5b4389..00000000 --- a/submodules/ton/tonlib-src/crypto/fift/words.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "Dictionary.h" - -namespace fift { - -// thrown by 'quit', 'bye' and 'halt' for exiting to top level -struct Quit { - int res; - Quit() : res(0) { - } - Quit(int _res) : res(_res) { - } -}; - -struct SkipToEof {}; - -void init_words_common(Dictionary& dictionary); -void init_words_vm(Dictionary& dictionary, bool debug_enabled = false); -void init_words_ton(Dictionary& dictionary); - -void import_cmdline_args(Dictionary& d, std::string arg0, int n, const char* const argv[]); - -int funny_interpret_loop(IntCtx& ctx); - -} // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/func/abscode.cpp b/submodules/ton/tonlib-src/crypto/func/abscode.cpp deleted file mode 100644 index 8d73c805..00000000 --- a/submodules/ton/tonlib-src/crypto/func/abscode.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * ABSTRACT CODE - * - */ - -TmpVar::TmpVar(var_idx_t _idx, int _cls, TypeExpr* _type, SymDef* sym, const SrcLocation* loc) - : v_type(_type), idx(_idx), cls(_cls), coord(0) { - if (sym) { - name = sym->sym_idx; - sym->value->idx = _idx; - } - if (loc) { - where = std::make_unique(*loc); - } - if (!_type) { - v_type = TypeExpr::new_hole(); - } -} - -void TmpVar::set_location(const SrcLocation& loc) { - if (where) { - *where = loc; - } else { - where = std::make_unique(loc); - } -} - -void TmpVar::dump(std::ostream& os) const { - show(os); - os << " : " << v_type << " (width "; - v_type->show_width(os); - os << ")"; - if (coord > 0) { - os << " = _" << (coord >> 8) << '.' << (coord & 255); - } else if (coord < 0) { - int n = (~coord >> 8), k = (~coord & 0xff); - if (k) { - os << " = (_" << n << ".._" << (n + k - 1) << ")"; - } else { - os << " = ()"; - } - } - os << std::endl; -} - -void TmpVar::show(std::ostream& os, int omit_idx) const { - if (cls & _Named) { - os << sym::symbols.get_name(name); - if (omit_idx && (omit_idx >= 2 || (cls & _UniqueName))) { - return; - } - } - os << '_' << idx; -} - -std::ostream& operator<<(std::ostream& os, const TmpVar& var) { - var.show(os); - return os; -} - -void VarDescr::show_value(std::ostream& os) const { - if (val & _Int) { - os << 'i'; - } - if (val & _Const) { - os << 'c'; - } - if (val & _Zero) { - os << '0'; - } - if (val & _NonZero) { - os << '!'; - } - if (val & _Pos) { - os << '>'; - } - if (val & _Neg) { - os << '<'; - } - if (val & _Bool) { - os << 'B'; - } - if (val & _Bit) { - os << 'b'; - } - if (val & _Even) { - os << 'E'; - } - if (val & _Odd) { - os << 'O'; - } - if (val & _Finite) { - os << 'f'; - } - if (val & _Nan) { - os << 'N'; - } - if (int_const.not_null()) { - os << '=' << int_const; - } -} - -void VarDescr::show(std::ostream& os, const char* name) const { - if (flags & _Last) { - os << '*'; - } - if (flags & _Unused) { - os << '?'; - } - if (name) { - os << name; - } - os << '_' << idx; - show_value(os); -} - -void VarDescr::set_const(long long value) { - return set_const(td::make_refint(value)); -} - -void VarDescr::set_const(td::RefInt256 value) { - int_const = std::move(value); - if (!int_const->signed_fits_bits(257)) { - int_const.write().invalidate(); - } - val = _Const | _Int; - int s = sgn(int_const); - if (s < -1) { - val |= _Nan | _NonZero; - } else if (s < 0) { - val |= _NonZero | _Neg | _Finite; - if (*int_const == -1) { - val |= _Bool; - } - } else if (s > 0) { - val |= _NonZero | _Pos | _Finite; - } else if (!s) { - if (*int_const == 1) { - val |= _Bit; - } - val |= _Zero | _Neg | _Pos | _Finite | _Bool | _Bit; - } - if (val & _Finite) { - val |= int_const->get_bit(0) ? _Odd : _Even; - } -} - -void VarDescr::set_const_nan() { - set_const(td::make_refint()); -} - -void VarDescr::operator|=(const VarDescr& y) { - val &= y.val; - if (is_int_const() && cmp(int_const, y.int_const) != 0) { - val &= ~_Const; - } - if (!(val & _Const)) { - int_const.clear(); - } -} - -void VarDescr::operator&=(const VarDescr& y) { - val |= y.val; - if (y.int_const.not_null() && int_const.is_null()) { - int_const = y.int_const; - } -} - -void VarDescr::set_value(const VarDescr& y) { - val = y.val; - int_const = y.int_const; -} - -void VarDescr::set_value(VarDescr&& y) { - val = y.val; - int_const = std::move(y.int_const); -} - -void VarDescr::clear_value() { - val = 0; - int_const.clear(); -} - -void VarDescrList::show(std::ostream& os) const { - if (unreachable) { - os << " "; - } - os << "["; - for (const auto& v : list) { - os << ' ' << v; - } - os << " ]\n"; -} - -void Op::flags_set_clear(int set, int clear) { - flags = (flags | set) & ~clear; - for (auto& op : block0) { - op.flags_set_clear(set, clear); - } - for (auto& op : block1) { - op.flags_set_clear(set, clear); - } -} -void Op::split_vars(const std::vector& vars) { - split_var_list(left, vars); - split_var_list(right, vars); - for (auto& op : block0) { - op.split_vars(vars); - } - for (auto& op : block1) { - op.split_vars(vars); - } -} - -void Op::split_var_list(std::vector& var_list, const std::vector& vars) { - int new_size = 0, changes = 0; - for (var_idx_t v : var_list) { - int c = vars.at(v).coord; - if (c < 0) { - ++changes; - new_size += (~c & 0xff); - } else { - ++new_size; - } - } - if (!changes) { - return; - } - std::vector new_var_list; - new_var_list.reserve(new_size); - for (var_idx_t v : var_list) { - int c = vars.at(v).coord; - if (c < 0) { - int n = (~c >> 8), k = (~c & 0xff); - while (k-- > 0) { - new_var_list.push_back(n++); - } - } else { - new_var_list.push_back(v); - } - } - var_list = std::move(new_var_list); -} - -void Op::show(std::ostream& os, const std::vector& vars, std::string pfx, int mode) const { - if (mode & 2) { - os << pfx << " ["; - for (const auto& v : var_info.list) { - os << ' '; - if (v.flags & VarDescr::_Last) { - os << '*'; - } - if (v.flags & VarDescr::_Unused) { - os << '?'; - } - os << vars[v.idx]; - if (mode & 4) { - os << ':'; - v.show_value(os); - } - } - os << " ]\n"; - } - std::string dis = disabled() ? " " : ""; - if (noreturn()) { - dis += " "; - } - if (!is_pure()) { - dis += " "; - } - switch (cl) { - case _Undef: - os << pfx << dis << "???\n"; - break; - case _Nop: - os << pfx << dis << "NOP\n"; - break; - case _Call: - os << pfx << dis << "CALL: "; - show_var_list(os, left, vars); - os << " := " << (fun_ref ? fun_ref->name() : "(null)") << " "; - if ((mode & 4) && args.size() == right.size()) { - show_var_list(os, args, vars); - } else { - show_var_list(os, right, vars); - } - os << std::endl; - break; - case _CallInd: - os << pfx << dis << "CALLIND: "; - show_var_list(os, left, vars); - os << " := EXEC "; - show_var_list(os, right, vars); - os << std::endl; - break; - case _Let: - os << pfx << dis << "LET "; - show_var_list(os, left, vars); - os << " := "; - show_var_list(os, right, vars); - os << std::endl; - break; - case _Tuple: - os << pfx << dis << "MKTUPLE "; - show_var_list(os, left, vars); - os << " := "; - show_var_list(os, right, vars); - os << std::endl; - break; - case _UnTuple: - os << pfx << dis << "UNTUPLE "; - show_var_list(os, left, vars); - os << " := "; - show_var_list(os, right, vars); - os << std::endl; - break; - case _IntConst: - os << pfx << dis << "CONST "; - show_var_list(os, left, vars); - os << " := " << int_const << std::endl; - break; - case _Import: - os << pfx << dis << "IMPORT "; - show_var_list(os, left, vars); - os << std::endl; - break; - case _Return: - os << pfx << dis << "RETURN "; - show_var_list(os, left, vars); - os << std::endl; - break; - case _GlobVar: - os << pfx << dis << "GLOBVAR "; - show_var_list(os, left, vars); - os << " := " << (fun_ref ? fun_ref->name() : "(null)") << std::endl; - break; - case _SetGlob: - os << pfx << dis << "SETGLOB "; - os << (fun_ref ? fun_ref->name() : "(null)") << " := "; - show_var_list(os, right, vars); - os << std::endl; - break; - case _Repeat: - os << pfx << dis << "REPEAT "; - show_var_list(os, left, vars); - os << ' '; - show_block(os, block0.get(), vars, pfx, mode); - os << std::endl; - break; - case _If: - os << pfx << dis << "IF "; - show_var_list(os, left, vars); - os << ' '; - show_block(os, block0.get(), vars, pfx, mode); - os << " ELSE "; - show_block(os, block1.get(), vars, pfx, mode); - os << std::endl; - break; - case _While: - os << pfx << dis << "WHILE "; - show_var_list(os, left, vars); - os << ' '; - show_block(os, block0.get(), vars, pfx, mode); - os << " DO "; - show_block(os, block1.get(), vars, pfx, mode); - os << std::endl; - break; - case _Until: - os << pfx << dis << "UNTIL "; - show_var_list(os, left, vars); - os << ' '; - show_block(os, block0.get(), vars, pfx, mode); - os << std::endl; - break; - case _Again: - os << pfx << dis << "AGAIN "; - show_var_list(os, left, vars); - os << ' '; - show_block(os, block0.get(), vars, pfx, mode); - os << std::endl; - break; - default: - os << pfx << dis << " "; - show_var_list(os, left, vars); - os << " -- "; - show_var_list(os, right, vars); - os << std::endl; - break; - } -} - -void Op::show_var_list(std::ostream& os, const std::vector& idx_list, - const std::vector& vars) const { - if (!idx_list.size()) { - os << "()"; - } else if (idx_list.size() == 1) { - os << vars.at(idx_list[0]); - } else { - os << "(" << vars.at(idx_list[0]); - for (std::size_t i = 1; i < idx_list.size(); i++) { - os << "," << vars.at(idx_list[i]); - } - os << ")"; - } -} - -void Op::show_var_list(std::ostream& os, const std::vector& list, const std::vector& vars) const { - auto n = list.size(); - if (!n) { - os << "()"; - } else { - os << "( "; - for (std::size_t i = 0; i < list.size(); i++) { - if (i) { - os << ", "; - } - if (list[i].is_unused()) { - os << '?'; - } - os << vars.at(list[i].idx) << ':'; - list[i].show_value(os); - } - os << " )"; - } -} - -void Op::show_block(std::ostream& os, const Op* block, const std::vector& vars, std::string pfx, int mode) { - os << "{" << std::endl; - std::string pfx2 = pfx + " "; - for (const Op& op : block) { - op.show(os, vars, pfx2, mode); - } - os << pfx << "}"; -} - -void CodeBlob::flags_set_clear(int set, int clear) { - for (auto& op : ops) { - op.flags_set_clear(set, clear); - } -} - -std::ostream& operator<<(std::ostream& os, const CodeBlob& code) { - code.print(os); - return os; -} - -// flags: +1 = show variable definition locations; +2 = show vars after each op; +4 = show var abstract value info after each op; +8 = show all variables at start -void CodeBlob::print(std::ostream& os, int flags) const { - os << "CODE BLOB: " << var_cnt << " variables, " << in_var_cnt << " input\n"; - if ((flags & 8) != 0) { - for (const auto& var : vars) { - var.dump(os); - if (var.where && (flags & 1) != 0) { - var.where->show(os); - os << " defined here:\n"; - var.where->show_context(os); - } - } - } - os << "------- BEGIN --------\n"; - for (const auto& op : ops) { - op.show(os, vars, "", flags); - } - os << "-------- END ---------\n\n"; -} - -var_idx_t CodeBlob::create_var(int cls, TypeExpr* var_type, SymDef* sym, const SrcLocation* location) { - vars.emplace_back(var_cnt, cls, var_type, sym, location); - if (sym) { - sym->value->idx = var_cnt; - } - return var_cnt++; -} - -bool CodeBlob::import_params(FormalArgList arg_list) { - if (var_cnt || in_var_cnt || op_cnt) { - return false; - } - std::vector list; - for (const auto& par : arg_list) { - TypeExpr* arg_type; - SymDef* arg_sym; - SrcLocation arg_loc; - std::tie(arg_type, arg_sym, arg_loc) = par; - list.push_back(create_var(arg_sym ? (TmpVar::_In | TmpVar::_Named) : TmpVar::_In, arg_type, arg_sym, &arg_loc)); - } - emplace_back(loc, Op::_Import, list); - in_var_cnt = var_cnt; - return true; -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/analyzer.cpp b/submodules/ton/tonlib-src/crypto/func/analyzer.cpp deleted file mode 100644 index 5af435bc..00000000 --- a/submodules/ton/tonlib-src/crypto/func/analyzer.cpp +++ /dev/null @@ -1,884 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * ANALYZE AND PREPROCESS ABSTRACT CODE - * - */ - -void CodeBlob::simplify_var_types() { - for (TmpVar& var : vars) { - TypeExpr::remove_indirect(var.v_type); - var.v_type->recompute_width(); - } -} - -int CodeBlob::split_vars(bool strict) { - int n = var_cnt, changes = 0; - for (int j = 0; j < var_cnt; j++) { - TmpVar& var = vars[j]; - if (strict && var.v_type->minw != var.v_type->maxw) { - throw src::ParseError{var.where.get(), "variable does not have fixed width, cannot manipulate it"}; - } - std::vector comp_types; - int k = var.v_type->extract_components(comp_types); - assert(k <= 254 && n <= 0x7fff00); - assert((unsigned)k == comp_types.size()); - if (k != 1) { - var.coord = ~((n << 8) + k); - for (int i = 0; i < k; i++) { - auto v = create_var(vars[j].cls, comp_types[i], 0, vars[j].where.get()); - assert(v == n + i); - assert(vars[v].idx == v); - vars[v].name = vars[j].name; - vars[v].coord = ((int)j << 8) + i + 1; - } - n += k; - ++changes; - } else if (strict && var.v_type->minw != 1) { - throw src::ParseError{var.where.get(), - "cannot work with variable or variable component of width greater than one"}; - } - } - if (!changes) { - return 0; - } - for (auto& op : ops) { - op.split_vars(vars); - } - return changes; -} - -bool CodeBlob::compute_used_code_vars() { - VarDescrList empty_var_info; - return compute_used_code_vars(ops, empty_var_info, true); -} - -bool CodeBlob::compute_used_code_vars(std::unique_ptr& ops_ptr, const VarDescrList& var_info, bool edit) const { - assert(ops_ptr); - if (!ops_ptr->next) { - assert(ops_ptr->cl == Op::_Nop); - return ops_ptr->set_var_info(var_info); - } - return compute_used_code_vars(ops_ptr->next, var_info, edit) | ops_ptr->compute_used_vars(*this, edit); -} - -bool operator==(const VarDescrList& x, const VarDescrList& y) { - if (x.size() != y.size()) { - return false; - } - for (std::size_t i = 0; i < x.size(); i++) { - if (x.list[i].idx != y.list[i].idx || x.list[i].flags != y.list[i].flags) { - return false; - } - } - return true; -} - -bool same_values(const VarDescr& x, const VarDescr& y) { - if (x.val != y.val || x.int_const.is_null() != y.int_const.is_null()) { - return false; - } - if (x.int_const.not_null() && cmp(x.int_const, y.int_const) != 0) { - return false; - } - return true; -} - -bool same_values(const VarDescrList& x, const VarDescrList& y) { - if (x.size() != y.size()) { - return false; - } - for (std::size_t i = 0; i < x.size(); i++) { - if (x.list[i].idx != y.list[i].idx || !same_values(x.list[i], y.list[i])) { - return false; - } - } - return true; -} - -bool Op::set_var_info(const VarDescrList& new_var_info) { - if (var_info == new_var_info) { - return false; - } - var_info = new_var_info; - return true; -} - -bool Op::set_var_info(VarDescrList&& new_var_info) { - if (var_info == new_var_info) { - return false; - } - var_info = std::move(new_var_info); - return true; -} - -bool Op::set_var_info_except(const VarDescrList& new_var_info, const std::vector& var_list) { - if (!var_list.size()) { - return set_var_info(new_var_info); - } - VarDescrList tmp_info{new_var_info}; - tmp_info -= var_list; - return set_var_info(tmp_info); -} - -bool Op::set_var_info_except(VarDescrList&& new_var_info, const std::vector& var_list) { - if (var_list.size()) { - new_var_info -= var_list; - } - return set_var_info(std::move(new_var_info)); -} -std::vector sort_unique_vars(const std::vector& var_list) { - std::vector vars{var_list}, unique_vars; - std::sort(vars.begin(), vars.end()); - vars.erase(std::unique(vars.begin(), vars.end()), vars.end()); - return vars; -} - -VarDescr* VarDescrList::operator[](var_idx_t idx) { - auto it = std::lower_bound(list.begin(), list.end(), idx); - return it != list.end() && it->idx == idx ? &*it : nullptr; -} - -const VarDescr* VarDescrList::operator[](var_idx_t idx) const { - auto it = std::lower_bound(list.begin(), list.end(), idx); - return it != list.end() && it->idx == idx ? &*it : nullptr; -} - -std::size_t VarDescrList::count(const std::vector idx_list) const { - std::size_t res = 0; - for (var_idx_t idx : idx_list) { - if (operator[](idx)) { - ++res; - } - } - return res; -} - -std::size_t VarDescrList::count_used(const std::vector idx_list) const { - std::size_t res = 0; - for (var_idx_t idx : idx_list) { - auto v = operator[](idx); - if (v && !v->is_unused()) { - ++res; - } - } - return res; -} - -VarDescrList& VarDescrList::operator-=(var_idx_t idx) { - auto it = std::lower_bound(list.begin(), list.end(), idx); - if (it != list.end() && it->idx == idx) { - list.erase(it); - } - return *this; -} - -VarDescrList& VarDescrList::operator-=(const std::vector& idx_list) { - for (var_idx_t idx : idx_list) { - *this -= idx; - } - return *this; -} - -VarDescrList& VarDescrList::add_var(var_idx_t idx, bool unused) { - auto it = std::lower_bound(list.begin(), list.end(), idx); - if (it == list.end() || it->idx != idx) { - list.emplace(it, idx, VarDescr::_Last | (unused ? VarDescr::_Unused : 0)); - } else if (it->is_unused() && !unused) { - it->clear_unused(); - } - return *this; -} - -VarDescrList& VarDescrList::add_vars(const std::vector& idx_list, bool unused) { - for (var_idx_t idx : idx_list) { - add_var(idx, unused); - } - return *this; -} - -VarDescr& VarDescrList::add(var_idx_t idx) { - auto it = std::lower_bound(list.begin(), list.end(), idx); - if (it == list.end() || it->idx != idx) { - it = list.emplace(it, idx); - } - return *it; -} - -VarDescr& VarDescrList::add_newval(var_idx_t idx) { - auto it = std::lower_bound(list.begin(), list.end(), idx); - if (it == list.end() || it->idx != idx) { - return *list.emplace(it, idx); - } else { - it->clear_value(); - return *it; - } -} - -VarDescrList& VarDescrList::clear_last() { - for (auto& var : list) { - if (var.flags & VarDescr::_Last) { - var.flags &= ~VarDescr::_Last; - } - } - return *this; -} - -VarDescrList VarDescrList::operator+(const VarDescrList& y) const { - VarDescrList res; - auto it1 = list.cbegin(); - auto it2 = y.list.cbegin(); - while (it1 != list.cend() && it2 != y.list.cend()) { - if (it1->idx < it2->idx) { - res.list.push_back(*it1++); - } else if (it1->idx > it2->idx) { - res.list.push_back(*it2++); - } else { - res.list.push_back(*it1++); - res.list.back() += *it2++; - } - } - while (it1 != list.cend()) { - res.list.push_back(*it1++); - } - while (it2 != y.list.cend()) { - res.list.push_back(*it2++); - } - return res; -} - -VarDescrList& VarDescrList::operator+=(const VarDescrList& y) { - return *this = *this + y; -} - -VarDescrList VarDescrList::operator|(const VarDescrList& y) const { - if (y.unreachable) { - return *this; - } - if (unreachable) { - return y; - } - VarDescrList res; - auto it1 = list.cbegin(); - auto it2 = y.list.cbegin(); - while (it1 != list.cend() && it2 != y.list.cend()) { - if (it1->idx < it2->idx) { - it1++; - } else if (it1->idx > it2->idx) { - it2++; - } else { - res.list.push_back(*it1++); - res.list.back() |= *it2++; - } - } - return res; -} - -VarDescrList& VarDescrList::operator|=(const VarDescrList& y) { - if (y.unreachable) { - return *this; - } else { - return *this = *this | y; - } -} - -VarDescrList& VarDescrList::operator&=(const VarDescrList& values) { - for (const VarDescr& vd : values.list) { - VarDescr* item = operator[](vd.idx); - if (item) { - *item &= vd; - } - } - unreachable |= values.unreachable; - return *this; -} - -VarDescrList& VarDescrList::import_values(const VarDescrList& values) { - if (values.unreachable) { - set_unreachable(); - } else - for (auto& vd : list) { - auto new_vd = values[vd.idx]; - if (new_vd) { - vd.set_value(*new_vd); - } else { - vd.clear_value(); - } - } - return *this; -} - -bool Op::std_compute_used_vars(bool disabled) { - // left = OP right - // var_info := (var_info - left) + right - VarDescrList new_var_info{next->var_info}; - new_var_info -= left; - new_var_info.clear_last(); - if (args.size() == right.size() && !disabled) { - for (const VarDescr& arg : args) { - new_var_info.add_var(arg.idx, arg.is_unused()); - } - } else { - new_var_info.add_vars(right, disabled); - } - return set_var_info(std::move(new_var_info)); -} - -bool Op::compute_used_vars(const CodeBlob& code, bool edit) { - assert(next); - const VarDescrList& next_var_info = next->var_info; - if (cl == _Nop) { - return set_var_info_except(next_var_info, left); - } - switch (cl) { - case _IntConst: - case _GlobVar: - case _Call: - case _CallInd: - case _Tuple: - case _UnTuple: { - // left = EXEC right; - if (!next_var_info.count_used(left) && is_pure()) { - // all variables in `left` are not needed - if (edit) { - disable(); - } - return std_compute_used_vars(true); - } - return std_compute_used_vars(); - } - case _SetGlob: { - // GLOB = right - if (right.empty() && edit) { - disable(); - } - return std_compute_used_vars(right.empty()); - } - case _Let: { - // left = right - std::size_t cnt = next_var_info.count_used(left); - assert(left.size() == right.size()); - auto l_it = left.cbegin(), r_it = right.cbegin(); - VarDescrList new_var_info{next_var_info}; - new_var_info -= left; - new_var_info.clear_last(); - std::vector new_left, new_right; - for (; l_it < left.cend(); ++l_it, ++r_it) { - if (std::find(l_it + 1, left.cend(), *l_it) == left.cend()) { - auto p = next_var_info[*l_it]; - new_var_info.add_var(*r_it, !p || p->is_unused()); - new_left.push_back(*l_it); - new_right.push_back(*r_it); - } - } - if (new_left.size() < left.size()) { - left = std::move(new_left); - right = std::move(new_right); - } - if (!cnt && edit) { - // all variables in `left` are not needed - disable(); - } - return set_var_info(std::move(new_var_info)); - } - case _Return: { - // return left - if (var_info.count(left) == left.size()) { - return false; - } - std::vector unique_vars = sort_unique_vars(left); - var_info.list.clear(); - for (var_idx_t i : unique_vars) { - var_info.list.emplace_back(i, VarDescr::_Last); - } - return true; - } - case _Import: { - // import left - std::vector unique_vars = sort_unique_vars(left); - var_info.list.clear(); - for (var_idx_t i : unique_vars) { - var_info.list.emplace_back(i, next_var_info[i] ? 0 : VarDescr::_Last); - } - return true; - } - case _If: { - // if (left) then block0 else block1 - // VarDescrList nx_var_info = next_var_info; - // nx_var_info.clear_last(); - code.compute_used_code_vars(block0, next_var_info, edit); - VarDescrList merge_info; - if (block1) { - code.compute_used_code_vars(block1, next_var_info, edit); - merge_info = block0->var_info + block1->var_info; - } else { - merge_info = block0->var_info + next_var_info; - } - merge_info.clear_last(); - merge_info += left; - return set_var_info(std::move(merge_info)); - } - case _While: { - // while (block0 || left) block1; - // ... block0 left { block1 block0 left } next - VarDescrList new_var_info{next_var_info}; - bool changes = false; - do { - VarDescrList after_cond{new_var_info}; - after_cond += left; - code.compute_used_code_vars(block0, after_cond, changes); - code.compute_used_code_vars(block1, block0->var_info, changes); - std::size_t n = new_var_info.size(); - new_var_info += block1->var_info; - new_var_info.clear_last(); - if (changes) { - break; - } - changes = (new_var_info.size() == n); - } while (changes <= edit); - new_var_info += left; - code.compute_used_code_vars(block0, new_var_info, edit); - return set_var_info(block0->var_info); - } - case _Until: { - // until (block0 || left); - // .. { block0 left } block0 left next - VarDescrList after_cond_first{next_var_info}; - after_cond_first += left; - code.compute_used_code_vars(block0, after_cond_first, false); - VarDescrList new_var_info{block0->var_info}; - bool changes = false; - do { - VarDescrList after_cond{new_var_info}; - after_cond += next_var_info; - after_cond += left; - code.compute_used_code_vars(block0, after_cond, changes); - std::size_t n = new_var_info.size(); - new_var_info += block0->var_info; - new_var_info.clear_last(); - if (changes) { - break; - } - changes = (new_var_info.size() == n); - } while (changes <= edit); - return set_var_info(std::move(new_var_info) + next_var_info); - } - case _Repeat: { - // repeat (left) block0 - // left { block0 } next - VarDescrList new_var_info{next_var_info}; - bool changes = false; - do { - code.compute_used_code_vars(block0, new_var_info, changes); - std::size_t n = new_var_info.size(); - new_var_info += block0->var_info; - new_var_info.clear_last(); - if (changes) { - break; - } - changes = (new_var_info.size() == n); - } while (changes <= edit); - new_var_info += left; - return set_var_info(std::move(new_var_info)); - } - case _Again: { - // for(;;) block0 - // { block0 } - VarDescrList new_var_info; - bool changes = false; - do { - code.compute_used_code_vars(block0, new_var_info, changes); - std::size_t n = new_var_info.size(); - new_var_info += block0->var_info; - new_var_info.clear_last(); - if (changes) { - break; - } - changes = (new_var_info.size() == n); - } while (changes <= edit); - return set_var_info(std::move(new_var_info)); - } - default: - std::cerr << "fatal: unknown operation in compute_used_vars()\n"; - throw src::ParseError{where, "unknown operation"}; - } -} - -bool prune_unreachable(std::unique_ptr& ops) { - if (!ops) { - return true; - } - Op& op = *ops; - if (op.cl == Op::_Nop) { - if (op.next) { - ops = std::move(op.next); - return prune_unreachable(ops); - } - return true; - } - bool reach; - switch (op.cl) { - case Op::_IntConst: - case Op::_GlobVar: - case Op::_SetGlob: - case Op::_Call: - case Op::_CallInd: - case Op::_Tuple: - case Op::_UnTuple: - case Op::_Import: - reach = true; - break; - case Op::_Let: { - reach = true; - break; - } - case Op::_Return: - reach = false; - break; - case Op::_If: { - // if left then block0 else block1; ... - VarDescr* c_var = op.var_info[op.left[0]]; - if (c_var && c_var->always_true()) { - op.block0->last().next = std::move(op.next); - ops = std::move(op.block0); - return prune_unreachable(ops); - } else if (c_var && c_var->always_false()) { - op.block1->last().next = std::move(op.next); - ops = std::move(op.block1); - return prune_unreachable(ops); - } else { - reach = prune_unreachable(op.block0) | prune_unreachable(op.block1); - } - break; - } - case Op::_While: { - // while (block0 || left) block1; - if (!prune_unreachable(op.block0)) { - // computation of block0 never returns - ops = std::move(op.block0); - return prune_unreachable(ops); - } - VarDescr* c_var = op.block0->last().var_info[op.left[0]]; - if (c_var && c_var->always_false()) { - // block1 never executed - op.block0->last().next = std::move(op.next); - ops = std::move(op.block0); - return false; - } else if (c_var && c_var->always_true()) { - if (!prune_unreachable(op.block1)) { - // block1 never returns - op.block0->last().next = std::move(op.block1); - ops = std::move(op.block0); - return false; - } - // infinite loop - op.cl = Op::_Again; - op.block0->last().next = std::move(op.block1); - op.left.clear(); - reach = false; - } else { - if (!prune_unreachable(op.block1)) { - // block1 never returns, while equivalent to block0 ; if left then block1 else next - op.cl = Op::_If; - std::unique_ptr new_op = std::move(op.block0); - op.block0 = std::move(op.block1); - op.block1 = std::make_unique(op.next->where, Op::_Nop); - new_op->last().next = std::move(ops); - ops = std::move(new_op); - } - reach = true; // block1 may be never executed - } - break; - } - case Op::_Repeat: { - // repeat (left) block0 - VarDescr* c_var = op.var_info[op.left[0]]; - if (c_var && c_var->always_nonpos()) { - // loop never executed - ops = std::move(op.next); - return prune_unreachable(ops); - } - if (c_var && c_var->always_pos()) { - if (!prune_unreachable(op.block0)) { - // block0 executed at least once, and it never returns - // replace code with block0 - ops = std::move(op.block0); - return false; - } - } else { - prune_unreachable(op.block0); - } - reach = true; - break; - } - case Op::_Until: - case Op::_Again: { - // do block0 until left; ... - if (!prune_unreachable(op.block0)) { - // block0 never returns, replace loop by block0 - ops = std::move(op.block0); - return false; - } - reach = true; - break; - } - default: - std::cerr << "fatal: unknown operation \n"; - throw src::ParseError{op.where, "unknown operation in prune_unreachable()"}; - } - if (reach) { - return prune_unreachable(op.next); - } else { - while (op.next->next) { - op.next = std::move(op.next->next); - } - return false; - } -} - -void CodeBlob::prune_unreachable_code() { - if (prune_unreachable(ops)) { - throw src::ParseError{loc, "control reaches end of function"}; - } -} - -void CodeBlob::fwd_analyze() { - VarDescrList values; - assert(ops && ops->cl == Op::_Import); - for (var_idx_t i : ops->left) { - values += i; - if (vars[i].v_type->is_int()) { - values[i]->val |= VarDescr::_Int; - } - } - ops->fwd_analyze(values); -} - -void Op::prepare_args(VarDescrList values) { - if (args.size() != right.size()) { - args.clear(); - for (var_idx_t i : right) { - args.emplace_back(i); - } - } - for (std::size_t i = 0; i < right.size(); i++) { - const VarDescr* val = values[right[i]]; - if (val) { - args[i].set_value(*val); - // args[i].clear_unused(); - } else { - args[i].clear_value(); - } - args[i].clear_unused(); - } -} - -VarDescrList Op::fwd_analyze(VarDescrList values) { - var_info.import_values(values); - switch (cl) { - case _Nop: - case _Import: - break; - case _Return: - values.set_unreachable(); - break; - case _IntConst: { - values.add_newval(left[0]).set_const(int_const); - break; - } - case _Call: { - prepare_args(values); - auto func = dynamic_cast(fun_ref->value); - if (func) { - std::vector res; - res.reserve(left.size()); - for (var_idx_t i : left) { - res.emplace_back(i); - } - AsmOpList tmp; - func->compile(tmp, res, args); // abstract interpretation of res := f (args) - int j = 0; - for (var_idx_t i : left) { - values.add_newval(i).set_value(res[j++]); - } - } else { - for (var_idx_t i : left) { - values.add_newval(i); - } - } - break; - } - case _Tuple: - case _UnTuple: - case _GlobVar: - case _CallInd: { - for (var_idx_t i : left) { - values.add_newval(i); - } - break; - } - case _SetGlob: - break; - case _Let: { - std::vector old_val; - assert(left.size() == right.size()); - for (std::size_t i = 0; i < right.size(); i++) { - const VarDescr* ov = values[right[i]]; - if (!ov && verbosity >= 5) { - std::cerr << "FATAL: error in assignment at right component #" << i << " (no value for _" << right[i] << ")" - << std::endl; - for (auto x : left) { - std::cerr << '_' << x << " "; - } - std::cerr << "= "; - for (auto x : right) { - std::cerr << '_' << x << " "; - } - std::cerr << std::endl; - } - // assert(ov); - if (ov) { - old_val.push_back(*ov); - } else { - old_val.emplace_back(); - } - } - for (std::size_t i = 0; i < left.size(); i++) { - values.add_newval(left[i]).set_value(std::move(old_val[i])); - } - break; - } - case _If: { - VarDescrList val1 = block0->fwd_analyze(values); - VarDescrList val2 = block1 ? block1->fwd_analyze(std::move(values)) : std::move(values); - values = val1 | val2; - break; - } - case _Repeat: { - bool atl1 = (values[left[0]] && values[left[0]]->always_pos()); - VarDescrList next_values = block0->fwd_analyze(values); - while (true) { - VarDescrList new_values = values | next_values; - if (same_values(new_values, values)) { - break; - } - values = std::move(new_values); - next_values = block0->fwd_analyze(values); - } - if (atl1) { - values = std::move(next_values); - } - break; - } - case _While: { - values = block0->fwd_analyze(values); - if (values[left[0]] && values[left[0]]->always_false()) { - // block1 never executed - block1->fwd_analyze(values); - break; - } - while (true) { - VarDescrList next_values = values | block0->fwd_analyze(block1->fwd_analyze(values)); - if (same_values(next_values, values)) { - break; - } - values = std::move(next_values); - } - break; - } - case _Until: - case _Again: { - while (true) { - VarDescrList next_values = values | block0->fwd_analyze(values); - if (same_values(next_values, values)) { - break; - } - values = std::move(next_values); - } - values = block0->fwd_analyze(values); - break; - } - default: - std::cerr << "fatal: unknown operation \n"; - throw src::ParseError{where, "unknown operation in fwd_analyze()"}; - } - if (next) { - return next->fwd_analyze(std::move(values)); - } else { - return values; - } -} - -bool Op::set_noreturn(bool nr) { - if (nr) { - flags |= _NoReturn; - } else { - flags &= ~_NoReturn; - } - return nr; -} - -bool Op::mark_noreturn() { - switch (cl) { - case _Nop: - if (!next) { - return set_noreturn(false); - } - // fallthrough - case _Import: - case _IntConst: - case _Let: - case _Tuple: - case _UnTuple: - case _SetGlob: - case _GlobVar: - case _CallInd: - case _Call: - return set_noreturn(next->mark_noreturn()); - case _Return: - return set_noreturn(true); - case _If: - return set_noreturn((block0->mark_noreturn() & (block1 && block1->mark_noreturn())) | next->mark_noreturn()); - case _Again: - block0->mark_noreturn(); - return set_noreturn(false); - case _Until: - return set_noreturn(block0->mark_noreturn() | next->mark_noreturn()); - case _While: - block1->mark_noreturn(); - return set_noreturn(block0->mark_noreturn() | next->mark_noreturn()); - case _Repeat: - block0->mark_noreturn(); - return set_noreturn(next->mark_noreturn()); - default: - std::cerr << "fatal: unknown operation \n"; - throw src::ParseError{where, "unknown operation in mark_noreturn()"}; - } -} - -void CodeBlob::mark_noreturn() { - ops->mark_noreturn(); -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/asmops.cpp b/submodules/ton/tonlib-src/crypto/func/asmops.cpp deleted file mode 100644 index cb0fff1b..00000000 --- a/submodules/ton/tonlib-src/crypto/func/asmops.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "parser/srcread.h" -#include "func.h" -#include - -namespace funC { - -/* - * - * ASM-OP LIST FUNCTIONS - * - */ - -int is_pos_pow2(td::RefInt256 x) { - if (sgn(x) > 0 && !sgn(x & (x - 1))) { - return x->bit_size(false) - 1; - } else { - return -1; - } -} - -int is_neg_pow2(td::RefInt256 x) { - return sgn(x) < 0 ? is_pos_pow2(-x) : 0; -} - -std::ostream& operator<<(std::ostream& os, AsmOp::SReg stack_reg) { - int i = stack_reg.idx; - if (i >= 0) { - if (i < 16) { - return os << 's' << i; - } else { - return os << i << " s()"; - } - } else if (i >= -2) { - return os << "s(" << i << ')'; - } else { - return os << i << " s()"; - } -} - -AsmOp AsmOp::Const(int arg, std::string push_op) { - std::ostringstream os; - os << arg << ' ' << push_op; - return AsmOp::Const(os.str()); -} - -AsmOp AsmOp::make_stk2(int a, int b, const char* str, int delta) { - std::ostringstream os; - os << SReg(a) << ' ' << SReg(b) << ' ' << str; - int c = std::max(a, b) + 1; - return AsmOp::Custom(os.str(), c, c + delta); -} - -AsmOp AsmOp::make_stk3(int a, int b, int c, const char* str, int delta) { - std::ostringstream os; - os << SReg(a) << ' ' << SReg(b) << ' ' << SReg(c) << ' ' << str; - int m = std::max(a, std::max(b, c)) + 1; - return AsmOp::Custom(os.str(), m, m + delta); -} - -AsmOp AsmOp::BlkSwap(int a, int b) { - std::ostringstream os; - if (a == 1 && b == 1) { - return AsmOp::Xchg(0, 1); - } else if (a == 1) { - if (b == 2) { - os << "ROT"; - } else { - os << b << " ROLL"; - } - } else if (b == 1) { - if (a == 2) { - os << "-ROT"; - } else { - os << a << " -ROLL"; - } - } else { - os << a << " " << b << " BLKSWAP"; - } - return AsmOp::Custom(os.str(), a + b, a + b); -} - -AsmOp AsmOp::BlkPush(int a, int b) { - std::ostringstream os; - if (a == 1) { - return AsmOp::Push(b); - } else if (a == 2 && b == 1) { - os << "2DUP"; - } else { - os << a << " " << b << " BLKPUSH"; - } - return AsmOp::Custom(os.str(), b + 1, a + b + 1); -} - -AsmOp AsmOp::BlkDrop(int a) { - std::ostringstream os; - if (a == 1) { - return AsmOp::Pop(); - } else if (a == 2) { - os << "2DROP"; - } else { - os << a << " BLKDROP"; - } - return AsmOp::Custom(os.str(), a, 0); -} - -AsmOp AsmOp::BlkDrop2(int a, int b) { - if (!b) { - return BlkDrop(a); - } - std::ostringstream os; - os << a << " " << b << " BLKDROP2"; - return AsmOp::Custom(os.str(), a + b, b); -} - -AsmOp AsmOp::BlkReverse(int a, int b) { - std::ostringstream os; - os << a << " " << b << " REVERSE"; - return AsmOp::Custom(os.str(), a + b, a + b); -} - -AsmOp AsmOp::Tuple(int a) { - switch (a) { - case 1: - return AsmOp::Custom("SINGLE", 1, 1); - case 2: - return AsmOp::Custom("PAIR", 2, 1); - case 3: - return AsmOp::Custom("TRIPLE", 3, 1); - } - std::ostringstream os; - os << a << " TUPLE"; - return AsmOp::Custom(os.str(), a, 1); -} - -AsmOp AsmOp::UnTuple(int a) { - switch (a) { - case 1: - return AsmOp::Custom("UNSINGLE", 1, 1); - case 2: - return AsmOp::Custom("UNPAIR", 1, 2); - case 3: - return AsmOp::Custom("UNTRIPLE", 1, 3); - } - std::ostringstream os; - os << a << " UNTUPLE"; - return AsmOp::Custom(os.str(), 1, a); -} - -AsmOp AsmOp::IntConst(td::RefInt256 x) { - if (x->signed_fits_bits(8)) { - return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT"); - } - if (!x->is_valid()) { - return AsmOp::Const("PUSHNAN"); - } - int k = is_pos_pow2(x); - if (k >= 0) { - return AsmOp::Const(k, "PUSHPOW2"); - } - k = is_pos_pow2(x + 1); - if (k >= 0) { - return AsmOp::Const(k, "PUSHPOW2DEC"); - } - k = is_pos_pow2(-x); - if (k >= 0) { - return AsmOp::Const(k, "PUSHNEGPOW2"); - } - return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT"); -} - -AsmOp AsmOp::BoolConst(bool f) { - return AsmOp::Const(f ? "TRUE" : "FALSE"); -} - -AsmOp AsmOp::Parse(std::string custom_op) { - if (custom_op == "NOP") { - return AsmOp::Nop(); - } else if (custom_op == "SWAP") { - return AsmOp::Xchg(1); - } else if (custom_op == "DROP") { - return AsmOp::Pop(0); - } else if (custom_op == "NIP") { - return AsmOp::Pop(1); - } else if (custom_op == "DUP") { - return AsmOp::Push(0); - } else if (custom_op == "OVER") { - return AsmOp::Push(1); - } else { - return AsmOp::Custom(custom_op); - } -} - -AsmOp AsmOp::Parse(std::string custom_op, int args, int retv) { - auto res = Parse(custom_op); - if (res.is_custom()) { - res.a = args; - res.b = retv; - } - return res; -} - -void AsmOp::out(std::ostream& os) const { - if (!op.empty()) { - os << op; - return; - } - switch (t) { - case a_none: - break; - case a_xchg: - if (!a && !(b & -2)) { - os << (b ? "SWAP" : "NOP"); - break; - } - os << SReg(a) << ' ' << SReg(b) << " XCHG"; - break; - case a_push: - if (!(a & -2)) { - os << (a ? "OVER" : "DUP"); - break; - } - os << SReg(a) << " PUSH"; - break; - case a_pop: - if (!(a & -2)) { - os << (a ? "NIP" : "DROP"); - break; - } - os << SReg(a) << " POP"; - break; - default: - throw src::Fatal{"unknown assembler operation"}; - } -} - -void AsmOp::out_indent_nl(std::ostream& os, bool no_eol) const { - for (int i = 0; i < indent; i++) { - os << " "; - } - out(os); - if (!no_eol) { - os << std::endl; - } -} - -std::string AsmOp::to_string() const { - if (!op.empty()) { - return op; - } else { - std::ostringstream os; - out(os); - return os.str(); - } -} - -bool AsmOpList::append(const std::vector& ops) { - for (const auto& op : ops) { - if (!append(op)) { - return false; - } - } - return true; -} - -const_idx_t AsmOpList::register_const(Const new_const) { - if (new_const.is_null()) { - return not_const; - } - unsigned idx; - for (idx = 0; idx < constants_.size(); idx++) { - if (!td::cmp(new_const, constants_[idx])) { - return idx; - } - } - constants_.push_back(std::move(new_const)); - return (const_idx_t)idx; -} - -Const AsmOpList::get_const(const_idx_t idx) { - if ((unsigned)idx < constants_.size()) { - return constants_[idx]; - } else { - return {}; - } -} - -void AsmOpList::show_var(std::ostream& os, var_idx_t idx) const { - if (!var_names_ || (unsigned)idx >= var_names_->size()) { - os << '_' << idx; - } else { - var_names_->at(idx).show(os, 2); - } -} - -void AsmOpList::show_var_ext(std::ostream& os, std::pair idx_pair) const { - auto i = idx_pair.first; - auto j = idx_pair.second; - if (!var_names_ || (unsigned)i >= var_names_->size()) { - os << '_' << i; - } else { - var_names_->at(i).show(os, 2); - } - if ((unsigned)j < constants_.size() && constants_[j].not_null()) { - os << '=' << constants_[j]; - } -} - -void AsmOpList::out(std::ostream& os, int mode) const { - if (!(mode & 2)) { - for (const auto& op : list_) { - op.out_indent_nl(os); - } - } else { - std::size_t n = list_.size(); - for (std::size_t i = 0; i < n; i++) { - const auto& op = list_[i]; - if (!op.is_comment() && i + 1 < n && list_[i + 1].is_comment()) { - op.out_indent_nl(os, true); - os << '\t'; - do { - i++; - } while (i + 1 < n && list_[i + 1].is_comment()); - list_[i].out(os); - os << std::endl; - } else { - op.out_indent_nl(os, false); - } - } - } -} - -bool apply_op(StackTransform& trans, const AsmOp& op) { - if (!trans.is_valid()) { - return false; - } - switch (op.t) { - case AsmOp::a_none: - return true; - case AsmOp::a_xchg: - return trans.apply_xchg(op.a, op.b, true); - case AsmOp::a_push: - return trans.apply_push(op.a); - case AsmOp::a_pop: - return trans.apply_pop(op.a); - case AsmOp::a_const: - return !op.a && op.b == 1 && trans.apply_push_newconst(); - case AsmOp::a_custom: - return op.is_gconst() && trans.apply_push_newconst(); - default: - return false; - } -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/builtins.cpp b/submodules/ton/tonlib-src/crypto/func/builtins.cpp deleted file mode 100644 index 91020be0..00000000 --- a/submodules/ton/tonlib-src/crypto/func/builtins.cpp +++ /dev/null @@ -1,1078 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { -using namespace std::literals::string_literals; - -/* - * - * SYMBOL VALUES - * - */ - -int glob_func_cnt, undef_func_cnt, glob_var_cnt; -std::vector glob_func, glob_vars; - -SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) { - sym_idx_t name_idx = sym::symbols.lookup(name, 1); - if (sym::symbols.is_keyword(name_idx)) { - std::cerr << "fatal: global function `" << name << "` already defined as a keyword" << std::endl; - } - SymDef* def = sym::define_global_symbol(name_idx, true); - if (!def) { - std::cerr << "fatal: global function `" << name << "` already defined" << std::endl; - std::exit(1); - } - return def; -} - -template -SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const T& func, bool impure = false) { - SymDef* def = predefine_builtin_func(name, func_type); - def->value = new SymValAsmFunc{func_type, func, impure}; - return def; -} - -template -SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const T& func, std::initializer_list arg_order, - std::initializer_list ret_order = {}, bool impure = false) { - SymDef* def = predefine_builtin_func(name, func_type); - def->value = new SymValAsmFunc{func_type, func, arg_order, ret_order, impure}; - return def; -} - -SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const AsmOp& macro, - std::initializer_list arg_order, std::initializer_list ret_order = {}, - bool impure = false) { - SymDef* def = predefine_builtin_func(name, func_type); - def->value = new SymValAsmFunc{func_type, make_simple_compile(macro), arg_order, ret_order, impure}; - return def; -} - -SymDef* force_autoapply(SymDef* def) { - if (def) { - auto val = dynamic_cast(def->value); - if (val) { - val->auto_apply = true; - } - } - return def; -} - -template -SymDef* define_builtin_const(std::string name, TypeExpr* const_type, Args&&... args) { - return force_autoapply( - define_builtin_func(name, TypeExpr::new_map(TypeExpr::new_unit(), const_type), std::forward(args)...)); -} - -bool SymValAsmFunc::compile(AsmOpList& dest, std::vector& out, std::vector& in) const { - if (simple_compile) { - return dest.append(simple_compile(out, in)); - } else if (ext_compile) { - return ext_compile(dest, out, in); - } else { - return false; - } -} - -/* - * - * DEFINE BUILT-IN FUNCTIONS - * - */ - -int emulate_negate(int a) { - int f = VarDescr::_Pos | VarDescr::_Neg; - if ((a & f) && (~a & f)) { - a ^= f; - } - f = VarDescr::_Bit | VarDescr::_Bool; - if ((a & f) && (~a & f)) { - a ^= f; - } - return a; -} - -int emulate_add(int a, int b) { - if (b & VarDescr::_Zero) { - return a; - } else if (a & VarDescr::_Zero) { - return b; - } - int u = a & b, v = a | b; - int r = VarDescr::_Int; - int t = u & (VarDescr::_Pos | VarDescr::_Neg); - if (v & VarDescr::_Nan) { - return r | VarDescr::_Nan; - } - // non-quiet addition always returns finite results! - r |= t | VarDescr::_Finite; - if (t) { - r |= v & VarDescr::_NonZero; - } - r |= v & VarDescr::_Nan; - if (u & (VarDescr::_Odd | VarDescr::_Even)) { - r |= VarDescr::_Even; - } else if (!(~v & (VarDescr::_Odd | VarDescr::_Even))) { - r |= VarDescr::_Odd | VarDescr::_NonZero; - } - return r; -} - -int emulate_sub(int a, int b) { - return emulate_add(a, emulate_negate(b)); -} - -int emulate_mul(int a, int b) { - if ((b & (VarDescr::_NonZero | VarDescr::_Bit)) == (VarDescr::_NonZero | VarDescr::_Bit)) { - return a; - } else if ((a & (VarDescr::_NonZero | VarDescr::_Bit)) == (VarDescr::_NonZero | VarDescr::_Bit)) { - return b; - } - int u = a & b, v = a | b; - int r = VarDescr::_Int; - if (v & VarDescr::_Nan) { - return r | VarDescr::_Nan; - } - // non-quiet multiplication always yields finite results, if any - r |= VarDescr::_Finite; - if (v & VarDescr::_Zero) { - // non-quiet multiplication - // the result is zero, if any result at all - return VarDescr::ConstZero; - } - if (u & (VarDescr::_Pos | VarDescr::_Neg)) { - r |= VarDescr::_Pos; - } else if (!(~v & (VarDescr::_Pos | VarDescr::_Neg))) { - r |= VarDescr::_Neg; - } - if (u & (VarDescr::_Bit | VarDescr::_Bool)) { - r |= VarDescr::_Bit; - } else if (!(~v & (VarDescr::_Bit | VarDescr::_Bool))) { - r |= VarDescr::_Bool; - } - r |= v & VarDescr::_Even; - r |= u & (VarDescr::_Odd | VarDescr::_NonZero); - return r; -} - -int emulate_lshift(int a, int b) { - if (((a | b) & VarDescr::_Nan) || !(~b & (VarDescr::_Neg | VarDescr::_NonZero))) { - return VarDescr::_Int | VarDescr::_Nan; - } - if (b & VarDescr::_Zero) { - return a; - } - int t = ((b & VarDescr::_NonZero) ? VarDescr::_Even : 0); - t |= b & VarDescr::_Finite; - return emulate_mul(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | VarDescr::_Even | t); -} - -int emulate_div(int a, int b) { - if ((b & (VarDescr::_NonZero | VarDescr::_Bit)) == (VarDescr::_NonZero | VarDescr::_Bit)) { - return a; - } else if ((b & (VarDescr::_NonZero | VarDescr::_Bool)) == (VarDescr::_NonZero | VarDescr::_Bool)) { - return emulate_negate(b); - } - if (b & VarDescr::_Zero) { - return VarDescr::_Int | VarDescr::_Nan; - } - int u = a & b, v = a | b; - int r = VarDescr::_Int; - if (v & VarDescr::_Nan) { - return r | VarDescr::_Nan; - } - // non-quiet division always yields finite results, if any - r |= VarDescr::_Finite; - if (a & VarDescr::_Zero) { - // non-quiet division - // the result is zero, if any result at all - return VarDescr::ConstZero; - } - if (u & (VarDescr::_Pos | VarDescr::_Neg)) { - r |= VarDescr::_Pos; - } else if (!(~v & (VarDescr::_Pos | VarDescr::_Neg))) { - r |= VarDescr::_Neg; - } - if (u & (VarDescr::_Bit | VarDescr::_Bool)) { - r |= VarDescr::_Bit; - } else if (!(~v & (VarDescr::_Bit | VarDescr::_Bool))) { - r |= VarDescr::_Bool; - } - return r; -} - -int emulate_rshift(int a, int b) { - if (((a | b) & VarDescr::_Nan) || !(~b & (VarDescr::_Neg | VarDescr::_NonZero))) { - return VarDescr::_Int | VarDescr::_Nan; - } - if (b & VarDescr::_Zero) { - return a; - } - int t = ((b & VarDescr::_NonZero) ? VarDescr::_Even : 0); - t |= b & VarDescr::_Finite; - return emulate_div(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | VarDescr::_Even | t); -} - -int emulate_mod(int a, int b, int round_mode = -1) { - if ((b & (VarDescr::_NonZero | VarDescr::_Bit)) == (VarDescr::_NonZero | VarDescr::_Bit)) { - return VarDescr::ConstZero; - } else if ((b & (VarDescr::_NonZero | VarDescr::_Bool)) == (VarDescr::_NonZero | VarDescr::_Bool)) { - return VarDescr::ConstZero; - } - if (b & VarDescr::_Zero) { - return VarDescr::_Int | VarDescr::_Nan; - } - int r = VarDescr::_Int; - if ((a | b) & VarDescr::_Nan) { - return r | VarDescr::_Nan; - } - // non-quiet division always yields finite results, if any - r |= VarDescr::_Finite; - if (a & VarDescr::_Zero) { - // non-quiet division - // the result is zero, if any result at all - return VarDescr::ConstZero; - } - if (round_mode < 0) { - r |= b & (VarDescr::_Pos | VarDescr::_Neg); - } else if (round_mode > 0) { - r |= emulate_negate(b) & (VarDescr::_Pos | VarDescr::_Neg); - } - if (a & (VarDescr::_Bit | VarDescr::_Bool)) { - if (r & VarDescr::_Pos) { - r |= VarDescr::_Bit; - } - if (r & VarDescr::_Neg) { - r |= VarDescr::_Bool; - } - } - if (b & VarDescr::_Even) { - r |= a & (VarDescr::_Even | VarDescr::_Odd); - } - return r; -} - -bool VarDescr::always_less(const VarDescr& other) const { - if (is_int_const() && other.is_int_const()) { - return int_const < other.int_const; - } - return (always_nonpos() && other.always_pos()) || (always_neg() && other.always_nonneg()); -} - -bool VarDescr::always_leq(const VarDescr& other) const { - if (is_int_const() && other.is_int_const()) { - return int_const <= other.int_const; - } - return always_nonpos() && other.always_nonneg(); -} - -bool VarDescr::always_greater(const VarDescr& other) const { - return other.always_less(*this); -} - -bool VarDescr::always_geq(const VarDescr& other) const { - return other.always_leq(*this); -} - -bool VarDescr::always_equal(const VarDescr& other) const { - return is_int_const() && other.is_int_const() && *int_const == *other.int_const; -} - -bool VarDescr::always_neq(const VarDescr& other) const { - if (is_int_const() && other.is_int_const()) { - return *int_const != *other.int_const; - } - return always_greater(other) || always_less(other) || (always_even() && other.always_odd()) || - (always_odd() && other.always_even()); -} - -AsmOp exec_op(std::string op) { - return AsmOp::Custom(op); -} - -AsmOp exec_op(std::string op, int args, int retv = 1) { - return AsmOp::Custom(op, args, retv); -} - -AsmOp exec_arg_op(std::string op, long long arg) { - std::ostringstream os; - os << arg << ' ' << op; - return AsmOp::Custom(os.str()); -} - -AsmOp exec_arg_op(std::string op, long long arg, int args, int retv) { - std::ostringstream os; - os << arg << ' ' << op; - return AsmOp::Custom(os.str(), args, retv); -} - -AsmOp exec_arg_op(std::string op, td::RefInt256 arg) { - std::ostringstream os; - os << arg << ' ' << op; - return AsmOp::Custom(os.str()); -} - -AsmOp exec_arg_op(std::string op, td::RefInt256 arg, int args, int retv) { - std::ostringstream os; - os << arg << ' ' << op; - return AsmOp::Custom(os.str(), args, retv); -} - -AsmOp exec_arg2_op(std::string op, long long imm1, long long imm2, int args, int retv) { - std::ostringstream os; - os << imm1 << ' ' << imm2 << ' ' << op; - return AsmOp::Custom(os.str(), args, retv); -} - -AsmOp push_const(td::RefInt256 x) { - return AsmOp::IntConst(std::move(x)); -} - -AsmOp compile_add(std::vector& res, std::vector& args) { - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (x.is_int_const() && y.is_int_const()) { - r.set_const(x.int_const + y.int_const); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - r.val = emulate_add(x.val, y.val); - if (y.is_int_const() && y.int_const->signed_fits_bits(8)) { - y.unused(); - if (y.always_zero()) { - return AsmOp::Nop(); - } - if (*y.int_const == 1) { - return exec_op("INC", 1); - } - if (*y.int_const == -1) { - return exec_op("DEC", 1); - } - return exec_arg_op("ADDCONST", y.int_const, 1); - } - if (x.is_int_const() && x.int_const->signed_fits_bits(8)) { - x.unused(); - if (x.always_zero()) { - return AsmOp::Nop(); - } - if (*x.int_const == 1) { - return exec_op("INC", 1); - } - if (*x.int_const == -1) { - return exec_op("DEC", 1); - } - return exec_arg_op("ADDCONST", x.int_const, 1); - } - return exec_op("ADD", 2); -} - -AsmOp compile_sub(std::vector& res, std::vector& args) { - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (x.is_int_const() && y.is_int_const()) { - r.set_const(x.int_const - y.int_const); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - r.val = emulate_sub(x.val, y.val); - if (y.is_int_const() && (-y.int_const)->signed_fits_bits(8)) { - y.unused(); - if (y.always_zero()) { - return {}; - } - if (*y.int_const == 1) { - return exec_op("DEC", 1); - } - if (*y.int_const == -1) { - return exec_op("INC", 1); - } - return exec_arg_op("ADDCONST", -y.int_const, 1); - } - if (x.always_zero()) { - x.unused(); - return exec_op("NEGATE", 1); - } - return exec_op("SUB", 2); -} - -AsmOp compile_negate(std::vector& res, std::vector& args) { - assert(res.size() == 1 && args.size() == 1); - VarDescr &r = res[0], &x = args[0]; - if (x.is_int_const()) { - r.set_const(-x.int_const); - x.unused(); - return push_const(r.int_const); - } - r.val = emulate_negate(x.val); - return exec_op("NEGATE", 1); -} - -AsmOp compile_mul_internal(VarDescr& r, VarDescr& x, VarDescr& y) { - if (x.is_int_const() && y.is_int_const()) { - r.set_const(x.int_const * y.int_const); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - r.val = emulate_mul(x.val, y.val); - if (y.is_int_const()) { - int k = is_pos_pow2(y.int_const); - if (y.int_const->signed_fits_bits(8) && k < 0) { - y.unused(); - if (y.always_zero() && x.always_finite()) { - // dubious optimization: NaN * 0 = ? - r.set_const(y.int_const); - return push_const(r.int_const); - } - if (*y.int_const == 1 && x.always_finite()) { - return AsmOp::Nop(); - } - if (*y.int_const == -1) { - return exec_op("NEGATE", 1); - } - return exec_arg_op("MULCONST", y.int_const, 1); - } - if (k > 0) { - y.unused(); - return exec_arg_op("LSHIFT#", k, 1); - } - if (k == 0) { - y.unused(); - return AsmOp::Nop(); - } - } - if (x.is_int_const()) { - int k = is_pos_pow2(x.int_const); - if (x.int_const->signed_fits_bits(8) && k < 0) { - x.unused(); - if (x.always_zero() && y.always_finite()) { - // dubious optimization: NaN * 0 = ? - r.set_const(x.int_const); - return push_const(r.int_const); - } - if (*x.int_const == 1 && y.always_finite()) { - return AsmOp::Nop(); - } - if (*x.int_const == -1) { - return exec_op("NEGATE", 1); - } - return exec_arg_op("MULCONST", x.int_const, 1); - } - if (k > 0) { - x.unused(); - return exec_arg_op("LSHIFT#", k, 1); - } - if (k == 0) { - x.unused(); - return AsmOp::Nop(); - } - } - return exec_op("MUL", 2); -} - -AsmOp compile_mul(std::vector& res, std::vector& args) { - assert(res.size() == 1 && args.size() == 2); - return compile_mul_internal(res[0], args[0], args[1]); -} - -AsmOp compile_lshift(std::vector& res, std::vector& args) { - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (y.is_int_const()) { - auto yv = y.int_const->to_long(); - if (yv < 0 || yv > 256) { - r.set_const_nan(); - x.unused(); - y.unused(); - return push_const(r.int_const); - } else if (x.is_int_const()) { - r.set_const(x.int_const << (int)yv); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - } - r.val = emulate_lshift(x.val, y.val); - if (y.is_int_const()) { - int k = (int)(y.int_const->to_long()); - if (!k /* && x.always_finite() */) { - // dubious optimization: what if x=NaN ? - y.unused(); - return AsmOp::Nop(); - } - y.unused(); - return exec_arg_op("LSHIFT#", k, 1); - } - if (x.is_int_const()) { - auto xv = x.int_const->to_long(); - if (xv == 1) { - x.unused(); - return exec_op("POW2", 1); - } - if (xv == -1) { - x.unused(); - return exec_op("NEGPOW2", 1); - } - } - return exec_op("LSHIFT", 2); -} - -AsmOp compile_rshift(std::vector& res, std::vector& args, int round_mode) { - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (y.is_int_const()) { - auto yv = y.int_const->to_long(); - if (yv < 0 || yv > 256) { - r.set_const_nan(); - x.unused(); - y.unused(); - return push_const(r.int_const); - } else if (x.is_int_const()) { - r.set_const(td::rshift(x.int_const, (int)yv, round_mode)); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - } - r.val = emulate_rshift(x.val, y.val); - std::string rshift = (round_mode < 0 ? "RSHIFT" : (round_mode ? "RSHIFTC" : "RSHIFTR")); - if (y.is_int_const()) { - int k = (int)(y.int_const->to_long()); - if (!k /* && x.always_finite() */) { - // dubious optimization: what if x=NaN ? - y.unused(); - return AsmOp::Nop(); - } - y.unused(); - return exec_arg_op(rshift + "#", k, 1); - } - return exec_op(rshift, 2); -} - -AsmOp compile_div_internal(VarDescr& r, VarDescr& x, VarDescr& y, int round_mode) { - if (x.is_int_const() && y.is_int_const()) { - r.set_const(div(x.int_const, y.int_const, round_mode)); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - r.val = emulate_div(x.val, y.val); - if (y.is_int_const()) { - if (*y.int_const == 0) { - x.unused(); - y.unused(); - r.set_const(div(y.int_const, y.int_const)); - return push_const(r.int_const); - } - if (*y.int_const == 1 && x.always_finite()) { - y.unused(); - return AsmOp::Nop(); - } - if (*y.int_const == -1) { - y.unused(); - return exec_op("NEGATE", 1); - } - int k = is_pos_pow2(y.int_const); - if (k > 0) { - y.unused(); - std::string op = "RSHIFT"; - if (round_mode >= 0) { - op += (round_mode > 0 ? 'C' : 'R'); - } - return exec_arg_op(op + '#', k, 1); - } - } - std::string op = "DIV"; - if (round_mode >= 0) { - op += (round_mode > 0 ? 'C' : 'R'); - } - return exec_op(op, 2); -} - -AsmOp compile_div(std::vector& res, std::vector& args, int round_mode) { - assert(res.size() == 1 && args.size() == 2); - return compile_div_internal(res[0], args[0], args[1], round_mode); -} - -AsmOp compile_mod(std::vector& res, std::vector& args, int round_mode) { - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (x.is_int_const() && y.is_int_const()) { - r.set_const(mod(x.int_const, y.int_const, round_mode)); - x.unused(); - y.unused(); - return push_const(r.int_const); - } - r.val = emulate_mod(x.val, y.val); - if (y.is_int_const()) { - if (*y.int_const == 0) { - x.unused(); - y.unused(); - r.set_const(mod(y.int_const, y.int_const)); - return push_const(r.int_const); - } - if ((*y.int_const == 1 || *y.int_const == -1) && x.always_finite()) { - x.unused(); - y.unused(); - r.set_const(td::zero_refint()); - return push_const(r.int_const); - } - int k = is_pos_pow2(y.int_const); - if (k > 0) { - y.unused(); - std::string op = "MODPOW2"; - if (round_mode >= 0) { - op += (round_mode > 0 ? 'C' : 'R'); - } - return exec_arg_op(op + '#', k, 1); - } - } - std::string op = "MOD"; - if (round_mode >= 0) { - op += (round_mode > 0 ? 'C' : 'R'); - } - return exec_op(op, 2); -} - -AsmOp compile_muldiv(std::vector& res, std::vector& args, int round_mode) { - assert(res.size() == 1 && args.size() == 3); - VarDescr &r = res[0], &x = args[0], &y = args[1], &z = args[2]; - if (x.is_int_const() && y.is_int_const() && z.is_int_const()) { - r.set_const(muldiv(x.int_const, y.int_const, z.int_const, round_mode)); - x.unused(); - y.unused(); - z.unused(); - return push_const(r.int_const); - } - if (x.always_zero() || y.always_zero()) { - // dubious optimization for z=0... - x.unused(); - y.unused(); - z.unused(); - r.set_const(td::make_refint(0)); - return push_const(r.int_const); - } - char c = (round_mode < 0) ? 0 : (round_mode > 0 ? 'C' : 'R'); - r.val = emulate_div(emulate_mul(x.val, y.val), z.val); - if (z.is_int_const()) { - if (*z.int_const == 0) { - x.unused(); - y.unused(); - z.unused(); - r.set_const(div(z.int_const, z.int_const)); - return push_const(r.int_const); - } - if (*z.int_const == 1) { - z.unused(); - return compile_mul_internal(r, x, y); - } - } - if (y.is_int_const() && *y.int_const == 1) { - y.unused(); - return compile_div_internal(r, x, z, round_mode); - } - if (x.is_int_const() && *x.int_const == 1) { - x.unused(); - return compile_div_internal(r, y, z, round_mode); - } - if (z.is_int_const()) { - int k = is_pos_pow2(z.int_const); - if (k > 0) { - z.unused(); - std::string op = "MULRSHIFT"; - if (c) { - op += c; - } - return exec_arg_op(op + '#', k, 2); - } - } - if (y.is_int_const()) { - int k = is_pos_pow2(y.int_const); - if (k > 0) { - y.unused(); - std::string op = "LSHIFT#DIV"; - if (c) { - op += c; - } - return exec_arg_op(op, k, 2); - } - } - if (x.is_int_const()) { - int k = is_pos_pow2(x.int_const); - if (k > 0) { - x.unused(); - std::string op = "LSHIFT#DIV"; - if (c) { - op += c; - } - return exec_arg_op(op, k, 2); - } - } - std::string op = "MULDIV"; - if (c) { - op += c; - } - return exec_op(op, 3); -} - -int compute_compare(td::RefInt256 x, td::RefInt256 y, int mode) { - int s = td::cmp(x, y); - if (mode == 7) { - return s; - } else { - return -((mode >> (1 - s)) & 1); - } -} - -// return value: -// 4 -> constant 1 -// 2 -> constant 0 -// 1 -> constant -1 -// 3 -> 0 or -1 -int compute_compare(const VarDescr& x, const VarDescr& y, int mode) { - switch (mode) { - case 1: // > - return x.always_greater(y) ? 1 : (x.always_leq(y) ? 2 : 3); - case 2: // = - return x.always_equal(y) ? 1 : (x.always_neq(y) ? 2 : 3); - case 3: // >= - return x.always_geq(y) ? 1 : (x.always_less(y) ? 2 : 3); - case 4: // < - return x.always_less(y) ? 1 : (x.always_geq(y) ? 2 : 3); - case 5: // <> - return x.always_neq(y) ? 1 : (x.always_equal(y) ? 2 : 3); - case 6: // <= - return x.always_leq(y) ? 1 : (x.always_greater(y) ? 2 : 3); - case 7: // <=> - return x.always_less(y) - ? 1 - : (x.always_equal(y) - ? 2 - : (x.always_greater(y) - ? 4 - : (x.always_leq(y) ? 3 : (x.always_geq(y) ? 6 : (x.always_neq(y) ? 5 : 7))))); - default: - return 7; - } -} - -AsmOp compile_cmp_int(std::vector& res, std::vector& args, int mode) { - assert(mode >= 1 && mode <= 7); - assert(res.size() == 1 && args.size() == 2); - VarDescr &r = res[0], &x = args[0], &y = args[1]; - if (x.is_int_const() && y.is_int_const()) { - int v = compute_compare(x.int_const, y.int_const, mode); - r.set_const(v); - x.unused(); - y.unused(); - return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0); - } - int v = compute_compare(x, y, mode); - // std::cerr << "compute_compare(" << x << ", " << y << ", " << mode << ") = " << v << std::endl; - assert(v); - if (!(v & (v - 1))) { - r.set_const(v - (v >> 2) - 2); - x.unused(); - y.unused(); - return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v & 1); - } - r.val = ~0; - if (v & 1) { - r.val &= VarDescr::ConstTrue; - } - if (v & 2) { - r.val &= VarDescr::ConstZero; - } - if (v & 4) { - r.val &= VarDescr::ConstOne; - } - // std::cerr << "result: " << r << std::endl; - static const char* cmp_int_names[] = {"", "GTINT", "EQINT", "GTINT", "LESSINT", "NEQINT", "LESSINT"}; - static const char* cmp_names[] = {"", "GREATER", "EQUAL", "GEQ", "LESS", "NEQ", "LEQ", "CMP"}; - static int cmp_int_delta[] = {0, 0, 0, -1, 0, 0, 1}; - if (mode != 7) { - if (y.is_int_const() && y.int_const >= -128 && y.int_const <= 127) { - y.unused(); - return exec_arg_op(cmp_int_names[mode], y.int_const + cmp_int_delta[mode], 1); - } - if (x.is_int_const() && x.int_const >= -128 && x.int_const <= 127) { - x.unused(); - mode = ((mode & 4) >> 2) | (mode & 2) | ((mode & 1) << 2); - return exec_arg_op(cmp_int_names[mode], x.int_const + cmp_int_delta[mode], 1); - } - } - return exec_op(cmp_names[mode], 2); -} - -AsmOp compile_throw(std::vector& res, std::vector& args) { - assert(res.empty() && args.size() == 1); - VarDescr& x = args[0]; - if (x.is_int_const() && x.int_const->unsigned_fits_bits(11)) { - x.unused(); - return exec_arg_op("THROW", x.int_const, 0, 0); - } else { - return exec_op("THROWANY", 1, 0); - } -} - -AsmOp compile_cond_throw(std::vector& res, std::vector& args, bool mode) { - assert(res.empty() && args.size() == 2); - VarDescr &x = args[0], &y = args[1]; - std::string suff = (mode ? "IF" : "IFNOT"); - bool skip_cond = false; - if (y.always_true() || y.always_false()) { - y.unused(); - skip_cond = true; - if (y.always_true() != mode) { - x.unused(); - return AsmOp::Nop(); - } - } - if (x.is_int_const() && x.int_const->unsigned_fits_bits(11)) { - x.unused(); - return skip_cond ? exec_arg_op("THROW", x.int_const, 0, 0) : exec_arg_op("THROW"s + suff, x.int_const, 1, 0); - } else { - return skip_cond ? exec_op("THROWANY", 1, 0) : exec_op("THROWANY"s + suff, 2, 0); - } -} - -AsmOp compile_bool_const(std::vector& res, std::vector& args, bool val) { - assert(res.size() == 1 && args.empty()); - VarDescr& r = res[0]; - r.set_const(val ? -1 : 0); - return AsmOp::Const(val ? "TRUE" : "FALSE"); -} - -// (slice, int) load_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -// (slice, int) load_uint(slice s, int len) asm( -> 1 0) "LDUX"; -// int preload_int(slice s, int len) asm "PLDIX"; -// int preload_uint(slice s, int len) asm "PLDUX"; -AsmOp compile_fetch_int(std::vector& res, std::vector& args, bool fetch, bool sgnd) { - assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch); - auto &y = args[1], &r = res.back(); - r.val = (sgnd ? VarDescr::FiniteInt : VarDescr::FiniteUInt); - int v = -1; - if (y.is_int_const() && y.int_const >= 0 && y.int_const <= 256) { - v = (int)y.int_const->to_long(); - if (!v) { - r.val = VarDescr::ConstZero; - } - if (v == 1) { - r.val = (sgnd ? VarDescr::ValBool : VarDescr::ValBit); - } - if (v > 0) { - y.unused(); - return exec_arg_op((fetch ? "LD"s : "PLD"s) + (sgnd ? 'I' : 'U'), v, 1, 1 + (unsigned)fetch); - } - } - return exec_op((fetch ? "LD"s : "PLD"s) + (sgnd ? "IX" : "UX"), 2, 1 + (unsigned)fetch); -} - -// builder store_uint(builder b, int x, int len) asm(x b len) "STUX"; -// builder store_int(builder b, int x, int len) asm(x b len) "STIX"; -AsmOp compile_store_int(std::vector& res, std::vector& args, bool sgnd) { - assert(args.size() == 3 && res.size() == 1); - auto& z = args[2]; - if (z.is_int_const() && z.int_const > 0 && z.int_const <= 256) { - z.unused(); - return exec_arg_op("ST"s + (sgnd ? 'I' : 'U'), z.int_const, 2, 1); - } - return exec_op("ST"s + (sgnd ? "IX" : "UX"), 3, 1); -} - -AsmOp compile_fetch_slice(std::vector& res, std::vector& args, bool fetch) { - assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch); - auto& y = args[1]; - int v = -1; - if (y.is_int_const() && y.int_const > 0 && y.int_const <= 256) { - v = (int)y.int_const->to_long(); - if (v > 0) { - y.unused(); - return exec_arg_op(fetch ? "LDSLICE" : "PLDSLICE", v, 1, 1 + (unsigned)fetch); - } - } - return exec_op(fetch ? "LDSLICEX" : "PLDSLICEX", 2, 1 + (unsigned)fetch); -} - -// _at(tuple t, int index) asm "INDEXVAR"; -AsmOp compile_tuple_at(std::vector& res, std::vector& args) { - assert(args.size() == 2 && res.size() == 1); - auto& y = args[1]; - if (y.is_int_const() && y.int_const >= 0 && y.int_const < 16) { - y.unused(); - return exec_arg_op("INDEX", y.int_const, 1, 1); - } - return exec_op("INDEXVAR", 2, 1); -} - -// int null?(X arg) -AsmOp compile_is_null(std::vector& res, std::vector& args) { - assert(args.size() == 1 && res.size() == 1); - auto &x = args[0], &r = res[0]; - if (x.always_null() || x.always_not_null()) { - x.unused(); - r.set_const(x.always_null() ? -1 : 0); - return push_const(r.int_const); - } - res[0].val = VarDescr::ValBool; - return exec_op("ISNULL", 1, 1); -} - -bool compile_run_method(AsmOpList& code, std::vector& res, std::vector& args, int n, - bool has_value) { - assert(args.size() == (unsigned)n + 1 && res.size() == (unsigned)has_value); - auto& x = args[0]; - if (x.is_int_const() && x.int_const->unsigned_fits_bits(14)) { - x.unused(); - code << exec_arg_op("PREPAREDICT", x.int_const, 0, 2); - } else { - code << exec_op("c3 PUSH", 0, 1); - } - code << exec_arg_op(has_value ? "1 CALLXARGS" : "0 CALLXARGS", n, n + 2, (unsigned)has_value); - return true; -} - -void define_builtins() { - using namespace std::placeholders; - auto Unit = TypeExpr::new_unit(); - auto Int = TypeExpr::new_atomic(_Int); - auto Cell = TypeExpr::new_atomic(_Cell); - auto Slice = TypeExpr::new_atomic(_Slice); - auto Builder = TypeExpr::new_atomic(_Builder); - // auto Null = TypeExpr::new_atomic(_Null); - auto Tuple = TypeExpr::new_atomic(_Tuple); - auto Int2 = TypeExpr::new_tensor({Int, Int}); - auto Int3 = TypeExpr::new_tensor({Int, Int, Int}); - auto TupleInt = TypeExpr::new_tensor({Tuple, Int}); - auto SliceInt = TypeExpr::new_tensor({Slice, Int}); - auto X = TypeExpr::new_var(); - auto Y = TypeExpr::new_var(); - auto Z = TypeExpr::new_var(); - auto XY = TypeExpr::new_tensor({X, Y}); - auto arith_bin_op = TypeExpr::new_map(Int2, Int); - auto arith_un_op = TypeExpr::new_map(Int, Int); - auto impure_bin_op = TypeExpr::new_map(Int2, Unit); - auto impure_un_op = TypeExpr::new_map(Int, Unit); - auto fetch_int_op = TypeExpr::new_map(SliceInt, SliceInt); - auto prefetch_int_op = TypeExpr::new_map(SliceInt, Int); - auto store_int_op = TypeExpr::new_map(TypeExpr::new_tensor({Builder, Int, Int}), Builder); - auto store_int_method = - TypeExpr::new_map(TypeExpr::new_tensor({Builder, Int, Int}), TypeExpr::new_tensor({Builder, Unit})); - auto fetch_slice_op = TypeExpr::new_map(SliceInt, TypeExpr::new_tensor({Slice, Slice})); - auto prefetch_slice_op = TypeExpr::new_map(SliceInt, Slice); - //auto arith_null_op = TypeExpr::new_map(TypeExpr::new_unit(), Int); - define_builtin_func("_+_", arith_bin_op, compile_add); - define_builtin_func("_-_", arith_bin_op, compile_sub); - define_builtin_func("-_", arith_un_op, compile_negate); - define_builtin_func("_*_", arith_bin_op, compile_mul); - define_builtin_func("_/_", arith_bin_op, std::bind(compile_div, _1, _2, -1)); - define_builtin_func("_~/_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); - define_builtin_func("_^/_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); - define_builtin_func("_%_", arith_bin_op, std::bind(compile_mod, _1, _2, -1)); - define_builtin_func("_~%_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); - define_builtin_func("_^%_", arith_bin_op, std::bind(compile_mod, _1, _2, 1)); - define_builtin_func("_/%_", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); - define_builtin_func("divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); - define_builtin_func("~divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); - define_builtin_func("moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0}); - define_builtin_func("~moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0}); - define_builtin_func("_<<_", arith_bin_op, compile_lshift); - define_builtin_func("_>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1)); - define_builtin_func("_~>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); - define_builtin_func("_^>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); - define_builtin_func("_&_", arith_bin_op, AsmOp::Custom("AND", 2)); - define_builtin_func("_|_", arith_bin_op, AsmOp::Custom("OR", 2)); - define_builtin_func("_^_", arith_bin_op, AsmOp::Custom("XOR", 2)); - define_builtin_func("~_", arith_un_op, AsmOp::Custom("NOT", 1)); - define_builtin_func("^_+=_", arith_bin_op, compile_add); - define_builtin_func("^_-=_", arith_bin_op, compile_sub); - define_builtin_func("^_*=_", arith_bin_op, compile_mul); - define_builtin_func("^_/=_", arith_bin_op, std::bind(compile_div, _1, _2, -1)); - define_builtin_func("^_~/=_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); - define_builtin_func("^_^/=_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); - define_builtin_func("^_%=_", arith_bin_op, std::bind(compile_mod, _1, _2, -1)); - define_builtin_func("^_~%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); - define_builtin_func("^_^%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 1)); - define_builtin_func("^_<<=_", arith_bin_op, compile_lshift); - define_builtin_func("^_>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1)); - define_builtin_func("^_~>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); - define_builtin_func("^_^>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); - define_builtin_func("^_&=_", arith_bin_op, AsmOp::Custom("AND", 2)); - define_builtin_func("^_|=_", arith_bin_op, AsmOp::Custom("OR", 2)); - define_builtin_func("^_^=_", arith_bin_op, AsmOp::Custom("XOR", 2)); - define_builtin_func("muldiv", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, -1)); - define_builtin_func("muldivr", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, 0)); - define_builtin_func("muldivc", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, 1)); - define_builtin_func("muldivmod", TypeExpr::new_map(Int3, Int2), AsmOp::Custom("MULDIVMOD", 3, 2)); - define_builtin_func("_==_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 2)); - define_builtin_func("_!=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 5)); - define_builtin_func("_<_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 4)); - define_builtin_func("_>_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 1)); - define_builtin_func("_<=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 6)); - define_builtin_func("_>=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 3)); - define_builtin_func("_<=>_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 7)); - define_builtin_const("true", Int, /* AsmOp::Const("TRUE") */ std::bind(compile_bool_const, _1, _2, true)); - define_builtin_const("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false)); - // define_builtin_func("null", Null, AsmOp::Const("PUSHNULL")); - define_builtin_const("nil", Tuple, AsmOp::Const("PUSHNULL")); - define_builtin_const("Nil", Tuple, AsmOp::Const("NIL")); - define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null); - define_builtin_func("throw", impure_un_op, compile_throw, true); - define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true); - define_builtin_func("throw_unless", impure_bin_op, std::bind(compile_cond_throw, _1, _2, false), true); - define_builtin_func("load_int", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, true), {}, {1, 0}); - define_builtin_func("load_uint", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, false), {}, {1, 0}); - define_builtin_func("preload_int", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, true)); - define_builtin_func("preload_uint", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, false)); - define_builtin_func("store_int", store_int_op, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); - define_builtin_func("store_uint", store_int_op, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); - define_builtin_func("~store_int", store_int_method, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); - define_builtin_func("~store_uint", store_int_method, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); - define_builtin_func("load_bits", fetch_slice_op, std::bind(compile_fetch_slice, _1, _2, true), {}, {1, 0}); - define_builtin_func("preload_bits", prefetch_slice_op, std::bind(compile_fetch_slice, _1, _2, false)); - define_builtin_func("int_at", TypeExpr::new_map(TupleInt, Int), compile_tuple_at); - define_builtin_func("cell_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at); - define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Slice), compile_tuple_at); - define_builtin_func("tuple_at", TypeExpr::new_map(TupleInt, Tuple), compile_tuple_at); - define_builtin_func("at", TypeExpr::new_forall({X}, TypeExpr::new_map(TupleInt, X)), compile_tuple_at); - define_builtin_func("touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, X)), AsmOp::Nop()); - define_builtin_func("~touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, TypeExpr::new_tensor({X, Unit}))), - AsmOp::Nop()); - define_builtin_func("touch2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(XY, XY)), AsmOp::Nop()); - define_builtin_func("~touch2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(XY, TypeExpr::new_tensor({XY, Unit}))), - AsmOp::Nop()); - define_builtin_func("~dump", TypeExpr::new_forall({X}, TypeExpr::new_map(X, TypeExpr::new_tensor({X, Unit}))), - AsmOp::Custom("s0 DUMP", 1, 1), true); - define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit), - [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true); - define_builtin_func("run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)), - [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true); - define_builtin_func( - "run_method2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y}), Unit)), - [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 2, false); }, {1, 2, 0}, {}, true); - define_builtin_func( - "run_method3", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y, Z}), Unit)), - [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 3, false); }, {1, 2, 3, 0}, {}, true); -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/codegen.cpp b/submodules/ton/tonlib-src/crypto/func/codegen.cpp deleted file mode 100644 index 26d8215e..00000000 --- a/submodules/ton/tonlib-src/crypto/func/codegen.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * GENERATE TVM STACK CODE - * - */ - -StackLayout Stack::vars() const { - StackLayout res; - res.reserve(s.size()); - for (auto x : s) { - res.push_back(x.first); - } - return res; -} - -int Stack::find(var_idx_t var, int from) const { - for (int i = from; i < depth(); i++) { - if (at(i).first == var) { - return i; - } - } - return -1; -} - -// finds var in [from .. to) -int Stack::find(var_idx_t var, int from, int to) const { - for (int i = from; i < depth() && i < to; i++) { - if (at(i).first == var) { - return i; - } - } - return -1; -} - -// finds var outside [from .. to) -int Stack::find_outside(var_idx_t var, int from, int to) const { - from = std::max(from, 0); - if (from >= to) { - return find(var); - } else { - int t = find(var, 0, from); - return t >= 0 ? t : find(var, to); - } -} - -int Stack::find_const(const_idx_t cst, int from) const { - for (int i = from; i < depth(); i++) { - if (at(i).second == cst) { - return i; - } - } - return -1; -} - -void Stack::forget_const() { - for (auto& vc : s) { - if (vc.second != not_const) { - vc.second = not_const; - } - } -} - -void Stack::issue_pop(int i) { - validate(i); - if (output_enabled()) { - o << AsmOp::Pop(i); - } - at(i) = get(0); - s.pop_back(); - modified(); -} - -void Stack::issue_push(int i) { - validate(i); - if (output_enabled()) { - o << AsmOp::Push(i); - } - s.push_back(get(i)); - modified(); -} - -void Stack::issue_xchg(int i, int j) { - validate(i); - validate(j); - if (i != j && get(i) != get(j)) { - if (output_enabled()) { - o << AsmOp::Xchg(i, j); - } - std::swap(at(i), at(j)); - modified(); - } -} - -int Stack::drop_vars_except(const VarDescrList& var_info, int excl_var) { - int dropped = 0, changes; - do { - changes = 0; - int n = depth(); - for (int i = 0; i < n; i++) { - var_idx_t idx = at(i).first; - if (((!var_info[idx] || var_info[idx]->is_unused()) && idx != excl_var) || find(idx, 0, i - 1) >= 0) { - // unneeded - issue_pop(i); - changes = 1; - break; - } - } - dropped += changes; - } while (changes); - return dropped; -} - -void Stack::show(int flags) { - std::ostringstream os; - for (auto i : s) { - os << ' '; - o.show_var_ext(os, i); - } - o << AsmOp::Comment(os.str()); - mode |= _Shown; -} - -void Stack::forget_var(var_idx_t idx) { - for (auto& x : s) { - if (x.first == idx) { - x = std::make_pair(_Garbage, not_const); - modified(); - } - } -} - -void Stack::push_new_var(var_idx_t idx) { - forget_var(idx); - s.emplace_back(idx, not_const); - modified(); -} - -void Stack::push_new_const(var_idx_t idx, const_idx_t cidx) { - forget_var(idx); - s.emplace_back(idx, cidx); - modified(); -} - -void Stack::assign_var(var_idx_t new_idx, var_idx_t old_idx) { - int i = find(old_idx); - assert(i >= 0 && "variable not found in stack"); - if (new_idx != old_idx) { - at(i).first = new_idx; - modified(); - } -} - -void Stack::do_copy_var(var_idx_t new_idx, var_idx_t old_idx) { - int i = find(old_idx); - assert(i >= 0 && "variable not found in stack"); - if (find(old_idx, i + 1) < 0) { - issue_push(i); - assert(at(0).first == old_idx); - } - assign_var(new_idx, old_idx); -} - -void Stack::enforce_state(const StackLayout& req_stack) { - int k = (int)req_stack.size(); - for (int i = 0; i < k; i++) { - var_idx_t x = req_stack[i]; - if (i < depth() && s[i].first == x) { - continue; - } - while (depth() > 0 && std::find(req_stack.cbegin(), req_stack.cend(), get(0).first) == req_stack.cend()) { - // current TOS entry is unused in req_stack, drop it - issue_pop(0); - } - int j = find(x); - if (j >= depth() - i) { - issue_push(j); - j = 0; - } - issue_xchg(j, depth() - i - 1); - assert(s[i].first == x); - } - while (depth() > k) { - issue_pop(0); - } - assert(depth() == k); - for (int i = 0; i < k; i++) { - assert(s[i].first == req_stack[i]); - } -} - -void Stack::merge_const(const Stack& req_stack) { - assert(s.size() == req_stack.s.size()); - for (std::size_t i = 0; i < s.size(); i++) { - assert(s[i].first == req_stack.s[i].first); - if (s[i].second != req_stack.s[i].second) { - s[i].second = not_const; - } - } -} - -void Stack::merge_state(const Stack& req_stack) { - enforce_state(req_stack.vars()); - merge_const(req_stack); -} - -void Stack::rearrange_top(const StackLayout& top, std::vector last) { - while (last.size() < top.size()) { - last.push_back(false); - } - int k = (int)top.size(); - for (int i = 0; i < k; i++) { - for (int j = i + 1; j < k; j++) { - if (top[i] == top[j]) { - last[i] = false; - break; - } - } - } - int ss = 0; - for (int i = 0; i < k; i++) { - if (last[i]) { - ++ss; - } - } - for (int i = 0; i < k; i++) { - var_idx_t x = top[i]; - // find s(j) containing x with j not in [ss, ss+i) - int j = find_outside(x, ss, ss + i); - if (last[i]) { - // rearrange x to be at s(ss-1) - issue_xchg(--ss, j); - assert(get(ss).first == x); - } else { - // create a new copy of x - issue_push(j); - issue_xchg(0, ss); - assert(get(ss).first == x); - } - } - assert(!ss); -} - -void Stack::rearrange_top(var_idx_t top, bool last) { - int i = find(top); - if (last) { - issue_xchg(0, i); - } else { - issue_push(i); - } - assert(get(0).first == top); -} - -bool Op::generate_code_step(Stack& stack) { - stack.opt_show(); - stack.drop_vars_except(var_info); - stack.opt_show(); - const auto& next_var_info = next->var_info; - switch (cl) { - case _Nop: - case _Import: - return true; - case _Return: { - stack.enforce_state(left); - stack.opt_show(); - return false; - } - case _IntConst: { - auto p = next_var_info[left[0]]; - if (!p || p->is_unused()) { - return true; - } - auto cidx = stack.o.register_const(int_const); - int i = stack.find_const(cidx); - if (i < 0) { - stack.o << push_const(int_const); - stack.push_new_const(left[0], cidx); - } else { - assert(stack.at(i).second == cidx); - stack.do_copy_var(left[0], stack[i]); - } - return true; - } - case _GlobVar: - if (dynamic_cast(fun_ref->value)) { - bool used = false; - for (auto i : left) { - auto p = next_var_info[i]; - if (p && !p->is_unused()) { - used = true; - } - } - if (!used || disabled()) { - return true; - } - std::string name = sym::symbols.get_name(fun_ref->sym_idx); - stack.o << AsmOp::Custom(name + " GETGLOB", 0, 1); - if (left.size() != 1) { - assert(left.size() <= 15); - stack.o << AsmOp::UnTuple((int)left.size()); - } - for (auto i : left) { - stack.push_new_var(i); - } - return true; - } else { - assert(left.size() == 1); - auto p = next_var_info[left[0]]; - if (!p || p->is_unused() || disabled()) { - return true; - } - stack.o << "CONT:<{"; - stack.o.indent(); - auto func = dynamic_cast(fun_ref->value); - if (func) { - // TODO: create and compile a true lambda instead of this (so that arg_order and ret_order would work correctly) - std::vector args0, res; - TypeExpr::remove_indirect(func->sym_type); - assert(func->get_type()->is_map()); - auto wr = func->get_type()->args.at(0)->get_width(); - auto wl = func->get_type()->args.at(1)->get_width(); - assert(wl >= 0 && wr >= 0); - for (int i = 0; i < wl; i++) { - res.emplace_back(0); - } - for (int i = 0; i < wr; i++) { - args0.emplace_back(0); - } - func->compile(stack.o, res, args0); // compile res := f (args0) - } else { - std::string name = sym::symbols.get_name(fun_ref->sym_idx); - stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size()); - } - stack.o.undent(); - stack.o << "}>"; - stack.push_new_var(left.at(0)); - return true; - } - case _Let: { - assert(left.size() == right.size()); - int i = 0; - std::vector active; - active.reserve(left.size()); - for (std::size_t k = 0; k < left.size(); k++) { - var_idx_t y = left[k]; // "y" = "x" - auto p = next_var_info[y]; - active.push_back(p && !p->is_unused()); - } - for (std::size_t k = 0; k < left.size(); k++) { - if (!active[k]) { - continue; - } - var_idx_t x = right[k]; // "y" = "x" - bool is_last = true; - for (std::size_t l = k + 1; l < right.size(); l++) { - if (right[l] == x && active[l]) { - is_last = false; - } - } - if (is_last) { - auto info = var_info[x]; - is_last = (info && info->is_last()); - } - if (is_last) { - stack.assign_var(--i, x); - } else { - stack.do_copy_var(--i, x); - } - } - i = 0; - for (std::size_t k = 0; k < left.size(); k++) { - if (active[k]) { - stack.assign_var(left[k], --i); - } - } - return true; - } - case _Tuple: - case _UnTuple: { - if (disabled()) { - return true; - } - std::vector last; - for (var_idx_t x : right) { - last.push_back(var_info[x] && var_info[x]->is_last()); - } - stack.rearrange_top(right, std::move(last)); - stack.opt_show(); - int k = (int)stack.depth() - (int)right.size(); - assert(k >= 0); - if (cl == _Tuple) { - stack.o << AsmOp::Tuple((int)right.size()); - assert(left.size() == 1); - } else { - stack.o << AsmOp::UnTuple((int)left.size()); - assert(right.size() == 1); - } - stack.s.resize(k); - for (int i = 0; i < (int)left.size(); i++) { - stack.push_new_var(left.at(i)); - } - return true; - } - case _Call: - case _CallInd: { - if (disabled()) { - return true; - } - SymValFunc* func = (fun_ref ? dynamic_cast(fun_ref->value) : nullptr); - auto arg_order = (func ? func->get_arg_order() : nullptr); - auto ret_order = (func ? func->get_ret_order() : nullptr); - assert(!arg_order || arg_order->size() == right.size()); - assert(!ret_order || ret_order->size() == left.size()); - std::vector right1; - if (args.size()) { - assert(args.size() == right.size()); - for (int i = 0; i < (int)right.size(); i++) { - int j = arg_order ? arg_order->at(i) : i; - const VarDescr& arg = args.at(j); - if (!arg.is_unused()) { - assert(var_info[arg.idx] && !var_info[arg.idx]->is_unused()); - right1.push_back(arg.idx); - } - } - } else if (arg_order) { - for (int i = 0; i < (int)right.size(); i++) { - right1.push_back(right.at(arg_order->at(i))); - } - } else { - right1 = right; - } - std::vector last; - for (var_idx_t x : right1) { - last.push_back(var_info[x] && var_info[x]->is_last()); - } - stack.rearrange_top(right1, std::move(last)); - stack.opt_show(); - int k = (int)stack.depth() - (int)right1.size(); - assert(k >= 0); - for (int i = 0; i < (int)right1.size(); i++) { - if (stack.s[k + i].first != right1[i]) { - std::cerr << stack.o; - } - assert(stack.s[k + i].first == right1[i]); - } - if (cl == _CallInd) { - // TODO: replace with exec_arg2_op() - stack.o << exec_arg2_op("CALLXARGS", (int)right.size() - 1, (int)left.size(), (int)right.size(), - (int)left.size()); - } else { - auto func = dynamic_cast(fun_ref->value); - if (func) { - std::vector res; - res.reserve(left.size()); - for (var_idx_t i : left) { - res.emplace_back(i); - } - func->compile(stack.o, res, args); // compile res := f (args) - } else { - auto fv = dynamic_cast(fun_ref->value); - std::string name = sym::symbols.get_name(fun_ref->sym_idx); - bool is_inline = (fv && (fv->flags & 3)); - stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(), - (int)left.size()); - } - } - stack.s.resize(k); - for (int i = 0; i < (int)left.size(); i++) { - int j = ret_order ? ret_order->at(i) : i; - stack.push_new_var(left.at(j)); - } - return true; - } - case _SetGlob: { - assert(fun_ref && dynamic_cast(fun_ref->value)); - std::vector last; - for (var_idx_t x : right) { - last.push_back(var_info[x] && var_info[x]->is_last()); - } - stack.rearrange_top(right, std::move(last)); - stack.opt_show(); - int k = (int)stack.depth() - (int)right.size(); - assert(k >= 0); - for (int i = 0; i < (int)right.size(); i++) { - if (stack.s[k + i].first != right[i]) { - std::cerr << stack.o; - } - assert(stack.s[k + i].first == right[i]); - } - if (right.size() > 1) { - stack.o << AsmOp::Tuple((int)right.size()); - } - if (!right.empty()) { - std::string name = sym::symbols.get_name(fun_ref->sym_idx); - stack.o << AsmOp::Custom(name + " SETGLOB", 1, 0); - } - stack.s.resize(k); - return true; - } - case _If: { - if (block0->is_empty() && block1->is_empty()) { - return true; - } - if (!next->noreturn() && (block0->noreturn() != block1->noreturn())) { - // simple fix of unbalanced returns in if/else branches - // (to be replaced with a finer condition working in loop bodies) - throw src::ParseError{where, "`if` and `else` branches should both return or both not return"}; - } - var_idx_t x = left[0]; - stack.rearrange_top(x, var_info[x] && var_info[x]->is_last()); - assert(stack[0] == x); - stack.opt_show(); - stack.s.pop_back(); - stack.modified(); - if (block1->is_empty()) { - // if (left) block0; ... - if (block0->noreturn()) { - stack.o << "IFJMP:<{"; - stack.o.indent(); - Stack stack_copy{stack}; - block0->generate_code_all(stack_copy); - stack.o.undent(); - stack.o << "}>"; - return true; - } - stack.o << "IF:<{"; - stack.o.indent(); - Stack stack_copy{stack}, stack_target{stack}; - stack_target.disable_output(); - stack_target.drop_vars_except(next->var_info); - block0->generate_code_all(stack_copy); - stack_copy.drop_vars_except(var_info); - stack_copy.opt_show(); - if (stack_copy == stack) { - stack.o.undent(); - stack.o << "}>"; - return true; - } - // stack_copy.drop_vars_except(next->var_info); - stack_copy.enforce_state(stack_target.vars()); - stack_copy.opt_show(); - if (stack_copy.vars() == stack.vars()) { - stack.o.undent(); - stack.o << "}>"; - stack.merge_const(stack_copy); - return true; - } - stack.o.undent(); - stack.o << "}>ELSE<{"; - stack.o.indent(); - stack.merge_state(stack_copy); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - return true; - } - if (block0->is_empty()) { - // if (!left) block1; ... - if (block1->noreturn()) { - stack.o << "IFNOTJMP:<{"; - stack.o.indent(); - Stack stack_copy{stack}; - block1->generate_code_all(stack_copy); - stack.o.undent(); - stack.o << "}>"; - return true; - } - stack.o << "IFNOT:<{"; - stack.o.indent(); - Stack stack_copy{stack}, stack_target{stack}; - stack_target.disable_output(); - stack_target.drop_vars_except(next->var_info); - block1->generate_code_all(stack_copy); - stack_copy.drop_vars_except(var_info); - stack_copy.opt_show(); - if (stack_copy.vars() == stack.vars()) { - stack.o.undent(); - stack.o << "}>"; - stack.merge_const(stack_copy); - return true; - } - // stack_copy.drop_vars_except(next->var_info); - stack_copy.enforce_state(stack_target.vars()); - stack_copy.opt_show(); - if (stack_copy.vars() == stack.vars()) { - stack.o.undent(); - stack.o << "}>"; - stack.merge_const(stack_copy); - return true; - } - stack.o.undent(); - stack.o << "}>ELSE<{"; - stack.o.indent(); - stack.merge_state(stack_copy); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - return true; - } - if (block0->noreturn()) { - stack.o << "IFJMP:<{"; - stack.o.indent(); - Stack stack_copy{stack}; - block0->generate_code_all(stack_copy); - stack.o.undent(); - stack.o << "}>"; - return block1->generate_code_all(stack); - } - if (block1->noreturn()) { - stack.o << "IFNOTJMP:<{"; - stack.o.indent(); - Stack stack_copy{stack}; - block1->generate_code_all(stack_copy); - stack.o.undent(); - stack.o << "}>"; - return block0->generate_code_all(stack); - } - stack.o << "IF:<{"; - stack.o.indent(); - Stack stack_copy{stack}; - block0->generate_code_all(stack_copy); - stack_copy.drop_vars_except(next->var_info); - stack_copy.opt_show(); - stack.o.undent(); - stack.o << "}>ELSE<{"; - stack.o.indent(); - block1->generate_code_all(stack); - stack.merge_state(stack_copy); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - return true; - } - case _Repeat: { - var_idx_t x = left[0]; - //stack.drop_vars_except(block0->var_info, x); - stack.rearrange_top(x, var_info[x] && var_info[x]->is_last()); - assert(stack[0] == x); - stack.opt_show(); - stack.s.pop_back(); - stack.modified(); - if (true || !next->is_empty()) { - stack.o << "REPEAT:<{"; - stack.o.indent(); - stack.forget_const(); - StackLayout layout1 = stack.vars(); - block0->generate_code_all(stack); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - return true; - } else { - stack.o << "REPEATEND"; - stack.forget_const(); - StackLayout layout1 = stack.vars(); - block0->generate_code_all(stack); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - return false; - } - } - case _Again: { - stack.drop_vars_except(block0->var_info); - stack.opt_show(); - if (!next->is_empty()) { - stack.o << "AGAIN:<{"; - stack.o.indent(); - stack.forget_const(); - StackLayout layout1 = stack.vars(); - block0->generate_code_all(stack); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - return true; - } else { - stack.o << "AGAINEND"; - stack.forget_const(); - StackLayout layout1 = stack.vars(); - block0->generate_code_all(stack); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - return false; - } - } - case _Until: { - // stack.drop_vars_except(block0->var_info); - // stack.opt_show(); - if (true || !next->is_empty()) { - stack.o << "UNTIL:<{"; - stack.o.indent(); - stack.forget_const(); - auto layout1 = stack.vars(); - block0->generate_code_all(stack); - layout1.push_back(left[0]); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - stack.o.undent(); - stack.o << "}>"; - stack.s.pop_back(); - stack.modified(); - return true; - } else { - stack.o << "UNTILEND"; - stack.forget_const(); - StackLayout layout1 = stack.vars(); - block0->generate_code_all(stack); - layout1.push_back(left[0]); - stack.enforce_state(std::move(layout1)); - stack.opt_show(); - return false; - } - } - case _While: { - // while (block0 | left) block1; ...next - var_idx_t x = left[0]; - stack.drop_vars_except(block0->var_info); - stack.opt_show(); - StackLayout layout1 = stack.vars(); - bool next_empty = false && next->is_empty(); - stack.o << "WHILE:<{"; - stack.o.indent(); - stack.forget_const(); - block0->generate_code_all(stack); - stack.rearrange_top(x, !next->var_info[x] && !block1->var_info[x]); - stack.opt_show(); - stack.s.pop_back(); - stack.modified(); - stack.o.undent(); - Stack stack_copy{stack}; - stack.o << (next_empty ? "}>DO:" : "}>DO<{"); - if (!next_empty) { - stack.o.indent(); - } - stack_copy.opt_show(); - block1->generate_code_all(stack_copy); - stack_copy.enforce_state(std::move(layout1)); - stack_copy.opt_show(); - if (!next_empty) { - stack.o.undent(); - stack.o << "}>"; - return true; - } else { - return false; - } - } - default: - std::cerr << "fatal: unknown operation \n"; - throw src::ParseError{where, "unknown operation in generate_code()"}; - } -} - -bool Op::generate_code_all(Stack& stack) { - if (generate_code_step(stack) && next) { - return next->generate_code_all(stack); - } else { - return false; - } -} - -void CodeBlob::generate_code(AsmOpList& out, int mode) { - Stack stack{out, mode}; - assert(ops && ops->cl == Op::_Import); - for (var_idx_t x : ops->left) { - stack.push_new_var(x); - } - ops->generate_code_all(stack); - if (!(mode & Stack::_DisableOpt)) { - optimize_code(out); - } -} - -void CodeBlob::generate_code(std::ostream& os, int mode, int indent) { - AsmOpList out_list(indent, &vars); - generate_code(out_list, mode); - out_list.out(os, mode); -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/func.cpp b/submodules/ton/tonlib-src/crypto/func/func.cpp deleted file mode 100644 index d3eaf160..00000000 --- a/submodules/ton/tonlib-src/crypto/func/func.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" -#include "parser/srcread.h" -#include "parser/lexer.h" -#include "parser/symtable.h" -#include -#include - -namespace funC { - -int verbosity, indent, opt_level = 2; -bool stack_layout_comments, op_rewrite_comments, program_envelope, asm_preamble; -std::ostream* outs = &std::cout; -std::string generated_from, boc_output_filename; - -/* - * - * OUTPUT CODE GENERATOR - * - */ - -void generate_output_func(SymDef* func_sym) { - SymValCodeFunc* func_val = dynamic_cast(func_sym->value); - assert(func_val); - std::string name = sym::symbols.get_name(func_sym->sym_idx); - if (verbosity >= 2) { - std::cerr << "\n\n=========================\nfunction " << name << " : " << func_val->get_type() << std::endl; - } - if (!func_val->code) { - std::cerr << "( function `" << name << "` undefined )\n"; - } else { - CodeBlob& code = *(func_val->code); - if (verbosity >= 3) { - code.print(std::cerr, 9); - } - code.simplify_var_types(); - if (verbosity >= 5) { - std::cerr << "after simplify_var_types: \n"; - code.print(std::cerr, 0); - } - code.prune_unreachable_code(); - if (verbosity >= 5) { - std::cerr << "after prune_unreachable: \n"; - code.print(std::cerr, 0); - } - code.split_vars(true); - if (verbosity >= 5) { - std::cerr << "after split_vars: \n"; - code.print(std::cerr, 0); - } - for (int i = 0; i < 8; i++) { - code.compute_used_code_vars(); - if (verbosity >= 4) { - std::cerr << "after compute_used_vars: \n"; - code.print(std::cerr, 6); - } - code.fwd_analyze(); - if (verbosity >= 5) { - std::cerr << "after fwd_analyze: \n"; - code.print(std::cerr, 6); - } - code.prune_unreachable_code(); - if (verbosity >= 5) { - std::cerr << "after prune_unreachable: \n"; - code.print(std::cerr, 6); - } - } - code.mark_noreturn(); - if (verbosity >= 3) { - code.print(std::cerr, 15); - } - if (verbosity >= 2) { - std::cerr << "\n---------- resulting code for " << name << " -------------\n"; - } - bool inline_ref = (func_val->flags & 2); - *outs << std::string(indent * 2, ' ') << name << " PROC" << (inline_ref ? "REF" : "") << ":<{\n"; - code.generate_code( - *outs, - (stack_layout_comments ? Stack::_StkCmt | Stack::_CptStkCmt : 0) | (opt_level < 2 ? Stack::_DisableOpt : 0), - indent + 1); - *outs << std::string(indent * 2, ' ') << "}>\n"; - if (verbosity >= 2) { - std::cerr << "--------------\n"; - } - } -} - -int generate_output() { - if (asm_preamble) { - *outs << "\"Asm.fif\" include\n"; - } - *outs << "// automatically generated from " << generated_from << std::endl; - if (program_envelope) { - *outs << "PROGRAM{\n"; - } - for (SymDef* func_sym : glob_func) { - SymValCodeFunc* func_val = dynamic_cast(func_sym->value); - assert(func_val); - std::string name = sym::symbols.get_name(func_sym->sym_idx); - *outs << std::string(indent * 2, ' '); - if (func_val->method_id.is_null()) { - *outs << "DECLPROC " << name << "\n"; - } else { - *outs << func_val->method_id << " DECLMETHOD " << name << "\n"; - } - } - for (SymDef* gvar_sym : glob_vars) { - assert(dynamic_cast(gvar_sym->value)); - std::string name = sym::symbols.get_name(gvar_sym->sym_idx); - *outs << std::string(indent * 2, ' ') << "DECLGLOBVAR " << name << "\n"; - } - int errors = 0; - for (SymDef* func_sym : glob_func) { - try { - generate_output_func(func_sym); - } catch (src::Error& err) { - std::cerr << "cannot generate code for function `" << sym::symbols.get_name(func_sym->sym_idx) << "`:\n" - << err << std::endl; - ++errors; - } - } - if (program_envelope) { - *outs << "}END>c\n"; - } - if (!boc_output_filename.empty()) { - *outs << "2 boc+>B \"" << boc_output_filename << "\" B>file\n"; - } - return errors; -} - -} // namespace funC - -void usage(const char* progname) { - std::cerr - << "usage: " << progname - << " [-vIAPSR][-O][-i][-o][-W] { ...}\n" - "\tGenerates Fift TVM assembler code from a funC source\n" - "-I\tEnables interactive mode (parse stdin)\n" - "-o\tWrites generated code into specified file instead of stdout\n" - "-v\tIncreases verbosity level (extra information output into stderr)\n" - "-i\tSets indentation for the output code (in two-space units)\n" - "-A\tPrefix code with `\"Asm.fif\" include` preamble\n" - "-O\tSets optimization level (2 by default)\n" - "-P\tEnvelope code into PROGRAM{ ... }END>c\n" - "-S\tInclude stack layout comments in the output code\n" - "-R\tInclude operation rewrite comments in the output code\n" - "-W\tInclude Fift code to serialize and save generated code into specified BoC file. Enables " - "-A and -P.\n"; - std::exit(2); -} - -std::string output_filename; - -int main(int argc, char* const argv[]) { - int i; - bool interactive = false; - while ((i = getopt(argc, argv, "Ahi:Io:O:PRSvW:")) != -1) { - switch (i) { - case 'A': - funC::asm_preamble = true; - break; - case 'I': - interactive = true; - break; - case 'i': - funC::indent = std::max(0, atoi(optarg)); - break; - case 'o': - output_filename = optarg; - break; - case 'O': - funC::opt_level = std::max(0, atoi(optarg)); - break; - case 'P': - funC::program_envelope = true; - break; - case 'R': - funC::op_rewrite_comments = true; - break; - case 'S': - funC::stack_layout_comments = true; - break; - case 'v': - ++funC::verbosity; - break; - case 'W': - funC::boc_output_filename = optarg; - funC::asm_preamble = funC::program_envelope = true; - break; - case 'h': - default: - usage(argv[0]); - } - } - - if (funC::program_envelope && !funC::indent) { - funC::indent = 1; - } - - funC::define_keywords(); - funC::define_builtins(); - - int ok = 0, proc = 0; - try { - while (optind < argc) { - funC::generated_from += std::string{"`"} + argv[optind] + "` "; - ok += funC::parse_source_file(argv[optind++]); - proc++; - } - if (interactive) { - funC::generated_from += "stdin "; - ok += funC::parse_source_stdin(); - proc++; - } - if (ok < proc) { - throw src::Fatal{"output code generation omitted because of errors"}; - } - if (!proc) { - throw src::Fatal{"no source files, no output"}; - } - std::unique_ptr fs; - if (!output_filename.empty()) { - fs = std::make_unique(output_filename, fs->trunc | fs->out); - if (!fs->is_open()) { - std::cerr << "failed to create output file " << output_filename << '\n'; - return 2; - } - funC::outs = fs.get(); - } - funC::generate_output(); - } catch (src::Fatal& fatal) { - std::cerr << "fatal: " << fatal << std::endl; - std::exit(1); - } catch (src::Error& error) { - std::cerr << error << std::endl; - std::exit(1); - } catch (funC::UnifyError& unif_err) { - std::cerr << "fatal: "; - unif_err.print_message(std::cerr); - std::cerr << std::endl; - std::exit(1); - } -} diff --git a/submodules/ton/tonlib-src/crypto/func/func.h b/submodules/ton/tonlib-src/crypto/func/func.h deleted file mode 100644 index 1506b974..00000000 --- a/submodules/ton/tonlib-src/crypto/func/func.h +++ /dev/null @@ -1,1592 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "parser/srcread.h" -#include "parser/lexer.h" -#include "parser/symtable.h" - -namespace funC { - -extern int verbosity; -extern bool op_rewrite_comments; - -constexpr int optimize_depth = 20; - -enum Keyword { - _Eof = -1, - _Ident = 0, - _Number, - _Special, - _String, - _Return = 0x80, - _Var, - _Repeat, - _Do, - _While, - _Until, - _If, - _Ifnot, - _Then, - _Else, - _Elseif, - _Elseifnot, - _Eq, - _Neq, - _Leq, - _Geq, - _Spaceship, - _Lshift, - _Rshift, - _RshiftR, - _RshiftC, - _DivR, - _DivC, - _ModR, - _ModC, - _DivMod, - _PlusLet, - _MinusLet, - _TimesLet, - _DivLet, - _DivRLet, - _DivCLet, - _ModLet, - _ModRLet, - _ModCLet, - _LshiftLet, - _RshiftLet, - _RshiftRLet, - _RshiftCLet, - _AndLet, - _OrLet, - _XorLet, - _Int, - _Cell, - _Slice, - _Builder, - _Cont, - _Tuple, - _Type, - _Mapsto, - _Forall, - _Asm, - _Impure, - _Global, - _Extern, - _Inline, - _InlineRef, - _AutoApply, - _MethodId, - _Operator, - _Infix, - _Infixl, - _Infixr -}; - -void define_keywords(); - -class IdSc { - int cls; - - public: - enum { undef = 0, dotid = 1, tildeid = 2 }; - IdSc(int _cls = undef) : cls(_cls) { - } - operator int() { - return cls; - } -}; - -// symbol subclass: -// 1 = begins with . (a const method) -// 2 = begins with ~ (a non-const method) -// 0 = else - -/* - * - * TYPE EXPRESSIONS - * - */ - -struct TypeExpr { - enum te_type { te_Unknown, te_Var, te_Indirect, te_Atomic, te_Tensor, te_Tuple, te_Map, te_Type, te_ForAll } constr; - enum { - _Int = Keyword::_Int, - _Cell = Keyword::_Cell, - _Slice = Keyword::_Slice, - _Builder = Keyword::_Builder, - _Cont = Keyword::_Cont, - _Tuple = Keyword::_Tuple, - _Type = Keyword::_Type - }; - int value; - int minw, maxw; - static constexpr int w_inf = 1023; - std::vector args; - TypeExpr(te_type _constr, int _val = 0) : constr(_constr), value(_val), minw(0), maxw(w_inf) { - } - TypeExpr(te_type _constr, int _val, int width) : constr(_constr), value(_val), minw(width), maxw(width) { - } - TypeExpr(te_type _constr, std::vector list) - : constr(_constr), value((int)list.size()), args(std::move(list)) { - compute_width(); - } - TypeExpr(te_type _constr, std::initializer_list list) - : constr(_constr), value((int)list.size()), args(std::move(list)) { - compute_width(); - } - TypeExpr(te_type _constr, TypeExpr* elem0) : constr(_constr), value(1), args{elem0} { - compute_width(); - } - TypeExpr(te_type _constr, TypeExpr* elem0, std::vector list) - : constr(_constr), value((int)list.size() + 1), args{elem0} { - args.insert(args.end(), list.begin(), list.end()); - compute_width(); - } - TypeExpr(te_type _constr, TypeExpr* elem0, std::initializer_list list) - : constr(_constr), value((int)list.size() + 1), args{elem0} { - args.insert(args.end(), list.begin(), list.end()); - compute_width(); - } - bool is_atomic() const { - return constr == te_Atomic; - } - bool is_atomic(int v) const { - return constr == te_Atomic && value == v; - } - bool is_int() const { - return is_atomic(_Int); - } - bool is_var() const { - return constr == te_Var; - } - bool is_map() const { - return constr == te_Map; - } - bool is_tuple() const { - return constr == te_Tuple; - } - bool has_fixed_width() const { - return minw == maxw; - } - int get_width() const { - return has_fixed_width() ? minw : -1; - } - void compute_width(); - bool recompute_width(); - void show_width(std::ostream& os); - std::ostream& print(std::ostream& os, int prio = 0); - void replace_with(TypeExpr* te2); - int extract_components(std::vector& comp_list); - static int holes, type_vars; - static TypeExpr* new_hole() { - return new TypeExpr{te_Unknown, ++holes}; - } - static TypeExpr* new_hole(int width) { - return new TypeExpr{te_Unknown, ++holes, width}; - } - static TypeExpr* new_unit() { - return new TypeExpr{te_Tensor, 0, 0}; - } - static TypeExpr* new_atomic(int value) { - return new TypeExpr{te_Atomic, value, 1}; - } - static TypeExpr* new_map(TypeExpr* from, TypeExpr* to); - static TypeExpr* new_func() { - return new_map(new_hole(), new_hole()); - } - static TypeExpr* new_tensor(std::vector list, bool red = true) { - return red && list.size() == 1 ? list[0] : new TypeExpr{te_Tensor, std::move(list)}; - } - static TypeExpr* new_tensor(std::initializer_list list) { - return new TypeExpr{te_Tensor, std::move(list)}; - } - static TypeExpr* new_tensor(TypeExpr* te1, TypeExpr* te2) { - return new_tensor({te1, te2}); - } - static TypeExpr* new_tensor(TypeExpr* te1, TypeExpr* te2, TypeExpr* te3) { - return new_tensor({te1, te2, te3}); - } - static TypeExpr* new_tuple(TypeExpr* arg0) { - return new TypeExpr{te_Tuple, arg0}; - } - static TypeExpr* new_tuple(std::vector list, bool red = false) { - return new_tuple(new_tensor(std::move(list), red)); - } - static TypeExpr* new_tuple(std::initializer_list list) { - return new_tuple(new_tensor(std::move(list))); - } - static TypeExpr* new_var() { - return new TypeExpr{te_Var, --type_vars, 1}; - } - static TypeExpr* new_var(int idx) { - return new TypeExpr{te_Var, idx, 1}; - } - static TypeExpr* new_forall(std::vector list, TypeExpr* body) { - return new TypeExpr{te_ForAll, body, std::move(list)}; - } - static TypeExpr* new_forall(std::initializer_list list, TypeExpr* body) { - return new TypeExpr{te_ForAll, body, std::move(list)}; - } - static bool remove_indirect(TypeExpr*& te, TypeExpr* forbidden = nullptr); - static bool remove_forall(TypeExpr*& te); - static bool remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector& new_vars); -}; - -std::ostream& operator<<(std::ostream& os, TypeExpr* type_expr); - -struct UnifyError { - TypeExpr* te1; - TypeExpr* te2; - std::string msg; - UnifyError(TypeExpr* _te1, TypeExpr* _te2, std::string _msg = "") : te1(_te1), te2(_te2), msg(_msg) { - } - void print_message(std::ostream& os) const; - std::string message() const; -}; - -std::ostream& operator<<(std::ostream& os, const UnifyError& ue); - -void unify(TypeExpr*& te1, TypeExpr*& te2); - -// extern int TypeExpr::holes; - -/* - * - * ABSTRACT CODE - * - */ - -using src::Lexem; -using src::SrcLocation; -using sym::SymDef; -using sym::sym_idx_t; -using sym::var_idx_t; -using const_idx_t = int; - -struct TmpVar { - TypeExpr* v_type; - var_idx_t idx; - enum { _In = 1, _Named = 2, _Tmp = 4, _UniqueName = 0x20 }; - int cls; - sym_idx_t name; - int coord; - std::unique_ptr where; - TmpVar(var_idx_t _idx, int _cls, TypeExpr* _type = 0, SymDef* sym = 0, const SrcLocation* loc = 0); - void show(std::ostream& os, int omit_idx = 0) const; - void dump(std::ostream& os) const; - void set_location(const SrcLocation& loc); -}; - -struct VarDescr { - var_idx_t idx; - enum { _Last = 1, _Unused = 2 }; - int flags; - enum { - _Const = 16, - _Int = 32, - _Zero = 64, - _NonZero = 128, - _Pos = 256, - _Neg = 512, - _Bool = 1024, - _Bit = 2048, - _Finite = 4096, - _Nan = 8192, - _Even = 16384, - _Odd = 32768, - _Null = (1 << 16), - _NotNull = (1 << 17) - }; - static constexpr int ConstZero = _Int | _Zero | _Pos | _Neg | _Bool | _Bit | _Finite | _Even | _NotNull; - static constexpr int ConstOne = _Int | _NonZero | _Pos | _Bit | _Finite | _Odd | _NotNull; - static constexpr int ConstTrue = _Int | _NonZero | _Neg | _Bool | _Finite | _Odd | _NotNull; - static constexpr int ValBit = ConstZero & ConstOne; - static constexpr int ValBool = ConstZero & ConstTrue; - static constexpr int FiniteInt = _Int | _Finite | _NotNull; - static constexpr int FiniteUInt = FiniteInt | _Pos; - int val; - td::RefInt256 int_const; - VarDescr(var_idx_t _idx = -1, int _flags = 0, int _val = 0) : idx(_idx), flags(_flags), val(_val) { - } - bool operator<(var_idx_t other_idx) const { - return idx < other_idx; - } - bool is_unused() const { - return flags & _Unused; - } - bool is_last() const { - return flags & _Last; - } - bool always_true() const { - return val & _NonZero; - } - bool always_false() const { - return val & _Zero; - } - bool always_nonzero() const { - return val & _NonZero; - } - bool always_zero() const { - return val & _Zero; - } - bool always_even() const { - return val & _Even; - } - bool always_odd() const { - return val & _Odd; - } - bool always_null() const { - return val & _Null; - } - bool always_not_null() const { - return val & _NotNull; - } - bool is_const() const { - return val & _Const; - } - bool is_int_const() const { - return (val & (_Int | _Const)) == (_Int | _Const); - } - bool always_nonpos() const { - return val & _Neg; - } - bool always_nonneg() const { - return val & _Pos; - } - bool always_pos() const { - return (val & (_Pos | _NonZero)) == (_Pos | _NonZero); - } - bool always_neg() const { - return (val & (_Neg | _NonZero)) == (_Neg | _NonZero); - } - bool always_finite() const { - return val & _Finite; - } - bool always_less(const VarDescr& other) const; - bool always_leq(const VarDescr& other) const; - bool always_greater(const VarDescr& other) const; - bool always_geq(const VarDescr& other) const; - bool always_equal(const VarDescr& other) const; - bool always_neq(const VarDescr& other) const; - void unused() { - flags |= _Unused; - } - void clear_unused() { - flags &= ~_Unused; - } - void set_const(long long value); - void set_const(td::RefInt256 value); - void set_const_nan(); - void operator+=(const VarDescr& y) { - flags &= y.flags; - } - void operator|=(const VarDescr& y); - void operator&=(const VarDescr& y); - void set_value(const VarDescr& y); - void set_value(VarDescr&& y); - void set_value(const VarDescr* y) { - if (y) { - set_value(*y); - } - } - void clear_value(); - void show_value(std::ostream& os) const; - void show(std::ostream& os, const char* var_name = nullptr) const; -}; - -inline std::ostream& operator<<(std::ostream& os, const VarDescr& vd) { - vd.show(os); - return os; -} - -struct VarDescrList { - std::vector list; - bool unreachable{false}; - VarDescrList() : list() { - } - VarDescrList(const std::vector& _list) : list(_list) { - } - VarDescrList(std::vector&& _list) : list(std::move(_list)) { - } - std::size_t size() const { - return list.size(); - } - VarDescr* operator[](var_idx_t idx); - const VarDescr* operator[](var_idx_t idx) const; - VarDescrList operator+(const VarDescrList& y) const; - VarDescrList& operator+=(const VarDescrList& y); - VarDescrList& clear_last(); - VarDescrList& operator+=(var_idx_t idx) { - return add_var(idx); - } - VarDescrList& operator+=(const std::vector& idx_list) { - return add_vars(idx_list); - } - VarDescrList& add_var(var_idx_t idx, bool unused = false); - VarDescrList& add_vars(const std::vector& idx_list, bool unused = false); - VarDescrList& operator-=(const std::vector& idx_list); - VarDescrList& operator-=(var_idx_t idx); - std::size_t count(const std::vector idx_list) const; - std::size_t count_used(const std::vector idx_list) const; - VarDescr& add(var_idx_t idx); - VarDescr& add_newval(var_idx_t idx); - VarDescrList& operator&=(const VarDescrList& values); - VarDescrList& import_values(const VarDescrList& values); - VarDescrList operator|(const VarDescrList& y) const; - VarDescrList& operator|=(const VarDescrList& values); - void show(std::ostream& os) const; - void set_unreachable() { - list.clear(); - unreachable = true; - } -}; - -inline std::ostream& operator<<(std::ostream& os, const VarDescrList& values) { - values.show(os); - return os; -} - -struct CodeBlob; - -template -class ListIterator { - T* ptr; - - public: - ListIterator() : ptr(nullptr) { - } - ListIterator(T* _ptr) : ptr(_ptr) { - } - ListIterator& operator++() { - ptr = ptr->next.get(); - return *this; - } - ListIterator& operator++(int) { - T* z = ptr; - ptr = ptr->next.get(); - return ListIterator{z}; - } - T& operator*() const { - return *ptr; - } - T* operator->() const { - return ptr; - } - bool operator==(const ListIterator& y) const { - return ptr == y.ptr; - } - bool operator!=(const ListIterator& y) const { - return ptr != y.ptr; - } -}; - -struct Stack; - -struct Op { - enum { - _Undef, - _Nop, - _Call, - _CallInd, - _Let, - _IntConst, - _GlobVar, - _SetGlob, - _Import, - _Return, - _Tuple, - _UnTuple, - _If, - _While, - _Until, - _Repeat, - _Again - }; - int cl; - enum { _Disabled = 1, _Reachable = 2, _NoReturn = 4, _ImpureR = 8, _ImpureW = 16, _Impure = 24 }; - int flags; - std::unique_ptr next; - SymDef* fun_ref; - SrcLocation where; - VarDescrList var_info; - std::vector args; - std::vector left, right; - std::unique_ptr block0, block1; - td::RefInt256 int_const; - Op(const SrcLocation& _where = {}, int _cl = _Undef) : cl(_cl), flags(0), fun_ref(nullptr), where(_where) { - } - Op(const SrcLocation& _where, int _cl, const std::vector& _left) - : cl(_cl), flags(0), fun_ref(nullptr), where(_where), left(_left) { - } - Op(const SrcLocation& _where, int _cl, std::vector&& _left) - : cl(_cl), flags(0), fun_ref(nullptr), where(_where), left(std::move(_left)) { - } - Op(const SrcLocation& _where, int _cl, const std::vector& _left, td::RefInt256 _const) - : cl(_cl), flags(0), fun_ref(nullptr), where(_where), left(_left), int_const(_const) { - } - Op(const SrcLocation& _where, int _cl, const std::vector& _left, const std::vector& _right, - SymDef* _fun = nullptr) - : cl(_cl), flags(0), fun_ref(_fun), where(_where), left(_left), right(_right) { - } - Op(const SrcLocation& _where, int _cl, std::vector&& _left, std::vector&& _right, - SymDef* _fun = nullptr) - : cl(_cl), flags(0), fun_ref(_fun), where(_where), left(std::move(_left)), right(std::move(_right)) { - } - bool disabled() const { - return flags & _Disabled; - } - bool enabled() const { - return !disabled(); - } - void disable() { - flags |= _Disabled; - } - bool unreachable() { - return !(flags & _Reachable); - } - void flags_set_clear(int set, int clear); - void show(std::ostream& os, const std::vector& vars, std::string pfx = "", int mode = 0) const; - void show_var_list(std::ostream& os, const std::vector& idx_list, const std::vector& vars) const; - void show_var_list(std::ostream& os, const std::vector& list, const std::vector& vars) const; - static void show_block(std::ostream& os, const Op* block, const std::vector& vars, std::string pfx = "", - int mode = 0); - void split_vars(const std::vector& vars); - static void split_var_list(std::vector& var_list, const std::vector& vars); - bool compute_used_vars(const CodeBlob& code, bool edit); - bool std_compute_used_vars(bool disabled = false); - bool set_var_info(const VarDescrList& new_var_info); - bool set_var_info(VarDescrList&& new_var_info); - bool set_var_info_except(const VarDescrList& new_var_info, const std::vector& var_list); - bool set_var_info_except(VarDescrList&& new_var_info, const std::vector& var_list); - void prepare_args(VarDescrList values); - VarDescrList fwd_analyze(VarDescrList values); - bool set_noreturn(bool nr); - bool mark_noreturn(); - bool noreturn() const { - return flags & _NoReturn; - } - bool is_empty() const { - return cl == _Nop && !next; - } - bool is_pure() const { - return !(flags & _Impure); - } - bool generate_code_step(Stack& stack); - bool generate_code_all(Stack& stack); - Op& last() { - return next ? next->last() : *this; - } - const Op& last() const { - return next ? next->last() : *this; - } - ListIterator begin() { - return ListIterator{this}; - } - ListIterator end() const { - return ListIterator{}; - } - ListIterator cbegin() { - return ListIterator{this}; - } - ListIterator cend() const { - return ListIterator{}; - } -}; - -inline ListIterator begin(const std::unique_ptr& op_list) { - return ListIterator{op_list.get()}; -} - -inline ListIterator end(const std::unique_ptr& op_list) { - return ListIterator{}; -} - -inline ListIterator cbegin(const Op* op_list) { - return ListIterator{op_list}; -} - -inline ListIterator cend(const Op* op_list) { - return ListIterator{}; -} - -inline ListIterator begin(const Op* op_list) { - return ListIterator{op_list}; -} - -inline ListIterator end(const Op* op_list) { - return ListIterator{}; -} - -inline ListIterator begin(Op* op_list) { - return ListIterator{op_list}; -} - -inline ListIterator end(Op* op_list) { - return ListIterator{}; -} - -typedef std::tuple FormalArg; -typedef std::vector FormalArgList; - -struct AsmOpList; - -struct CodeBlob { - int var_cnt, in_var_cnt, op_cnt; - TypeExpr* ret_type; - std::string name; - SrcLocation loc; - std::vector vars; - std::unique_ptr ops; - std::unique_ptr* cur_ops; - std::stack*> cur_ops_stack; - CodeBlob(TypeExpr* ret = nullptr) : var_cnt(0), in_var_cnt(0), op_cnt(0), ret_type(ret), cur_ops(&ops) { - } - template - Op& emplace_back(const Args&... args) { - Op& res = *(*cur_ops = std::make_unique(args...)); - cur_ops = &(res.next); - return res; - } - bool import_params(FormalArgList arg_list); - var_idx_t create_var(int cls, TypeExpr* var_type = 0, SymDef* sym = 0, const SrcLocation* loc = 0); - var_idx_t create_tmp_var(TypeExpr* var_type = 0, const SrcLocation* loc = 0) { - return create_var(TmpVar::_Tmp, var_type, nullptr, loc); - } - int split_vars(bool strict = false); - bool compute_used_code_vars(); - bool compute_used_code_vars(std::unique_ptr& ops, const VarDescrList& var_info, bool edit) const; - void print(std::ostream& os, int flags = 0) const; - void push_set_cur(std::unique_ptr& new_cur_ops) { - cur_ops_stack.push(cur_ops); - cur_ops = &new_cur_ops; - } - void close_blk(const SrcLocation& location) { - *cur_ops = std::make_unique(location, Op::_Nop); - } - void pop_cur() { - cur_ops = cur_ops_stack.top(); - cur_ops_stack.pop(); - } - void close_pop_cur(const SrcLocation& location) { - close_blk(location); - pop_cur(); - } - void simplify_var_types(); - void flags_set_clear(int set, int clear); - void prune_unreachable_code(); - void fwd_analyze(); - void mark_noreturn(); - void generate_code(AsmOpList& out_list, int mode = 0); - void generate_code(std::ostream& os, int mode = 0, int indent = 0); -}; - -/* - * - * SYMBOL VALUES - * - */ - -struct SymVal : sym::SymValBase { - TypeExpr* sym_type; - td::RefInt256 method_id; - bool impure; - bool auto_apply{false}; - short flags; // +1 = inline, +2 = inline_ref - SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false) - : sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) { - } - ~SymVal() override = default; - TypeExpr* get_type() const { - return sym_type; - } - virtual const std::vector* get_arg_order() const { - return nullptr; - } - virtual const std::vector* get_ret_order() const { - return nullptr; - } -}; - -struct SymValFunc : SymVal { - std::vector arg_order, ret_order; - ~SymValFunc() override = default; - SymValFunc(int val, TypeExpr* _ft, bool _impure = false) : SymVal(_Func, val, _ft, _impure) { - } - SymValFunc(int val, TypeExpr* _ft, std::initializer_list _arg_order, std::initializer_list _ret_order = {}, - bool _impure = false) - : SymVal(_Func, val, _ft, _impure), arg_order(_arg_order), ret_order(_ret_order) { - } - - const std::vector* get_arg_order() const override { - return arg_order.empty() ? nullptr : &arg_order; - } - const std::vector* get_ret_order() const override { - return ret_order.empty() ? nullptr : &ret_order; - } -}; - -struct SymValCodeFunc : SymValFunc { - CodeBlob* code; - ~SymValCodeFunc() override = default; - SymValCodeFunc(int val, TypeExpr* _ft, bool _impure = false) : SymValFunc(val, _ft, _impure), code(nullptr) { - } -}; - -struct SymValType : sym::SymValBase { - TypeExpr* sym_type; - SymValType(int _type, int _idx, TypeExpr* _stype = nullptr) : sym::SymValBase(_type, _idx), sym_type(_stype) { - } - ~SymValType() override = default; - TypeExpr* get_type() const { - return sym_type; - } -}; - -struct SymValGlobVar : sym::SymValBase { - TypeExpr* sym_type; - int out_idx{0}; - SymValGlobVar(int val, TypeExpr* gvtype, int oidx = 0) - : sym::SymValBase(_GlobVar, val), sym_type(gvtype), out_idx(oidx) { - } - ~SymValGlobVar() override = default; - TypeExpr* get_type() const { - return sym_type; - } -}; - -extern int glob_func_cnt, undef_func_cnt, glob_var_cnt; -extern std::vector glob_func, glob_vars; - -/* - * - * PARSE SOURCE - * - */ - -// defined in parse-func.cpp -bool parse_source(std::istream* is, const src::FileDescr* fdescr); -bool parse_source_file(const char* filename); -bool parse_source_stdin(); - -/* - * - * EXPRESSIONS - * - */ - -struct Expr { - enum { - _None, - _Apply, - _VarApply, - _TypeApply, - _MkTuple, - _Tensor, - _Const, - _Var, - _Glob, - _GlobVar, - _Letop, - _LetFirst, - _Hole, - _Type, - _CondExpr - }; - int cls; - int val{0}; - enum { _IsType = 1, _IsRvalue = 2, _IsLvalue = 4, _IsHole = 8, _IsNewVar = 16, _IsImpure = 32 }; - int flags{0}; - SrcLocation here; - td::RefInt256 intval; - SymDef* sym{nullptr}; - TypeExpr* e_type{nullptr}; - std::vector args; - Expr(int c = _None) : cls(c) { - } - Expr(int c, const SrcLocation& loc) : cls(c), here(loc) { - } - Expr(int c, std::vector _args) : cls(c), args(std::move(_args)) { - } - Expr(int c, std::initializer_list _arglist) : cls(c), args(std::move(_arglist)) { - } - Expr(int c, SymDef* _sym, std::initializer_list _arglist) : cls(c), sym(_sym), args(std::move(_arglist)) { - } - Expr(int c, SymDef* _sym, std::vector _arglist) : cls(c), sym(_sym), args(std::move(_arglist)) { - } - Expr(int c, sym_idx_t name_idx, std::initializer_list _arglist); - ~Expr() { - for (auto& arg_ptr : args) { - delete arg_ptr; - } - } - Expr* copy() const; - void pb_arg(Expr* expr) { - args.push_back(expr); - } - void set_val(int _val) { - val = _val; - } - bool is_rvalue() const { - return flags & _IsRvalue; - } - bool is_lvalue() const { - return flags & _IsLvalue; - } - bool is_type() const { - return flags & _IsType; - } - bool is_type_apply() const { - return cls == _TypeApply; - } - bool is_mktuple() const { - return cls == _MkTuple; - } - void chk_rvalue(const Lexem& lem) const; - void chk_lvalue(const Lexem& lem) const; - void chk_type(const Lexem& lem) const; - bool deduce_type(const Lexem& lem); - void set_location(const SrcLocation& loc) { - here = loc; - } - const SrcLocation& get_location() const { - return here; - } - int define_new_vars(CodeBlob& code); - int predefine_vars(); - std::vector pre_compile(CodeBlob& code, bool lval = false) const; - static std::vector pre_compile_let(CodeBlob& code, Expr* lhs, Expr* rhs, const SrcLocation& here); - var_idx_t new_tmp(CodeBlob& code) const; - std::vector new_tmp_vect(CodeBlob& code) const { - return {new_tmp(code)}; - } -}; - -/* - * - * GENERATE CODE - * - */ - -typedef std::vector StackLayout; -typedef std::pair var_const_idx_t; -typedef std::vector StackLayoutExt; -constexpr const_idx_t not_const = -1; -using Const = td::RefInt256; - -struct AsmOp { - enum Type { a_none, a_xchg, a_push, a_pop, a_const, a_custom, a_magic }; - int t{a_none}; - int indent{0}; - int a, b, c; - bool gconst{false}; - std::string op; - struct SReg { - int idx; - SReg(int _idx) : idx(_idx) { - } - }; - AsmOp() = default; - AsmOp(int _t) : t(_t) { - } - AsmOp(int _t, std::string _op) : t(_t), op(std::move(_op)) { - } - AsmOp(int _t, int _a) : t(_t), a(_a) { - } - AsmOp(int _t, int _a, std::string _op) : t(_t), a(_a), op(std::move(_op)) { - } - AsmOp(int _t, int _a, int _b) : t(_t), a(_a), b(_b) { - } - AsmOp(int _t, int _a, int _b, std::string _op) : t(_t), a(_a), b(_b), op(std::move(_op)) { - compute_gconst(); - } - AsmOp(int _t, int _a, int _b, int _c) : t(_t), a(_a), b(_b), c(_c) { - } - AsmOp(int _t, int _a, int _b, int _c, std::string _op) : t(_t), a(_a), b(_b), c(_c), op(std::move(_op)) { - } - void out(std::ostream& os) const; - void out_indent_nl(std::ostream& os, bool no_nl = false) const; - std::string to_string() const; - void compute_gconst() { - gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC" || op == "NEWB" || op == "TRUE" || op == "FALSE" || op == "NOW")); - } - bool is_nop() const { - return t == a_none && op.empty(); - } - bool is_comment() const { - return t == a_none && !op.empty(); - } - bool is_custom() const { - return t == a_custom; - } - bool is_very_custom() const { - return is_custom() && a >= 255; - } - bool is_push() const { - return t == a_push; - } - bool is_push(int x) const { - return is_push() && a == x; - } - bool is_push(int* x) const { - *x = a; - return is_push(); - } - bool is_pop() const { - return t == a_pop; - } - bool is_pop(int x) const { - return is_pop() && a == x; - } - bool is_xchg() const { - return t == a_xchg; - } - bool is_xchg(int x, int y) const { - return is_xchg() && b == y && a == x; - } - bool is_xchg(int* x, int* y) const { - *x = a; - *y = b; - return is_xchg(); - } - bool is_xchg_short() const { - return is_xchg() && (a <= 1 || b <= 1); - } - bool is_swap() const { - return is_xchg(0, 1); - } - bool is_const() const { - return t == a_const && !a && b == 1; - } - bool is_gconst() const { - return !a && b == 1 && (t == a_const || gconst); - } - static AsmOp Nop() { - return AsmOp(a_none); - } - static AsmOp Xchg(int a, int b = 0) { - return a == b ? AsmOp(a_none) : (a < b ? AsmOp(a_xchg, a, b) : AsmOp(a_xchg, b, a)); - } - static AsmOp Push(int a) { - return AsmOp(a_push, a); - } - static AsmOp Pop(int a = 0) { - return AsmOp(a_pop, a); - } - static AsmOp Xchg2(int a, int b) { - return make_stk2(a, b, "XCHG2", 0); - } - static AsmOp XcPu(int a, int b) { - return make_stk2(a, b, "XCPU", 1); - } - static AsmOp PuXc(int a, int b) { - return make_stk2(a, b, "PUXC", 1); - } - static AsmOp Push2(int a, int b) { - return make_stk2(a, b, "PUSH2", 2); - } - static AsmOp Xchg3(int a, int b, int c) { - return make_stk3(a, b, c, "XCHG3", 0); - } - static AsmOp Xc2Pu(int a, int b, int c) { - return make_stk3(a, b, c, "XC2PU", 1); - } - static AsmOp XcPuXc(int a, int b, int c) { - return make_stk3(a, b, c, "XCPUXC", 1); - } - static AsmOp XcPu2(int a, int b, int c) { - return make_stk3(a, b, c, "XCPU2", 3); - } - static AsmOp PuXc2(int a, int b, int c) { - return make_stk3(a, b, c, "PUXC2", 3); - } - static AsmOp PuXcPu(int a, int b, int c) { - return make_stk3(a, b, c, "PUXCPU", 3); - } - static AsmOp Pu2Xc(int a, int b, int c) { - return make_stk3(a, b, c, "PU2XC", 3); - } - static AsmOp Push3(int a, int b, int c) { - return make_stk3(a, b, c, "PUSH3", 3); - } - static AsmOp BlkSwap(int a, int b); - static AsmOp BlkPush(int a, int b); - static AsmOp BlkDrop(int a); - static AsmOp BlkDrop2(int a, int b); - static AsmOp BlkReverse(int a, int b); - static AsmOp make_stk2(int a, int b, const char* str, int delta); - static AsmOp make_stk3(int a, int b, int c, const char* str, int delta); - static AsmOp IntConst(td::RefInt256 value); - static AsmOp BoolConst(bool f); - static AsmOp Const(std::string push_op) { - return AsmOp(a_const, 0, 1, std::move(push_op)); - } - static AsmOp Const(int arg, std::string push_op); - static AsmOp Comment(std::string comment) { - return AsmOp(a_none, std::string{"// "} + comment); - } - static AsmOp Custom(std::string custom_op) { - return AsmOp(a_custom, 255, 255, custom_op); - } - static AsmOp Parse(std::string custom_op); - static AsmOp Custom(std::string custom_op, int args, int retv = 1) { - return AsmOp(a_custom, args, retv, custom_op); - } - static AsmOp Parse(std::string custom_op, int args, int retv = 1); - static AsmOp Tuple(int a); - static AsmOp UnTuple(int a); -}; - -inline std::ostream& operator<<(std::ostream& os, const AsmOp& op) { - op.out(os); - return os; -} - -std::ostream& operator<<(std::ostream& os, AsmOp::SReg stack_reg); - -struct AsmOpList { - std::vector list_; - int indent_{0}; - const std::vector* var_names_{nullptr}; - std::vector constants_; - void out(std::ostream& os, int mode = 0) const; - AsmOpList(int indent = 0, const std::vector* var_names = nullptr) : indent_(indent), var_names_(var_names) { - } - template - AsmOpList& add(Args&&... args) { - list_.emplace_back(std::forward(args)...); - adjust_last(); - return *this; - } - bool append(const AsmOp& op) { - list_.push_back(op); - adjust_last(); - return true; - } - bool append(const std::vector& ops); - bool append(std::initializer_list ops) { - return append(std::vector(std::move(ops))); - } - AsmOpList& operator<<(const AsmOp& op) { - return add(op); - } - AsmOpList& operator<<(AsmOp&& op) { - return add(std::move(op)); - } - AsmOpList& operator<<(std::string str) { - return add(AsmOp::Type::a_custom, 255, 255, str); - } - const_idx_t register_const(Const new_const); - Const get_const(const_idx_t idx); - void show_var(std::ostream& os, var_idx_t idx) const; - void show_var_ext(std::ostream& os, std::pair idx_pair) const; - void adjust_last() { - if (list_.back().is_nop()) { - list_.pop_back(); - } else { - list_.back().indent = indent_; - } - } - void indent() { - ++indent_; - } - void undent() { - --indent_; - } - void set_indent(int new_indent) { - indent_ = new_indent; - } -}; - -inline std::ostream& operator<<(std::ostream& os, const AsmOpList& op_list) { - op_list.out(os); - return os; -} - -class IndentGuard { - AsmOpList& aol_; - - public: - IndentGuard(AsmOpList& aol) : aol_(aol) { - aol.indent(); - } - ~IndentGuard() { - aol_.undent(); - } -}; - -struct AsmOpCons { - std::unique_ptr car; - std::unique_ptr cdr; - AsmOpCons(std::unique_ptr head, std::unique_ptr tail) : car(std::move(head)), cdr(std::move(tail)) { - } - static std::unique_ptr cons(std::unique_ptr head, std::unique_ptr tail) { - return std::make_unique(std::move(head), std::move(tail)); - } -}; - -using AsmOpConsList = std::unique_ptr; - -int is_pos_pow2(td::RefInt256 x); -int is_neg_pow2(td::RefInt256 x); - -/* - * - * STACK TRANSFORMS - * - */ - -/* -A stack transform is a map f:N={0,1,...} -> N, such that f(x) = x + d_f for almost all x:N and for a fixed d_f:N. -They form a monoid under composition: (fg)(x)=f(g(x)). -They act on stacks S on the right: Sf=S', such that S'[n]=S[f(n)]. - -A stack transform f is determined by d_f and the finite set A of all pairs (x,y), such that x>=d_f, f(x-d_f) = y and y<>x. They are listed in increasing order by x. -*/ -struct StackTransform { - enum { max_n = 16, inf_x = 0x7fffffff, c_start = -1000 }; - int d{0}, n{0}, dp{0}, c{0}; - bool invalid{false}; - std::array, max_n> A; - StackTransform() = default; - // list of f(0),f(1),...,f(s); assumes next values are f(s)+1,f(s)+2,... - StackTransform(std::initializer_list list); - StackTransform& operator=(std::initializer_list list); - bool assign(const StackTransform& other); - static StackTransform id() { - return {}; - } - bool invalidate() { - invalid = true; - return false; - } - bool is_valid() const { - return !invalid; - } - bool set_id() { - d = n = dp = c = 0; - invalid = false; - return true; - } - bool shift(int offs) { // post-composes with x -> x + offs - d += offs; - return offs <= 0 || remove_negative(); - } - bool remove_negative(); - bool touch(int i) { - dp = std::max(dp, i + d + 1); - return true; - } - bool is_permutation() const; // is f:N->N bijective ? - bool is_trivial_after(int x) const; // f(x') = x' + d for all x' >= x - int preimage_count(int y) const; // card f^{-1}(y) - std::vector preimage(int y) const; - bool apply_xchg(int i, int j, bool relaxed = false); - bool apply_push(int i); - bool apply_pop(int i = 0); - bool apply_push_newconst(); - bool apply_blkpop(int k); - bool apply(const StackTransform& other); // this = this * other - bool preapply(const StackTransform& other); // this = other * this - // c := a * b - static bool compose(const StackTransform& a, const StackTransform& b, StackTransform& c); - StackTransform& operator*=(const StackTransform& other); - StackTransform operator*(const StackTransform& b) const &; - bool equal(const StackTransform& other, bool relaxed = false) const; - bool almost_equal(const StackTransform& other) const { - return equal(other, true); - } - bool operator==(const StackTransform& other) const { - return dp == other.dp && almost_equal(other); - } - bool operator<=(const StackTransform& other) const { - return dp <= other.dp && almost_equal(other); - } - bool operator>=(const StackTransform& other) const { - return dp >= other.dp && almost_equal(other); - } - int get(int i) const; - int touch_get(int i, bool relaxed = false) { - if (!relaxed) { - touch(i); - } - return get(i); - } - bool set(int i, int v, bool relaxed = false); - int operator()(int i) const { - return get(i); - } - class Pos { - StackTransform& t_; - int p_; - - public: - Pos(StackTransform& t, int p) : t_(t), p_(p) { - } - Pos& operator=(const Pos& other) = delete; - operator int() const { - return t_.get(p_); - } - const Pos& operator=(int v) const { - t_.set(p_, v); - return *this; - } - }; - Pos operator[](int i) { - return Pos(*this, i); - } - static const StackTransform rot; - static const StackTransform rot_rev; - bool is_id() const { - return is_valid() && !d && !n; - } - bool is_xchg(int i, int j) const; - bool is_xchg(int* i, int* j) const; - bool is_xchg_xchg(int i, int j, int k, int l) const; - bool is_xchg_xchg(int* i, int* j, int* k, int* l) const; - bool is_push(int i) const; - bool is_push(int* i) const; - bool is_pop(int i) const; - bool is_pop(int* i) const; - bool is_pop_pop(int i, int j) const; - bool is_pop_pop(int* i, int* j) const; - bool is_rot() const; - bool is_rotrev() const; - bool is_push_rot(int i) const; - bool is_push_rot(int* i) const; - bool is_push_rotrev(int i) const; - bool is_push_rotrev(int* i) const; - bool is_push_xchg(int i, int j, int k) const; - bool is_push_xchg(int* i, int* j, int* k) const; - bool is_xchg2(int i, int j) const; - bool is_xchg2(int* i, int* j) const; - bool is_xcpu(int i, int j) const; - bool is_xcpu(int* i, int* j) const; - bool is_puxc(int i, int j) const; - bool is_puxc(int* i, int* j) const; - bool is_push2(int i, int j) const; - bool is_push2(int* i, int* j) const; - bool is_xchg3(int* i, int* j, int* k) const; - bool is_xc2pu(int* i, int* j, int* k) const; - bool is_xcpuxc(int* i, int* j, int* k) const; - bool is_xcpu2(int* i, int* j, int* k) const; - bool is_puxc2(int i, int j, int k) const; - bool is_puxc2(int* i, int* j, int* k) const; - bool is_puxcpu(int* i, int* j, int* k) const; - bool is_pu2xc(int i, int j, int k) const; - bool is_pu2xc(int* i, int* j, int* k) const; - bool is_push3(int i, int j, int k) const; - bool is_push3(int* i, int* j, int* k) const; - bool is_blkswap(int i, int j) const; - bool is_blkswap(int* i, int* j) const; - bool is_blkpush(int i, int j) const; - bool is_blkpush(int* i, int* j) const; - bool is_blkdrop(int* i) const; - bool is_blkdrop2(int i, int j) const; - bool is_blkdrop2(int* i, int* j) const; - bool is_reverse(int i, int j) const; - bool is_reverse(int* i, int* j) const; - bool is_nip_seq(int i, int j = 0) const; - bool is_nip_seq(int* i) const; - bool is_nip_seq(int* i, int* j) const; - bool is_pop_blkdrop(int i, int k) const; - bool is_pop_blkdrop(int* i, int* k) const; - bool is_2pop_blkdrop(int i, int j, int k) const; - bool is_2pop_blkdrop(int* i, int* j, int* k) const; - bool is_const_rot(int c) const; - bool is_const_rot(int* c) const; - bool is_const_pop(int c, int i) const; - bool is_const_pop(int* c, int* i) const; - bool is_push_const(int i, int c) const; - bool is_push_const(int* i, int* c) const; - - void show(std::ostream& os, int mode = 0) const; - - static StackTransform Xchg(int i, int j, bool relaxed = false); - static StackTransform Push(int i); - static StackTransform Pop(int i); - - private: - int try_load(int& i, int offs = 0) const; // returns A[i++].first + offs or inf_x - bool try_store(int x, int y); // appends (x,y) to A -}; - -//extern const StackTransform StackTransform::rot, StackTransform::rot_rev; - -inline std::ostream& operator<<(std::ostream& os, const StackTransform& trans) { - trans.show(os); - return os; -} - -bool apply_op(StackTransform& trans, const AsmOp& op); - -/* - * - * STACK OPERATION OPTIMIZER - * - */ - -struct Optimizer { - enum { n = optimize_depth }; - AsmOpConsList code_; - int l_{0}, l2_{0}, p_, pb_, q_, indent_; - bool debug_{false}; - std::unique_ptr op_[n], oq_[n]; - AsmOpCons* op_cons_[n]; - int offs_[n]; - StackTransform tr_[n]; - int mode_{0}; - Optimizer() { - } - Optimizer(bool debug, int mode = 0) : debug_(debug), mode_(mode) { - } - Optimizer(AsmOpConsList code, bool debug = false, int mode = 0) : Optimizer(debug, mode) { - set_code(std::move(code)); - } - void set_code(AsmOpConsList code_); - void unpack(); - void pack(); - void apply(); - bool find_at_least(int pb); - bool find(); - bool optimize(); - bool compute_stack_transforms(); - bool say(std::string str) const; - bool show_stack_transforms() const; - void show_head() const; - void show_left() const; - void show_right() const; - bool find_const_op(int* op_idx, int cst); - bool is_push_const(int* i, int* c) const; - bool rewrite_push_const(int i, int c); - bool is_const_push_xchgs(); - bool rewrite_const_push_xchgs(); - bool is_const_rot(int* c) const; - bool rewrite_const_rot(int c); - bool is_const_pop(int* c, int* i) const; - bool rewrite_const_pop(int c, int i); - bool rewrite(int p, AsmOp&& new_op); - bool rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2); - bool rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3); - bool rewrite(AsmOp&& new_op) { - return rewrite(p_, std::move(new_op)); - } - bool rewrite(AsmOp&& new_op1, AsmOp&& new_op2) { - return rewrite(p_, std::move(new_op1), std::move(new_op2)); - } - bool rewrite(AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3) { - return rewrite(p_, std::move(new_op1), std::move(new_op2), std::move(new_op3)); - } - bool rewrite_nop(); - bool is_pred(const std::function& pred, int min_p = 2); - bool is_same_as(const StackTransform& trans, int min_p = 2); - bool is_rot(); - bool is_rotrev(); - bool is_tuck(); - bool is_2dup(); - bool is_2drop(); - bool is_2swap(); - bool is_2over(); - bool is_xchg(int* i, int* j); - bool is_xchg_xchg(int* i, int* j, int* k, int* l); - bool is_push(int* i); - bool is_pop(int* i); - bool is_pop_pop(int* i, int* j); - bool is_nop(); - bool is_push_rot(int* i); - bool is_push_rotrev(int* i); - bool is_push_xchg(int* i, int* j, int* k); - bool is_xchg2(int* i, int* j); - bool is_xcpu(int* i, int* j); - bool is_puxc(int* i, int* j); - bool is_push2(int* i, int* j); - bool is_xchg3(int* i, int* j, int* k); - bool is_xc2pu(int* i, int* j, int* k); - bool is_xcpuxc(int* i, int* j, int* k); - bool is_xcpu2(int* i, int* j, int* k); - bool is_puxc2(int* i, int* j, int* k); - bool is_puxcpu(int* i, int* j, int* k); - bool is_pu2xc(int* i, int* j, int* k); - bool is_push3(int* i, int* j, int* k); - bool is_blkswap(int* i, int* j); - bool is_blkpush(int* i, int* j); - bool is_blkdrop(int* i); - bool is_blkdrop2(int* i, int* j); - bool is_reverse(int* i, int* j); - bool is_nip_seq(int* i, int* j); - bool is_pop_blkdrop(int* i, int* k); - bool is_2pop_blkdrop(int* i, int* j, int* k); - AsmOpConsList extract_code(); -}; - -AsmOpConsList optimize_code_head(AsmOpConsList op_list, int mode = 0); -AsmOpConsList optimize_code(AsmOpConsList op_list, int mode); -void optimize_code(AsmOpList& ops); - -struct Stack { - StackLayoutExt s; - AsmOpList& o; - enum { _StkCmt = 1, _CptStkCmt = 2, _DisableOpt = 4, _DisableOut = 128, _Shown = 256, _Garbage = -0x10000 }; - int mode; - Stack(AsmOpList& _o, int _mode = 0) : o(_o), mode(_mode) { - } - Stack(AsmOpList& _o, const StackLayoutExt& _s, int _mode = 0) : s(_s), o(_o), mode(_mode) { - } - Stack(AsmOpList& _o, StackLayoutExt&& _s, int _mode = 0) : s(std::move(_s)), o(_o), mode(_mode) { - } - int depth() const { - return (int)s.size(); - } - var_idx_t operator[](int i) const { - validate(i); - return s[depth() - i - 1].first; - } - var_const_idx_t& at(int i) { - validate(i); - return s[depth() - i - 1]; - } - var_const_idx_t at(int i) const { - validate(i); - return s[depth() - i - 1]; - } - var_const_idx_t get(int i) const { - return at(i); - } - bool output_disabled() const { - return mode & _DisableOut; - } - bool output_enabled() const { - return !output_disabled(); - } - void disable_output() { - mode |= _DisableOut; - } - StackLayout vars() const; - int find(var_idx_t var, int from = 0) const; - int find(var_idx_t var, int from, int to) const; - int find_const(const_idx_t cst, int from = 0) const; - int find_outside(var_idx_t var, int from, int to) const; - void forget_const(); - void validate(int i) const { - assert(i >= 0 && i < depth() && "invalid stack reference"); - } - void modified() { - mode &= ~_Shown; - } - void issue_pop(int i); - void issue_push(int i); - void issue_xchg(int i, int j); - int drop_vars_except(const VarDescrList& var_info, int excl_var = 0x80000000); - void forget_var(var_idx_t idx); - void push_new_var(var_idx_t idx); - void push_new_const(var_idx_t idx, const_idx_t cidx); - void assign_var(var_idx_t new_idx, var_idx_t old_idx); - void do_copy_var(var_idx_t new_idx, var_idx_t old_idx); - void enforce_state(const StackLayout& req_stack); - void rearrange_top(const StackLayout& top, std::vector last); - void rearrange_top(var_idx_t top, bool last); - void merge_const(const Stack& req_stack); - void merge_state(const Stack& req_stack); - void show(int _mode); - void show() { - show(mode); - } - void opt_show() { - if ((mode & (_StkCmt | _Shown)) == _StkCmt) { - show(mode); - } - } - bool operator==(const Stack& y) const & { - return s == y.s; - } -}; - -/* - * - * SPECIFIC SYMBOL VALUES, - * BUILT-IN FUNCTIONS AND OPERATIONS - * - */ - -typedef std::function&, std::vector&)> simple_compile_func_t; -typedef std::function&, std::vector&)> compile_func_t; - -inline simple_compile_func_t make_simple_compile(AsmOp op) { - return [op](std::vector& out, std::vector& in) -> AsmOp { return op; }; -} - -inline compile_func_t make_ext_compile(std::vector ops) { - return [ops = std::move(ops)](AsmOpList & dest, std::vector & out, std::vector & in)->bool { - return dest.append(ops); - }; -} - -inline compile_func_t make_ext_compile(AsmOp op) { - return - [op](AsmOpList& dest, std::vector& out, std::vector& in) -> bool { return dest.append(op); }; -} - -struct SymValAsmFunc : SymValFunc { - simple_compile_func_t simple_compile; - compile_func_t ext_compile; - ~SymValAsmFunc() override = default; - SymValAsmFunc(TypeExpr* ft, const AsmOp& _macro, bool impure = false) - : SymValFunc(-1, ft, impure), simple_compile(make_simple_compile(_macro)) { - } - SymValAsmFunc(TypeExpr* ft, std::vector _macro, bool impure = false) - : SymValFunc(-1, ft, impure), ext_compile(make_ext_compile(std::move(_macro))) { - } - SymValAsmFunc(TypeExpr* ft, simple_compile_func_t _compile, bool impure = false) - : SymValFunc(-1, ft, impure), simple_compile(std::move(_compile)) { - } - SymValAsmFunc(TypeExpr* ft, compile_func_t _compile, bool impure = false) - : SymValFunc(-1, ft, impure), ext_compile(std::move(_compile)) { - } - SymValAsmFunc(TypeExpr* ft, simple_compile_func_t _compile, std::initializer_list arg_order, - std::initializer_list ret_order = {}, bool impure = false) - : SymValFunc(-1, ft, arg_order, ret_order, impure), simple_compile(std::move(_compile)) { - } - SymValAsmFunc(TypeExpr* ft, compile_func_t _compile, std::initializer_list arg_order, - std::initializer_list ret_order = {}, bool impure = false) - : SymValFunc(-1, ft, arg_order, ret_order, impure), ext_compile(std::move(_compile)) { - } - bool compile(AsmOpList& dest, std::vector& out, std::vector& in) const; -}; - -// defined in builtins.cpp -AsmOp exec_arg_op(std::string op, long long arg); -AsmOp exec_arg_op(std::string op, long long arg, int args, int retv = 1); -AsmOp exec_arg_op(std::string op, td::RefInt256 arg); -AsmOp exec_arg_op(std::string op, td::RefInt256 arg, int args, int retv = 1); -AsmOp exec_arg2_op(std::string op, long long imm1, long long imm2, int args, int retv = 1); -AsmOp push_const(td::RefInt256 x); - -void define_builtins(); - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp b/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp deleted file mode 100644 index c0a8985a..00000000 --- a/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -using namespace std::literals::string_literals; - -namespace funC { - -/* - * - * EXPRESSIONS - * - */ - -Expr* Expr::copy() const { - auto res = new Expr{*this}; - for (auto& arg : res->args) { - arg = arg->copy(); - } - return res; -} - -Expr::Expr(int c, sym_idx_t name_idx, std::initializer_list _arglist) : cls(c), args(std::move(_arglist)) { - sym = sym::lookup_symbol(name_idx); - if (!sym) { - } -} - -void Expr::chk_rvalue(const Lexem& lem) const { - if (!is_rvalue()) { - lem.error_at("rvalue expected before `", "`"); - } -} - -void Expr::chk_lvalue(const Lexem& lem) const { - if (!is_lvalue()) { - lem.error_at("lvalue expected before `", "`"); - } -} - -void Expr::chk_type(const Lexem& lem) const { - if (!is_type()) { - lem.error_at("type expression expected before `", "`"); - } -} - -bool Expr::deduce_type(const Lexem& lem) { - if (e_type) { - return true; - } - switch (cls) { - case _Apply: { - if (!sym) { - return false; - } - SymVal* sym_val = dynamic_cast(sym->value); - if (!sym_val || !sym_val->get_type()) { - return false; - } - std::vector arg_types; - for (const auto& arg : args) { - arg_types.push_back(arg->e_type); - } - TypeExpr* fun_type = TypeExpr::new_map(TypeExpr::new_tensor(arg_types), TypeExpr::new_hole()); - try { - unify(fun_type, sym_val->sym_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot apply function " << sym->name() << " : " << sym_val->get_type() << " to arguments of type " - << fun_type->args[0] << ": " << ue; - lem.error(os.str()); - } - e_type = fun_type->args[1]; - TypeExpr::remove_indirect(e_type); - return true; - } - case _VarApply: { - assert(args.size() == 2); - TypeExpr* fun_type = TypeExpr::new_map(args[1]->e_type, TypeExpr::new_hole()); - try { - unify(fun_type, args[0]->e_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot apply expression of type " << args[0]->e_type << " to an expression of type " << args[1]->e_type - << ": " << ue; - lem.error(os.str()); - } - e_type = fun_type->args[1]; - TypeExpr::remove_indirect(e_type); - return true; - } - case _Letop: { - assert(args.size() == 2); - try { - // std::cerr << "in assignment: " << args[0]->e_type << " from " << args[1]->e_type << std::endl; - unify(args[0]->e_type, args[1]->e_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot assign an expression of type " << args[1]->e_type << " to a variable or pattern of type " - << args[0]->e_type << ": " << ue; - lem.error(os.str()); - } - e_type = args[0]->e_type; - TypeExpr::remove_indirect(e_type); - return true; - } - case _LetFirst: { - assert(args.size() == 2); - TypeExpr* rhs_type = TypeExpr::new_tensor({args[0]->e_type, TypeExpr::new_hole()}); - try { - // std::cerr << "in implicit assignment of a modifying method: " << rhs_type << " and " << args[1]->e_type << std::endl; - unify(rhs_type, args[1]->e_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot implicitly assign an expression of type " << args[1]->e_type - << " to a variable or pattern of type " << rhs_type << " in modifying method `" << sym::symbols.get_name(val) - << "` : " << ue; - lem.error(os.str()); - } - e_type = rhs_type->args[1]; - TypeExpr::remove_indirect(e_type); - // std::cerr << "result type is " << e_type << std::endl; - return true; - } - case _CondExpr: { - assert(args.size() == 3); - auto flag_type = TypeExpr::new_atomic(_Int); - try { - unify(args[0]->e_type, flag_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "condition in a conditional expression has non-integer type " << args[0]->e_type << ": " << ue; - lem.error(os.str()); - } - try { - unify(args[1]->e_type, args[2]->e_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "the two variants in a conditional expression have different types " << args[1]->e_type << " and " - << args[2]->e_type << " : " << ue; - lem.error(os.str()); - } - e_type = args[1]->e_type; - TypeExpr::remove_indirect(e_type); - return true; - } - } - return false; -} - -int Expr::define_new_vars(CodeBlob& code) { - switch (cls) { - case _Tensor: - case _MkTuple: - case _TypeApply: { - int res = 0; - for (const auto& x : args) { - res += x->define_new_vars(code); - } - return res; - } - case _Var: - if (val < 0) { - val = code.create_var(TmpVar::_Named, e_type, sym, &here); - return 1; - } - break; - case _Hole: - if (val < 0) { - val = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - } - break; - } - return 0; -} - -int Expr::predefine_vars() { - switch (cls) { - case _Tensor: - case _MkTuple: - case _TypeApply: { - int res = 0; - for (const auto& x : args) { - res += x->predefine_vars(); - } - return res; - } - case _Var: - if (!sym) { - assert(val < 0 && here.defined()); - sym = sym::define_symbol(~val, false, here); - // std::cerr << "predefining variable " << sym::symbols.get_name(~val) << std::endl; - if (!sym) { - throw src::ParseError{here, std::string{"redefined variable `"} + sym::symbols.get_name(~val) + "`"}; - } - sym->value = new SymVal{SymVal::_Var, -1, e_type}; - return 1; - } - break; - } - return 0; -} - -var_idx_t Expr::new_tmp(CodeBlob& code) const { - return code.create_tmp_var(e_type, &here); -} - -std::vector Expr::pre_compile_let(CodeBlob& code, Expr* lhs, Expr* rhs, const SrcLocation& here) { - while (lhs->is_type_apply()) { - lhs = lhs->args.at(0); - } - while (rhs->is_type_apply()) { - rhs = rhs->args.at(0); - } - if (lhs->is_mktuple()) { - if (rhs->is_mktuple()) { - return pre_compile_let(code, lhs->args.at(0), rhs->args.at(0), here); - } - auto right = rhs->pre_compile(code); - TypeExpr::remove_indirect(rhs->e_type); - auto unpacked_type = rhs->e_type->args.at(0); - std::vector tmp{code.create_tmp_var(unpacked_type, &rhs->here)}; - code.emplace_back(lhs->here, Op::_UnTuple, tmp, std::move(right)); - auto tvar = new Expr{_Var}; - tvar->set_val(tmp[0]); - tvar->set_location(rhs->here); - tvar->e_type = unpacked_type; - pre_compile_let(code, lhs->args.at(0), tvar, here); - return tmp; - } - auto right = rhs->pre_compile(code); - if (lhs->cls == Expr::_GlobVar) { - assert(lhs->sym); - auto& op = code.emplace_back(here, Op::_SetGlob, std::vector{}, right, lhs->sym); - op.flags |= Op::_Impure; - } else { - auto left = lhs->pre_compile(code, true); - code.emplace_back(here, Op::_Let, std::move(left), right); - } - return right; -} - -std::vector Expr::pre_compile(CodeBlob& code, bool lval) const { - if (lval && !(cls == _Tensor || cls == _Var || cls == _Hole || cls == _TypeApply)) { - std::cerr << "lvalue expression constructor is " << cls << std::endl; - throw src::Fatal{"cannot compile lvalue expression with unknown constructor"}; - } - switch (cls) { - case _Tensor: { - std::vector res; - for (const auto& x : args) { - auto add = x->pre_compile(code, lval); - res.insert(res.end(), add.cbegin(), add.cend()); - } - return res; - } - case _Apply: { - assert(sym); - std::vector res; - auto func = dynamic_cast(sym->value); - if (func && func->arg_order.size() == args.size()) { - //std::cerr << "!!! reordering " << args.size() << " arguments of " << sym->name() << std::endl; - std::vector> add_list(args.size()); - for (int i : func->arg_order) { - add_list[i] = args[i]->pre_compile(code); - } - for (const auto& add : add_list) { - res.insert(res.end(), add.cbegin(), add.cend()); - } - } else { - for (const auto& x : args) { - auto add = x->pre_compile(code); - res.insert(res.end(), add.cbegin(), add.cend()); - } - } - auto rvect = new_tmp_vect(code); - auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym); - if (flags & _IsImpure) { - op.flags |= Op::_Impure; - } - return rvect; - } - case _TypeApply: - return args[0]->pre_compile(code, lval); - case _Var: - case _Hole: - return {val}; - case _VarApply: - if (args[0]->cls == _Glob) { - auto res = args[1]->pre_compile(code); - auto rvect = new_tmp_vect(code); - auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), args[0]->sym); - if (args[0]->flags & _IsImpure) { - op.flags |= Op::_Impure; - } - return rvect; - } else { - auto res = args[1]->pre_compile(code); - auto tfunc = args[0]->pre_compile(code); - if (tfunc.size() != 1) { - throw src::Fatal{"stack tuple used as a function"}; - } - res.push_back(tfunc[0]); - auto rvect = new_tmp_vect(code); - code.emplace_back(here, Op::_CallInd, rvect, std::move(res)); - return rvect; - } - case _Const: { - auto rvect = new_tmp_vect(code); - code.emplace_back(here, Op::_IntConst, rvect, intval); - return rvect; - } - case _Glob: - case _GlobVar: { - auto rvect = new_tmp_vect(code); - code.emplace_back(here, Op::_GlobVar, rvect, std::vector{}, sym); - return rvect; - } - case _Letop: { - return pre_compile_let(code, args.at(0), args.at(1), here); - } - case _LetFirst: { - auto rvect = new_tmp_vect(code); - auto right = args[1]->pre_compile(code); - auto left = args[0]->pre_compile(code, true); - left.push_back(rvect[0]); - code.emplace_back(here, Op::_Let, std::move(left), std::move(right)); - return rvect; - } - case _MkTuple: { - auto left = new_tmp_vect(code); - auto right = args[0]->pre_compile(code); - code.emplace_back(here, Op::_Tuple, left, std::move(right)); - return left; - } - case _CondExpr: { - auto cond = args[0]->pre_compile(code); - assert(cond.size() == 1); - auto rvect = new_tmp_vect(code); - Op& if_op = code.emplace_back(here, Op::_If, cond); - code.push_set_cur(if_op.block0); - code.emplace_back(here, Op::_Let, rvect, args[1]->pre_compile(code)); - code.close_pop_cur(args[1]->here); - code.push_set_cur(if_op.block1); - code.emplace_back(here, Op::_Let, rvect, args[2]->pre_compile(code)); - code.close_pop_cur(args[2]->here); - return rvect; - } - default: - std::cerr << "expression constructor is " << cls << std::endl; - throw src::Fatal{"cannot compile expression with unknown constructor"}; - } -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/keywords.cpp b/submodules/ton/tonlib-src/crypto/func/keywords.cpp deleted file mode 100644 index 47975e7f..00000000 --- a/submodules/ton/tonlib-src/crypto/func/keywords.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace src { - -int lexem_is_special(std::string str) { - return 0; // no special lexems -} - -} // namespace src - -namespace funC { - -/* - * - * KEYWORD DEFINITION - * - */ - -void define_keywords() { - sym::symbols.add_kw_char('+') - .add_kw_char('-') - .add_kw_char('*') - .add_kw_char('/') - .add_kw_char('%') - .add_kw_char('?') - .add_kw_char(':') - .add_kw_char(',') - .add_kw_char(';') - .add_kw_char('(') - .add_kw_char(')') - .add_kw_char('[') - .add_kw_char(']') - .add_kw_char('{') - .add_kw_char('}') - .add_kw_char('=') - .add_kw_char('_') - .add_kw_char('<') - .add_kw_char('>') - .add_kw_char('&') - .add_kw_char('|') - .add_kw_char('^') - .add_kw_char('~'); - - using Kw = funC::Keyword; - sym::symbols.add_keyword("==", Kw::_Eq) - .add_keyword("!=", Kw::_Neq) - .add_keyword("<=", Kw::_Leq) - .add_keyword(">=", Kw::_Geq) - .add_keyword("<=>", Kw::_Spaceship) - .add_keyword("<<", Kw::_Lshift) - .add_keyword(">>", Kw::_Rshift) - .add_keyword("~>>", Kw::_RshiftR) - .add_keyword("^>>", Kw::_RshiftC) - .add_keyword("~/", Kw::_DivR) - .add_keyword("^/", Kw::_DivC) - .add_keyword("~%", Kw::_ModR) - .add_keyword("^%", Kw::_ModC) - .add_keyword("/%", Kw::_DivMod) - .add_keyword("+=", Kw::_PlusLet) - .add_keyword("-=", Kw::_MinusLet) - .add_keyword("*=", Kw::_TimesLet) - .add_keyword("/=", Kw::_DivLet) - .add_keyword("~/=", Kw::_DivRLet) - .add_keyword("^/=", Kw::_DivCLet) - .add_keyword("%=", Kw::_ModLet) - .add_keyword("~%=", Kw::_ModRLet) - .add_keyword("^%=", Kw::_ModCLet) - .add_keyword("<<=", Kw::_LshiftLet) - .add_keyword(">>=", Kw::_RshiftLet) - .add_keyword("~>>=", Kw::_RshiftRLet) - .add_keyword("^>>=", Kw::_RshiftCLet) - .add_keyword("&=", Kw::_AndLet) - .add_keyword("|=", Kw::_OrLet) - .add_keyword("^=", Kw::_XorLet); - - sym::symbols.add_keyword("return", Kw::_Return) - .add_keyword("var", Kw::_Var) - .add_keyword("repeat", Kw::_Repeat) - .add_keyword("do", Kw::_Do) - .add_keyword("while", Kw::_While) - .add_keyword("until", Kw::_Until) - .add_keyword("if", Kw::_If) - .add_keyword("ifnot", Kw::_Ifnot) - .add_keyword("then", Kw::_Then) - .add_keyword("else", Kw::_Else) - .add_keyword("elseif", Kw::_Elseif) - .add_keyword("elseifnot", Kw::_Elseifnot); - - sym::symbols.add_keyword("int", Kw::_Int) - .add_keyword("cell", Kw::_Cell) - .add_keyword("slice", Kw::_Slice) - .add_keyword("builder", Kw::_Builder) - .add_keyword("cont", Kw::_Cont) - .add_keyword("tuple", Kw::_Tuple) - .add_keyword("type", Kw::_Type) - .add_keyword("->", Kw::_Mapsto) - .add_keyword("forall", Kw::_Forall); - - sym::symbols.add_keyword("extern", Kw::_Extern) - .add_keyword("global", Kw::_Global) - .add_keyword("asm", Kw::_Asm) - .add_keyword("impure", Kw::_Impure) - .add_keyword("inline", Kw::_Inline) - .add_keyword("inline_ref", Kw::_InlineRef) - .add_keyword("auto_apply", Kw::_AutoApply) - .add_keyword("method_id", Kw::_MethodId) - .add_keyword("operator", Kw::_Operator) - .add_keyword("infix", Kw::_Infix) - .add_keyword("infixl", Kw::_Infixl) - .add_keyword("infixr", Kw::_Infixr); -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/optimize.cpp b/submodules/ton/tonlib-src/crypto/func/optimize.cpp deleted file mode 100644 index f8dc3d82..00000000 --- a/submodules/ton/tonlib-src/crypto/func/optimize.cpp +++ /dev/null @@ -1,654 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * PEEPHOLE OPTIMIZER - * - */ - -void Optimizer::set_code(AsmOpConsList code) { - code_ = std::move(code); - unpack(); -} - -void Optimizer::unpack() { - int i = 0, j = 0; - for (AsmOpCons *p = code_.get(); p && i < n; p = p->cdr.get(), ++j) { - if (p->car->is_very_custom()) { - break; - } - if (p->car->is_comment()) { - continue; - } - op_cons_[i] = p; - op_[i] = std::move(p->car); - offs_[i] = j; - ++i; - } - l_ = i; - indent_ = (i ? op_[0]->indent : 0); -} - -void Optimizer::pack() { - for (int i = 0; i < l_; i++) { - op_cons_[i]->car = std::move(op_[i]); - op_cons_[i] = nullptr; - } - l_ = 0; -} - -void Optimizer::apply() { - if (!p_ && !q_) { - return; - } - assert(p_ > 0 && p_ <= l_ && q_ >= 0 && q_ <= n && l_ <= n); - for (int i = p_; i < l_; i++) { - assert(op_[i]); - op_cons_[i]->car = std::move(op_[i]); - op_cons_[i] = nullptr; - } - for (int c = offs_[p_ - 1]; c >= 0; --c) { - code_ = std::move(code_->cdr); - } - for (int j = q_ - 1; j >= 0; j--) { - assert(oq_[j]); - oq_[j]->indent = indent_; - code_ = AsmOpCons::cons(std::move(oq_[j]), std::move(code_)); - } - l_ = 0; -} - -AsmOpConsList Optimizer::extract_code() { - pack(); - return std::move(code_); -} - -void Optimizer::show_head() const { - if (!debug_) { - return; - } - std::cerr << "optimizing"; - for (int i = 0; i < l_; i++) { - if (op_[i]) { - std::cerr << ' ' << *op_[i] << ' '; - } else { - std::cerr << " (null) "; - } - } - std::cerr << std::endl; -} - -void Optimizer::show_left() const { - if (!debug_) { - return; - } - std::cerr << "// *** rewriting"; - for (int i = 0; i < p_; i++) { - if (op_[i]) { - std::cerr << ' ' << *op_[i] << ' '; - } else { - std::cerr << " (null) "; - } - } -} - -void Optimizer::show_right() const { - if (!debug_) { - return; - } - std::cerr << "->"; - for (int i = 0; i < q_; i++) { - if (oq_[i]) { - std::cerr << ' ' << *oq_[i] << ' '; - } else { - std::cerr << " (null) "; - } - } - std::cerr << std::endl; -} - -bool Optimizer::say(std::string str) const { - if (debug_) { - std::cerr << str << std::endl; - } - return true; -} - -bool Optimizer::find_const_op(int* op_idx, int cst) { - for (int i = 0; i < l2_; i++) { - if (op_[i]->is_gconst() && tr_[i].get(0) == cst) { - *op_idx = i; - return true; - } - } - return false; -} - -bool Optimizer::is_push_const(int* i, int* c) const { - return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_push_const(i, c); -} - -// PUSHCONST c ; PUSH s(i+1) ; SWAP -> PUSH s(i) ; PUSHCONST c -bool Optimizer::rewrite_push_const(int i, int c) { - p_ = pb_; - q_ = 2; - int idx = -1; - if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) { - return false; - } - show_left(); - oq_[1] = std::move(op_[idx]); - oq_[0] = std::move(op_[!idx]); - *oq_[0] = AsmOp::Push(i); - show_right(); - return true; -} - -bool Optimizer::is_const_rot(int* c) const { - return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_const_rot(c); -} - -bool Optimizer::rewrite_const_rot(int c) { - p_ = pb_; - q_ = 2; - int idx = -1; - if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) { - return false; - } - show_left(); - oq_[0] = std::move(op_[idx]); - oq_[1] = std::move(op_[!idx]); - *oq_[1] = AsmOp::Custom("ROT", 3, 3); - show_right(); - return true; -} - -bool Optimizer::is_const_pop(int* c, int* i) const { - return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_const_pop(c, i); -} - -bool Optimizer::rewrite_const_pop(int c, int i) { - p_ = pb_; - q_ = 2; - int idx = -1; - if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) { - return false; - } - show_left(); - oq_[0] = std::move(op_[idx]); - oq_[1] = std::move(op_[!idx]); - *oq_[1] = AsmOp::Pop(i); - show_right(); - return true; -} - -bool Optimizer::is_const_push_xchgs() { - if (!(pb_ >= 2 && pb_ <= l2_ && op_[0]->is_gconst())) { - return false; - } - StackTransform t; - int pos = 0, i; - for (i = 1; i < pb_; i++) { - int a, b; - if (op_[i]->is_xchg(&a, &b)) { - if (pos == a) { - pos = b; - } else if (pos == b) { - pos = a; - } else { - t.apply_xchg(a - (a > pos), b - (b > pos)); - } - } else if (op_[i]->is_push(&a)) { - if (pos == a) { - return false; - } - t.apply_push(a - (a > pos)); - ++pos; - } else { - return false; - } - } - if (pos) { - return false; - } - t.apply_push_newconst(); - if (t <= tr_[i - 1]) { - p_ = i; - return true; - } else { - return false; - } -} - -bool Optimizer::rewrite_const_push_xchgs() { - if (!p_) { - return false; - } - show_left(); - auto c_op = std::move(op_[0]); - assert(c_op->is_gconst()); - StackTransform t; - q_ = 0; - int pos = 0; - for (int i = 1; i < p_; i++) { - int a, b; - if (op_[i]->is_xchg(&a, &b)) { - if (a == pos) { - pos = b; - } else if (b == pos) { - pos = a; - } else { - oq_[q_] = std::move(op_[i]); - if (a > pos) { - oq_[q_]->a = a - 1; - } - if (b > pos) { - oq_[q_]->b = b - 1; - } - assert(apply_op(t, *oq_[q_])); - ++q_; - } - } else { - assert(op_[i]->is_push(&a)); - assert(a != pos); - oq_[q_] = std::move(op_[i]); - if (a > pos) { - oq_[q_]->a = a - 1; - } - assert(apply_op(t, *oq_[q_])); - ++q_; - ++pos; - } - } - assert(!pos); - t.apply_push_newconst(); - assert(t <= tr_[p_ - 1]); - oq_[q_++] = std::move(c_op); - show_right(); - return true; -} - -bool Optimizer::rewrite(int p, AsmOp&& new_op) { - assert(p > 0 && p <= l_); - p_ = p; - q_ = 1; - show_left(); - oq_[0] = std::move(op_[0]); - *oq_[0] = new_op; - show_right(); - return true; -} - -bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) { - assert(p > 1 && p <= l_); - p_ = p; - q_ = 2; - show_left(); - oq_[0] = std::move(op_[0]); - *oq_[0] = new_op1; - oq_[1] = std::move(op_[1]); - *oq_[1] = new_op2; - show_right(); - return true; -} - -bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3) { - assert(p > 2 && p <= l_); - p_ = p; - q_ = 3; - show_left(); - oq_[0] = std::move(op_[0]); - *oq_[0] = new_op1; - oq_[1] = std::move(op_[1]); - *oq_[1] = new_op2; - oq_[2] = std::move(op_[2]); - *oq_[2] = new_op3; - show_right(); - return true; -} - -bool Optimizer::rewrite_nop() { - assert(p_ > 0 && p_ <= l_); - q_ = 0; - show_left(); - show_right(); - return true; -} - -bool Optimizer::is_pred(const std::function& pred, int min_p) { - min_p = std::max(min_p, pb_); - for (int p = l2_; p >= min_p; p--) { - if (pred(tr_[p - 1])) { - p_ = p; - return true; - } - } - return false; -} - -bool Optimizer::is_same_as(const StackTransform& trans, int min_p) { - return is_pred([&trans](const auto& t) { return t >= trans; }, min_p); -} - -// s1 s3 XCHG ; s0 s2 XCHG -> 2SWAP -bool Optimizer::is_2swap() { - static const StackTransform t_2swap{2, 3, 0, 1, 4}; - return is_same_as(t_2swap); -} - -// s3 PUSH ; s3 PUSH -> 2OVER -bool Optimizer::is_2over() { - static const StackTransform t_2over{2, 3, 0}; - return is_same_as(t_2over); -} - -bool Optimizer::is_2dup() { - static const StackTransform t_2dup{0, 1, 0}; - return is_same_as(t_2dup); -} - -bool Optimizer::is_tuck() { - static const StackTransform t_tuck{0, 1, 0, 2}; - return is_same_as(t_tuck); -} - -bool Optimizer::is_2drop() { - static const StackTransform t_2drop{2}; - return is_same_as(t_2drop); -} - -bool Optimizer::is_rot() { - return is_pred([](const auto& t) { return t.is_rot(); }); -} - -bool Optimizer::is_rotrev() { - return is_pred([](const auto& t) { return t.is_rotrev(); }); -} - -bool Optimizer::is_nop() { - return is_pred([](const auto& t) { return t.is_id(); }, 1); -} - -bool Optimizer::is_xchg(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_xchg(i, j) && ((*i < 16 && *j < 16) || (!*i && *j < 256)); }); -} - -bool Optimizer::is_xchg_xchg(int* i, int* j, int* k, int* l) { - return is_pred([i, j, k, l](const auto& t) { - return t.is_xchg_xchg(i, j, k, l) && (*i < 2 && *j < (*i ? 16 : 256) && *k < 2 && *l < (*k ? 16 : 256)); - }) && - (!(p_ == 2 && op_[0]->is_xchg(*i, *j) && op_[1]->is_xchg(*k, *l))); -} - -bool Optimizer::is_push(int* i) { - return is_pred([i](const auto& t) { return t.is_push(i) && *i < 256; }); -} - -bool Optimizer::is_pop(int* i) { - return is_pred([i](const auto& t) { return t.is_pop(i) && *i < 256; }); -} - -bool Optimizer::is_pop_pop(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_pop_pop(i, j) && *i < 256 && *j < 256; }, 3); -} - -bool Optimizer::is_push_rot(int* i) { - return is_pred([i](const auto& t) { return t.is_push_rot(i) && *i < 16; }, 3); -} - -bool Optimizer::is_push_rotrev(int* i) { - return is_pred([i](const auto& t) { return t.is_push_rotrev(i) && *i < 16; }, 3); -} - -bool Optimizer::is_push_xchg(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_push_xchg(i, j, k) && *i < 16 && *j < 16 && *k < 16; }) && - !(p_ == 2 && op_[0]->is_push() && op_[1]->is_xchg()); -} - -bool Optimizer::is_xchg2(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_xchg2(i, j) && *i < 16 && *j < 16; }); -} - -bool Optimizer::is_xcpu(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_xcpu(i, j) && *i < 16 && *j < 16; }); -} - -bool Optimizer::is_puxc(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_puxc(i, j) && *i < 16 && *j < 15; }); -} - -bool Optimizer::is_push2(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_push2(i, j) && *i < 16 && *j < 16; }); -} - -bool Optimizer::is_xchg3(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_xchg3(i, j, k) && *i < 16 && *j < 16 && *k < 16; }); -} - -bool Optimizer::is_xc2pu(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_xc2pu(i, j, k) && *i < 16 && *j < 16 && *k < 16; }); -} - -bool Optimizer::is_xcpuxc(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_xcpuxc(i, j, k) && *i < 16 && *j < 16 && *k < 15; }); -} - -bool Optimizer::is_xcpu2(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_xcpu2(i, j, k) && *i < 16 && *j < 16 && *k < 16; }); -} - -bool Optimizer::is_puxc2(int* i, int* j, int* k) { - return is_pred( - [i, j, k](const auto& t) { return t.is_puxc2(i, j, k) && *i < 16 && *j < 15 && *k < 15 && *j + *k != -1; }); -} - -bool Optimizer::is_puxcpu(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_puxcpu(i, j, k) && *i < 16 && *j < 15 && *k < 15; }); -} - -bool Optimizer::is_pu2xc(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_pu2xc(i, j, k) && *i < 16 && *j < 15 && *k < 14; }); -} - -bool Optimizer::is_push3(int* i, int* j, int* k) { - return is_pred([i, j, k](const auto& t) { return t.is_push3(i, j, k) && *i < 16 && *j < 16 && *k < 16; }); -} - -bool Optimizer::is_blkswap(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_blkswap(i, j) && *i > 0 && *j > 0 && *i <= 16 && *j <= 16; }); -} - -bool Optimizer::is_blkpush(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_blkpush(i, j) && *i > 0 && *i < 16 && *j < 16; }); -} - -bool Optimizer::is_blkdrop(int* i) { - return is_pred([i](const auto& t) { return t.is_blkdrop(i) && *i > 0 && *i < 16; }); -} - -bool Optimizer::is_blkdrop2(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_blkdrop2(i, j) && *i > 0 && *i < 16 && *j > 0 && *j < 16; }); -} - -bool Optimizer::is_reverse(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_reverse(i, j) && *i >= 2 && *i <= 17 && *j < 16; }); -} - -bool Optimizer::is_nip_seq(int* i, int* j) { - return is_pred([i, j](const auto& t) { return t.is_nip_seq(i, j) && *i >= 3 && *i <= 15; }); -} - -bool Optimizer::is_pop_blkdrop(int* i, int* k) { - return is_pred([i, k](const auto& t) { return t.is_pop_blkdrop(i, k) && *i >= *k && *k >= 2 && *k <= 15; }, 3); -} - -bool Optimizer::is_2pop_blkdrop(int* i, int* j, int* k) { - return is_pred( - [i, j, k](const auto& t) { return t.is_2pop_blkdrop(i, j, k) && *i >= *k && *j >= *k && *k >= 2 && *k <= 15; }, - 3); -} - -bool Optimizer::compute_stack_transforms() { - StackTransform trans; - for (int i = 0; i < l_; i++) { - if (!apply_op(trans, *op_[i])) { - l2_ = i; - return true; - } - tr_[i] = trans; - } - l2_ = l_; - return true; -} - -bool Optimizer::show_stack_transforms() const { - show_head(); - // slow version - /* - StackTransform trans2; - std::cerr << "id = " << trans2 << std::endl; - for (int i = 0; i < l_; i++) { - StackTransform op; - if (!apply_op(op, *op_[i])) { - std::cerr << "* (" << *op_[i] << " = invalid)\n"; - break; - } - trans2 *= op; - std::cerr << "* " << *op_[i] << " = " << op << " -> " << trans2 << std::endl; - } - */ - // fast version - StackTransform trans; - for (int i = 0; i < l_; i++) { - std::cerr << trans << std::endl << *op_[i] << " -> "; - if (!apply_op(trans, *op_[i])) { - std::cerr << " " << std::endl; - return true; - } - } - std::cerr << trans << std::endl; - return true; -} - -bool Optimizer::find_at_least(int pb) { - p_ = q_ = 0; - pb_ = pb; - // show_stack_transforms(); - int i, j, k, l, c; - return (is_push_const(&i, &c) && rewrite_push_const(i, c)) || (is_nop() && rewrite_nop()) || - (!(mode_ & 1) && is_const_rot(&c) && rewrite_const_rot(c)) || - (is_const_push_xchgs() && rewrite_const_push_xchgs()) || (is_const_pop(&c, &i) && rewrite_const_pop(c, i)) || - (is_xchg(&i, &j) && rewrite(AsmOp::Xchg(i, j))) || (is_push(&i) && rewrite(AsmOp::Push(i))) || - (is_pop(&i) && rewrite(AsmOp::Pop(i))) || (is_pop_pop(&i, &j) && rewrite(AsmOp::Pop(i), AsmOp::Pop(j))) || - (is_xchg_xchg(&i, &j, &k, &l) && rewrite(AsmOp::Xchg(i, j), AsmOp::Xchg(k, l))) || - (!(mode_ & 1) && - ((is_rot() && rewrite(AsmOp::Custom("ROT", 3, 3))) || (is_rotrev() && rewrite(AsmOp::Custom("-ROT", 3, 3))) || - (is_2dup() && rewrite(AsmOp::Custom("2DUP", 2, 4))) || - (is_2swap() && rewrite(AsmOp::Custom("2SWAP", 2, 4))) || - (is_2over() && rewrite(AsmOp::Custom("2OVER", 2, 4))) || - (is_tuck() && rewrite(AsmOp::Custom("TUCK", 2, 3))) || - (is_2drop() && rewrite(AsmOp::Custom("2DROP", 2, 0))) || (is_xchg2(&i, &j) && rewrite(AsmOp::Xchg2(i, j))) || - (is_xcpu(&i, &j) && rewrite(AsmOp::XcPu(i, j))) || (is_puxc(&i, &j) && rewrite(AsmOp::PuXc(i, j))) || - (is_push2(&i, &j) && rewrite(AsmOp::Push2(i, j))) || (is_blkswap(&i, &j) && rewrite(AsmOp::BlkSwap(i, j))) || - (is_blkpush(&i, &j) && rewrite(AsmOp::BlkPush(i, j))) || (is_blkdrop(&i) && rewrite(AsmOp::BlkDrop(i))) || - (is_push_rot(&i) && rewrite(AsmOp::Push(i), AsmOp::Custom("ROT"))) || - (is_push_rotrev(&i) && rewrite(AsmOp::Push(i), AsmOp::Custom("-ROT"))) || - (is_push_xchg(&i, &j, &k) && rewrite(AsmOp::Push(i), AsmOp::Xchg(j, k))) || - (is_reverse(&i, &j) && rewrite(AsmOp::BlkReverse(i, j))) || - (is_blkdrop2(&i, &j) && rewrite(AsmOp::BlkDrop2(i, j))) || - (is_nip_seq(&i, &j) && rewrite(AsmOp::Xchg(i, j), AsmOp::BlkDrop(i))) || - (is_pop_blkdrop(&i, &k) && rewrite(AsmOp::Pop(i), AsmOp::BlkDrop(k))) || - (is_2pop_blkdrop(&i, &j, &k) && (k >= 3 && k <= 13 && i != j + 1 && i <= 15 && j <= 14 - ? rewrite(AsmOp::Xchg2(j + 1, i), AsmOp::BlkDrop(k + 2)) - : rewrite(AsmOp::Pop(i), AsmOp::Pop(j), AsmOp::BlkDrop(k)))) || - (is_xchg3(&i, &j, &k) && rewrite(AsmOp::Xchg3(i, j, k))) || - (is_xc2pu(&i, &j, &k) && rewrite(AsmOp::Xc2Pu(i, j, k))) || - (is_xcpuxc(&i, &j, &k) && rewrite(AsmOp::XcPuXc(i, j, k))) || - (is_xcpu2(&i, &j, &k) && rewrite(AsmOp::XcPu2(i, j, k))) || - (is_puxc2(&i, &j, &k) && rewrite(AsmOp::PuXc2(i, j, k))) || - (is_puxcpu(&i, &j, &k) && rewrite(AsmOp::PuXcPu(i, j, k))) || - (is_pu2xc(&i, &j, &k) && rewrite(AsmOp::Pu2Xc(i, j, k))) || - (is_push3(&i, &j, &k) && rewrite(AsmOp::Push3(i, j, k))))); -} - -bool Optimizer::find() { - if (!compute_stack_transforms()) { - return false; - } - for (int pb = l_; pb > 0; --pb) { - if (find_at_least(pb)) { - return true; - } - } - return false; -} - -bool Optimizer::optimize() { - bool f = false; - while (find()) { - f = true; - apply(); - unpack(); - } - return f; -} - -AsmOpConsList optimize_code_head(AsmOpConsList op_list, int mode) { - Optimizer opt(std::move(op_list), op_rewrite_comments, mode); - opt.optimize(); - return opt.extract_code(); -} - -AsmOpConsList optimize_code(AsmOpConsList op_list, int mode) { - std::vector> v; - while (op_list) { - if (!op_list->car->is_comment()) { - op_list = optimize_code_head(std::move(op_list), mode); - } - if (op_list) { - v.push_back(std::move(op_list->car)); - op_list = std::move(op_list->cdr); - } - } - for (auto it = v.rbegin(); it < v.rend(); ++it) { - op_list = AsmOpCons::cons(std::move(*it), std::move(op_list)); - } - return std::move(op_list); -} - -void optimize_code(AsmOpList& ops) { - AsmOpConsList op_list; - for (auto it = ops.list_.rbegin(); it < ops.list_.rend(); ++it) { - op_list = AsmOpCons::cons(std::make_unique(std::move(*it)), std::move(op_list)); - } - for (int mode : {1, 1, 1, 1, 0, 0, 0, 0}) { - op_list = optimize_code(std::move(op_list), mode); - } - ops.list_.clear(); - while (op_list) { - ops.list_.push_back(std::move(*(op_list->car))); - op_list = std::move(op_list->cdr); - } -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/parse-func.cpp b/submodules/ton/tonlib-src/crypto/func/parse-func.cpp deleted file mode 100644 index 3aad90ef..00000000 --- a/submodules/ton/tonlib-src/crypto/func/parse-func.cpp +++ /dev/null @@ -1,1325 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" -#include "td/utils/crypto.h" -#include "common/refint.h" -#include - -namespace sym { - -int compute_symbol_subclass(std::string str) { - using funC::IdSc; - if (str.size() < 2) { - return IdSc::undef; - } else if (str[0] == '.') { - return IdSc::dotid; - } else if (str[0] == '~') { - return IdSc::tildeid; - } else { - return IdSc::undef; - } -} - -} // namespace sym - -namespace funC { -using namespace std::literals::string_literals; -using src::Lexer; -using sym::symbols; -using td::Ref; - -inline bool is_dot_ident(sym_idx_t idx) { - return symbols.get_subclass(idx) == IdSc::dotid; -} - -inline bool is_tilde_ident(sym_idx_t idx) { - return symbols.get_subclass(idx) == IdSc::tildeid; -} - -inline bool is_special_ident(sym_idx_t idx) { - return symbols.get_subclass(idx) != IdSc::undef; -} - -/* - * - * PARSE SOURCE - * - */ - -// TE ::= TA | TA -> TE -// TA ::= int | ... | cont | var | _ | () | ( TE { , TE } ) | [ TE { , TE } ] -TypeExpr* parse_type(Lexer& lex); - -TypeExpr* parse_type1(Lexer& lex) { - switch (lex.tp()) { - case _Int: - lex.next(); - return TypeExpr::new_atomic(_Int); - case _Cell: - lex.next(); - return TypeExpr::new_atomic(_Cell); - case _Slice: - lex.next(); - return TypeExpr::new_atomic(_Slice); - case _Builder: - lex.next(); - return TypeExpr::new_atomic(_Builder); - case _Cont: - lex.next(); - return TypeExpr::new_atomic(_Cont); - case _Tuple: - lex.next(); - return TypeExpr::new_atomic(_Tuple); - case _Var: - case '_': - lex.next(); - return TypeExpr::new_hole(); - case _Ident: { - auto sym = sym::lookup_symbol(lex.cur().val); - if (sym && dynamic_cast(sym->value)) { - auto val = dynamic_cast(sym->value); - lex.next(); - return val->get_type(); - } - lex.cur().error_at("`", "` is not a type identifier"); - } - } - int c; - if (lex.tp() == '[') { - lex.next(); - c = ']'; - } else { - lex.expect('('); - c = ')'; - } - if (lex.tp() == c) { - lex.next(); - return c == ')' ? TypeExpr::new_unit() : TypeExpr::new_tuple({}); - } - auto t1 = parse_type(lex); - if (lex.tp() == ')') { - lex.expect(c); - return t1; - } - std::vector tlist{1, t1}; - while (lex.tp() == ',') { - lex.next(); - tlist.push_back(parse_type(lex)); - } - lex.expect(c); - return c == ')' ? TypeExpr::new_tensor(std::move(tlist)) : TypeExpr::new_tuple(std::move(tlist)); -} - -TypeExpr* parse_type(Lexer& lex) { - auto res = parse_type1(lex); - if (lex.tp() == _Mapsto) { - lex.next(); - auto to = parse_type(lex); - return TypeExpr::new_map(res, to); - } else { - return res; - } -} - -FormalArg parse_formal_arg(Lexer& lex, int fa_idx) { - TypeExpr* arg_type = 0; - SrcLocation loc = lex.cur().loc; - if (lex.tp() == '_') { - lex.next(); - if (lex.tp() == ',' || lex.tp() == ')') { - return std::make_tuple(TypeExpr::new_hole(), (SymDef*)nullptr, loc); - } - arg_type = TypeExpr::new_hole(); - loc = lex.cur().loc; - } else if (lex.tp() != _Ident) { - arg_type = parse_type(lex); - } else { - auto sym = sym::lookup_symbol(lex.cur().val); - if (sym && dynamic_cast(sym->value)) { - auto val = dynamic_cast(sym->value); - lex.next(); - arg_type = val->get_type(); - } else { - arg_type = TypeExpr::new_hole(); - } - } - if (lex.tp() == '_' || lex.tp() == ',' || lex.tp() == ')') { - if (lex.tp() == '_') { - loc = lex.cur().loc; - lex.next(); - } - return std::make_tuple(arg_type, (SymDef*)nullptr, loc); - } - if (lex.tp() != _Ident) { - lex.expect(_Ident, "formal parameter name"); - } - loc = lex.cur().loc; - SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc); - if (!new_sym_def) { - lex.cur().error_at("cannot define symbol `", "`"); - } - if (new_sym_def->value) { - lex.cur().error_at("redefined formal parameter `", "`"); - } - new_sym_def->value = new SymVal{SymVal::_Param, fa_idx, arg_type}; - lex.next(); - return std::make_tuple(arg_type, new_sym_def, loc); -} - -void parse_global_var_decl(Lexer& lex) { - TypeExpr* var_type = 0; - SrcLocation loc = lex.cur().loc; - if (lex.tp() == '_') { - lex.next(); - var_type = TypeExpr::new_hole(); - loc = lex.cur().loc; - } else if (lex.tp() != _Ident) { - var_type = parse_type(lex); - } else { - auto sym = sym::lookup_symbol(lex.cur().val); - if (sym && dynamic_cast(sym->value)) { - auto val = dynamic_cast(sym->value); - lex.next(); - var_type = val->get_type(); - } else { - var_type = TypeExpr::new_hole(); - } - } - if (lex.tp() != _Ident) { - lex.expect(_Ident, "global variable name"); - } - loc = lex.cur().loc; - SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc); - if (!sym_def) { - lex.cur().error_at("cannot define global symbol `", "`"); - } - if (sym_def->value) { - auto val = dynamic_cast(sym_def->value); - if (!val) { - lex.cur().error_at("symbol `", "` cannot be redefined as a global variable"); - } - try { - unify(var_type, val->sym_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot unify new type " << var_type << " of global variable `" << sym_def->name() - << "` with its previous type " << val->sym_type << ": " << ue; - lex.cur().error(os.str()); - } - } else { - sym_def->value = new SymValGlobVar{glob_var_cnt++, var_type}; - glob_vars.push_back(sym_def); - } - lex.next(); -} - -FormalArgList parse_formal_args(Lexer& lex) { - FormalArgList args; - lex.expect('(', "formal argument list"); - if (lex.tp() == ')') { - lex.next(); - return args; - } - int fa_idx = 0; - args.push_back(parse_formal_arg(lex, fa_idx++)); - while (lex.tp() == ',') { - lex.next(); - args.push_back(parse_formal_arg(lex, fa_idx++)); - } - lex.expect(')'); - return args; -} - -TypeExpr* extract_total_arg_type(const FormalArgList& arg_list) { - if (arg_list.empty()) { - return TypeExpr::new_unit(); - } - if (arg_list.size() == 1) { - return std::get<0>(arg_list[0]); - } - std::vector type_list; - for (auto& x : arg_list) { - type_list.push_back(std::get<0>(x)); - } - return TypeExpr::new_tensor(std::move(type_list)); -} - -void parse_global_var_decls(Lexer& lex) { - lex.expect(_Global); - while (true) { - parse_global_var_decl(lex); - if (lex.tp() != ',') { - break; - } - lex.expect(','); - } - lex.expect(';'); -} - -SymValCodeFunc* make_new_glob_func(SymDef* func_sym, TypeExpr* func_type, bool impure = false) { - SymValCodeFunc* res = new SymValCodeFunc{glob_func_cnt, func_type, impure}; - func_sym->value = res; - glob_func.push_back(func_sym); - glob_func_cnt++; - return res; -} - -bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) { - if (!func_name) { - func_name = cur.val; - } - SymDef* def = sym::lookup_symbol(func_name); - if (!def) { - cur.loc.show_error(std::string{"undefined function `"} + symbols.get_name(func_name) + - "`, defining a global function of unknown type"); - def = sym::define_global_symbol(func_name, 0, cur.loc); - assert(def && "cannot define global function"); - ++undef_func_cnt; - make_new_glob_func(def, TypeExpr::new_hole()); // was: ... ::new_func() - return true; - } - SymVal* val = dynamic_cast(def->value); - if (!val) { - cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no value and no type"); - return false; - } else if (!val->get_type()) { - cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no type, possibly not a function"); - return false; - } else { - return true; - } -} - -Expr* make_func_apply(Expr* fun, Expr* x) { - Expr* res; - if (fun->cls == Expr::_Glob) { - if (x->cls == Expr::_Tensor) { - res = new Expr{Expr::_Apply, fun->sym, x->args}; - } else { - res = new Expr{Expr::_Apply, fun->sym, {x}}; - } - res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure); - } else { - res = new Expr{Expr::_VarApply, {fun, x}}; - res->flags = Expr::_IsRvalue; - } - return res; -} - -Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv = false); - -// parse ( E { , E } ) | () | [ E { , E } ] | [] | id | num | _ -Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) { - if (lex.tp() == '(' || lex.tp() == '[') { - bool tf = (lex.tp() == '['); - int clbr = (tf ? ']' : ')'); - SrcLocation loc{lex.cur().loc}; - lex.next(); - if (lex.tp() == clbr) { - lex.next(); - Expr* res = new Expr{Expr::_Tensor, {}}; - res->flags = Expr::_IsRvalue; - res->here = loc; - res->e_type = TypeExpr::new_unit(); - if (tf) { - res = new Expr{Expr::_MkTuple, {res}}; - res->flags = Expr::_IsRvalue; - res->here = loc; - res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type); - } - return res; - } - Expr* res = parse_expr(lex, code, nv); - if (lex.tp() == ')') { - lex.expect(clbr); - return res; - } - std::vector type_list; - type_list.push_back(res->e_type); - int f = res->flags; - res = new Expr{Expr::_Tensor, {res}}; - while (lex.tp() == ',') { - lex.next(); - auto x = parse_expr(lex, code, nv); - res->pb_arg(x); - if ((f ^ x->flags) & Expr::_IsType) { - lex.cur().error("mixing type and non-type expressions inside the same tuple"); - } - f &= x->flags; - type_list.push_back(x->e_type); - } - res->here = loc; - res->flags = f; - res->e_type = TypeExpr::new_tensor(std::move(type_list), !tf); - if (tf) { - res = new Expr{Expr::_MkTuple, {res}}; - res->flags = f; - res->here = loc; - res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type); - } - lex.expect(clbr); - return res; - } - int t = lex.tp(); - if (t == Lexem::Number) { - Expr* res = new Expr{Expr::_Const, lex.cur().loc}; - res->flags = Expr::_IsRvalue; - res->intval = td::string_to_int256(lex.cur().str); - if (res->intval.is_null()) { - lex.cur().error_at("invalid integer constant `", "`"); - } - res->e_type = TypeExpr::new_atomic(_Int); - lex.next(); - return res; - } - if (t == '_') { - Expr* res = new Expr{Expr::_Hole, lex.cur().loc}; - res->val = -1; - res->flags = (Expr::_IsLvalue | Expr::_IsHole | Expr::_IsNewVar); - res->e_type = TypeExpr::new_hole(); - lex.next(); - return res; - } - if (t == _Var) { - Expr* res = new Expr{Expr::_Type, lex.cur().loc}; - res->flags = Expr::_IsType; - res->e_type = TypeExpr::new_hole(); - lex.next(); - return res; - } - if (t == _Int || t == _Cell || t == _Slice || t == _Builder || t == _Cont || t == _Type || t == _Tuple) { - Expr* res = new Expr{Expr::_Type, lex.cur().loc}; - res->flags = Expr::_IsType; - res->e_type = TypeExpr::new_atomic(t); - lex.next(); - return res; - } - if (t == _Ident) { - auto sym = sym::lookup_symbol(lex.cur().val); - if (sym && dynamic_cast(sym->value)) { - auto val = dynamic_cast(sym->value); - Expr* res = new Expr{Expr::_Type, lex.cur().loc}; - res->flags = Expr::_IsType; - res->e_type = val->get_type(); - lex.next(); - return res; - } - if (sym && dynamic_cast(sym->value)) { - auto val = dynamic_cast(sym->value); - Expr* res = new Expr{Expr::_GlobVar, lex.cur().loc}; - res->e_type = val->get_type(); - res->sym = sym; - res->flags = Expr::_IsLvalue | Expr::_IsRvalue | Expr::_IsImpure; - lex.next(); - return res; - } - bool auto_apply = false; - Expr* res = new Expr{Expr::_Var, lex.cur().loc}; - if (nv) { - res->val = ~lex.cur().val; - res->e_type = TypeExpr::new_hole(); - res->flags = Expr::_IsLvalue | Expr::_IsNewVar; - // std::cerr << "defined new variable " << lex.cur().str << " : " << res->e_type << std::endl; - } else { - if (!sym) { - check_global_func(lex.cur()); - sym = sym::lookup_symbol(lex.cur().val); - } - res->sym = sym; - SymVal* val = nullptr; - if (sym) { - val = dynamic_cast(sym->value); - } - if (!val) { - lex.cur().error_at("undefined identifier `", "`"); - } else if (val->type == SymVal::_Func) { - res->e_type = val->get_type(); - res->cls = Expr::_Glob; - auto_apply = val->auto_apply; - } else if (val->idx < 0) { - lex.cur().error_at("accessing variable `", "` being defined"); - } else { - res->val = val->idx; - res->e_type = val->get_type(); - // std::cerr << "accessing variable " << lex.cur().str << " : " << res->e_type << std::endl; - } - // std::cerr << "accessing symbol " << lex.cur().str << " : " << res->e_type << (val->impure ? " (impure)" : " (pure)") << std::endl; - res->flags = Expr::_IsLvalue | Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0); - } - if (auto_apply) { - int impure = res->flags & Expr::_IsImpure; - delete res; - res = new Expr{Expr::_Apply, sym, {}}; - res->flags = Expr::_IsRvalue | impure; - } - res->deduce_type(lex.cur()); - lex.next(); - return res; - } - lex.expect(Lexem::Ident); - return nullptr; -} - -// parse E { E } -Expr* parse_expr90(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr100(lex, code, nv); - while (lex.tp() == '(' || lex.tp() == '[' || (lex.tp() == _Ident && !is_special_ident(lex.cur().val))) { - if (res->is_type()) { - Expr* x = parse_expr100(lex, code, true); - x->chk_lvalue(lex.cur()); // chk_lrvalue() ? - TypeExpr* tp = res->e_type; - delete res; - res = new Expr{Expr::_TypeApply, {x}}; - res->e_type = tp; - res->here = lex.cur().loc; - try { - unify(res->e_type, x->e_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "cannot transform expression of type " << x->e_type << " to explicitly requested type " << res->e_type - << ": " << ue; - lex.cur().error(os.str()); - } - res->flags = x->flags; - } else { - Expr* x = parse_expr100(lex, code, false); - x->chk_rvalue(lex.cur()); - res = make_func_apply(res, x); - res->here = lex.cur().loc; - res->deduce_type(lex.cur()); - } - } - return res; -} - -// parse E { .method E | ~method E } -Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr90(lex, code, nv); - while (lex.tp() == _Ident && is_special_ident(lex.cur().val)) { - auto modify = is_tilde_ident(lex.cur().val); - auto obj = res; - if (modify) { - obj->chk_lvalue(lex.cur()); - } else { - obj->chk_rvalue(lex.cur()); - } - auto loc = lex.cur().loc; - auto name = lex.cur().val; - auto sym = sym::lookup_symbol(name); - if (!sym || !dynamic_cast(sym->value)) { - auto name1 = symbols.lookup(lex.cur().str.substr(1)); - if (name1) { - auto sym1 = sym::lookup_symbol(name1); - if (sym1 && dynamic_cast(sym1->value)) { - name = name1; - sym = sym1; - } - } - } - check_global_func(lex.cur(), name); - if (verbosity >= 2) { - std::cerr << "using symbol `" << symbols.get_name(name) << "` for method call of " << lex.cur().str << std::endl; - } - sym = sym::lookup_symbol(name); - SymValFunc* val = sym ? dynamic_cast(sym->value) : nullptr; - if (!val) { - lex.cur().error_at("undefined method identifier `", "`"); - } - lex.next(); - auto x = parse_expr100(lex, code, false); - x->chk_rvalue(lex.cur()); - if (x->cls == Expr::_Tensor) { - res = new Expr{Expr::_Apply, name, {obj}}; - res->args.insert(res->args.end(), x->args.begin(), x->args.end()); - } else { - res = new Expr{Expr::_Apply, name, {obj, x}}; - } - res->here = loc; - res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0); - res->deduce_type(lex.cur()); - if (modify) { - auto tmp = res; - res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}}; - res->here = loc; - res->flags = tmp->flags; - res->set_val(name); - res->deduce_type(lex.cur()); - } - } - return res; -} - -// parse [ ~ ] E -Expr* parse_expr75(Lexer& lex, CodeBlob& code, bool nv) { - if (lex.tp() == '~') { - sym_idx_t name = symbols.lookup_add("~_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr80(lex, code, false); - x->chk_rvalue(lex.cur()); - auto res = new Expr{Expr::_Apply, name, {x}}; - res->here = loc; - res->set_val('~'); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - return res; - } else { - return parse_expr80(lex, code, nv); - } -} - -// parse E { (* | / | % | /% ) E } -Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr75(lex, code, nv); - while (lex.tp() == '*' || lex.tp() == '/' || lex.tp() == '%' || lex.tp() == _DivMod || lex.tp() == _DivC || - lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR || lex.tp() == '&') { - res->chk_rvalue(lex.cur()); - int t = lex.tp(); - sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); - SrcLocation loc{lex.cur().loc}; - check_global_func(lex.cur(), name); - lex.next(); - auto x = parse_expr75(lex, code, false); - x->chk_rvalue(lex.cur()); - res = new Expr{Expr::_Apply, name, {res, x}}; - res->here = loc; - res->set_val(t); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } - return res; -} - -// parse [-] E { (+ | - | `|` | ^) E } -Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res; - int t = lex.tp(); - if (t == '-') { - sym_idx_t name = symbols.lookup_add("-_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr30(lex, code, false); - x->chk_rvalue(lex.cur()); - res = new Expr{Expr::_Apply, name, {x}}; - res->here = loc; - res->set_val(t); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } else { - res = parse_expr30(lex, code, nv); - } - while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') { - res->chk_rvalue(lex.cur()); - t = lex.tp(); - sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr30(lex, code, false); - x->chk_rvalue(lex.cur()); - res = new Expr{Expr::_Apply, name, {res, x}}; - res->here = loc; - res->set_val(t); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } - return res; -} - -// parse E { ( << | >> | >>~ | >>^ ) E } -Expr* parse_expr17(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr20(lex, code, nv); - while (lex.tp() == _Lshift || lex.tp() == _Rshift || lex.tp() == _RshiftC || lex.tp() == _RshiftR) { - res->chk_rvalue(lex.cur()); - int t = lex.tp(); - sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr20(lex, code, false); - x->chk_rvalue(lex.cur()); - res = new Expr{Expr::_Apply, name, {res, x}}; - res->here = loc; - res->set_val(t); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } - return res; -} - -// parse E [ (== | < | > | <= | >= | != | <=> ) E ] -Expr* parse_expr15(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr17(lex, code, nv); - if (lex.tp() == _Eq || lex.tp() == '<' || lex.tp() == '>' || lex.tp() == _Leq || lex.tp() == _Geq || - lex.tp() == _Neq || lex.tp() == _Spaceship) { - res->chk_rvalue(lex.cur()); - int t = lex.tp(); - sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr17(lex, code, false); - x->chk_rvalue(lex.cur()); - res = new Expr{Expr::_Apply, name, {res, x}}; - res->here = loc; - res->set_val(t); - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } - return res; -} - -// parse E [ ? E : E ] -Expr* parse_expr13(Lexer& lex, CodeBlob& code, bool nv) { - Expr* res = parse_expr15(lex, code, nv); - if (lex.tp() == '?') { - res->chk_rvalue(lex.cur()); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto x = parse_expr(lex, code, false); - x->chk_rvalue(lex.cur()); - lex.expect(':'); - auto y = parse_expr13(lex, code, false); - y->chk_rvalue(lex.cur()); - res = new Expr{Expr::_CondExpr, {res, x, y}}; - res->here = loc; - res->flags = Expr::_IsRvalue; - res->deduce_type(lex.cur()); - } - return res; -} - -// parse LE1 (= | += | -= | ... ) E2 -Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) { - auto x = parse_expr13(lex, code, nv); - int t = lex.tp(); - if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet || - t == _ModLet || t == _ModCLet || t == _ModRLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || - t == _RshiftRLet || t == _AndLet || t == _OrLet || t == _XorLet) { - x->chk_lvalue(lex.cur()); - x->chk_rvalue(lex.cur()); - sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_"); - check_global_func(lex.cur(), name); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto y = parse_expr10(lex, code, false); - y->chk_rvalue(lex.cur()); - Expr* z = new Expr{Expr::_Apply, name, {x, y}}; - z->here = loc; - z->set_val(t); - z->flags = Expr::_IsRvalue; - z->deduce_type(lex.cur()); - Expr* res = new Expr{Expr::_Letop, {x->copy(), z}}; - res->here = loc; - res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue; - res->set_val(t); - res->deduce_type(lex.cur()); - return res; - } else if (t == '=') { - x->chk_lvalue(lex.cur()); - SrcLocation loc{lex.cur().loc}; - lex.next(); - auto y = parse_expr10(lex, code, false); - y->chk_rvalue(lex.cur()); - x->predefine_vars(); - x->define_new_vars(code); - Expr* res = new Expr{Expr::_Letop, {x, y}}; - res->here = loc; - res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue; - res->set_val(t); - res->deduce_type(lex.cur()); - return res; - } else { - return x; - } -} - -Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv) { - return parse_expr10(lex, code, nv); -} - -namespace blk_fl { -enum { end = 1, ret = 2, empty = 4 }; -typedef int val; -constexpr val init = end | empty; -void combine(val& x, const val y) { - x |= y & ret; - x &= y | ~(end | empty); -} -void combine_parallel(val& x, const val y) { - x &= y | ~(ret | empty); - x |= y & end; -} -} // namespace blk_fl - -blk_fl::val parse_return_stmt(Lexer& lex, CodeBlob& code) { - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - try { - // std::cerr << "in return: "; - unify(expr->e_type, code.ret_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "previous function return type " << code.ret_type - << " cannot be unified with return statement expression type " << expr->e_type << ": " << ue; - lex.cur().error(os.str()); - } - std::vector tmp_vars = expr->pre_compile(code); - code.emplace_back(lex.cur().loc, Op::_Return, std::move(tmp_vars)); - lex.expect(';'); - return blk_fl::ret; -} - -blk_fl::val parse_implicit_ret_stmt(Lexer& lex, CodeBlob& code) { - auto ret_type = TypeExpr::new_unit(); - try { - // std::cerr << "in implicit return: "; - unify(ret_type, code.ret_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "previous function return type " << code.ret_type - << " cannot be unified with implicit end-of-block return type " << ret_type << ": " << ue; - lex.cur().error(os.str()); - } - code.emplace_back(lex.cur().loc, Op::_Return); - return blk_fl::ret; -} - -blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code); - -blk_fl::val parse_block_stmt(Lexer& lex, CodeBlob& code, bool no_new_scope = false) { - lex.expect('{'); - if (!no_new_scope) { - sym::open_scope(lex); - } - blk_fl::val res = blk_fl::init; - bool warned = false; - while (lex.tp() != '}') { - if (!(res & blk_fl::end) && !warned) { - lex.cur().loc.show_warning("unreachable code"); - warned = true; - } - blk_fl::combine(res, parse_stmt(lex, code)); - } - if (!no_new_scope) { - sym::close_scope(lex); - } - lex.expect('}'); - return res; -} - -blk_fl::val parse_repeat_stmt(Lexer& lex, CodeBlob& code) { - SrcLocation loc{lex.cur().loc}; - lex.expect(_Repeat); - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - auto cnt_type = TypeExpr::new_atomic(_Int); - try { - unify(expr->e_type, cnt_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "repeat count value of type " << expr->e_type << " is not an integer: " << ue; - lex.cur().error(os.str()); - } - std::vector tmp_vars = expr->pre_compile(code); - if (tmp_vars.size() != 1) { - lex.cur().error("repeat count value is not a singleton"); - } - Op& repeat_op = code.emplace_back(loc, Op::_Repeat, tmp_vars); - code.push_set_cur(repeat_op.block0); - blk_fl::val res = parse_block_stmt(lex, code); - code.close_pop_cur(lex.cur().loc); - return res | blk_fl::end; -} - -blk_fl::val parse_while_stmt(Lexer& lex, CodeBlob& code) { - SrcLocation loc{lex.cur().loc}; - lex.expect(_While); - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - auto cnt_type = TypeExpr::new_atomic(_Int); - try { - unify(expr->e_type, cnt_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "while condition value of type " << expr->e_type << " is not an integer: " << ue; - lex.cur().error(os.str()); - } - Op& while_op = code.emplace_back(loc, Op::_While); - code.push_set_cur(while_op.block0); - while_op.left = expr->pre_compile(code); - code.close_pop_cur(lex.cur().loc); - if (while_op.left.size() != 1) { - lex.cur().error("while condition value is not a singleton"); - } - code.push_set_cur(while_op.block1); - blk_fl::val res1 = parse_block_stmt(lex, code); - code.close_pop_cur(lex.cur().loc); - return res1 | blk_fl::end; -} - -blk_fl::val parse_do_stmt(Lexer& lex, CodeBlob& code) { - Op& while_op = code.emplace_back(lex.cur().loc, Op::_Until); - lex.expect(_Do); - code.push_set_cur(while_op.block0); - sym::open_scope(lex); - blk_fl::val res = parse_block_stmt(lex, code, true); - lex.expect(_Until); - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - sym::close_scope(lex); - auto cnt_type = TypeExpr::new_atomic(_Int); - try { - unify(expr->e_type, cnt_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "`until` condition value of type " << expr->e_type << " is not an integer: " << ue; - lex.cur().error(os.str()); - } - while_op.left = expr->pre_compile(code); - code.close_pop_cur(lex.cur().loc); - if (while_op.left.size() != 1) { - lex.cur().error("`until` condition value is not a singleton"); - } - return res & ~blk_fl::empty; -} - -blk_fl::val parse_if_stmt(Lexer& lex, CodeBlob& code, int first_lex = _If) { - SrcLocation loc{lex.cur().loc}; - lex.expect(first_lex); - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - auto flag_type = TypeExpr::new_atomic(_Int); - try { - unify(expr->e_type, flag_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "`if` condition value of type " << expr->e_type << " is not an integer: " << ue; - lex.cur().error(os.str()); - } - std::vector tmp_vars = expr->pre_compile(code); - if (tmp_vars.size() != 1) { - lex.cur().error("condition value is not a singleton"); - } - Op& if_op = code.emplace_back(loc, Op::_If, tmp_vars); - code.push_set_cur(if_op.block0); - blk_fl::val res1 = parse_block_stmt(lex, code); - blk_fl::val res2 = blk_fl::init; - code.close_pop_cur(lex.cur().loc); - if (lex.tp() == _Else) { - lex.expect(_Else); - code.push_set_cur(if_op.block1); - res2 = parse_block_stmt(lex, code); - code.close_pop_cur(lex.cur().loc); - } else if (lex.tp() == _Elseif || lex.tp() == _Elseifnot) { - code.push_set_cur(if_op.block1); - res2 = parse_if_stmt(lex, code, lex.tp()); - code.close_pop_cur(lex.cur().loc); - } else { - if_op.block1 = std::make_unique(lex.cur().loc, Op::_Nop); - } - if (first_lex == _Ifnot || first_lex == _Elseifnot) { - std::swap(if_op.block0, if_op.block1); - } - blk_fl::combine_parallel(res1, res2); - return res1; -} - -blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code) { - switch (lex.tp()) { - case _Return: { - lex.next(); - return parse_return_stmt(lex, code); - } - case '{': { - return parse_block_stmt(lex, code); - } - case ';': { - lex.next(); - return blk_fl::init; - } - case _Repeat: - return parse_repeat_stmt(lex, code); - case _If: - case _Ifnot: - return parse_if_stmt(lex, code, lex.tp()); - case _Do: - return parse_do_stmt(lex, code); - case _While: - return parse_while_stmt(lex, code); - default: { - auto expr = parse_expr(lex, code); - expr->chk_rvalue(lex.cur()); - expr->pre_compile(code); - lex.expect(';'); - return blk_fl::end; - } - } -} - -CodeBlob* parse_func_body(Lexer& lex, FormalArgList arg_list, TypeExpr* ret_type) { - lex.expect('{'); - CodeBlob* blob = new CodeBlob{ret_type}; - blob->import_params(std::move(arg_list)); - blk_fl::val res = blk_fl::init; - bool warned = false; - while (lex.tp() != '}') { - if (!(res & blk_fl::end) && !warned) { - lex.cur().loc.show_warning("unreachable code"); - warned = true; - } - blk_fl::combine(res, parse_stmt(lex, *blob)); - } - if (res & blk_fl::end) { - parse_implicit_ret_stmt(lex, *blob); - } - blob->close_blk(lex.cur().loc); - lex.expect('}'); - return blob; -} - -SymValAsmFunc* parse_asm_func_body(Lexer& lex, TypeExpr* func_type, const FormalArgList& arg_list, TypeExpr* ret_type, - bool impure = false) { - auto loc = lex.cur().loc; - lex.expect(_Asm); - int cnt = (int)arg_list.size(); - int width = ret_type->get_width(); - if (width < 0 || width > 16) { - throw src::ParseError{loc, "return type of an assembler built-in function must have a well-defined fixed width"}; - } - if (arg_list.size() > 16) { - throw src::ParseError{loc, "assembler built-in function must have at most 16 arguments"}; - } - std::vector cum_arg_width; - cum_arg_width.push_back(0); - int tot_width = 0; - for (auto& arg : arg_list) { - int arg_width = std::get(arg)->get_width(); - if (arg_width < 0 || arg_width > 16) { - throw src::ParseError{std::get(arg), - "parameters of an assembler built-in function must have a well-defined fixed width"}; - } - cum_arg_width.push_back(tot_width += arg_width); - } - std::vector asm_ops; - std::vector arg_order, ret_order; - if (lex.tp() == '(') { - lex.expect('('); - if (lex.tp() != _Mapsto) { - std::vector visited(cnt, false); - for (int i = 0; i < cnt; i++) { - if (lex.tp() != _Ident) { - lex.expect(_Ident); - } - auto sym = sym::lookup_symbol(lex.cur().val); - int j; - for (j = 0; j < cnt; j++) { - if (std::get(arg_list[j]) == sym) { - break; - } - } - if (j == cnt) { - lex.cur().error("formal argument name expected"); - } - if (visited[j]) { - lex.cur().error("formal argument listed twice"); - } - visited[j] = true; - int c1 = cum_arg_width[j], c2 = cum_arg_width[j + 1]; - while (c1 < c2) { - arg_order.push_back(c1++); - } - lex.next(); - } - assert(arg_order.size() == (unsigned)tot_width); - } - if (lex.tp() == _Mapsto) { - lex.expect(_Mapsto); - std::vector visited(width, false); - for (int i = 0; i < width; i++) { - if (lex.tp() != Lexem::Number || lex.cur().str.size() > 3) { - lex.expect(Lexem::Number); - } - int j = atoi(lex.cur().str.c_str()); - if (j < 0 || j >= width || visited[j]) { - lex.cur().error("expected integer return value index 0 .. width-1"); - } - visited[j] = true; - ret_order.push_back(j); - lex.next(); - } - } - lex.expect(')'); - } - while (lex.tp() == _String) { - asm_ops.push_back(AsmOp::Parse(lex.cur().str, cnt, width)); - lex.next(); - if (asm_ops.back().is_custom()) { - cnt = width; - } - } - if (asm_ops.empty()) { - throw src::ParseError{lex.cur().loc, "string with assembler instruction expected"}; - } - lex.expect(';'); - auto res = new SymValAsmFunc{func_type, asm_ops, impure}; - res->arg_order = std::move(arg_order); - res->ret_order = std::move(ret_order); - return res; -} - -std::vector parse_type_var_list(Lexer& lex) { - std::vector res; - lex.expect(_Forall); - int idx = 0; - while (true) { - if (lex.tp() == _Type) { - lex.next(); - } - if (lex.tp() != _Ident) { - throw src::ParseError{lex.cur().loc, "free type identifier expected"}; - } - auto loc = lex.cur().loc; - SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc); - if (new_sym_def->value) { - lex.cur().error_at("redefined type variable `", "`"); - } - auto var = TypeExpr::new_var(idx); - new_sym_def->value = new SymValType{SymVal::_Typename, idx++, var}; - res.push_back(var); - lex.next(); - if (lex.tp() != ',') { - break; - } - lex.next(); - } - lex.expect(_Mapsto); - return res; -} - -void type_var_usage(TypeExpr* expr, const std::vector& typevars, std::vector& used) { - if (expr->constr != TypeExpr::te_Var) { - for (auto arg : expr->args) { - type_var_usage(arg, typevars, used); - } - return; - } - for (std::size_t i = 0; i < typevars.size(); i++) { - if (typevars[i] == expr) { - used.at(i) = true; - return; - } - } - return; -} - -TypeExpr* compute_type_closure(TypeExpr* expr, const std::vector& typevars) { - if (typevars.empty()) { - return expr; - } - std::vector used(typevars.size(), false); - type_var_usage(expr, typevars, used); - std::vector used_vars; - for (std::size_t i = 0; i < typevars.size(); i++) { - if (used.at(i)) { - used_vars.push_back(typevars[i]); - } - } - if (!used_vars.empty()) { - expr = TypeExpr::new_forall(std::move(used_vars), expr); - } - return expr; -} - -void parse_func_def(Lexer& lex) { - SrcLocation loc{lex.cur().loc}; - sym::open_scope(lex); - std::vector type_vars; - if (lex.tp() == _Forall) { - type_vars = parse_type_var_list(lex); - } - auto ret_type = parse_type(lex); - if (lex.tp() != _Ident) { - throw src::ParseError{lex.cur().loc, "function name identifier expected"}; - } - Lexem func_name = lex.cur(); - lex.next(); - FormalArgList arg_list = parse_formal_args(lex); - bool impure = (lex.tp() == _Impure); - if (impure) { - lex.next(); - } - int f = 0; - if (lex.tp() == _Inline || lex.tp() == _InlineRef) { - f = (lex.tp() == _Inline) ? 1 : 2; - lex.next(); - } - td::RefInt256 method_id; - std::string method_name; - if (lex.tp() == _MethodId) { - lex.next(); - if (lex.tp() == '(') { - lex.expect('('); - if (lex.tp() == Lexem::String) { - method_name = lex.cur().str; - } else if (lex.tp() == Lexem::Number) { - method_name = lex.cur().str; - method_id = td::string_to_int256(method_name); - if (method_id.is_null()) { - lex.cur().error_at("invalid integer constant `", "`"); - } - } else { - throw src::ParseError{lex.cur().loc, "integer or string method identifier expected"}; - } - lex.next(); - lex.expect(')'); - } else { - method_name = func_name.str; - } - if (method_id.is_null()) { - unsigned crc = td::crc16(method_name); - method_id = td::make_refint((crc & 0xffff) | 0x10000); - } - } - if (lex.tp() != ';' && lex.tp() != '{' && lex.tp() != _Asm) { - lex.expect('{', "function body block expected"); - } - TypeExpr* func_type = TypeExpr::new_map(extract_total_arg_type(arg_list), ret_type); - func_type = compute_type_closure(func_type, type_vars); - if (verbosity >= 1) { - std::cerr << "function " << func_name.str << " : " << func_type << std::endl; - } - SymDef* func_sym = sym::define_global_symbol(func_name.val, 0, loc); - assert(func_sym); - SymValFunc* func_sym_val = dynamic_cast(func_sym->value); - if (func_sym->value) { - if (func_sym->value->type != SymVal::_Func || !func_sym_val) { - lex.cur().error("was not defined as a function before"); - } - try { - unify(func_sym_val->sym_type, func_type); - } catch (UnifyError& ue) { - std::ostringstream os; - os << "previous type of function " << func_name.str << " : " << func_sym_val->sym_type - << " cannot be unified with new type " << func_type << ": " << ue; - lex.cur().error(os.str()); - } - } - if (lex.tp() == ';') { - make_new_glob_func(func_sym, func_type, impure); - lex.next(); - } else if (lex.tp() == '{') { - if (dynamic_cast(func_sym_val)) { - lex.cur().error("function `"s + func_name.str + "` has been already defined as an assembler built-in"); - } - SymValCodeFunc* func_sym_code; - if (func_sym_val) { - func_sym_code = dynamic_cast(func_sym_val); - if (!func_sym_code) { - lex.cur().error("function `"s + func_name.str + "` has been already defined in an yet-unknown way"); - } - } else { - func_sym_code = make_new_glob_func(func_sym, func_type, impure); - } - if (func_sym_code->code) { - lex.cur().error("redefinition of function `"s + func_name.str + "`"); - } - CodeBlob* code = parse_func_body(lex, arg_list, ret_type); - code->name = func_name.str; - code->loc = loc; - // code->print(std::cerr); // !!!DEBUG!!! - func_sym_code->code = code; - } else { - if (func_sym_val) { - if (dynamic_cast(func_sym_val)) { - lex.cur().error("function `"s + func_name.str + "` was already declared as an ordinary function"); - } - if (dynamic_cast(func_sym_val)) { - lex.cur().error("redefinition of built-in assembler function `"s + func_name.str + "`"); - } - lex.cur().error("redefinition of previously (somehow) defined function `"s + func_name.str + "`"); - } - func_sym->value = parse_asm_func_body(lex, func_type, arg_list, ret_type, impure); - } - if (method_id.not_null()) { - auto val = dynamic_cast(func_sym->value); - if (!val) { - lex.cur().error("cannot set method id for unknown function `"s + func_name.str + "`"); - } - if (val->method_id.is_null()) { - val->method_id = std::move(method_id); - } else if (td::cmp(val->method_id, method_id) != 0) { - lex.cur().error("integer method identifier for `"s + func_name.str + "` changed from " + - val->method_id->to_dec_string() + " to a different value " + method_id->to_dec_string()); - } - } - if (f) { - auto val = dynamic_cast(func_sym->value); - if (!val) { - lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline"); - } - if (!(val->flags & 3)) { - val->flags = (short)(val->flags | f); - } else if ((val->flags & 3) != f) { - lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration"); - } - } - if (verbosity >= 1) { - std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl; - } - sym::close_scope(lex); -} - -std::vector source_fdescr; - -bool parse_source(std::istream* is, src::FileDescr* fdescr) { - src::SourceReader reader{is, fdescr}; - Lexer lex{reader, true, ";,()[] ~."}; - while (lex.tp() != _Eof) { - if (lex.tp() == _Global) { - parse_global_var_decls(lex); - } else { - parse_func_def(lex); - } - } - return true; -} - -bool parse_source_file(const char* filename) { - if (!filename || !*filename) { - throw src::Fatal{"source file name is an empty string"}; - } - src::FileDescr* cur_source = new src::FileDescr{filename}; - source_fdescr.push_back(cur_source); - std::ifstream ifs{filename}; - if (ifs.fail()) { - throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"}; - } - return parse_source(&ifs, cur_source); -} - -bool parse_source_stdin() { - src::FileDescr* cur_source = new src::FileDescr{"stdin", true}; - source_fdescr.push_back(cur_source); - return parse_source(&std::cin, cur_source); -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/stack-transform.cpp b/submodules/ton/tonlib-src/crypto/func/stack-transform.cpp deleted file mode 100644 index 4d9b6a5f..00000000 --- a/submodules/ton/tonlib-src/crypto/func/stack-transform.cpp +++ /dev/null @@ -1,1056 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * GENERIC STACK TRANSFORMATIONS - * - */ - -StackTransform::StackTransform(std::initializer_list list) { - *this = list; -} - -StackTransform &StackTransform::operator=(std::initializer_list list) { - if (list.size() > 255) { - invalidate(); - return *this; - } - set_id(); - if (!list.size()) { - return *this; - } - int m = (int)list.size(); - d = list.begin()[m - 1] - (m - 1); - if (d >= 128 || d < -128) { - invalidate(); - return *this; - } - for (int i = 0; i < m - 1; i++) { - int x = d + i; - int y = list.begin()[i]; - if (y != x) { - if (x != (short)x || y != (short)y || n == max_n) { - invalidate(); - return *this; - } - dp = std::max(dp, std::max(x, y) + 1); - A[n++] = std::make_pair((short)x, (short)y); - } - } - return *this; -} - -bool StackTransform::assign(const StackTransform &other) { - if (!other.is_valid() || (unsigned)other.n > max_n) { - return invalidate(); - } - d = other.d; - n = other.n; - dp = other.dp; - c = other.c; - invalid = false; - for (int i = 0; i < n; i++) { - A[i] = other.A[i]; - } - return true; -} - -int StackTransform::get(int x) const { - if (!is_valid()) { - return -1; - } - if (x <= c_start) { - return x - c; - } - x += d; - int i; - for (i = 0; i < n && A[i].first < x; i++) { - } - if (i < n && A[i].first == x) { - return A[i].second; - } else { - return x; - } -} - -bool StackTransform::set(int x, int y, bool relaxed) { - if (!is_valid()) { - return false; - } - if (x < 0) { - return (relaxed && y == x + d) || invalidate(); - } - if (!relaxed) { - touch(x); - } - x += d; - int i; - for (i = 0; i < n && A[i].first < x; i++) { - } - if (i < n && A[i].first == x) { - if (x != y) { - if (y != (short)y) { - return invalidate(); - } - A[i].second = (short)y; - } else { - --n; - for (; i < n; i++) { - A[i] = A[i + 1]; - } - } - } else { - if (x != y) { - if (x != (short)x || y != (short)y || n == max_n) { - return invalidate(); - } - for (int j = n++; j > i; j--) { - A[j] = A[j - 1]; - } - A[i].first = (short)x; - A[i].second = (short)y; - touch(x - d); - touch(y); - } - } - return true; -} - -// f(x') = x' + d for all x' >= x ? -bool StackTransform::is_trivial_after(int x) const { - return is_valid() && (!n || A[n - 1].first < x + d); -} - -// card f^{-1}(y) -int StackTransform::preimage_count(int y) const { - if (!is_valid()) { - return -1; - } - int count = (y >= d); - for (const auto &pair : A) { - if (pair.second == y) { - ++count; - } else if (pair.first == y) { - --count; - } - } - return count; -} - -// f^{-1}(y) -std::vector StackTransform::preimage(int y) const { - if (!is_valid()) { - return {}; - } - std::vector res; - bool f = (y >= d); - for (const auto &pair : A) { - if (pair.first > y && f) { - res.push_back(y - d); - f = false; - } - if (pair.first == y) { - f = false; - } else if (pair.second == y) { - res.push_back(pair.first - d); - } - } - return res; -} - -// is f:N->N bijective ? -bool StackTransform::is_permutation() const { - if (!is_valid() || d) { - return false; - } - assert(n <= max_n); - std::array X, Y; - for (int i = 0; i < n; i++) { - X[i] = A[i].first; - Y[i] = A[i].second; - if (Y[i] < 0) { - return false; - } - } - std::sort(Y.begin(), Y.begin() + n); - for (int i = 0; i < n; i++) { - if (X[i] != Y[i]) { - return false; - } - } - return true; -} - -bool StackTransform::remove_negative() { - int s = 0; - while (s < n && A[s].first < d) { - ++s; - } - if (s) { - n -= s; - for (int i = 0; i < n; i++) { - A[i] = A[i + s]; - } - } - return true; -} - -int StackTransform::try_load(int &i, int offs) const { - return i < n ? A[i++].first + offs : inf_x; -} - -bool StackTransform::try_store(int x, int y) { - if (x == y || x < d) { - return true; - } - if (n == max_n || x != (short)x || y != (short)y) { - return invalidate(); - } - A[n].first = (short)x; - A[n++].second = (short)y; - return true; -} - -// c := a * b -bool StackTransform::compose(const StackTransform &a, const StackTransform &b, StackTransform &c) { - if (!a.is_valid() || !b.is_valid()) { - return c.invalidate(); - } - c.d = a.d + b.d; - c.n = 0; - c.dp = std::max(a.dp, b.dp + a.d); - c.c = a.c + b.c; - c.invalid = false; - int i = 0, j = 0; - int x1 = a.try_load(i); - int x2 = b.try_load(j, a.d); - while (true) { - if (x1 < x2) { - int y = a.A[i - 1].second; - if (!c.try_store(x1, y)) { - return false; - } - x1 = a.try_load(i); - } else if (x2 < inf_x) { - if (x1 == x2) { - x1 = a.try_load(i); - } - int y = b.A[j - 1].second; - if (!c.try_store(x2, a(y))) { - return false; - } - x2 = b.try_load(j, a.d); - } else { - return true; - } - } -} - -// this = this * other -bool StackTransform::apply(const StackTransform &other) { - StackTransform res; - if (!compose(*this, other, res)) { - return invalidate(); - } - return assign(res); -} - -// this = other * this -bool StackTransform::preapply(const StackTransform &other) { - StackTransform res; - if (!compose(other, *this, res)) { - return invalidate(); - } - return assign(res); -} - -StackTransform StackTransform::operator*(const StackTransform &b) const & { - StackTransform res; - compose(*this, b, res); - return res; -} - -// this = this * other -StackTransform &StackTransform::operator*=(const StackTransform &other) { - StackTransform res; - (compose(*this, other, res) && assign(res)) || invalidate(); - return *this; -} - -bool StackTransform::apply_xchg(int i, int j, bool relaxed) { - if (!is_valid() || i < 0 || j < 0) { - return invalidate(); - } - if (i == j) { - return relaxed || touch(i); - } - int u = touch_get(i), v = touch_get(j); - return set(i, v) && set(j, u); -} - -bool StackTransform::apply_push(int i) { - if (!is_valid() || i < 0) { - return invalidate(); - } - int u = touch_get(i); - return shift(-1) && set(0, u); -} - -bool StackTransform::apply_push_newconst() { - if (!is_valid()) { - return false; - } - return shift(-1) && set(0, c_start - c++); -} - -bool StackTransform::apply_pop(int i) { - if (!is_valid() || i < 0) { - return invalidate(); - } - if (!i) { - return touch(0) && shift(1); - } else { - return set(i, get(0)) && shift(1); - } -} - -bool StackTransform::apply_blkpop(int k) { - if (!is_valid() || k < 0) { - return invalidate(); - } - return !k || (touch(k - 1) && shift(k)); -} - -bool StackTransform::equal(const StackTransform &other, bool relaxed) const { - if (!is_valid() || !other.is_valid()) { - return false; - } - if (!(n == other.n && d == other.d)) { - return false; - } - for (int i = 0; i < n; i++) { - if (A[i] != other.A[i]) { - return false; - } - } - return relaxed || dp == other.dp; -} - -StackTransform StackTransform::Xchg(int i, int j, bool relaxed) { - StackTransform t; - t.apply_xchg(i, j, relaxed); - return t; -} - -StackTransform StackTransform::Push(int i) { - StackTransform t; - t.apply_push(i); - return t; -} - -StackTransform StackTransform::Pop(int i) { - StackTransform t; - t.apply_pop(i); - return t; -} - -bool StackTransform::is_xchg(int i, int j) const { - if (i == j) { - return is_id(); - } - return is_valid() && !d && n == 2 && i >= 0 && j >= 0 && get(i) == j && get(j) == i; -} - -bool StackTransform::is_xchg(int *i, int *j) const { - if (!is_valid() || d || n > 2 || !dp) { - return false; - } - if (!n) { - *i = *j = 0; - return true; - } - if (n != 2) { - return false; - } - int a = A[0].first, b = A[1].first; - if (A[0].second != b || A[1].second != a) { - return false; - } - *i = std::min(a, b); - *j = std::max(a, b); - return true; -} - -bool StackTransform::is_xchg_xchg(int i, int j, int k, int l) const { - if (is_valid() && !d && n <= 4 && (i | j | k | l) >= 0) { - StackTransform t; - return t.apply_xchg(i, j) && t.apply_xchg(k, l) && t <= *this; - } else { - return false; - } -} - -bool StackTransform::is_xchg_xchg(int *i, int *j, int *k, int *l) const { - if (!is_valid() || d || n > 4 || !dp || !is_permutation()) { - return false; - } - if (!n) { - *i = *j = *k = *l = 0; - return true; - } - if (n <= 2) { - *k = *l = 0; - return is_xchg(i, j); - } - if (n == 3) { - // rotation: a -> b -> c -> a - int a = A[0].first; - int b = A[0].second; - int s = (b == A[2].first ? 2 : 1); - int c = A[s].second; - if (b != A[s].first || c != A[3 - s].first || a != A[3 - s].second) { - return false; - } - // implement as XCHG s(a),s(c) ; XCHG s(a),s(b) - *i = *k = a; - *j = c; - *l = b; - return is_xchg_xchg(*i, *j, *k, *l); - } - *i = A[0].first; - *j = A[0].second; - if (get(*j) != *i) { - return false; - } - for (int s = 1; s < 4; s++) { - if (A[s].first != *j) { - *k = A[s].first; - *l = A[s].second; - return get(*l) == *k && is_xchg_xchg(*i, *j, *k, *l); - } - } - return false; -} - -bool StackTransform::is_push(int i) const { - return is_valid() && d == -1 && n == 1 && A[0].first == -1 && A[0].second == i; -} - -bool StackTransform::is_push(int *i) const { - if (is_valid() && d == -1 && n == 1 && A[0].first == -1 && A[0].second >= 0) { - *i = A[0].second; - return true; - } else { - return false; - } -} - -// 1 2 3 4 .. = pop0 -// 0 2 3 4 .. = pop1 -// 1 0 3 4 .. = pop2 -// 1 2 0 4 .. = pop3 -// POP s(i) : 1 2 ... i-1 0 i+1 ... ; d=1, n=1, {(i,0)} -bool StackTransform::is_pop(int i) const { - if (!is_valid() || d != 1 || n > 1 || i < 0) { - return false; - } - if (!i) { - return !n; - } - return n == 1 && A[0].first == i && !A[0].second; -} - -bool StackTransform::is_pop(int *i) const { - if (!is_valid() || d != 1 || n > 1) { - return false; - } - if (!n) { - *i = 0; - return true; - } - if (n == 1 && !A[0].second) { - *i = A[0].first; - return true; - } - return false; -} - -// POP s(i) ; POP s(j) : 2 ... i-1 0 i+1 ... j 1 j+2 ... ; d=2, n=2, {(i,0),(j+1,1)} if i <> j+1 -bool StackTransform::is_pop_pop(int i, int j) const { - if (is_valid() && d == 2 && n <= 2 && i >= 0 && j >= 0) { - StackTransform t; - return t.apply_pop(i) && t.apply_pop(j) && t <= *this; - } else { - return false; - } -} - -bool StackTransform::is_pop_pop(int *i, int *j) const { - if (!is_valid() || d != 2 || n > 2) { - return false; - } - if (!n) { - *i = *j = 0; // 2DROP - } else if (n == 2) { - *i = A[0].first - A[0].second; - *j = A[1].first - A[1].second; - if (A[0].second > A[1].second) { - std::swap(*i, *j); - } - } else if (!A[0].second) { - *i = A[0].first; - *j = 0; - } else { - *i = 0; - *j = A[0].first - 1; - } - return is_pop_pop(*i, *j); -} - -const StackTransform StackTransform::rot{2, 0, 1, 3}; -const StackTransform StackTransform::rot_rev{1, 2, 0, 3}; - -bool StackTransform::is_rot() const { - return equal(rot, true); -} - -bool StackTransform::is_rotrev() const { - return equal(rot_rev, true); -} - -// PUSH i ; ROT == 1 i 0 2 3 -bool StackTransform::is_push_rot(int i) const { - return is_valid() && d == -1 && i >= 0 && is_trivial_after(3) && get(0) == 1 && get(1) == i && get(2) == 0; -} - -bool StackTransform::is_push_rot(int *i) const { - return is_valid() && (*i = get(1)) >= 0 && is_push_rot(*i); -} - -// PUSH i ; -ROT == 0 1 i 2 3 -bool StackTransform::is_push_rotrev(int i) const { - return is_valid() && d == -1 && i >= 0 && is_trivial_after(3) && get(0) == 0 && get(1) == 1 && get(2) == i; -} - -bool StackTransform::is_push_rotrev(int *i) const { - return is_valid() && (*i = get(2)) >= 0 && is_push_rotrev(*i); -} - -// PUSH s(i) ; XCHG s(j),s(k) --> i 0 1 .. i .. -// PUSH s(i) ; XCHG s(0),s(k) --> k-1 0 1 .. k-2 i k .. -bool StackTransform::is_push_xchg(int i, int j, int k) const { - StackTransform t; - return is_valid() && d == -1 && n <= 3 && t.apply_push(i) && t.apply_xchg(j, k) && t <= *this; -} - -bool StackTransform::is_push_xchg(int *i, int *j, int *k) const { - if (!(is_valid() && d == -1 && n <= 3 && n > 0)) { - return false; - } - int s = get(0); - if (s < 0) { - return false; - } - *i = s; - *j = 0; - if (n == 1) { - *k = 0; - } else if (n == 2) { - *k = s + 1; - *i = get(s + 1); - } else { - *j = A[1].first + 1; - *k = A[2].first + 1; - } - return is_push_xchg(*i, *j, *k); -} - -// XCHG s1,s(i) ; XCHG s0,s(j) -bool StackTransform::is_xchg2(int i, int j) const { - StackTransform t; - return is_valid() && !d && t.apply_xchg(1, i) && t.apply_xchg(0, j) && t <= *this; -} - -bool StackTransform::is_xchg2(int *i, int *j) const { - if (!is_valid() || d || n > 4 || n == 1 || dp < 2) { - return false; - } - *i = get(1); - *j = get(0); - if (!n) { - return true; - } - if (*i < 0 || *j < 0) { - return false; - } - if (n == 2 && !*i) { - *j = *i; // XCHG s0,s1 = XCHG2 s0,s0 - } else if (n == 3 && *i) { - // XCHG2 s(i),s(i) = XCHG s1,s(i) ; XCHG s0,s(i) : 0->1, 1->i - *j = *i; - } // XCHG2 s0,s(i) = XCHG s0,s1 ; XCHG s0,s(i) : 0->i, 1->0 - return is_xchg2(*i, *j); -} - -// XCHG s0,s(i) ; PUSH s(j) = PUSH s(j') ; XCHG s1,s(i+1) -// j'=j if j!=0, j!=i -// j'=0 if j=i -// j'=i if j=0 -bool StackTransform::is_xcpu(int i, int j) const { - StackTransform t; - return is_valid() && d == -1 && t.apply_xchg(0, i) && t.apply_push(j) && t <= *this; -} - -bool StackTransform::is_xcpu(int *i, int *j) const { - if (!is_valid() || d != -1 || n > 3 || dp < 1) { - return false; - } - *i = get(1); - *j = get(0); - if (!*j) { - *j = *i; - } else if (*j == *i) { - *j = 0; - } - return is_xcpu(*i, *j); -} - -// PUSH s(i) ; XCHG s0, s1 ; XCHG s0, s(j+1) -bool StackTransform::is_puxc(int i, int j) const { - StackTransform t; - return is_valid() && d == -1 && t.apply_push(i) && t.apply_xchg(0, 1) && t.apply_xchg(0, j + 1) && t <= *this; -} - -// j > 0 : 0 -> j, 1 -> i -// j = 0 : 0 -> i, 1 -> 0 ( PUSH s(i) ) -// j = -1 : 0 -> 0, 1 -> i ( PUSH s(i) ; XCHG s0, s1 ) -bool StackTransform::is_puxc(int *i, int *j) const { - if (!is_valid() || d != -1 || n > 3) { - return false; - } - *i = get(1); - *j = get(0); - if (!*i && is_push(*j)) { - std::swap(*i, *j); - return is_puxc(*i, *j); - } - if (!*j) { - --*j; - } - return is_puxc(*i, *j); -} - -// PUSH s(i) ; PUSH s(j+1) -bool StackTransform::is_push2(int i, int j) const { - StackTransform t; - return is_valid() && d == -2 && t.apply_push(i) && t.apply_push(j + 1) && t <= *this; -} - -bool StackTransform::is_push2(int *i, int *j) const { - if (!is_valid() || d != -2 || n > 2) { - return false; - } - *i = get(1); - *j = get(0); - return is_push2(*i, *j); -} - -// XCHG s2,s(i) ; XCHG s1,s(j) ; XCHG s0,s(k) -bool StackTransform::is_xchg3(int *i, int *j, int *k) const { - if (!is_valid() || d || dp < 3 || !is_permutation()) { - return false; - } - for (int s = 2; s >= 0; s--) { - *i = get(s); - StackTransform t = Xchg(2, *i) * *this; - if (t.is_xchg2(j, k)) { - return true; - } - } - return false; -} - -// XCHG s1,s(i) ; XCHG s0,s(j) ; PUSH s(k) -bool StackTransform::is_xc2pu(int *i, int *j, int *k) const { - if (!is_valid() || d != -1 || dp < 2) { - return false; - } - for (int s = 2; s >= 1; s--) { - *i = get(s); - StackTransform t = Xchg(1, *i) * *this; - if (t.is_xcpu(j, k)) { - return true; - } - } - return false; -} - -// XCHG s1,s(i) ; PUSH s(j) ; XCHG s0,s1 ; XCHG s0,s(k+1) -bool StackTransform::is_xcpuxc(int *i, int *j, int *k) const { - if (!is_valid() || d != -1 || dp < 2) { - return false; - } - for (int s = 2; s >= 0; s--) { - *i = get(s); - StackTransform t = Xchg(1, *i) * *this; - if (t.is_puxc(j, k)) { - return true; - } - } - return false; -} - -// XCHG s0,s(i) ; PUSH s(j) ; PUSH s(k+1) -bool StackTransform::is_xcpu2(int *i, int *j, int *k) const { - if (!is_valid() || d != -2 || dp < 1) { - return false; - } - *i = get(2); - StackTransform t = Xchg(0, *i) * *this; - return t.is_push2(j, k); -} - -// PUSH s(i) ; XCHG s0,s2 ; XCHG s1,s(j+1) ; XCHG s0,s(k+1) -// 0 -> i or 1 -> i or 2 -> i ; i has two preimages -// 0 -> k if k >= 2, k != j -// 1 -> j=k if j = k >= 2 -// 1 -> j if j >= 2, k != 0 -// 0 -> j if j >= 2, k = 0 -// => i in {f(0), f(1), f(2)} ; j in {-1, 0, 1, f(0), f(1)} ; k in {-1, 0, 1, f(0), f(1)} -bool StackTransform::is_puxc2(int *i, int *j, int *k) const { - if (!is_valid() || d != -1 || dp < 2) { - return false; - } - for (int s = 2; s >= 0; s--) { - *i = get(s); - if (preimage_count(*i) != 2) { - continue; - } - for (int u = -1; u <= 3; u++) { - *j = (u >= 2 ? get(u - 2) : u); - for (int v = -1; v <= 3; v++) { - *k = (v >= 2 ? get(v - 2) : v); - if (is_puxc2(*i, *j, *k)) { - return true; - } - } - } - } - return false; -} - -// PUSH s(i) ; XCHG s0,s2 ; XCHG s1,s(j+1) ; XCHG s0,s(k+1) -bool StackTransform::is_puxc2(int i, int j, int k) const { - StackTransform t; - return is_valid() && d == -1 && dp >= 2 // basic checks - && t.apply_push(i) && t.apply_xchg(0, 2) // PUSH s(i) ; XCHG s0,s2 - && t.apply_xchg(1, j + 1) // XCHG s1,s(j+1) - && t.apply_xchg(0, k + 1) && t <= *this; // XCHG s0,s(k+2) -} - -// PUSH s(i) ; XCHG s0,s1 ; XCHG s0,s(j+1) ; PUSH s(k+1) -bool StackTransform::is_puxcpu(int *i, int *j, int *k) const { - if (!is_valid() || d != -2 || dp < 1) { - return false; - } - StackTransform t = *this; - if (t.apply_pop() && t.is_puxc(i, j)) { - int y = get(0); - auto v = t.preimage(y); - if (!v.empty()) { - *k = v[0] - 1; - t.apply_push(*k + 1); - return t <= *this; - } - } - return false; -} - -// PUSH s(i) ; XCHG s0,s1 ; PUSH s(j+1) ; XCHG s0,s1 ; XCHG s0,s(k+2) -// 2 -> i; 1 -> j (if j >= 1, k != -1), 1 -> i (if j = 0, k != -1), 1 -> 0 (if j = -1, k != -1) -// 0 -> k (if k >= 1), 0 -> i (if k = 0), 0 -> j (if k = -1, j >= 1) -bool StackTransform::is_pu2xc(int *i, int *j, int *k) const { - if (!is_valid() || d != -2 || dp < 1) { - return false; - } - *i = get(2); - for (int v = -2; v <= 1; v++) { - *k = (v <= 0 ? v : get(0)); // one of -2, -1, 0, get(0) - for (int u = -1; u <= 1; u++) { - *j = (u <= 0 ? u : get(v != -1)); // one of -1, 0, get(0), get(1) - if (is_pu2xc(*i, *j, *k)) { - return true; - } - } - } - return false; -} - -bool StackTransform::is_pu2xc(int i, int j, int k) const { - StackTransform t; - return is_valid() && d == -2 && dp >= 1 // basic checks - && t.apply_push(i) && t.apply_xchg(0, 1) // PUSH s(i) ; XCHG s0,s1 - && t.apply_push(j + 1) && t.apply_xchg(0, 1) // PUSH s(j+1) ; XCHG s0,s1 - && t.apply_xchg(0, k + 2) && t <= *this; // XCHG s0,s(k+2) -} - -// PUSH s(i) ; PUSH s(j+1) ; PUSH s(k+2) -bool StackTransform::is_push3(int i, int j, int k) const { - StackTransform t; - return is_valid() && d == -3 && t.apply_push(i) && t.apply_push(j + 1) && t.apply_push(k + 2) && t <= *this; -} - -bool StackTransform::is_push3(int *i, int *j, int *k) const { - if (!is_valid() || d != -3 || n > 3) { - return false; - } - *i = get(2); - *j = get(1); - *k = get(0); - return is_push3(*i, *j, *k); -} - -bool StackTransform::is_blkswap(int *i, int *j) const { - if (!is_valid() || d || !is_permutation()) { - return false; - } - *j = get(0); - if (*j <= 0) { - return false; - } - auto v = preimage(0); - if (v.size() != 1) { - return false; - } - *i = v[0]; - return *i > 0 && is_blkswap(*i, *j); -} - -bool StackTransform::is_blkswap(int i, int j) const { - if (!is_valid() || d || i <= 0 || j <= 0 || dp < i + j || !is_trivial_after(i + j)) { - return false; - } - for (int s = 0; s < i; s++) { - if (get(s) != s + j) { - return false; - } - } - for (int s = 0; s < j; s++) { - if (get(s + i) != s) { - return false; - } - } - return true; -} - -// equivalent to i times DROP -bool StackTransform::is_blkdrop(int *i) const { - if (is_valid() && d > 0 && !n) { - *i = d; - return true; - } - return false; -} - -// 0 1 .. j-1 j+i j+i+1 ... -bool StackTransform::is_blkdrop2(int i, int j) const { - if (!is_valid() || d != i || i <= 0 || j < 0 || dp < i + j || n != j || !is_trivial_after(j)) { - return false; - } - for (int s = 0; s < j; s++) { - if (get(s) != s) { - return false; - } - } - return true; -} - -bool StackTransform::is_blkdrop2(int *i, int *j) const { - if (is_valid() && is_blkdrop2(d, n)) { - *i = d; - *j = n; - return true; - } - return false; -} - -// equivalent to i times PUSH s(j) -bool StackTransform::is_blkpush(int *i, int *j) const { - if (!is_valid() || d >= 0) { - return false; - } - *i = -d; - *j = get(*i - 1); - return is_blkpush(*i, *j); -} - -bool StackTransform::is_blkpush(int i, int j) const { - if (!is_valid() || d >= 0 || d != -i || j < 0 || dp < i + j || !is_trivial_after(i)) { - return false; - } - StackTransform t; - for (int s = 0; s < i; s++) { - if (!t.apply_push(j)) { - return false; - } - } - return t <= *this; -} - -bool StackTransform::is_reverse(int *i, int *j) const { - if (!is_valid() || d || !is_permutation() || n < 2) { - return false; - } - *j = A[0].first; - *i = A[n - 1].first - A[0].first + 1; - return is_reverse(*i, *j); -} - -bool StackTransform::is_reverse(int i, int j) const { - if (!is_valid() || d || !is_trivial_after(i + j) || n < 2 || A[0].first != j || A[n - 1].first != j + i - 1) { - return false; - } - for (int s = 0; s < i; s++) { - if (get(j + s) != j + i - 1 - s) { - return false; - } - } - return true; -} - -// 0 i+1 i+2 ... == i*NIP -// j i+1 i+2 ... == XCHG s(i),s(j) ; BLKDROP i -bool StackTransform::is_nip_seq(int i, int j) const { - return is_valid() && d == i && i > j && j >= 0 && n == 1 && A[0].first == i && A[0].second == j; -} - -bool StackTransform::is_nip_seq(int *i) const { - *i = d; - return is_nip_seq(*i); -} - -bool StackTransform::is_nip_seq(int *i, int *j) const { - if (is_valid() && n > 0) { - *i = d; - *j = A[0].second; - return is_nip_seq(*i, *j); - } else { - return false; - } -} - -// POP s(i); BLKDROP k (usually for i >= k >= 0) -bool StackTransform::is_pop_blkdrop(int i, int k) const { - StackTransform t; - return is_valid() && d == k + 1 && t.apply_pop(i) && t.apply_blkpop(k) && t <= *this; -} - -// POP s(i); BLKDROP k == XCHG s0,s(i); BLKDROP k+1 for i >= k >= 0 -// k+1 k+2 .. i-1 0 i+1 .. -bool StackTransform::is_pop_blkdrop(int *i, int *k) const { - if (is_valid() && n == 1 && d > 0 && !A[0].second) { - *k = d - 1; - *i = A[0].first; - return is_pop_blkdrop(*i, *k); - } else { - return false; - } -} - -// POP s(i); POP s(j); BLKDROP k (usually for i<>j >= k >= 0) -bool StackTransform::is_2pop_blkdrop(int i, int j, int k) const { - StackTransform t; - return is_valid() && d == k + 2 && t.apply_pop(i) && t.apply_pop(j) && t.apply_blkpop(k) && t <= *this; -} - -// POP s(i); POP s(j); BLKDROP k == XCHG s0,s(i); XCHG s1,s(j+1); BLKDROP k+2 (usually for i<>j >= k >= 2) -// k+2 k+3 .. i-1 0 i+1 ... j 1 j+2 ... -bool StackTransform::is_2pop_blkdrop(int *i, int *j, int *k) const { - if (is_valid() && n == 2 && d >= 2 && A[0].second + A[1].second == 1) { - *k = d - 2; - int t = (A[0].second > 0); - *i = A[t].first; - *j = A[1 - t].first - 1; - return is_2pop_blkdrop(*i, *j, *k); - } else { - return false; - } -} - -// PUSHCONST c ; ROT == 1 -1000 0 2 3 -bool StackTransform::is_const_rot(int c) const { - return is_valid() && d == -1 && is_trivial_after(3) && get(0) == 1 && c <= c_start && get(1) == c && get(2) == 0; -} - -bool StackTransform::is_const_rot(int *c) const { - return is_valid() && (*c = get(1)) <= c_start && is_const_rot(*c); -} - -// PUSHCONST c ; POP s(i) == 0 1 .. i-1 -1000 i+1 ... -bool StackTransform::is_const_pop(int c, int i) const { - return is_valid() && !d && n == 1 && i > 0 && c <= c_start && get(i - 1) == c; -} - -bool StackTransform::is_const_pop(int *c, int *i) const { - if (is_valid() && !d && n == 1 && A[0].second <= c_start) { - *i = A[0].first + 1; - *c = A[0].second; - return is_const_pop(*c, *i); - } else { - return false; - } -} - -// PUSH i ; PUSHCONST c == c i 0 1 2 ... -bool StackTransform::is_push_const(int i, int c) const { - return is_valid() && d == -2 && c <= c_start && i >= 0 && is_trivial_after(2) && get(0) == c && get(1) == i; -} - -bool StackTransform::is_push_const(int *i, int *c) const { - return is_valid() && d == -2 && n == 2 && is_push_const(*i = get(1), *c = get(0)); -} - -void StackTransform::show(std::ostream &os, int mode) const { - if (!is_valid()) { - os << ""; - return; - } - int mi = 0, ma = 0; - if (n > 0 && A[0].first < d) { - mi = A[0].first - d; - } - if (n > 0) { - ma = std::max(ma, A[n - 1].first - d + 1); - } - ma = std::max(ma + 1, dp - d); - os << '{'; - if (dp == d) { - os << '|'; - } - for (int i = mi; i < ma; i++) { - os << get(i) << (i == -1 ? '?' : (i == dp - d - 1 ? '|' : ' ')); - } - os << get(ma) << "..}"; -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/func/test/a10.fc b/submodules/ton/tonlib-src/crypto/func/test/a10.fc deleted file mode 100644 index 70c7871d..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a10.fc +++ /dev/null @@ -1,9 +0,0 @@ -_ f(int a, int x) { - int y = 0; - int z = 0; - while ((y = x * x) > a) { - x -= 1; - z = 1; - } - return (y, z); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a11.fc b/submodules/ton/tonlib-src/crypto/func/test/a11.fc deleted file mode 100644 index 45bdf1f3..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a11.fc +++ /dev/null @@ -1,28 +0,0 @@ -_ f(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, int cnt, cell credits, cell vdict, int elect) { - return (ds, elect, credits); -} - -_ g(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, int cnt, cell credits, int elect) { - return (ds, elect, credits); -} - -_ h(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, cell credits, int elect) { - return (ds, elect, credits); -} - -_ h2(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, cell credits, int elect) { - return (ds, credits, elect); -} - -_ h3(int pubkey, int adnl_addr, int stake, int tot_weight, tuple vinfo) { - return (pubkey, tot_weight, stake, vinfo); -} - -_ z(int a, int b) { - return (b, 0, a); -} - -_ z2(int a, int b) { - return (0, a, b); -} - diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6.fc b/submodules/ton/tonlib-src/crypto/func/test/a6.fc deleted file mode 100644 index 3a387aac..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6.fc +++ /dev/null @@ -1,89 +0,0 @@ -(int, int) f(int a, int b, int c, int d, int e, int f) { - ;; solve a 2x2 linear equation - int D = a * d - b * c; - int Dx = e * d - b * f; - int Dy = a * f - e * c; - return (Dx / D, Dy / D); -} - -int calc_phi() { - var n = 1; - repeat (70) { n *= 10; } - var p = var q = 1; - do { - (p, q) = (q, p + q); - } until (q > n); - return muldivr(p, n, q); -} - -int calc_sqrt2() { - var n = 1; - repeat (70) { n *= 10; } - var p = var q = 1; - do { - var t = p + q; - (p, q) = (q, t + q); - } until (q > n); - return muldivr(p, n, q); -} - -var calc_root(m) { - int base = 1; - repeat(70) { base *= 10; } - var (a, b, c) = (1, 0, - m); - var (p1, q1, p2, q2) = (1, 0, 0, 1); - do { - int k = -1; - var (a1, b1, c1) = (0, 0, 0); - do { - k += 1; - (a1, b1, c1) = (a, b, c); - c += b; - c += b += a; - } until (c > 0); - (a, b, c) = (- c1, - b1, - a1); - (p1, q1) = (k * p1 + q1, p1); - (p2, q2) = (k * p2 + q2, p2); - } until (p1 > base); - return (p1, q1, p2, q2); -} - -{- -operator _/%_ infix 20; - -(int, int) ((int x) /% (int y)) { - return (x / y, x % y); -} - -(int, int) _/%_ (int x, int y) { - return (x / y, x % y); -} --} - -forall A, B, C -> -(B, C, A) rot (A x, B y, C z) { - return (y, z, x); -} - -int ataninv(int base, int q) { ;; computes base*atan(1/q) - base ~/= q; - q *= - q; - int sum = 0; - int n = 1; - do { - sum += base ~/ n; - base ~/= q; - n += 2; - } until base == 0; - return sum; -} - -int calc_pi() { - int base = 64; - repeat (70) { base *= 10; } - return (ataninv(base << 2, 5) - ataninv(base, 239)) ~>> 4; -} - -int main() { - return calc_pi(); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6.fp b/submodules/ton/tonlib-src/crypto/func/test/a6.fp deleted file mode 100644 index 00c2e76e..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6.fp +++ /dev/null @@ -1,75 +0,0 @@ -f(int a, int b, int c, int d, int e, int f) : (int, int) { - var D = a * d - b * c; - var Dx : int = e * d - b * f; - var Dy : int = a * f - e * c; - return (Dx / D, Dy / D); -} - -calc_phi() : int = { - var n : int = 1; - repeat (10) { - n *= 10; - } - var p = var q = 1; - do { - (p, q) = (q, p + q); - } until q > n; - return muldivr(p, n, q); -} - -calc_sqrt2() : int = { - var n = 1; - repeat (70) { n *= 10; } - var p = var q = 1; - do { - var t = p + q; - (p, q) = (q, t + q); - } until q > n; - return muldivr(p, n, q); -} - -calc_phi() : int = { - var n = 1; - repeat (70) { n *= 10; } - var p = var q = 1; - do { - (p, q) = (q, p + q); - } until q > n; - return muldivr(p, n, q); -} - -operator _/%_ infix 20; - -(x : int) /% (y : int) : (int, int) = { - return (x / y, x % y); -} - -{- -_/%_ (int x, int y) : (int, int) = { - return (x / y, x % y); -} --} - -rot < A : type, B : type, C : type > - (x : A, y : B, z : C) : (B, C, A) { - return (y, z, x); -} - -ataninv(base : int, q : int) : int { ;; computes base*atan(1/q) - base /~= q; - q *= - q; - var sum : int = 0; - var n = 1; - do { - sum += base /~ n; - base /~= q; - n += 2; - } while base; - return sum; -} - -calc_pi() : int { - var base = 64; - repeat (70) { base *= 10; } - return (ataninv(base << 2, 5) - ataninv(base, 239)) >>~ 4; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_1.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_1.fc deleted file mode 100644 index 9af7f254..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6_1.fc +++ /dev/null @@ -1,6 +0,0 @@ -(int, int) f(int a, int b, int c, int d, int e, int f) { - int D = a * d - b * c; - int Dx = e * d - b * f; - int Dy = a * f - e * c; - return (Dx / D, Dy / D); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_2.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_2.fc deleted file mode 100644 index 970ad624..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6_2.fc +++ /dev/null @@ -1,130 +0,0 @@ -var f(a, b, c, d, e, f) { - var D = a * d - b * c; - var Dx = e * d - b * f; - var Dy = a * f - e * c; - return (Dx / D, Dy / D); -} - -var test8() { - return -4; -} - -var test3(a) { - int x = a * 10; - a += 1; - int x = x + 3; - { - int y = x + 2; - x = y + a; - } - int z = 5; - return x * (z + a); -} - -var test2(a) { - (var x, var y) = a /% 10; - return x + y; -} - -var test2a(a) { - var (x, y) = a /% 10; - return x + y; -} - -var test2b(a) { - var z = a /% 10; - return _+_ z; -} - -var test2c(a) { - return _+_ (a /% 10); -} - -var twice(f, x) { - return f (f x); -} - -var test() { - return f(1, 2, 3, 4, 7, 17); -} - -var rot(a, b, c) { - return (b, c, a); -} - -var rot_int(int a, int b, int c) { - return (b, c, a); -} - -(int, _) dup_int(x) { - return (x, x); -} - -var calc_phi() { - var n = 10; - n *= n; - n *= n; - n *= n; - n *= n; - n *= n; - n *= n; - var p = var q = 1; - (p, q) = (q, p + q); - (p, q) = (q, p + q); - (p, q) = (q, p + q); - (p, q) = (q, p + q); - (p, q) = (q, p + q); - (p, q) = (q, p + q); - (p, q) = (q, p + q); - return muldivr(p, n, q); -} - -var t0() { - var x = 1; - return x; -} - -var t1() { - return 2; -} - -var t2(int x) { - return 2; - return x += 1; -} - -var t3(int x, var y) { - int z = (x + y) * (x - y); -} - -var t3b(int x, var y) { - int z = (x + y) * (x - y); - return z; -} - -var t4((int, int, int) z) { - var (_, u, _) = z; - return u; -} - -int foo(int t); - -var t5(x) { - var f = t2; - return twice(f, x) * f(x); -} - -var proj1(a, b) { return a; } -var proj1a(a, b) { var c = a; return c; } -var proj1b(a, b) { int c = a; return c; } -var proj1c(a, b) { var c = a + 2; return c; } -var proj1d(a, b) { return a + 2; } -var proj1e(int a, _) { return a; } -int proj1f(_ a, int) { return a; } -int proj1g(int, a) { return a; } - -var test1(a) { - a = a + 1; - return a; -} - diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc deleted file mode 100644 index 7c8ff3af..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc +++ /dev/null @@ -1,22 +0,0 @@ -forall A, B, C -> -(B, C, A) rot(A x, B y, C z) { - return (y, z, x); -} - -forall A, B, C -> -_ rot2(A x, B y, C z) { - return rot(rot(x, y, z)); -} - -_ test() { - return rot2(2, 3, 9); -} - -_ test2(cell x, slice y, tuple z) { - return rot2(x, y, z); -} - -forall A -> -_ test3(cell x, A y, int z) { - return rot2(x, y, z); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_4.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_4.fc deleted file mode 100644 index d7e6596a..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6_4.fc +++ /dev/null @@ -1,20 +0,0 @@ -var calc_root(m) { - int base = 1; - repeat(70) { base *= 10; } - var (a, b, c) = (1, 0, - m); - var (p1, q1, p2, q2) = (1, 0, 0, 1); - do { - int k = -1; - var (a1, b1, c1) = (0, 0, 0); - do { - k += 1; - (a1, b1, c1) = (a, b, c); - c += b; - c += b += a; - } until (c > 0); - (a, b, c) = (- c1, - b1, - a1); - (p1, q1) = (k * p1 + q1, p1); - (p2, q2) = (k * p2 + q2, p2); - } until (p1 > base); - return (p1, q1, p2, q2); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_5.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_5.fc deleted file mode 100644 index ece7cd38..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a6_5.fc +++ /dev/null @@ -1,20 +0,0 @@ -var twice(f, x) { - return f (f x); -} - -_ sqr(x) { - return x * x; -} - -var main(x) { - var f = sqr; - return twice(f, x) * f(x); -} - -var pow6(x) { - return twice(sqr, x) * sqr(x); -} - -_ q() { - return false; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a7.fc b/submodules/ton/tonlib-src/crypto/func/test/a7.fc deleted file mode 100644 index f86be30a..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a7.fc +++ /dev/null @@ -1,12 +0,0 @@ -int steps(int x) { - var n = 0; - while (x > 1) { - n += 1; - if (x & 1) { - x = 3 * x + 1; - } else { - x >>= 1; - } - } - return n; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a8.fc b/submodules/ton/tonlib-src/crypto/func/test/a8.fc deleted file mode 100644 index 1cd18a33..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a8.fc +++ /dev/null @@ -1,28 +0,0 @@ -int A(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(d, e, f); -} - -int B(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(b, d, e) + f; -} - -int C(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(b, d, c) + muldiv(d, d, f); -} - -int D(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(b, d, c) + muldiv(e, e, f); -} - -int E(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(c, d, e) + muldiv(c, c, f); -} - -int F(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(a, d, c) + muldiv(f, f, e); -} - -int G(int a, int b, int c, int d, int e, int f) { - return muldiv(a, b, c) + muldiv(b, c, d) + muldiv(b, c, e) + f; -} - diff --git a/submodules/ton/tonlib-src/crypto/func/test/a9.fc b/submodules/ton/tonlib-src/crypto/func/test/a9.fc deleted file mode 100644 index e9cc1450..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a9.fc +++ /dev/null @@ -1,23 +0,0 @@ -int f(int x) { - if (2 * x + 1 == 7) { - return x + 17; - } else { - return 239; - } -} - -int f2(int x) { - return 2 * x + 1 == 6 ? x + 17 : 239; -} - -int g(int x) { - return x & 1 ? 3 * x + 1 : x / 2; -} - -_ H(int x, int y) { - return (x < y, x <= y, x == y, x >= y, x > y, x != y, x <=> y); -} - -int q() { - return 4; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/a9_1.fc b/submodules/ton/tonlib-src/crypto/func/test/a9_1.fc deleted file mode 100644 index 0dc9de0c..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/a9_1.fc +++ /dev/null @@ -1,28 +0,0 @@ -_ F(int x) { - x = 2; - return x + 1; -} - -_ G(x) { - var y = x + 1; - x = 2; - return (x - 1, y); -} - -_ H(x) { - var y = x + 1; - x = 2; - return (x * y, y); -} - -_ I(x) { - int y = 17; - int z = x - y; - return (z, y); -} - -_ J(x) { - int y = 239; - int z = x - y; - return (z, y); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b1.fc b/submodules/ton/tonlib-src/crypto/func/test/b1.fc deleted file mode 100644 index ce522934..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b1.fc +++ /dev/null @@ -1,63 +0,0 @@ -int now() asm "NOW"; - -int cell_hash(cell c) -asm "HASHCU"; - -int slice_hash(slice s) -asm "HASHSU"; - -int check_signature(int hash, slice signature, int public_key) -asm "CHKSIGNU"; - -;; () throw_if(int excno, int cond) impure -;; asm "THROWARGIF"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -() accept_message() impure asm "ACCEPT"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(cell, slice) load_ref(slice s) asm "LDREF"; -(int, slice) zload_int(slice s, int len) asm "LDIX"; -(int, slice) zload_uint(slice s, int len) asm "LDUX"; -int zpreload_int(slice s, int len) asm "PLDIX"; -int zpreload_uint(slice s, int len) asm "PLDUX"; -(slice, slice) load_bits(slice s, int len) asm "LDSLICEX"; -slice preload_bits(slice s, int len) asm "PLDSLICEX"; -cell set_idict_ref(cell value, int index, cell dict, int key_len) asm "DICTISETREF"; -builder begin_cell() asm "NEWC"; -builder store_ref(cell c, builder b) asm "STREF"; -builder zstore_uint(int x, builder b, int len) asm "STUX"; -builder zstore_int(int x, builder b, int len) asm "STIX"; -cell end_cell(builder b) asm "ENDC"; - -;; Simple configuration smart contract - -() recv_internal(cell in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(cell in_msg) impure { - var (signature, cs0) = load_bits(begin_parse(in_msg), 512); - var (msg_seqno, cs) = zload_uint(cs0, 32); - (var valid_until, cs) = zload_uint(cs, 32); - throw_if(35, valid_until < now()); - var (cfg_dict, cs2) = load_ref(begin_parse(get_data())); - (var stored_seqno, cs2) = zload_uint(cs2, 32); - (var public_key, cs2) = zload_uint(cs2, 256); - end_parse(cs2); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(cs0), signature, public_key)); - accept_message(); - (var param_index, cs) = zload_uint(cs, 32); - (var param_value, cs) = load_ref(cs); - end_parse(cs); -;; cfg_dict = set_idict_ref(param_value, param_index, cfg_dict, 32); -;; var cb = begin_cell(); -;; cb = store_ref(cfg_dict, cb); - var cb = store_ref(set_idict_ref(param_value, param_index, cfg_dict, 32), begin_cell()); - cb = zstore_uint(stored_seqno + 1, cb, 32); - cb = zstore_uint(public_key, cb, 256); - set_data(end_cell(cb)); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b2.fc b/submodules/ton/tonlib-src/crypto/func/test/b2.fc deleted file mode 100644 index 90322ae0..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b2.fc +++ /dev/null @@ -1,60 +0,0 @@ -int now() asm "NOW"; - -int cell_hash(cell c) -asm "HASHCU"; - -int slice_hash(slice s) -asm "HASHSU"; - -int check_signature(int hash, slice signature, int public_key) -asm "CHKSIGNU"; - -;; () throw_if(int excno, int cond) impure -;; asm "THROWARGIF"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -() accept_message() impure asm "ACCEPT"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF"; -;; (slice, int) load_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -;; (slice, int) load_uint(slice s, int len) asm( -> 1 0) "LDUX"; -;; int preload_int(slice s, int len) asm "PLDIX"; -;; int preload_uint(slice s, int len) asm "PLDUX"; -(slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX"; -slice preload_bits(slice s, int len) asm "PLDSLICEX"; -cell set_idict_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -builder begin_cell() asm "NEWC"; -builder store_ref(builder b, cell c) asm(c b) "STREF"; -;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX"; -;; builder store_int(builder b, int x, int len) asm(x b len) "STIX"; -cell end_cell(builder b) asm "ENDC"; - -;; Simple configuration smart contract - -() recv_internal(cell in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(cell in_msg) impure { - var (cs0, signature) = load_bits(begin_parse(in_msg), 512); - var (cs, msg_seqno) = load_uint(cs0, 32); - (cs, var valid_until) = load_uint(cs, 32); - throw_if(35, valid_until < now()); - var (cs2, cfg_dict) = load_ref(begin_parse(get_data())); - (cs2, var stored_seqno) = load_uint(cs2, 32); - (cs2, var public_key) = load_uint(cs2, 256); - end_parse(cs2); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(cs0), signature, public_key)); - accept_message(); - (cs, var param_index) = load_uint(cs, 32); - (cs, var param_value) = load_ref(cs); - end_parse(cs); - var cb = store_ref(begin_cell(), set_idict_ref(cfg_dict, 32, param_index, param_value)); - cb = store_uint(cb, stored_seqno + 1, 32); - cb = store_uint(cb, public_key, 256); - set_data(end_cell(cb)); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b2_0.fc b/submodules/ton/tonlib-src/crypto/func/test/b2_0.fc deleted file mode 100644 index c2783f86..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b2_0.fc +++ /dev/null @@ -1,63 +0,0 @@ -int now() asm "NOW"; - -int cell_hash(cell c) -asm "HASHCU"; - -int slice_hash(slice s) -asm "HASHSU"; - -int check_signature(int hash, slice signature, int public_key) -asm "CHKSIGNU"; - -;; () throw_if(int excno, int cond) impure -;; asm "THROWARGIF"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -() accept_message() impure asm "ACCEPT"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF"; -(slice, int) zload_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -(slice, int) zload_uint(slice s, int len) asm( -> 1 0) "LDUX"; -int zpreload_int(slice s, int len) asm "PLDIX"; -int zpreload_uint(slice s, int len) asm "PLDUX"; -(slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX"; -slice preload_bits(slice s, int len) asm "PLDSLICEX"; -cell set_idict_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -builder begin_cell() asm "NEWC"; -builder store_ref(builder b, cell c) asm(c b) "STREF"; -builder zstore_uint(builder b, int x, int len) asm(x b len) "STUX"; -builder zstore_int(builder b, int x, int len) asm(x b len) "STIX"; -cell end_cell(builder b) asm "ENDC"; - -;; Simple configuration smart contract - -() recv_internal(cell in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(cell in_msg) impure { - var (cs0, signature) = load_bits(begin_parse(in_msg), 512); - var (cs, msg_seqno) = zload_uint(cs0, 32); - (cs, var valid_until) = zload_uint(cs, 32); - throw_if(35, valid_until < now()); - var (cs2, cfg_dict) = load_ref(begin_parse(get_data())); - (cs2, var stored_seqno) = zload_uint(cs2, 32); - (cs2, var public_key) = zload_uint(cs2, 256); - end_parse(cs2); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(cs0), signature, public_key)); - accept_message(); - (cs, var param_index) = zload_uint(cs, 32); - (cs, var param_value) = load_ref(cs); - end_parse(cs); -;; cfg_dict = set_idict_ref(cfg_dict, 32, param_index, param_value); -;; var cb = begin_cell(); -;; cb = store_ref(cb, cfg_dict); - var cb = store_ref(begin_cell(), set_idict_ref(cfg_dict, 32, param_index, param_value)); - cb = zstore_uint(cb, stored_seqno + 1, 32); - cb = zstore_uint(cb, public_key, 256); - set_data(end_cell(cb)); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b2_1.fc b/submodules/ton/tonlib-src/crypto/func/test/b2_1.fc deleted file mode 100644 index 1ff79d05..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b2_1.fc +++ /dev/null @@ -1,62 +0,0 @@ -int now() asm "NOW"; - -int cell_hash(cell c) -asm "HASHCU"; - -int slice_hash(slice s) -asm "HASHSU"; - -int check_signature(int hash, slice signature, int public_key) -asm "CHKSIGNU"; - -;; () throw_if(int excno, int cond) impure -;; asm "THROWARGIF"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -() accept_message() impure asm "ACCEPT"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF"; -;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX"; -;; int preload_int(slice s, int len) asm "PLDIX"; -;; int preload_uint(slice s, int len) asm "PLDUX"; -(slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX"; -slice preload_bits(slice s, int len) asm "PLDSLICEX"; -cell set_idict_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -(cell, ()) ~set_idict_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -builder begin_cell() asm "NEWC"; -builder store_ref(builder b, cell c) asm(c b) "STREF"; -;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX"; -;; builder store_int(builder b, int x, int len) asm(x b len) "STIX"; -cell end_cell(builder b) asm "ENDC"; - -;; Simple configuration smart contract - -() recv_internal(cell in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(cell in_msg) impure { - var cs = begin_parse(in_msg); - var signature = cs~load_bits(512); - var cs0 = cs; - int msg_seqno = cs~load_uint(32); - var valid_until = cs~load_uint(32); - throw_if(35, valid_until < now()); - var cs2 = begin_parse(get_data()); - var cfg_dict = cs2~load_ref(); - var stored_seqno = cs2~load_uint(32); - var public_key = cs2~load_uint(256); - cs2.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(cs0), signature, public_key)); - accept_message(); - var param_index = cs~load_uint(32); - var param_value = cs~load_ref(); - cs.end_parse(); - cfg_dict~set_idict_ref(32, param_index, param_value); - set_data(begin_cell().store_ref(cfg_dict).store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b2_2.fc b/submodules/ton/tonlib-src/crypto/func/test/b2_2.fc deleted file mode 100644 index d137ff68..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b2_2.fc +++ /dev/null @@ -1,58 +0,0 @@ -int now() asm "NOW"; - -int cell_hash(cell c) -asm "HASHCU"; - -int slice_hash(slice s) -asm "HASHSU"; - -int check_signature(int hash, slice signature, int public_key) -asm "CHKSIGNU"; - -;; () throw_if(int excno, int cond) impure -;; asm "THROWARGIF"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -() accept_message() impure asm "ACCEPT"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF"; -;; (slice, int) load_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -;; (slice, int) load_uint(slice s, int len) asm( -> 1 0) "LDUX"; -;; int .preload_int(slice s, int len) asm "PLDIX"; -;; int .preload_uint(slice s, int len) asm "PLDUX"; -(slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX"; -;; slice .preload_bits(slice s, int len) asm "PLDSLICEX"; -cell set_idict_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -builder begin_cell() asm "NEWC"; -builder store_ref(builder b, cell c) asm(c b) "STREF"; -;;builder .store_uint(builder b, int x, int len) asm(x b len) "STUX"; -;;builder .store_int(builder b, int x, int len) asm(x b len) "STIX"; -cell .end_cell(builder b) asm "ENDC"; - -;; Simple configuration smart contract - -() recv_internal(cell in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(cell in_msg) impure { - var (cs0, signature) = load_bits(begin_parse(in_msg), 512); - var (cs, msg_seqno) = load_uint(cs0, 32); - (cs, var valid_until) = load_uint(cs, 32); - throw_if(35, valid_until < now()); - var (cs2, cfg_dict) = load_ref(begin_parse(get_data())); - (cs2, var stored_seqno) = load_uint(cs2, 32); - (cs2, var public_key) = load_uint(cs2, 256); - end_parse(cs2); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(cs0), signature, public_key)); - accept_message(); - (cs, var param_index) = load_uint(cs, 32); - (cs, var param_value) = load_ref(cs); - end_parse(cs); - set_data(begin_cell().store_ref(cfg_dict.set_idict_ref(32, param_index, param_value)) - .store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b3.fc b/submodules/ton/tonlib-src/crypto/func/test/b3.fc deleted file mode 100644 index 0e1e4034..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/b3.fc +++ /dev/null @@ -1,20 +0,0 @@ -;; inline test -_ unpack() inline { - var ds = get_data().begin_parse(); - var res = (ds~load_uint(8), ds~load_int(32), ds~load_int(32)); - return res; -} - -() pack(a, x, y) impure inline_ref { - set_data(begin_cell() - .store_uint(a, 8) - .store_int(x, 32) - .store_int(y, 32) - .end_cell()); -} - -() main() impure { - var (a, x, y) = unpack(); - x += y; - pack(a, x, y); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/c1.fc b/submodules/ton/tonlib-src/crypto/func/test/c1.fc deleted file mode 100644 index 1a07baca..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/c1.fc +++ /dev/null @@ -1,37 +0,0 @@ -global int x, y, z; -global (cell, slice) y; -global ((int, int) -> int) op; - -_ get() { - var t = z + 1; - return x; -} - -_ pre_next() { - return x + 1; -} - -() init() impure { - ;; global x; - x = 0; -} - -int next() impure { - ;; global x; - return x += 1; -} - -_ set_y(x, w) { - y = (w, x); -} - -_ get_y() impure { - return y; -} - -int main(int c) { - init(); - c += next(); - return c + pre_next(); -} - diff --git a/submodules/ton/tonlib-src/crypto/func/test/c2.fc b/submodules/ton/tonlib-src/crypto/func/test/c2.fc deleted file mode 100644 index 277c7053..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/c2.fc +++ /dev/null @@ -1,10 +0,0 @@ -global ((int, int) -> int) op; - -int check_assoc(int a, int b, int c) { - return op(op(a, b), c) == op(a, op(b, c)); -} - -int main() { - op = _+_; - return check_assoc(2, 3, 9); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/c2_1.fc b/submodules/ton/tonlib-src/crypto/func/test/c2_1.fc deleted file mode 100644 index 3bf863a6..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/c2_1.fc +++ /dev/null @@ -1,7 +0,0 @@ -_ check_assoc(op, a, b, c) { - return op(op(a, b), c) == op(a, op(b, c)); -} - -int main() { - return check_assoc(_+_, 2, 3, 9); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w1.fc b/submodules/ton/tonlib-src/crypto/func/test/w1.fc deleted file mode 100644 index 6efd4f3e..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w1.fc +++ /dev/null @@ -1,9 +0,0 @@ -(int, int) nested_if(int id) method_id { - dump_stack(); - if (id > 0) { - if (id > 10) { - return (2 * id, 3 * id); - } - } - return (5, 6); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w2.fc b/submodules/ton/tonlib-src/crypto/func/test/w2.fc deleted file mode 100644 index 3bbcd415..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w2.fc +++ /dev/null @@ -1,14 +0,0 @@ -_ f(cs) { - return (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), - cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), - cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), - cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), - cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8)); -} - -_ main(cs) { - var (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, - x11, x12, x13, x14, x15, x16, x17, x18, x19) = f(cs); - return x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 - + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w3.fc b/submodules/ton/tonlib-src/crypto/func/test/w3.fc deleted file mode 100644 index 0de8e551..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w3.fc +++ /dev/null @@ -1,13 +0,0 @@ -() main(cs) impure { - int i = 0; - if (cs.slice_refs()) { - do { - i = i + 1; - } until(i > 10); - } - set_data(begin_cell() - .store_uint(1, 32) - .store_uint(2, 32) - .store_uint(i, 32) - .end_cell()); -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w4.fc b/submodules/ton/tonlib-src/crypto/func/test/w4.fc deleted file mode 100644 index 1c0e2cef..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w4.fc +++ /dev/null @@ -1,13 +0,0 @@ -_ main(cell dict, int t3) { - int index = -1; - do { - (index, slice value, int found) = dict.udict_get_next?(32, index); - if (found) { - (int temp1, int temp2) = (value~load_uint(16), value~load_uint(32)); - if (t3 > temp2) { - dict~udict_delete_get?(32, index); - } - } - } until ( ~ found); - return dict; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w5.fc b/submodules/ton/tonlib-src/crypto/func/test/w5.fc deleted file mode 100644 index 330a5050..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w5.fc +++ /dev/null @@ -1,14 +0,0 @@ -(cell) recv_external(slice in_msg) impure { - cell mydict = new_dict(); - builder r = begin_cell().store_int(10, 16); - mydict~udict_set_builder(32, 1, r ); - int index = -1; - do { - (var index, var value, var found) = mydict.udict_get_next?(32, index); - } until ( ~ found ); - return mydict; -} - -() recv_internal() impure { - ;; Nothing -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w6.fc b/submodules/ton/tonlib-src/crypto/func/test/w6.fc deleted file mode 100644 index 37251a58..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w6.fc +++ /dev/null @@ -1,12 +0,0 @@ -int test(int x) method_id { - int i = 0; - ;; int f = false; - do { - i = i + 1; - if (i > 5) { - return 1; - } - int f = (i * i == 64); - } until (f); - return -1; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w7.fc b/submodules/ton/tonlib-src/crypto/func/test/w7.fc deleted file mode 100644 index dddfd627..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w7.fc +++ /dev/null @@ -1,14 +0,0 @@ -int test(int y) { - int x = 1; - if (y > 0) { - return 1; - } - return x > 0; -} - -int f(int y) { - if (y > 0) { - return 1; - } - return 2; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w8.fc b/submodules/ton/tonlib-src/crypto/func/test/w8.fc deleted file mode 100644 index bd0696e7..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w8.fc +++ /dev/null @@ -1,22 +0,0 @@ -int check_signatures(msg_hash, signatures, signers, bitmask_size) impure { - var bitmask = 0; - var id = -1; - do { - (id, var signature, var f) = signatures.udict_get_next?(32, id); - if (f){ - var sig = signature.preload_bits(512); - var public_key = -1; - do { - (public_key, var cs, var _found) = signers.udict_get_next?(256, public_key); - if (_found){ - if (check_signature(msg_hash, sig, public_key)){ - var signer_index = cs~load_uint(bitmask_size); - bitmask = bitmask | (1 << (signer_index - 1)); - } - } - } until (~ _found); - ;; signature~touch(); - } - } until (~ f); - return bitmask; -} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w9.fc b/submodules/ton/tonlib-src/crypto/func/test/w9.fc deleted file mode 100644 index d9435542..00000000 --- a/submodules/ton/tonlib-src/crypto/func/test/w9.fc +++ /dev/null @@ -1,8 +0,0 @@ -_ g(s) { - var (z, t) = (17, s); - while (z > 0) { - t = s; - z -= 1; - } - return ~ t; -} diff --git a/submodules/ton/tonlib-src/crypto/func/unify-types.cpp b/submodules/ton/tonlib-src/crypto/func/unify-types.cpp deleted file mode 100644 index 517299e9..00000000 --- a/submodules/ton/tonlib-src/crypto/func/unify-types.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "func.h" - -namespace funC { - -/* - * - * TYPE EXPRESSIONS - * - */ - -int TypeExpr::holes = 0, TypeExpr::type_vars = 0; // not thread safe, but it is ok for now - -void TypeExpr::compute_width() { - switch (constr) { - case te_Atomic: - case te_Map: - minw = maxw = 1; - break; - case te_Tensor: - minw = maxw = 0; - for (TypeExpr* arg : args) { - minw += arg->minw; - maxw += arg->maxw; - } - if (minw > w_inf) { - minw = w_inf; - } - if (maxw > w_inf) { - maxw = w_inf; - } - break; - case te_Tuple: - minw = maxw = 1; - for (TypeExpr* arg : args) { - arg->compute_width(); - } - break; - case te_Indirect: - minw = args[0]->minw; - maxw = args[0]->maxw; - break; - default: - minw = 0; - maxw = w_inf; - break; - } -} - -bool TypeExpr::recompute_width() { - switch (constr) { - case te_Tensor: - case te_Indirect: { - int min = 0, max = 0; - for (TypeExpr* arg : args) { - min += arg->minw; - max += arg->maxw; - } - if (min > maxw || max < minw) { - return false; - } - if (min > w_inf) { - min = w_inf; - } - if (max > w_inf) { - max = w_inf; - } - if (minw < min) { - minw = min; - } - if (maxw > max) { - maxw = max; - } - return true; - } - case te_Tuple: { - for (TypeExpr* arg : args) { - if (arg->minw > 1 || arg->maxw < 1 || arg->minw > arg->maxw) { - return false; - } - } - return true; - } - default: - return false; - } -} - -int TypeExpr::extract_components(std::vector& comp_list) { - if (constr != te_Indirect && constr != te_Tensor) { - comp_list.push_back(this); - return 1; - } - int res = 0; - for (TypeExpr* arg : args) { - res += arg->extract_components(comp_list); - } - return res; -} - -TypeExpr* TypeExpr::new_map(TypeExpr* from, TypeExpr* to) { - return new TypeExpr{te_Map, std::vector{from, to}}; -} - -void TypeExpr::replace_with(TypeExpr* te2) { - if (te2 == this) { - return; - } - constr = te_Indirect; - value = 0; - minw = te2->minw; - maxw = te2->maxw; - args.clear(); - args.push_back(te2); -} - -bool TypeExpr::remove_indirect(TypeExpr*& te, TypeExpr* forbidden) { - assert(te); - while (te->constr == te_Indirect) { - te = te->args[0]; - } - if (te->constr == te_Unknown) { - return te != forbidden; - } - bool res = true; - for (auto& x : te->args) { - res &= remove_indirect(x, forbidden); - } - return res; -} - -bool TypeExpr::remove_forall(TypeExpr*& te) { - assert(te); - if (te->constr != te_ForAll) { - return false; - } - assert(te->args.size() >= 1); - std::vector new_vars; - for (std::size_t i = 1; i < te->args.size(); i++) { - new_vars.push_back(new_hole(1)); - } - TypeExpr* te2 = te; - // std::cerr << "removing universal quantifier in " << te << std::endl; - te = te->args[0]; - remove_forall_in(te, te2, new_vars); - // std::cerr << "-> " << te << std::endl; - return true; -} - -bool TypeExpr::remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector& new_vars) { - assert(te); - assert(te2 && te2->constr == te_ForAll); - if (te->constr == te_Var) { - for (std::size_t i = 0; i < new_vars.size(); i++) { - if (te == te2->args[i + 1]) { - te = new_vars[i]; - return true; - } - } - return false; - } - if (te->constr == te_ForAll) { - return false; - } - if (te->args.empty()) { - return false; - } - auto te1 = new TypeExpr(*te); - bool res = false; - for (auto& arg : te1->args) { - res |= remove_forall_in(arg, te2, new_vars); - } - if (res) { - te = te1; - } else { - delete te1; - } - return res; -} - -void TypeExpr::show_width(std::ostream& os) { - os << minw; - if (maxw != minw) { - os << ".."; - if (maxw < w_inf) { - os << maxw; - } - } -} - -std::ostream& operator<<(std::ostream& os, TypeExpr* type_expr) { - if (!type_expr) { - return os << "(null-type-ptr)"; - } - return type_expr->print(os); -} - -std::ostream& TypeExpr::print(std::ostream& os, int lex_level) { - switch (constr) { - case te_Unknown: - return os << "??" << value; - case te_Var: - if (value >= -26 && value < 0) { - return os << "_" << (char)(91 + value); - } else if (value >= 0 && value < 26) { - return os << (char)(65 + value); - } else { - return os << "TVAR" << value; - } - case te_Indirect: - return os << args[0]; - case te_Atomic: { - switch (value) { - case _Int: - return os << "int"; - case _Cell: - return os << "cell"; - case _Slice: - return os << "slice"; - case _Builder: - return os << "builder"; - case _Cont: - return os << "cont"; - case _Tuple: - return os << "tuple"; - case _Type: - return os << "type"; - default: - return os << "atomic-type-" << value; - } - } - case te_Tensor: { - if (lex_level > -127) { - os << "("; - } - auto c = args.size(); - if (c) { - for (const auto& x : args) { - x->print(os); - if (--c) { - os << ", "; - } - } - } - if (lex_level > -127) { - os << ")"; - } - return os; - } - case te_Tuple: { - os << "["; - auto c = args.size(); - if (c == 1 && args[0]->constr == te_Tensor) { - args[0]->print(os, -127); - } else if (c) { - for (const auto& x : args) { - x->print(os); - if (--c) { - os << ", "; - } - } - } - return os << "]"; - } - case te_Map: { - assert(args.size() == 2); - if (lex_level > 0) { - os << "("; - } - args[0]->print(os, 1); - os << " -> "; - args[1]->print(os); - if (lex_level > 0) { - os << ")"; - } - return os; - } - case te_ForAll: { - assert(args.size() >= 1); - if (lex_level > 0) { - os << '('; - } - os << "Forall "; - for (std::size_t i = 1; i < args.size(); i++) { - os << (i > 1 ? ' ' : '('); - args[i]->print(os); - } - os << ") "; - args[0]->print(os); - if (lex_level > 0) { - os << ')'; - } - return os; - } - default: - return os << "unknown-type-expr-" << constr; - } -} - -void UnifyError::print_message(std::ostream& os) const { - os << "cannot unify type " << te1 << " with " << te2; - if (!msg.empty()) { - os << ": " << msg; - } -} - -std::ostream& operator<<(std::ostream& os, const UnifyError& ue) { - ue.print_message(os); - return os; -} - -std::string UnifyError::message() const { - std::ostringstream os; - UnifyError::print_message(os); - return os.str(); -} - -void check_width_compat(TypeExpr* te1, TypeExpr* te2) { - if (te1->minw > te2->maxw || te2->minw > te1->maxw) { - std::ostringstream os{"cannot unify types of widths ", std::ios_base::ate}; - te1->show_width(os); - os << " and "; - te2->show_width(os); - throw UnifyError{te1, te2, os.str()}; - } -} - -void check_update_widths(TypeExpr* te1, TypeExpr* te2) { - check_width_compat(te1, te2); - te1->minw = te2->minw = std::max(te1->minw, te2->minw); - te1->maxw = te2->maxw = std::min(te1->maxw, te2->maxw); - assert(te1->minw <= te1->maxw); -} - -void unify(TypeExpr*& te1, TypeExpr*& te2) { - assert(te1 && te2); - // std::cerr << "unify( " << te1 << " , " << te2 << " )\n"; - while (te1->constr == TypeExpr::te_Indirect) { - te1 = te1->args[0]; - } - while (te2->constr == TypeExpr::te_Indirect) { - te2 = te2->args[0]; - } - if (te1 == te2) { - return; - } - if (te1->constr == TypeExpr::te_ForAll) { - TypeExpr* te = te1; - if (!TypeExpr::remove_forall(te)) { - throw UnifyError{te1, te2, "cannot remove universal type quantifier while performing type unification"}; - } - unify(te, te2); - return; - } - if (te2->constr == TypeExpr::te_ForAll) { - TypeExpr* te = te2; - if (!TypeExpr::remove_forall(te)) { - throw UnifyError{te2, te1, "cannot remove universal type quantifier while performing type unification"}; - } - unify(te1, te); - return; - } - if (te1->constr == TypeExpr::te_Unknown) { - if (te2->constr == TypeExpr::te_Unknown) { - assert(te1->value != te2->value); - } - if (!TypeExpr::remove_indirect(te2, te1)) { - throw UnifyError{te1, te2, "type unification results in an infinite cyclic type"}; - } - check_update_widths(te1, te2); - te1->replace_with(te2); - te1 = te2; - return; - } - if (te2->constr == TypeExpr::te_Unknown) { - if (!TypeExpr::remove_indirect(te1, te2)) { - throw UnifyError{te2, te1, "type unification results in an infinite cyclic type"}; - } - check_update_widths(te2, te1); - te2->replace_with(te1); - te2 = te1; - return; - } - if (te1->constr != te2->constr || te1->value != te2->value || te1->args.size() != te2->args.size()) { - throw UnifyError{te1, te2}; - } - for (std::size_t i = 0; i < te1->args.size(); i++) { - unify(te1->args[i], te2->args[i]); - } - if (te1->constr == TypeExpr::te_Tensor) { - if (!te1->recompute_width()) { - throw UnifyError{te1, te2, "type unification incompatible with known width of first type"}; - } - if (!te2->recompute_width()) { - throw UnifyError{te2, te1, "type unification incompatible with known width of first type"}; - } - check_update_widths(te1, te2); - } - te1->replace_with(te2); - te1 = te2; -} - -} // namespace funC diff --git a/submodules/ton/tonlib-src/crypto/openssl/bignum.cpp b/submodules/ton/tonlib-src/crypto/openssl/bignum.cpp deleted file mode 100644 index 74dd6bbf..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/bignum.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "openssl/bignum.h" - -#ifdef OPENSSL_IS_BORINGSSL -#include -#endif - -// impl only -#include - -namespace arith { - -BN_CTX* get_ctx(void) { - thread_local BN_CTX* ctx = BN_CTX_new(); - return ctx; -} - -BignumBitref& BignumBitref::operator=(bool val) { - if (val) { - BN_set_bit(ptr, n); - } else { - BN_clear_bit(ptr, n); - } - return *this; -} - -const Bignum operator+(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_add(z.bn_ptr(), x.bn_ptr(), y.bn_ptr())); - return z; -} - -const Bignum operator+(const Bignum& x, long y) { - if (y > 0) { - Bignum z(x); - bn_assert(BN_add_word(z.bn_ptr(), y)); - return z; - } else if (y < 0) { - Bignum z(x); - bn_assert(BN_sub_word(z.bn_ptr(), -y)); - return z; - } else { - return x; - } -} - -/* - const Bignum operator+ (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_add_word (x.bn_ptr(), y)); - } else if (y < 0) { - bn_assert (BN_sub_word (x.bn_ptr(), -y)); - } - return std::move (x); - } - */ - -/* - const Bignum operator+ (long y, Bignum&& x) { - return x + y; - } - */ - -const Bignum operator-(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_sub(z.bn_ptr(), x.bn_ptr(), y.bn_ptr())); - return z; -} - -/* - const Bignum operator- (Bignum&& x, long y) { - return x + (-y); - } - */ - -const Bignum operator*(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_mul(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -const Bignum operator*(const Bignum& x, long y) { - if (y > 0) { - Bignum z(x); - bn_assert(BN_mul_word(z.bn_ptr(), y)); - return z; - } else if (y < 0) { - Bignum z(x); - z.negate(); - bn_assert(BN_mul_word(z.bn_ptr(), -y)); - return z; - } else { - Bignum z(0); - return z; - } -} - -/* - const Bignum operator* (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_mul_word (x.bn_ptr(), y)); - } else if (y < 0) { - x.negate(); - bn_assert (BN_mul_word (x.bn_ptr(), -y)); - } else { - x = 0; - } - return std::move (x); - } - */ - -const Bignum operator/(const Bignum& x, const Bignum& y) { - Bignum z, w; - bn_assert(BN_div(z.bn_ptr(), w.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -const Bignum Bignum::divmod(const Bignum& y) { - Bignum w; - bn_assert(BN_div(val, w.bn_ptr(), val, y.bn_ptr(), get_ctx())); - return w; -} - -const Bignum operator%(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_mod(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -unsigned long operator%(const Bignum& x, unsigned long y) { - BN_ULONG rem = BN_mod_word(x.bn_ptr(), y); - bn_assert(rem != (BN_ULONG)(-1)); - return static_cast(rem); -} - -const Bignum operator<<(const Bignum& x, int r) { - Bignum z; - bn_assert(BN_lshift(z.bn_ptr(), x.bn_ptr(), r)); - return z; -} - -const Bignum operator>>(const Bignum& x, int r) { - Bignum z; - bn_assert(BN_rshift(z.bn_ptr(), x.bn_ptr(), r)); - return z; -} - -const Bignum abs(const Bignum& x) { - Bignum T(x); - if (T.sign() < 0) { - T.negate(); - } - return T; -} - -const Bignum sqr(const Bignum& x) { - Bignum z; - bn_assert(BN_sqr(z.bn_ptr(), x.bn_ptr(), get_ctx())); - return z; -} - -void Bignum::export_msb(unsigned char* buffer, std::size_t size) const { - bn_assert(size <= (1 << 20)); - bn_assert(sign() >= 0); - std::size_t n = BN_num_bytes(val); - bn_assert(n <= size); - bn_assert(BN_bn2bin(val, buffer + size - n) == static_cast(n)); - std::memset(buffer, 0, size - n); -} - -Bignum& Bignum::import_msb(const unsigned char* buffer, std::size_t size) { - bn_assert(size <= (1 << 20)); - std::size_t i = 0; - while (i < size && !buffer[i]) { - i++; - } - bn_assert(BN_bin2bn(buffer + i, static_cast(size - i), val) == val); - return *this; -} - -void Bignum::export_lsb(unsigned char* buffer, std::size_t size) const { - bn_assert(size <= (1 << 20)); - bn_assert(sign() >= 0); - std::size_t n = BN_num_bytes(val); - bn_assert(n <= size); - bn_assert(BN_bn2bin(val, buffer) == (int)n); - std::memset(buffer + n, 0, size - n); - for (std::size_t i = 0; 2 * i + 1 < n; i++) { - std::swap(buffer[i], buffer[n - 1 - i]); - } -} - -Bignum& Bignum::import_lsb(const unsigned char* buffer, std::size_t size) { - bn_assert(size <= (1 << 20)); - while (size > 0 && !buffer[size - 1]) { - size--; - } - if (!size) { - // Use BN_set_word, because from 1.1.0 BN_zero may return void - bn_assert(BN_set_word(val, 0)); - return *this; - } - unsigned char tmp_buff[1024]; - unsigned char* tmp = (size < 1024 ? tmp_buff : new unsigned char[size]); - unsigned char* ptr = tmp + size; - for (std::size_t i = 0; i < size; i++) { - *--ptr = buffer[i]; - } - bn_assert(BN_bin2bn(tmp, static_cast(size), val) == val); - if (tmp != tmp_buff) { - delete[] tmp; - } - return *this; -} - -std::string Bignum::to_str() const { - char* ptr = BN_bn2dec(val); - std::string z(ptr); - OPENSSL_free(ptr); - return z; -} - -std::string Bignum::to_hex() const { - char* ptr = BN_bn2hex(val); - std::string z(ptr); - OPENSSL_free(ptr); - return z; -} - -std::ostream& operator<<(std::ostream& os, const Bignum& x) { - return os << x.to_str(); -} - -std::istream& operator>>(std::istream& is, Bignum& x) { - std::string word; - is >> word; - x = dec_string(word); - return is; -} - -bool is_prime(const Bignum& p, int nchecks, bool trial_div) { - return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), trial_div, 0); -} -} // namespace arith diff --git a/submodules/ton/tonlib-src/crypto/openssl/bignum.h b/submodules/ton/tonlib-src/crypto/openssl/bignum.h deleted file mode 100644 index 2a8dd8a0..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/bignum.h +++ /dev/null @@ -1,384 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include - -#include -#include "td/utils/bits.h" -#include "td/utils/misc.h" - -namespace arith { -struct dec_string { - std::string str; - explicit dec_string(const std::string& s) : str(s) { - } -}; - -struct hex_string { - std::string str; - explicit hex_string(const std::string& s) : str(s) { - } -}; - -struct bin_string { - std::string str; - explicit bin_string(const std::string& s) : str(s) { - } -}; -} // namespace arith - -namespace arith { - -inline void bn_assert(int cond); -BN_CTX* get_ctx(); - -class BignumBitref { - BIGNUM* ptr; - int n; - - public: - BignumBitref(BIGNUM* x, int _n) : ptr(x), n(_n){}; - operator bool() const { - return BN_is_bit_set(ptr, n); - } - BignumBitref& operator=(bool val); -}; - -class Bignum { - BIGNUM* val; - - public: - class bignum_error {}; - Bignum() { - val = BN_new(); - } - Bignum(long x) { - val = BN_new(); - set_long(x); - } - ~Bignum() { - BN_free(val); - } - Bignum(const bin_string& bs) { - val = BN_new(); - set_raw_bytes(bs.str); - } - Bignum(const dec_string& ds) { - val = BN_new(); - set_dec_str(ds.str); - } - Bignum(const hex_string& hs) { - val = BN_new(); - set_hex_str(hs.str); - } - Bignum(const Bignum& x) { - val = BN_new(); - BN_copy(val, x.val); - } - //Bignum (Bignum&& x) { val = x.val; } - void clear() { - BN_clear(val); - } // use this for sensitive data - Bignum& operator=(const Bignum& x) { - BN_copy(val, x.val); - return *this; - } - Bignum& operator=(Bignum&& x) { - swap(x); - return *this; - } - Bignum& operator=(long x) { - return set_long(x); - } - Bignum& operator=(const dec_string& ds) { - return set_dec_str(ds.str); - } - Bignum& operator=(const hex_string& hs) { - return set_hex_str(hs.str); - } - Bignum& swap(Bignum& x) { - std::swap(val, x.val); - return *this; - } - BIGNUM* bn_ptr() { - return val; - } - const BIGNUM* bn_ptr() const { - return val; - } - bool is_zero() const { - return BN_is_zero(val); - } - int sign() const { - return BN_is_zero(val) ? 0 : (BN_is_negative(val) ? -1 : 1); - } - bool odd() const { - return BN_is_odd(val); - } - int num_bits() const { - return BN_num_bits(val); - } - int num_bytes() const { - return BN_num_bytes(val); - } - bool operator[](int n) const { - return BN_is_bit_set(val, n); - } - BignumBitref operator[](int n) { - return BignumBitref(val, n); - } - void export_msb(unsigned char* buffer, std::size_t size) const; - Bignum& import_msb(const unsigned char* buffer, std::size_t size); - Bignum& import_msb(const std::string& s) { - return import_msb((const unsigned char*)s.c_str(), s.size()); - } - void export_lsb(unsigned char* buffer, std::size_t size) const; - Bignum& import_lsb(const unsigned char* buffer, std::size_t size); - Bignum& import_lsb(const std::string& s) { - return import_lsb((const unsigned char*)s.c_str(), s.size()); - } - - Bignum& set_dec_str(std::string s) { - bn_assert(BN_dec2bn(&val, s.c_str())); - return *this; - } - - Bignum& set_raw_bytes(std::string s) { - CHECK(BN_bin2bn(reinterpret_cast(s.c_str()), td::narrow_cast(s.size()), val)); - return *this; - } - - Bignum& set_hex_str(std::string s) { - bn_assert(BN_hex2bn(&val, s.c_str())); - return *this; - } - - Bignum& set_ulong(unsigned long x) { - bn_assert(BN_set_word(val, x)); - return *this; - } - - Bignum& set_long(long x) { - set_ulong(std::abs(x)); - return x < 0 ? negate() : *this; - } - - Bignum& negate() { - BN_set_negative(val, !BN_is_negative(val)); - return *this; - } - - Bignum& operator+=(const Bignum& y) { - bn_assert(BN_add(val, val, y.val)); - return *this; - } - - Bignum& operator+=(long y) { - bn_assert((y >= 0 ? BN_add_word : BN_sub_word)(val, std::abs(y))); - return *this; - } - - Bignum& operator-=(long y) { - bn_assert((y >= 0 ? BN_sub_word : BN_add_word)(val, std::abs(y))); - return *this; - } - - Bignum& operator*=(const Bignum& y) { - bn_assert(BN_mul(val, val, y.val, get_ctx())); - return *this; - } - - Bignum& operator*=(long y) { - if (y < 0) { - negate(); - } - bn_assert(BN_mul_word(val, std::abs(y))); - return *this; - } - - Bignum& operator<<=(int r) { - bn_assert(BN_lshift(val, val, r)); - return *this; - } - - Bignum& operator>>=(int r) { - bn_assert(BN_rshift(val, val, r)); - return *this; - } - - Bignum& operator/=(const Bignum& y) { - Bignum w; - bn_assert(BN_div(val, w.val, val, y.val, get_ctx())); - return *this; - } - - Bignum& operator/=(long y) { - bn_assert(BN_div_word(val, std::abs(y)) != (BN_ULONG)(-1)); - return y < 0 ? negate() : *this; - } - - Bignum& operator%=(const Bignum& y) { - bn_assert(BN_mod(val, val, y.val, get_ctx())); - return *this; - } - - Bignum& operator%=(long y) { - BN_ULONG rem = BN_mod_word(val, std::abs(y)); - bn_assert(rem != (BN_ULONG)(-1)); - return set_long(static_cast(y < 0 ? td::bits_negate64(rem) : rem)); - } - - unsigned long divmod(unsigned long y) { - BN_ULONG rem = BN_div_word(val, y); - bn_assert(rem != (BN_ULONG)(-1)); - return static_cast(rem); - } - - const Bignum divmod(const Bignum& y); - - std::string to_str() const; - std::string to_hex() const; -}; - -inline void bn_assert(int cond) { - if (!cond) { - throw Bignum::bignum_error(); - } -} - -BN_CTX* get_ctx(void); - -const Bignum operator+(const Bignum& x, const Bignum& y); -const Bignum operator+(const Bignum& x, long y); - -/* - const Bignum operator+ (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_add_word (x.bn_ptr(), y)); - } else if (y < 0) { - bn_assert (BN_sub_word (x.bn_ptr(), -y)); - } - return std::move (x); - } - */ - -inline const Bignum operator+(long y, const Bignum& x) { - return x + y; -} - -/* - const Bignum operator+ (long y, Bignum&& x) { - return x + y; - } - */ - -const Bignum operator-(const Bignum& x, const Bignum& y); -inline const Bignum operator-(const Bignum& x, long y) { - return x + (-y); -} - -/* - const Bignum operator- (Bignum&& x, long y) { - return x + (-y); - } - */ - -const Bignum operator*(const Bignum& x, const Bignum& y); -const Bignum operator*(const Bignum& x, long y); - -/* - const Bignum operator* (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_mul_word (x.bn_ptr(), y)); - } else if (y < 0) { - x.negate(); - bn_assert (BN_mul_word (x.bn_ptr(), -y)); - } else { - x = 0; - } - return std::move (x); - } - */ - -inline const Bignum operator*(long y, const Bignum& x) { - return x * y; -} - -const Bignum operator/(const Bignum& x, const Bignum& y); -const Bignum operator%(const Bignum& x, const Bignum& y); -unsigned long operator%(const Bignum& x, unsigned long y); - -const Bignum operator<<(const Bignum& x, int r); -const Bignum operator>>(const Bignum& x, int r); - -const Bignum abs(const Bignum& x); -const Bignum sqr(const Bignum& x); - -std::ostream& operator<<(std::ostream& os, const Bignum& x); -std::istream& operator>>(std::istream& is, Bignum& x); - -bool is_prime(const Bignum& p, int nchecks = 64, bool trial_div = true); - -inline int cmp(const Bignum& x, const Bignum& y) { - return BN_cmp(x.bn_ptr(), y.bn_ptr()); -} - -inline bool operator==(const Bignum& x, const Bignum& y) { - return cmp(x, y) == 0; -} - -inline bool operator!=(const Bignum& x, const Bignum& y) { - return cmp(x, y) != 0; -} - -inline bool operator<(const Bignum& x, const Bignum& y) { - return cmp(x, y) < 0; -} - -inline bool operator<=(const Bignum& x, const Bignum& y) { - return cmp(x, y) <= 0; -} - -inline bool operator>(const Bignum& x, const Bignum& y) { - return cmp(x, y) > 0; -} - -inline bool operator>=(const Bignum& x, const Bignum& y) { - return cmp(x, y) >= 0; -} - -inline bool operator==(const Bignum& x, long y) { - if (y >= 0) { - return BN_is_word(x.bn_ptr(), y); - } else { - return x == Bignum(y); - } -} - -inline bool operator!=(const Bignum& x, long y) { - if (y >= 0) { - return !BN_is_word(x.bn_ptr(), y); - } else { - return x != Bignum(y); - } -} - -} // namespace arith diff --git a/submodules/ton/tonlib-src/crypto/openssl/digest.h b/submodules/ton/tonlib-src/crypto/openssl/digest.h deleted file mode 100644 index d0dfc4c0..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/digest.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2019 Telegram Systems LLP -*/ -#pragma once -#include - -#include -#include - -#include "td/utils/Slice.h" - -namespace digest { -struct OpensslEVP_SHA1 { - enum { digest_bytes = 20 }; - static const EVP_MD *get_evp() { - return EVP_sha1(); - } -}; - -struct OpensslEVP_SHA256 { - enum { digest_bytes = 32 }; - static const EVP_MD *get_evp() { - return EVP_sha256(); - } -}; - -struct OpensslEVP_SHA512 { - enum { digest_bytes = 64 }; - static const EVP_MD *get_evp() { - return EVP_sha512(); - } -}; - -template -class HashCtx { - EVP_MD_CTX *ctx{nullptr}; - void init(); - void clear(); - - public: - enum { digest_bytes = H::digest_bytes }; - HashCtx() { - init(); - } - HashCtx(const void *data, std::size_t len) { - init(); - feed(data, len); - } - ~HashCtx() { - clear(); - } - void reset(); - void feed(const void *data, std::size_t len); - void feed(td::Slice slice) { - feed(slice.data(), slice.size()); - } - std::size_t extract(unsigned char buffer[digest_bytes]); - std::size_t extract(td::MutableSlice slice); - std::string extract(); -}; - -template -void HashCtx::init() { - ctx = EVP_MD_CTX_create(); - reset(); -} - -template -void HashCtx::reset() { - EVP_DigestInit_ex(ctx, H::get_evp(), 0); -} - -template -void HashCtx::clear() { - EVP_MD_CTX_destroy(ctx); - ctx = nullptr; -} - -template -void HashCtx::feed(const void *data, std::size_t len) { - EVP_DigestUpdate(ctx, data, len); -} - -template -std::size_t HashCtx::extract(unsigned char buffer[digest_bytes]) { - unsigned olen = 0; - EVP_DigestFinal_ex(ctx, buffer, &olen); - assert(olen == digest_bytes); - return olen; -} - -template -std::size_t HashCtx::extract(td::MutableSlice slice) { - return extract(slice.ubegin()); -} - -template -std::string HashCtx::extract() { - unsigned char buffer[digest_bytes]; - unsigned olen = 0; - EVP_DigestFinal_ex(ctx, buffer, &olen); - assert(olen == digest_bytes); - return std::string((char *)buffer, olen); -} - -typedef HashCtx SHA1; -typedef HashCtx SHA256; -typedef HashCtx SHA512; - -template -std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void *data, std::size_t size) { - T hasher(data, size); - return hasher.extract(buffer); -} - -template -std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void *data1, std::size_t size1, const void *data2, - std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(buffer); -} - -template -std::string hash_str(const void *data, std::size_t size) { - T hasher(data, size); - return hasher.extract(); -} - -template -std::string hash_two_str(const void *data1, std::size_t size1, const void *data2, std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(); -} -} // namespace digest diff --git a/submodules/ton/tonlib-src/crypto/openssl/digest.hpp b/submodules/ton/tonlib-src/crypto/openssl/digest.hpp deleted file mode 100644 index 5c232df9..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/digest.hpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include - -#include -#include - -#include "td/utils/Slice.h" - -namespace digest { -struct OpensslEVP_SHA1 { - enum { digest_bytes = 20 }; - static const EVP_MD *get_evp() { - return EVP_sha1(); - } -}; - -struct OpensslEVP_SHA256 { - enum { digest_bytes = 32 }; - static const EVP_MD *get_evp() { - return EVP_sha256(); - } -}; - -struct OpensslEVP_SHA512 { - enum { digest_bytes = 64 }; - static const EVP_MD *get_evp() { - return EVP_sha512(); - } -}; - -template -class HashCtx { - EVP_MD_CTX *ctx{nullptr}; - void init(); - void clear(); - - public: - enum { digest_bytes = H::digest_bytes }; - HashCtx() { - init(); - } - HashCtx(const void *data, std::size_t len) { - init(); - feed(data, len); - } - ~HashCtx() { - clear(); - } - void reset(); - void feed(const void *data, std::size_t len); - void feed(td::Slice slice) { - feed(slice.data(), slice.size()); - } - std::size_t extract(unsigned char buffer[digest_bytes]); - std::size_t extract(td::MutableSlice slice); - std::string extract(); -}; - -template -void HashCtx::init() { - ctx = EVP_MD_CTX_create(); - reset(); -} - -template -void HashCtx::reset() { - EVP_DigestInit_ex(ctx, H::get_evp(), 0); -} - -template -void HashCtx::clear() { - EVP_MD_CTX_destroy(ctx); - ctx = nullptr; -} - -template -void HashCtx::feed(const void *data, std::size_t len) { - EVP_DigestUpdate(ctx, data, len); -} - -template -std::size_t HashCtx::extract(unsigned char buffer[digest_bytes]) { - unsigned olen = 0; - EVP_DigestFinal_ex(ctx, buffer, &olen); - assert(olen == digest_bytes); - return olen; -} - -template -std::size_t HashCtx::extract(td::MutableSlice slice) { - return extract(slice.ubegin()); -} - -template -std::string HashCtx::extract() { - unsigned char buffer[digest_bytes]; - unsigned olen = 0; - EVP_DigestFinal_ex(ctx, buffer, &olen); - assert(olen == digest_bytes); - return std::string((char *)buffer, olen); -} - -typedef HashCtx SHA1; -typedef HashCtx SHA256; -typedef HashCtx SHA512; - -template -std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void *data, std::size_t size) { - T hasher(data, size); - return hasher.extract(buffer); -} - -template -std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void *data1, std::size_t size1, const void *data2, - std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(buffer); -} - -template -std::string hash_str(const void *data, std::size_t size) { - T hasher(data, size); - return hasher.extract(); -} - -template -std::string hash_two_str(const void *data1, std::size_t size1, const void *data2, std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(); -} -} // namespace digest diff --git a/submodules/ton/tonlib-src/crypto/openssl/rand.cpp b/submodules/ton/tonlib-src/crypto/openssl/rand.cpp deleted file mode 100644 index 57f5c05f..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/rand.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "openssl/rand.hpp" - -#include "td/utils/common.h" - -#include -#include - -namespace prng { -int os_get_random_bytes(void *buf, int n); - -bool RandomGen::ok() const { - return RAND_status(); -} - -void RandomGen::seed_add(const void *data, std::size_t size, double entropy) { - RAND_add(data, static_cast(size), entropy > 0 ? entropy : static_cast(size)); -} - -void RandomGen::randomize(bool force) { - if (!force && ok()) { - return; - } - unsigned char buffer[128]; - int n = os_get_random_bytes(buffer, 128); - seed_add(buffer, n); - assert(ok()); -} - -bool RandomGen::rand_bytes(void *data, std::size_t size, bool strong) { -#if OPENSSL_VERSION_NUMBER < 0x10101000L - int res = (strong ? RAND_bytes : RAND_pseudo_bytes)((unsigned char *)data, static_cast(size)); -#else - int res = RAND_bytes((unsigned char *)data, static_cast(size)); -#endif - if (res != 0 && res != 1) { - throw rand_error(); - } - return res; -} - -std::string RandomGen::rand_string(std::size_t size, bool strong) { - std::string result(size, '\0'); - if (size > 0 && !rand_bytes(&result[0], size, strong)) { - throw rand_error(); - } - return result; -} - -RandomGen &rand_gen() { - // RandomGen is stateless, OpenSSL will handle concurrent access - static RandomGen MainPRNG; - return MainPRNG; -} -} // namespace prng - -//------------------------- move to separate OS-dependent file? -#if TD_WINDOWS -namespace prng { -int os_get_random_bytes(void *buf, int n) { - return 0; -} -} // namespace prng -#else -#include -#include - -namespace prng { - -int os_get_random_bytes(void *buf, int n) { - using namespace std; - int r = 0; - int h = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (h >= 0) { - r = static_cast(read(h, buf, n)); - if (r > 0) { - //std::cerr << "added " << r << " bytes of real entropy to secure random numbers seed" << std::endl; - } else { - r = 0; - } - close(h); - } - - if (r < n) { - h = open("/dev/urandom", O_RDONLY); - if (h < 0) { - return r; - } - int s = static_cast(read(h, (char *)buf + r, n - r)); - close(h); - if (s < 0) { - return r; - } - r += s; - } - - if (r >= 8) { - *(long *)buf ^= lrand48(); - srand48(*(long *)buf); - } - - return r; -} -} // namespace prng -#endif diff --git a/submodules/ton/tonlib-src/crypto/openssl/rand.hpp b/submodules/ton/tonlib-src/crypto/openssl/rand.hpp deleted file mode 100644 index 6ead2be7..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/rand.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include - -namespace prng { - -// use this generator unless need a separate one -class RandomGen; -RandomGen &rand_gen(); - -class RandomGen { - public: - struct rand_error {}; - void randomize(bool force = true); - void seed_add(const void *data, std::size_t size, double entropy = 0); - bool ok() const; - RandomGen() { - randomize(false); - } - RandomGen(const void *seed, std::size_t size) { - seed_add(seed, size); - randomize(false); - } - bool rand_bytes(void *data, std::size_t size, bool strong = false); - bool strong_rand_bytes(void *data, std::size_t size) { - return rand_bytes(data, size, true); - } - template - bool rand_obj(T &obj) { - return rand_bytes(&obj, sizeof(T)); - } - template - bool rand_objs(T *ptr, std::size_t count) { - return rand_bytes(ptr, sizeof(T) * count); - } - std::string rand_string(std::size_t size, bool strong = false); -}; -} // namespace prng diff --git a/submodules/ton/tonlib-src/crypto/openssl/residue.cpp b/submodules/ton/tonlib-src/crypto/openssl/residue.cpp deleted file mode 100644 index 20c81e24..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/residue.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "residue.h" - -// --- impl -#include - -namespace arith { -class Residue; -class ResidueRing; - -void ResidueRing::init() { - Zero = new Residue(0, td::Ref(this)); - One = new Residue(1, td::Ref(this)); -} - -ResidueRing::~ResidueRing() { - delete Zero; - delete One; - delete Img_i; - Zero = One = Img_i = 0; -} - -const Residue operator+(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_ref()); - bn_assert(BN_mod_add(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator-(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_ref()); - bn_assert(BN_mod_sub(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator*(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_ref()); - bn_assert(BN_mod_mul(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator-(const Residue& x) { - Residue z(x); - z.val.negate(); - return z.reduce(); -} - -Residue& Residue::operator+=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_add(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -Residue& Residue::operator-=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_sub(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -Residue& Residue::operator*=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_mul(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -bool operator==(const Residue& x, const Residue& y) { - x.same_ring(y); - return x.extract() == y.extract(); -} - -bool operator!=(const Residue& x, const Residue& y) { - x.same_ring(y); - return x.extract() != y.extract(); -} - -Residue sqr(const Residue& x) { - Residue z(x.ring_ref()); - bn_assert(BN_mod_sqr(z.val.bn_ptr(), x.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -Residue power(const Residue& x, const Bignum& y) { - Residue z(x.ring_ref()); - bn_assert(BN_mod_exp(z.val.bn_ptr(), x.val.bn_ptr(), y.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -Residue inverse(const Residue& x) { - assert(x.ring_ref()->is_prime()); - return power(x, x.ring_ref()->get_modulus() - 2); -} - -const Residue& ResidueRing::img_i() const { - if (!Img_i) { - assert(is_prime()); - assert(modulus % 4 == 1); - int g = 2; - Bignum n = (modulus - 1) / 4; - while (true) { - Residue t = power(frac(g), n); - if (t != one() && t != frac(-1)) { - Img_i = new Residue(t); - break; - } - g++; - } - } - return *Img_i; -} - -Residue sqrt(const Residue& x) { - assert(x.ring_of().is_prime()); - const ResidueRing& R = x.ring_of(); - const Bignum& p = R.get_modulus(); - if (x.is_zero() || !p.odd()) { - return x; - } - if (p[1]) { // p=3 (mod 4) - return power(x, (p + 1) >> 2); - } else if (p[2]) { - // p=5 (mod 8) - Residue t = power(x, (p + 3) >> 3); - return (sqr(t) == x) ? t : R.img_i() * t; - } else { - assert(p[2]); - return R.zero(); - } -} - -Residue ResidueRing::frac(long num, long denom) const { - assert(denom); - if (denom < 0) { - num = -num; - denom = -denom; - } - if (!(num % denom)) { - return Residue(num / denom, self_ref()); - } else { - return Residue(num, self_ref()) * inverse(Residue(denom, self_ref())); - } -} - -std::string Residue::to_str() const { - return "Mod(" + val.to_str() + "," + modulus().to_str() + ")"; -} - -std::ostream& operator<<(std::ostream& os, const Residue& x) { - return os << x.to_str(); -} - -std::istream& operator>>(std::istream& is, Residue& x) { - std::string word; - is >> word; - x = dec_string(word); - return is; -} -} // namespace arith diff --git a/submodules/ton/tonlib-src/crypto/openssl/residue.h b/submodules/ton/tonlib-src/crypto/openssl/residue.h deleted file mode 100644 index adea1de7..00000000 --- a/submodules/ton/tonlib-src/crypto/openssl/residue.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "bignum.h" -#include "common/refcnt.hpp" - -namespace arith { -class Residue; -class ResidueRing; - -class ResidueRing : public td::CntObject { - public: - struct bad_modulus {}; - - private: - const Bignum modulus; - bool prime; - Residue* Zero; - Residue* One; - mutable Residue* Img_i; - void init(); - - public: - typedef Residue element; - explicit ResidueRing(Bignum mod) : modulus(mod), prime(arith::is_prime(mod)), Zero(0), One(0), Img_i(0) { - init(); - } - ~ResidueRing(); - const Bignum& get_modulus() const { - return modulus; - } - bool is_prime() const { - return prime; - } - const Residue& zero() const { - return *Zero; - } - const Residue& one() const { - return *One; - } - const Residue& img_i() const; - Residue frac(long num, long denom = 1) const; - Residue convert(long num) const; - Residue convert(const Bignum& x) const; - - Bignum reduce(const Bignum& x) const { - Bignum r = x % modulus; - if (r.sign() < 0) { - r += modulus; - } - return r; - } - - Bignum& do_reduce(Bignum& x) const { - x %= modulus; - if (x.sign() < 0) { - x += modulus; - } - return x; - } - - private: - td::Ref self_ref() const { - return td::Ref{this}; - } -}; - -class Residue { - public: - struct not_same_ring {}; - - private: - td::Ref ring; - mutable Bignum val; - Residue& reduce() { - ring->do_reduce(val); - return *this; - } - - public: - explicit Residue(td::Ref R) : ring(R) { - } - Residue(const Bignum& x, td::Ref R) : ring(R), val(R->reduce(x)) { - } - ~Residue() { - } - Residue(const Residue& x) : ring(x.ring), val(x.val) { - } - Bignum extract() const { - return val; - } - const Bignum& extract_raw() const { - return val; - } - const Bignum& modulus() const { - return ring->get_modulus(); - } - void same_ring(const Residue& y) const { - if (ring != y.ring) { - throw not_same_ring(); - } - } - const ResidueRing& ring_of() const { - return *ring; - } - td::Ref ring_ref() const { - return ring; - } - bool is_zero() const { - return (val == 0); - } - Residue& operator=(const Residue& x) { - same_ring(x); - val = x.val; - return *this; - } - Residue& operator=(const Bignum& x) { - val = ring->reduce(x); - return *this; - } - Residue& operator+=(const Residue& y); - Residue& operator-=(const Residue& y); - Residue& operator*=(const Residue& y); - Residue& operator+=(long y) { - val += y; - return reduce(); - } - Residue& operator-=(long y) { - val -= y; - return reduce(); - } - Residue& operator*=(long y) { - val *= y; - return reduce(); - } - Residue& negate() { - val.negate(); - return reduce(); - } - friend const Residue operator+(const Residue& x, const Residue& y); - friend const Residue operator-(const Residue& x, const Residue& y); - friend const Residue operator*(const Residue& x, const Residue& y); - friend const Residue operator-(const Residue& x); - friend Residue sqr(const Residue& x); - friend Residue power(const Residue& x, const Bignum& y); - friend Residue inverse(const Residue& x); - std::string to_str() const; -}; - -const Residue operator+(const Residue& x, const Residue& y); -const Residue operator-(const Residue& x, const Residue& y); -const Residue operator*(const Residue& x, const Residue& y); -const Residue operator-(const Residue& x); - -bool operator==(const Residue& x, const Residue& y); -bool operator!=(const Residue& x, const Residue& y); - -Residue sqr(const Residue& x); -Residue power(const Residue& x, const Bignum& y); -Residue inverse(const Residue& x); -Residue sqrt(const Residue& x); - -inline Residue ResidueRing::convert(long x) const { - return Residue(x, td::Ref(this)); -} - -inline Residue ResidueRing::convert(const Bignum& x) const { - return Residue(x, td::Ref(this)); -} - -std::ostream& operator<<(std::ostream& os, const Residue& x); -std::istream& operator>>(std::istream& is, Residue& x); -} // namespace arith diff --git a/submodules/ton/tonlib-src/crypto/parser/lexer.cpp b/submodules/ton/tonlib-src/crypto/parser/lexer.cpp deleted file mode 100644 index 87c63c3f..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/lexer.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "lexer.h" -#include "symtable.h" -#include -#include - -namespace src { - -/* - * - * LEXER - * - */ - -std::string Lexem::lexem_name_str(int idx) { - if (idx == Eof) { - return "end of file"; - } else if (idx == Ident) { - return "identifier"; - } else if (idx == Number) { - return "number"; - } else if (idx == String) { - return "string"; - } else if (idx == Special) { - return "special"; - } else if (sym::symbols.get_keyword(idx)) { - return "`" + sym::symbols.get_keyword(idx)->str + "`"; - } else { - std::ostringstream os{""; - return os.str(); - } -} - -std::string Lexem::name_str() const { - if (tp == Ident) { - return std::string{"identifier `"} + sym::symbols.get_name(val) + "`"; - } else if (tp == String) { - return std::string{"string \""} + str + '"'; - } else { - return lexem_name_str(tp); - } -} - -bool is_number(std::string str) { - auto st = str.begin(), en = str.end(); - if (st == en) { - return false; - } - if (*st == '-') { - st++; - } - bool hex = false; - if (st + 1 < en && *st == '0' && st[1] == 'x') { - st += 2; - hex = true; - } - if (st == en) { - return false; - } - while (st < en) { - int c = *st; - if (c >= '0' && c <= '9') { - ++st; - continue; - } - if (!hex) { - return false; - } - c |= 0x20; - if (c < 'a' || c > 'f') { - return false; - } - ++st; - } - return true; -} - -int Lexem::classify() { - if (tp != Unknown) { - return tp; - } - sym::sym_idx_t i = sym::symbols.lookup(str); - if (i) { - assert(str == sym::symbols[i]->str); - str = sym::symbols[i]->str; - sym::sym_idx_t idx = sym::symbols[i]->idx; - tp = (idx < 0 ? -idx : Ident); - val = i; - } else if (is_number(str)) { - tp = Number; - } else { - tp = lexem_is_special(str); - } - if (tp == Unknown) { - tp = Ident; - val = sym::symbols.lookup(str, 1); - } - return tp; -} - -int Lexem::set(std::string _str, const SrcLocation& _loc, int _tp, int _val) { - str = _str; - loc = _loc; - tp = _tp; - val = _val; - return classify(); -} - -Lexer::Lexer(SourceReader& _src, bool init, std::string active_chars, std::string eol_cmts, std::string open_cmts, - std::string close_cmts, std::string quote_chars) - : src(_src), eof(false), lexem("", src.here(), Lexem::Undefined), peek_lexem("", {}, Lexem::Undefined) { - std::memset(char_class, 0, sizeof(char_class)); - unsigned char activity = cc::active; - for (char c : active_chars) { - if (c == ' ') { - if (!--activity) { - activity = cc::allow_repeat; - } - } else if ((unsigned)c < 0x80) { - char_class[(unsigned)c] |= activity; - } - } - set_spec(eol_cmt, eol_cmts); - set_spec(cmt_op, open_cmts); - set_spec(cmt_cl, close_cmts); - for (int c : quote_chars) { - if (c > ' ' && c <= 0x7f) { - char_class[(unsigned)c] |= cc::quote_char; - } - } - if (init) { - next(); - } -} - -void Lexer::set_spec(std::array& arr, std::string setup) { - arr[0] = arr[1] = arr[2] = -0x100; - std::size_t n = setup.size(), i; - for (i = 0; i < n; i++) { - if (setup[i] == ' ') { - continue; - } - if (i == n - 1 || setup[i + 1] == ' ') { - arr[0] = setup[i]; - } else if (i == n - 2 || (i < n - 2 && setup[i + 2] == ' ')) { - arr[1] = setup[i]; - arr[2] = setup[++i]; - } else { - while (i < n && setup[i] != ' ') { - i++; - } - } - } -} - -void Lexer::expect(int exp_tp, const char* msg) { - if (tp() != exp_tp) { - throw ParseError{lexem.loc, (msg ? std::string{msg} : Lexem::lexem_name_str(exp_tp)) + " expected instead of " + - cur().name_str()}; - } - next(); -} - -const Lexem& Lexer::next() { - if (peek_lexem.valid()) { - lexem = std::move(peek_lexem); - peek_lexem.clear({}, Lexem::Undefined); - eof = (lexem.tp == Lexem::Eof); - return lexem; - } - if (eof) { - return lexem.clear(src.here(), Lexem::Eof); - } - long long comm = 1; - while (!src.seek_eof()) { - int cc = src.cur_char(), nc = src.next_char(); - if (cc == eol_cmt[0] || (cc == eol_cmt[1] && nc == eol_cmt[2])) { - src.load_line(); - } else if (cc == cmt_op[1] && nc == cmt_op[2]) { - src.advance(2); - comm = comm * 2 + 1; - } else if (cc == cmt_op[0]) { - src.advance(1); - comm *= 2; - } else if (comm == 1) { - break; - } else if (cc == cmt_cl[1] && nc == cmt_cl[2]) { - if (!(comm & 1)) { - src.error(std::string{"a `"} + (char)cmt_op[0] + "` comment closed by `" + (char)cmt_cl[1] + (char)cmt_cl[2] + - "`"); - } - comm >>= 1; - src.advance(2); - } else if (cc == cmt_cl[0]) { - if (!(comm & 1)) { - src.error(std::string{"a `"} + (char)cmt_op[1] + (char)cmt_op[2] + "` comment closed by `" + (char)cmt_cl[0] + - "`"); - } - comm >>= 1; - src.advance(1); - } else { - src.advance(1); - } - if (comm < 0) { - src.error("too many nested comments"); - } - } - if (src.seek_eof()) { - eof = true; - if (comm > 1) { - if (comm & 1) { - src.error(std::string{"`"} + (char)cmt_op[1] + (char)cmt_op[2] + "` comment extends past end of file"); - } else { - src.error(std::string{"`"} + (char)cmt_op[0] + "` comment extends past end of file"); - } - } - return lexem.clear(src.here(), Lexem::Eof); - } - int c = src.cur_char(); - const char* end = src.get_ptr(); - if (is_quote_char(c) || c == '`') { - int qc = c; - ++end; - while (end < src.get_end_ptr() && *end != qc) { - ++end; - } - if (*end != qc) { - src.error(qc == '`' ? "a `back-quoted` token extends past end of line" : "string extends past end of line"); - } - lexem.set(std::string{src.get_ptr() + 1, end}, src.here(), qc == '`' ? Lexem::Unknown : Lexem::String); - src.set_ptr(end + 1); - // std::cerr << lexem.name_str() << ' ' << lexem.str << std::endl; - return lexem; - } - int len = 0, pc = -0x100; - while (end < src.get_end_ptr()) { - c = *end; - bool repeated = (c == pc && is_repeatable(c)); - if (c == ' ' || c == 9 || (len && is_left_active(c) && !repeated)) { - break; - } - ++len; - ++end; - if (is_right_active(c) && !repeated) { - break; - } - pc = c; - } - lexem.set(std::string{src.get_ptr(), end}, src.here()); - src.set_ptr(end); - // std::cerr << lexem.name_str() << ' ' << lexem.str << std::endl; - return lexem; -} - -const Lexem& Lexer::peek() { - if (peek_lexem.valid()) { - return peek_lexem; - } - if (eof) { - return lexem.clear(src.here(), Lexem::Eof); - } - Lexem keep = std::move(lexem); - next(); - peek_lexem = std::move(lexem); - lexem = std::move(keep); - eof = false; - return peek_lexem; -} - -} // namespace src diff --git a/submodules/ton/tonlib-src/crypto/parser/lexer.h b/submodules/ton/tonlib-src/crypto/parser/lexer.h deleted file mode 100644 index 12556e46..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/lexer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "srcread.h" -#include -#include -#include - -namespace src { - -/* - * - * LEXER - * - */ - -int lexem_is_special(std::string str); // return 0 if no special lexems are needed - -struct Lexem { - enum { Undefined = -2, Eof = -1, Unknown = 0, Ident = 0, Number = 1, Special = 2, String = 3 }; - int tp; - int val; - std::string str; - SrcLocation loc; - int classify(); - Lexem(std::string _str = "", const SrcLocation& _loc = {}, int _tp = Unknown, int _val = 0) - : tp(_tp), val(_val), str(_str), loc(_loc) { - classify(); - } - int set(std::string _str = "", const SrcLocation& _loc = {}, int _tp = Unknown, int _val = 0); - Lexem& clear(const SrcLocation& _loc = {}, int _tp = Unknown, int _val = 0) { - tp = _tp; - val = _val; - loc = _loc; - str = ""; - return *this; - } - bool valid() const { - return tp != Undefined; - } - std::string name_str() const; - void error(std::string _str) const { - throw ParseError{loc, _str}; - } - void error_at(std::string str1, std::string str2) const { - error(str1 + str + str2); - } - - static std::string lexem_name_str(int idx); -}; - -class Lexer { - SourceReader& src; - bool eof; - Lexem lexem, peek_lexem; - unsigned char char_class[128]; - std::array eol_cmt, cmt_op, cmt_cl; - enum cc { left_active = 2, right_active = 1, active = 3, allow_repeat = 4, quote_char = 8 }; - - public: - bool eof_found() const { - return eof; - } - Lexer(SourceReader& _src, bool init = false, std::string active_chars = ";,() ~.", std::string eol_cmts = ";;", - std::string open_cmts = "{-", std::string close_cmts = "-}", std::string quote_chars = "\""); - const Lexem& next(); - const Lexem& cur() const { - return lexem; - } - const Lexem& peek(); - int tp() const { - return lexem.tp; - } - void expect(int exp_tp, const char* msg = 0); - int classify_char(unsigned c) const { - return c < 0x80 ? char_class[c] : 0; - } - bool is_active(int c) const { - return (classify_char(c) & cc::active) == cc::active; - } - bool is_left_active(int c) const { - return (classify_char(c) & cc::left_active); - } - bool is_right_active(int c) const { - return (classify_char(c) & cc::right_active); - } - bool is_repeatable(int c) const { - return (classify_char(c) & cc::allow_repeat); - } - bool is_quote_char(int c) const { - return (classify_char(c) & cc::quote_char); - } - - private: - void set_spec(std::array& arr, std::string setup); -}; - -} // namespace src diff --git a/submodules/ton/tonlib-src/crypto/parser/srcread.cpp b/submodules/ton/tonlib-src/crypto/parser/srcread.cpp deleted file mode 100644 index 332f1539..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/srcread.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "srcread.h" -#include - -namespace src { - -/* - * - * SOURCE FILE READER - * - */ - -std::ostream& operator<<(std::ostream& os, const FileDescr* fdescr) { - return os << (fdescr ? (fdescr->is_stdin ? "stdin" : fdescr->filename) : "unknown-location"); -} - -std::ostream& operator<<(std::ostream& os, const Fatal& fatal) { - return os << fatal.get_msg(); -} - -const char* FileDescr::convert_offset(long offset, long* line_no, long* line_pos, long* line_size) const { - long lno = 0, lpos = -1, lsize = 0; - const char* lstart = nullptr; - if (offset >= 0 && offset < (long)text.size()) { - auto it = std::upper_bound(line_offs.begin(), line_offs.end(), offset); - lno = it - line_offs.begin(); - if (lno && it != line_offs.end()) { - lsize = it[0] - it[-1]; - lpos = offset - it[-1]; - lstart = text.data() + it[-1]; - } - } else { - lno = (long)line_offs.size(); - } - if (line_no) { - *line_no = lno; - } - if (line_pos) { - *line_pos = lpos; - } - if (line_size) { - *line_size = lsize; - } - return lstart; -} - -const char* FileDescr::push_line(std::string new_line) { - if (line_offs.empty()) { - line_offs.push_back(0); - } - std::size_t cur_size = text.size(); - text += new_line; - text += '\0'; - line_offs.push_back((long)text.size()); - return text.data() + cur_size; -} - -void SrcLocation::show(std::ostream& os) const { - os << fdescr; - long line_no, line_pos; - if (fdescr && convert_pos(&line_no, &line_pos)) { - os << ':' << line_no; - if (line_pos >= 0) { - os << ':' << (line_pos + 1); - } - } -} - -bool SrcLocation::show_context(std::ostream& os) const { - long line_no, line_pos, line_size; - if (!fdescr || !convert_pos(&line_no, &line_pos, &line_size)) { - return false; - } - bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < line_size); - const char* here = fdescr->text.data() + char_offs; - const char* base = here - line_pos; - const char* start = skip_left ? here - 100 : base; - const char* end = skip_right ? here + 100 : base + line_size; - os << " "; - if (skip_left) { - os << "... "; - } - for (const char* ptr = start; ptr < end; ptr++) { - os << (char)*ptr; - } - if (skip_right) { - os << " ..."; - } - os << std::endl; - os << " "; - if (skip_left) { - os << "... "; - } - for (const char* ptr = start; ptr < here; ptr++) { - char c = *ptr; - os << (c == 9 || c == 10 ? c : ' '); - } - os << '^' << std::endl; - return true; -} - -std::ostream& operator<<(std::ostream& os, const SrcLocation& loc) { - loc.show(os); - return os; -} - -void SrcLocation::show_gen_error(std::ostream& os, std::string message, std::string err_type) const { - show(os); - if (!err_type.empty()) { - os << ": " << err_type; - } - os << ": " << message << std::endl; - show_context(os); -} - -std::ostream& operator<<(std::ostream& os, const Error& error) { - error.show(os); - return os; -} - -void ParseError::show(std::ostream& os) const { - os << where << ": error: " << message << std::endl; - where.show_context(os); -} - -SourceReader::SourceReader(std::istream* _is, FileDescr* _fdescr) - : ifs(_is), fdescr(_fdescr), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) { - load_line(); -} - -void SourceReader::set_eof() { - if (!eof) { - eof = true; - start = cur = end = 0; - } -} - -int SourceReader::skip_spc() { - if (!cur) { - return 0; - } - const char* ptr = cur; - int res = 0; - while (*ptr == ' ' || *ptr == 9) { - ++ptr; - ++res; - } - set_ptr(ptr); - return res; -} - -bool SourceReader::seek_eof() { - while (seek_eoln()) { - if (!load_line()) { - return true; - } - } - return false; -} - -const char* SourceReader::set_ptr(const char* ptr) { - if (ptr != cur) { - if (ptr < cur || ptr > end) { - error("parsing position went outside of line"); - } - loc.char_offs += ptr - cur; - cur = ptr; - } - return ptr; -} - -bool SourceReader::load_line() { - if (eof) { - return false; - } - loc.set_eof(); - if (ifs->eof()) { - set_eof(); - return false; - } - std::getline(*ifs, cur_line); - if (ifs->fail()) { - set_eof(); - if (!ifs->eof()) { - error("cannot read line from source stream"); - } - return false; - } - std::size_t len = cur_line.size(); - if (len > 0xffffff) { - set_eof(); - error("line too long"); - return false; - } - if (len && cur_line.back() == '\r') { - // CP/M line breaks support - cur_line.pop_back(); - --len; - } - cur_line_len = (int)len; - if (fdescr) { - cur = start = fdescr->push_line(std::move(cur_line)); - end = start + len; - loc.char_offs = (std::size_t)(cur - fdescr->text.data()); - cur_line.clear(); - } else { - cur = start = cur_line.c_str(); - end = start + cur_line_len; - } - return true; -} - -} // namespace src diff --git a/submodules/ton/tonlib-src/crypto/parser/srcread.h b/submodules/ton/tonlib-src/crypto/parser/srcread.h deleted file mode 100644 index 9352a242..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/srcread.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include - -namespace src { - -/* - * - * SOURCE FILE READER - * - */ - -struct FileDescr { - std::string filename; - std::string text; - std::vector line_offs; - bool is_stdin; - FileDescr(std::string _fname, bool _stdin = false) : filename(std::move(_fname)), is_stdin(_stdin) { - } - const char* push_line(std::string new_line); - const char* convert_offset(long offset, long* line_no, long* line_pos, long* line_size = nullptr) const; -}; - -struct Fatal { - std::string message; - Fatal(std::string _msg) : message(std::move(_msg)) { - } - std::string get_msg() const { - return message; - } -}; - -std::ostream& operator<<(std::ostream& os, const Fatal& fatal); - -struct SrcLocation { - const FileDescr* fdescr; - long char_offs; - SrcLocation() : fdescr(nullptr), char_offs(-1) { - } - SrcLocation(const FileDescr* _fdescr, long offs = -1) : fdescr(_fdescr), char_offs(-1) { - } - bool defined() const { - return fdescr; - } - bool eof() const { - return char_offs == -1; - } - void set_eof() { - char_offs = -1; - } - const char* convert_pos(long* line_no, long* line_pos, long* line_size = nullptr) const { - return defined() ? fdescr->convert_offset(char_offs, line_no, line_pos, line_size) : nullptr; - } - void show(std::ostream& os) const; - bool show_context(std::ostream& os) const; - void show_gen_error(std::ostream& os, std::string message, std::string err_type = "") const; - void show_note(std::string err_msg) const { - show_gen_error(std::cerr, err_msg, "note"); - } - void show_warning(std::string err_msg) const { - show_gen_error(std::cerr, err_msg, "warning"); - } - void show_error(std::string err_msg) const { - show_gen_error(std::cerr, err_msg, "error"); - } -}; - -std::ostream& operator<<(std::ostream& os, const SrcLocation& loc); - -struct Error { - virtual ~Error() = default; - virtual void show(std::ostream& os) const = 0; -}; - -std::ostream& operator<<(std::ostream& os, const Error& error); - -struct ParseError : Error { - SrcLocation where; - std::string message; - ParseError(const SrcLocation& _where, std::string _msg) : where(_where), message(_msg) { - } - ParseError(const SrcLocation* _where, std::string _msg) : message(_msg) { - if (_where) { - where = *_where; - } - } - ~ParseError() override = default; - void show(std::ostream& os) const override; -}; - -class SourceReader { - std::istream* ifs; - FileDescr* fdescr; - SrcLocation loc; - bool eof; - std::string cur_line; - int cur_line_len; - void set_eof(); - const char *start, *cur, *end; - - public: - SourceReader(std::istream* _is, FileDescr* _fdescr); - bool load_line(); - bool is_eof() const { - return eof; - } - int is_eoln() const { - return cur == end; - } - int skip_spc(); - bool seek_eoln() { - skip_spc(); - return is_eoln(); - } - bool seek_eof(); - const char* cur_line_cstr() const { - return cur_line.c_str(); - } - const SrcLocation& here() const { - return loc; - } - char cur_char() const { - return *cur; - } - char next_char() const { - return cur[1]; - } - const char* get_ptr() const { - return cur; - } - const char* get_end_ptr() const { - return end; - } - const char* set_ptr(const char* ptr); - void advance(int n) { - set_ptr(get_ptr() + n); - } - void error(std::string err_msg) { - throw ParseError{loc, err_msg}; - } -}; - -} // namespace src diff --git a/submodules/ton/tonlib-src/crypto/parser/symtable.cpp b/submodules/ton/tonlib-src/crypto/parser/symtable.cpp deleted file mode 100644 index a8843da9..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/symtable.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "symtable.h" -#include -#include - -namespace sym { - -/* - * - * SYMBOL VALUES (DECLARED) - * - */ - -int scope_level; - -SymTable<100003> symbols; - -SymDef* sym_def[symbols.hprime]; -SymDef* global_sym_def[symbols.hprime]; -std::vector> symbol_stack; -std::vector scope_opened_at; - -std::string Symbol::unknown_symbol_name(sym_idx_t i) { - if (!i) { - return "_"; - } else { - std::ostringstream os; - os << "SYM#" << i; - return os.str(); - } -} - -sym_idx_t SymTableBase::gen_lookup(std::string str, int mode, sym_idx_t idx) { - unsigned long long h1 = 1, h2 = 1; - for (char c : str) { - h1 = ((h1 * 239) + (unsigned char)(c)) % p; - h2 = ((h2 * 17) + (unsigned char)(c)) % (p - 1); - } - ++h2; - ++h1; - while (true) { - if (sym_table[h1]) { - if (sym_table[h1]->str == str) { - return (mode & 2) ? not_found : sym_idx_t(h1); - } - h1 += h2; - if (h1 > p) { - h1 -= p; - } - } else { - if (!(mode & 1)) { - return not_found; - } - if (def_sym >= ((long long)p * 3) / 4) { - throw SymTableOverflow{def_sym}; - } - sym_table[h1] = std::make_unique(str, idx <= 0 ? sym_idx_t(h1) : -idx); - ++def_sym; - return sym_idx_t(h1); - } - } -} - -SymTableBase& SymTableBase::add_keyword(std::string str, sym_idx_t idx) { - if (idx <= 0) { - idx = ++def_kw; - } - sym_idx_t res = gen_lookup(str, -1, idx); - if (!res) { - throw SymTableKwRedef{str}; - } - if (idx < max_kw_idx) { - keywords[idx] = res; - } - return *this; -} - -void open_scope(src::Lexer& lex) { - ++scope_level; - scope_opened_at.push_back(lex.cur().loc); -} - -void close_scope(src::Lexer& lex) { - if (!scope_level) { - throw src::Fatal{"cannot close the outer scope"}; - } - while (!symbol_stack.empty() && symbol_stack.back().first == scope_level) { - SymDef old_def = symbol_stack.back().second; - auto idx = old_def.sym_idx; - symbol_stack.pop_back(); - SymDef* cur_def = sym_def[idx]; - assert(cur_def); - assert(cur_def->level == scope_level && cur_def->sym_idx == idx); - //std::cerr << "restoring local symbol `" << old_def.name << "` of level " << scope_level << " to its previous level " << old_def.level << std::endl; - if (cur_def->value) { - //std::cerr << "deleting value of symbol " << old_def.name << ":" << old_def.level << " at " << (const void*) it->second.value << std::endl; - delete cur_def->value; - } - if (!old_def.level && !old_def.value) { - delete cur_def; // ??? keep the definition always? - sym_def[idx] = nullptr; - } else { - cur_def->value = std::move(old_def.value); - cur_def->level = old_def.level; - } - old_def.value = nullptr; - } - --scope_level; - scope_opened_at.pop_back(); -} - -SymDef* lookup_symbol(sym_idx_t idx, int flags) { - if (!idx) { - return nullptr; - } - if ((flags & 1) && sym_def[idx]) { - return sym_def[idx]; - } - if ((flags & 2) && global_sym_def[idx]) { - return global_sym_def[idx]; - } - return nullptr; -} - -SymDef* lookup_symbol(std::string name, int flags) { - return lookup_symbol(symbols.lookup(name), flags); -} - -SymDef* define_global_symbol(sym_idx_t name_idx, bool force_new, const src::SrcLocation& loc) { - if (!name_idx) { - return nullptr; - } - auto found = global_sym_def[name_idx]; - if (found) { - return force_new && found->value ? nullptr : found; - } - return global_sym_def[name_idx] = new SymDef(0, name_idx, loc); -} - -SymDef* define_symbol(sym_idx_t name_idx, bool force_new, const src::SrcLocation& loc) { - if (!name_idx) { - return nullptr; - } - if (!scope_level) { - return define_global_symbol(name_idx, force_new, loc); - } - auto found = sym_def[name_idx]; - if (found) { - if (found->level < scope_level) { - symbol_stack.push_back(std::make_pair(scope_level, *found)); - found->level = scope_level; - } else if (found->value && force_new) { - return nullptr; - } - found->value = 0; - found->loc = loc; - return found; - } - found = sym_def[name_idx] = new SymDef(scope_level, name_idx, loc); - symbol_stack.push_back(std::make_pair(scope_level, SymDef{0, name_idx})); - return found; -} - -} // namespace sym diff --git a/submodules/ton/tonlib-src/crypto/parser/symtable.h b/submodules/ton/tonlib-src/crypto/parser/symtable.h deleted file mode 100644 index 81a828a8..00000000 --- a/submodules/ton/tonlib-src/crypto/parser/symtable.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "srcread.h" -#include "lexer.h" -#include - -namespace sym { - -/* - * - * SYMBOL VALUES (DECLARED) - * - */ - -typedef int var_idx_t; - -struct SymValBase { - enum { _Param, _Var, _Func, _Typename, _GlobVar }; - int type; - int idx; - SymValBase(int _type, int _idx) : type(_type), idx(_idx) { - } - virtual ~SymValBase() = default; -}; - -/* - * - * SYMBOL TABLE - * - */ - -// defined outside this module (by the end user) -int compute_symbol_subclass(std::string str); // return 0 if unneeded - -typedef int sym_idx_t; - -struct Symbol { - std::string str; - sym_idx_t idx; - int subclass; - Symbol(std::string _str, sym_idx_t _idx, int _sc) : str(_str), idx(_idx), subclass(_sc) { - } - Symbol(std::string _str, sym_idx_t _idx) : str(_str), idx(_idx) { - subclass = compute_symbol_subclass(std::move(_str)); - } - static std::string unknown_symbol_name(sym_idx_t i); -}; - -class SymTableBase { - unsigned p; - std::unique_ptr* sym_table; - sym_idx_t def_kw, def_sym; - static constexpr int max_kw_idx = 10000; - sym_idx_t keywords[max_kw_idx]; - - public: - SymTableBase(unsigned p_, std::unique_ptr* sym_table_) - : p(p_), sym_table(sym_table_), def_kw(0x100), def_sym(0) { - std::memset(keywords, 0, sizeof(keywords)); - } - static constexpr sym_idx_t not_found = 0; - SymTableBase& add_keyword(std::string str, sym_idx_t idx = 0); - SymTableBase& add_kw_char(char c) { - return add_keyword(std::string{c}, c); - } - sym_idx_t lookup(std::string str, int mode = 0) { - return gen_lookup(str, mode); - } - sym_idx_t lookup_add(std::string str) { - return gen_lookup(str, 1); - } - Symbol* operator[](sym_idx_t i) const { - return sym_table[i].get(); - } - bool is_keyword(sym_idx_t i) const { - return sym_table[i] && sym_table[i]->idx < 0; - } - std::string get_name(sym_idx_t i) const { - return sym_table[i] ? sym_table[i]->str : Symbol::unknown_symbol_name(i); - } - int get_subclass(sym_idx_t i) const { - return sym_table[i] ? sym_table[i]->subclass : 0; - } - Symbol* get_keyword(int i) const { - return ((unsigned)i < (unsigned)max_kw_idx) ? sym_table[keywords[i]].get() : nullptr; - } - - protected: - sym_idx_t gen_lookup(std::string str, int mode = 0, sym_idx_t idx = 0); -}; - -template -class SymTable : public SymTableBase { - public: - static constexpr int hprime = pp; - static int size() { - return pp + 1; - } - - private: - std::unique_ptr sym[pp + 1]; - - public: - SymTable() : SymTableBase(pp, sym) { - } - SymTable& add_keyword(std::string str, sym_idx_t idx = 0) { - SymTableBase::add_keyword(str, idx); - return *this; - } - SymTable& add_kw_char(char c) { - return add_keyword(std::string{c}, c); - } -}; - -struct SymTableOverflow { - int sym_def; - SymTableOverflow(int x) : sym_def(x) { - } -}; - -struct SymTableKwRedef { - std::string kw; - SymTableKwRedef(std::string _kw) : kw(_kw) { - } -}; - -extern SymTable<100003> symbols; - -extern int scope_level; - -struct SymDef { - int level; - sym_idx_t sym_idx; - SymValBase* value; - src::SrcLocation loc; - SymDef(int lvl, sym_idx_t idx, const src::SrcLocation& _loc = {}, SymValBase* val = 0) - : level(lvl), sym_idx(idx), value(val), loc(_loc) { - } - bool has_name() const { - return sym_idx; - } - std::string name() const { - return symbols.get_name(sym_idx); - } -}; - -extern SymDef* sym_def[symbols.hprime]; -extern SymDef* global_sym_def[symbols.hprime]; -extern std::vector> symbol_stack; -extern std::vector scope_opened_at; - -void open_scope(src::Lexer& lex); -void close_scope(src::Lexer& lex); -SymDef* lookup_symbol(sym_idx_t idx, int flags = 3); -SymDef* lookup_symbol(std::string name, int flags = 3); - -SymDef* define_global_symbol(sym_idx_t name_idx, bool force_new = false, const src::SrcLocation& loc = {}); -SymDef* define_symbol(sym_idx_t name_idx, bool force_new = false, const src::SrcLocation& loc = {}); - -} // namespace sym diff --git a/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif b/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif deleted file mode 100644 index 3254f072..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif +++ /dev/null @@ -1,382 +0,0 @@ -"Asm.fif" include -"TonUtil.fif" include - -31 -1<< constant wc_undef -0 constant wc_base --1 constant wc_master - -{ wcid@ 2dup <> swap wc_undef <> and - abort"workchain_id already set to another value" - wcid! } : setworkchain -{ globalid@ 2dup <> swap and - abort"global_id already set to another value" - dup 0= abort"global_id cannot be zero" - globalid! } : setglobalid - - constant empty_cell - -variable @default-subwallet-id -@default-subwallet-id 0! -{ @default-subwallet-id @ } : default-subwallet-id -{ @default-subwallet-id ! } : default-subwallet-id! - -// b x --> b' ( serializes a Gram amount ) -{ -1 { 1+ 2dup 8 * ufits } until - rot over 4 u, -rot 8 * u, } : Gram, - -// workchain-id -- wc-zero-state -{ ref, 0 1 u, - ref, - ref, 0 1 u, b> - dup isShardState? not abort"invalid ShardState created" -} : mkemptyShardState - -' dictnew : Libs{ -'nop : }Libs -{ 8 config! } : config.version! -1 constant capIhr -2 constant capCreateStats -4 constant capBounceMsgBody -8 constant capReportVersion -16 constant capSplitMergeTransactions -32 constant capShortDequeue - -// max-validators masterchain-validators min-validators -- -{ swap rot 16 config! } : config.validator_num! - -// min-stake max-stake min-total-stake max-factor -- -{ 4 0 reverse - 17 config! -} : config.validator_stake_limits! - -// elected-for elections-begin-before elections-end-before stakes-frozen -{ 4 0 reverse 15 config! } : config.election_params! - -variable validator-dict -dictnew 0 validator-dict 2! -variable validators-weight -validators-weight 0! - -{ validator-dict @ second } : validator# -{ dup 0<= abort"validator weight must be non-negative" - 64 ufits not abort"validator weight must fit into 64 bits" -} : check-val-weight -// ( val-pubkey weight -- c ) -{ dup check-val-weight - over Blen 32 <> abort"validator public key must be 32 bytes long" - -} : serialize-validator -// ( val-pubkey adnl weight -- c ) -{ dup check-val-weight - over 256 ufits not abort"adnl address must fit into 256 bits" - rot dup Blen 32 <> abort"validator public key must be 32 bytes long" - -} : serialize-adnl-validator -// ( weight val-cell -- ) -{ swap validators-weight +! - - 34 config! -} : config.validators! - -variable workchain-dict -// root-hash file-hash enable-utime actual-min-split min-split max-split workchain-id -- -{ - dup isWorkchainDescr? not abort"invalid WorkchainDescr created" - s s>c 12 config! } : config.workchains! - -variable special-dict -// special-smc-addr -- -{ x{} swap special-dict @ 256 udict! not abort"cannot add a new special smart contract" - special-dict ! -} : make_special -{ special-dict @ dict>s s>c 31 config! } : config.special! - -// ( l -- D ) Converts a list of parameter indices into a dictionary -{ dictnew { swap uncons -rot idict! not abort"cannot add parameter index" over null? - } until nip -} : param-list-to-dict -{ param-list-to-dict 9 config! } : config.mandatory_params! -{ param-list-to-dict 10 config! } : config.critical_params! - -// min_tot_rounds max_tot_rounds min_wins max_losses min_store_sec max_store_sec bit_price cell_price -- -{ 8 untuple 8 0 reverse } : cfg-prop-setup -// normal-prop-params critical-prop-params -- -{ swap cfg-prop-setup swap cfg-prop-setup } : make-proposals-setup -{ make-proposals-setup 11 config! } : config.param_proposals_setup! - -// deposit bit_pps cell_pps -{ 3 0 reverse } : create-complaint-pricing -{ create-complaint-pricing 13 config! } : config.complaint_prices! - -// bit-pps cell-pps mc-bit-pps mc-cell-pps -- -{ udict! 0= abort"cannot create storage prices dictionary" - 18 config! -} : config.storage_prices! -{ 16 << } : sg* -{ 16 < -} : make-gas-prices-basic -// gas_price ... delete_due_limit flat_gas_limit flat_gas_rate -- c -{ 2dup or { -} : make-msg-fwd-prices -{ make-msg-fwd-prices 24 config! } : config.mc_fwd_prices! -{ make-msg-fwd-prices 25 config! } : config.fwd_prices! - -// mc-cc-lifetime sh-cc-lifetime sh-val-lifetime sh-val-num mc-shuffle -{ 4 1 reverse -} : make-catchain-params -{ make-catchain-params 28 config! } : config.catchain_params! -// round-candidates next-cand-delay-ms consensus-timeout-ms fast-attempts attempt-duration cc-max-deps max-block-size max-collated-size new-cc-ids -{ 8 1 reverse } : make-vsession-params -{ make-vsession-params 29 config! } : config.consensus_params! - -// b [underload soft hard] -- b' -{ untriple 3 roll x{c3} s, 3 roll 32 u, rot 32 u, swap 32 u, } : param_limits, -// bytes-limits gas-limits lt-limits -- c -{ -} : make-block-limits -{ make-block-limits 22 config! } : config.mc_block_limits! -{ make-block-limits 23 config! } : config.block_limits! - -// mc-block-create-fee bc-block-create-fee -{ } : make-block-create-fees -{ make-block-create-fees 14 config! } : config.block_create_fees! - -{ } : make-smc-addr-cell -{ make-smc-addr-cell 0 config! } : config.config_smc! -{ make-smc-addr-cell 1 config! } : config.elector_smc! -{ make-smc-addr-cell 2 config! } : config.minter_smc! -{ make-smc-addr-cell 3 config! } : config.collector_smc! - -{ 7 config! } : config.to_mint! - -1000000000 constant Gram -1000000 constant mGram -1000 constant uGram -1 constant nGram -{ Gram * } : Gram* -{ mGram * } : mGram* -{ uGram * } : uGram* -'nop : nGram* -{ Gram swap */r } : Gram*/ -{ mGram swap */r } : mGram*/ -{ uGram swap */r } : uGram*/ -{ /r } : nGram*/ - -// GR$.17 is equivalent to 170000000 -{ bl word (number) ?dup 0= abort"not a valid Gram amount" - 1- { Gram swap */r } { Gram * } cond - 1 'nop -} ::_ GR$ - -{ 10 << } : *Ki -{ 20 << } : *Mi -{ 30 << } : *Gi -{ 10 < - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno - c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key - s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet - s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno - s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash - s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key - CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs - ACCEPT - WHILE:<{ - DUP SREFS // public_key stored_seqno stored_subwallet cs _51 - }>DO<{ // public_key stored_seqno stored_subwallet cs - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode - SENDRAWMSG - }> // public_key stored_seqno stored_subwallet cs - ENDS SWAP INC // public_key stored_subwallet seqno' - NEWC 32 STU 32 STU 256 STU ENDC c4 POP -}>c -=: WCode3 - -"auto/wallet-code.fif" include =: WCode0 -"auto/restricted-wallet-code.fif" include =: RWCode1 -"auto/restricted-wallet2-code.fif" include =: RWCode2 -"auto/restricted-wallet3-code.fif" include =: RWCode3 - -// pubkey amount -- -{ over ."Key " pubkey>$ type ." -> " - RWCode1 // code - // data - empty_cell // libs - 3 roll // balance - 0 // split_depth - 0 // ticktock - 2 // mode: create - register_smc - Masterchain swap 6 .Addr cr -} : create-wallet1 - -// pubkey amount -{ over ."W0 Key " pubkey>$ type space dup .GR ." -> " - WCode3 // code - // data - empty_cell // libs - 3 roll // balance - 0 0 2 register_smc - Masterchain swap 6 .Addr cr -} : create-wallet0 - -// D x t -- D' -{ idict! not abort"cannot add value" -} : rdict-entry -{ 86400 * } : days* -{ 365 * days* } : years* -// balance -- dict -{ dictnew - over 31 -1<< rdict-entry - over 3/4 */ 91 days* rdict-entry - over 1/2 */ 183 days* rdict-entry - swap 1/4 */ 365 days* rdict-entry - 0 548 days* rdict-entry -} : make-rdict1 -{ dictnew - over 31 -1<< rdict-entry - over .9 */ 0 rdict-entry - over .6775 */ 1 years* rdict-entry - over .445 */ 2 years* rdict-entry - swap .2225 */ 3 years* rdict-entry - 0 4 years* 86400 + rdict-entry -} : make-rdict2 - -variable 'make-rdict -{ 'make-rdict @ execute } : make-rdict - -variable rwallet-start-at rwallet-start-at 0! -now 86400 / 1+ 86400 * rwallet-start-at ! - -// pubkey amount -- -{ over ."Key " pubkey>$ type ." -> " - RWCode2 // code - // data - empty_cell // libs - 3 roll // balance - 0 // split_depth - 0 // ticktock - 2 // mode: create - register_smc - Masterchain swap 6 .Addr cr -} : create-wallet2 - -variable rwallet-init-pubkey - -// pubkey -- addr -{ RWCode3 // code - // data - empty_cell // libs - 0 // balance - 0 0 0 register_smc // compute address only -} : precompute-wallet3-addr - -variable w3-addr - -// pubkey amount 'rdict -- -{ 'make-rdict ! over precompute-wallet3-addr w3-addr ! - over ."RW3 Key " pubkey>$ type space dup .GR ." -> " - RWCode3 // code - // data - empty_cell // libs - 3 roll // balance - 0 // split_depth - 0 // ticktock - w3-addr @ // address - 6 // mode: create+setaddr - register_smc - Masterchain swap 6 .Addr cr -} : create-wallet3-internal - -{ ' make-rdict1 create-wallet3-internal } : create-wallet3 -{ ' make-rdict2 create-wallet3-internal } : create-wallet3b - -// pubkey amount -{ over ."Key " pubkey>$ type space dup .GR ." -> " - WCode0 // code - // data - empty_cell // libs - 3 roll // balance - 0 // split_depth - 0 // ticktock - 2 // mode: create - register_smc - Masterchain swap 6 .Addr cr -} : create-wallet0a - -{ dup tlb-type-lookup { nip } { "unknown TLB type " swap $+ abort } cond } : $>tlb -{ bl word $>tlb 1 'nop } ::_ tlb: -{ " cr - ."Compiles asm from file and stores serialization in a way prepared for usage from c++ to " cr 1 halt -} : usage - - -$# 3 - ' usage if - - -$1 =: source -$2 =: destination -$3 =: name - -."Include source from " source type cr -source include - -boc>B -."Convert boc to base64" cr -B>base64 - -{ char " chr tuck $+ $+ } : wrp -wrp // "" -"with_tvm_code(" name wrp $+ +", " swap ");" 10 hold $+ $+ // "with_tm_code("");\n" - -$>B - -."Store tvm code to " destination type cr -destination B>file diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto-dns.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto-dns.fif deleted file mode 100644 index 6ef2ef0e..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto-dns.fif +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -"dns-msg-body.boc" =: savefile - -begin-options - " [-o] (add|update|prolong) ... " +cr +tab - +"Creates the internal message body containing a request to automatic DNS smart contract created by new-auto-dns.fif, " - +"to be sent later with a suitable payment from a wallet to , and saves it into ('" savefile $+ +"' by default). " - +"The operation to be performed is one of" +cr +tab - +"add { owner | cat (smc | next | adnl | text ) }" +cr +tab - +"update { owner | cat (smc | next | adnl | text ) }" +cr +tab - +"prolong " - disable-digit-options generic-help-setopt - "o" "--output" { =: savefile } short-long-option-arg - "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 4 < ' usage if -4 :$1..n - -$1 true parse-load-address =: bounce 2=: dest-addr -$2 dup =: main-op-name atom =: main-op -$3 dup =: subdomain $len 127 > abort"subdomain name too long" -$4 parse-int dup 30 1<< < { now + } if =: expire-at - -{ $* @ dup null? { second $@ ! } { drop } cond } : @skip -{ $* @ null? } : @end? -{ $* @ uncons $* ! } : @next -{ @next drop } 4 times - -main-op dup `add eq? over `update eq? or swap `prolong eq? or -{ "unknown main operation '" main-op-name $+ +"'; one of 'add', 'update' or 'prolong' expected" abort } ifnot -main-op `prolong eq? not =: need-params - -$# 4 > need-params <> abort"extra parameters, or no parameters for chosen main operation" - -variable Values dictnew Values ! -// ( i c -- ) -{ over 0= abort"category cannot be zero" - idict!+ not abort"duplicate category id" - Values ! -} : register-value - -{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer" - dup 16 fits not abort"category does not fit into 16 bit integer" - dup 0= abort"category must be non-zero" -} : parse-cat-num -{ @end? abort"smart contract address expected" - @next false parse-load-address drop -} : cl-parse-smc-addr -{ @end? abort"adnl address expected" - @next parse-adnl-addr -} : cl-parse-adnl-addr -{ } : serialize-smc-addr -{ } : serialize-next-resolver -{ } : serialize-adnl-addr -{ } : serialize-text -{ @end? abort"subdomain record value expected" @next - dup "smc" $= { drop cl-parse-smc-addr serialize-smc-addr } { - dup "next" $= { drop cl-parse-smc-addr serialize-next-resolver } { - dup "adnl" $= { drop cl-parse-adnl-addr serialize-adnl-addr } { - dup "text" $= { drop @next serialize-text } { - "unknown record type "' swap $+ +"'" abort - } cond } cond } cond } cond -} : parse-value -{ @next dup "owner" $= { drop -2 cl-parse-smc-addr serialize-smc-addr } { - dup "cat" $= { drop parse-cat-num parse-value } { - "unknown action '" swap $+ +"'" abort - } cond } cond - register-value -} : parse-action -{ { @end? not } { parse-action } while } : parse-actions -parse-actions - -// ( S -- S1 .. Sn n ) -{ 1 swap { dup "." $pos dup 0>= } { $| 1 $| nip rot 1+ swap } while drop swap -} : split-by-dots -// ( S -- s ) -{ dup $len dup 0= abort"subdomain cannot be empty" 126 > abort"subdomain too long" - dup 0 chr $pos 1+ abort"subdomain contains null characters" - split-by-dots s - -main-op ( _( `add 0x72656764 ) _( `update 0x75706464 ) _( `prolong 0x70726f6c ) ) -assq-val not abort"unknown main operation" -=: op-id - -."Automatic DNS smart contract address = " dest-addr 2dup .addr cr 6 .Addr cr - -."Action: " main-op .l subdomain type space expire-at . cr -."Operation code: 0x" op-id 8 0X. cr -."Value: " -Values @ dup null? { drop ."(none)" } { =: actions-builder - -// create an internal message -now 32 << actions-builder hashu 32 1<<1- and + =: query_id -s tuck sbits 8 / 7 i, swap s, - main-op `prolong eq? { Values @ ref, } ifnot - expire-at 32 u, b> -dup ."Internal message body is: " B dup Bx. cr -."Query_id is " query_id dup . ."= 0x" X. cr -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp deleted file mode 100644 index e485cd82..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("config", "te6ccgECLgEACMgAART/APSkE/S88sgLAQIBIAIDAgFICgsCAvEEBQHNDDtRNDU0x/T//QE0YAggCRTUfRqcCFukmwhjjch0CDXScInjinTB9cLH/gjuwHAErCOFzCAIlhRZvRuVFUh9G4wgCRAFfRaMAN/kmwh4pMTXwPi4o6C2zzfA8jMEssfy//0AMntVIAYC2SDCNcYINMf0x/THwH4I7nyYyDXZIMGvPJn7UTQ1NMf0//0BNFRUrryoSWCEFZvdGW64wIG+QFUEHb5EPKi+AAFpKk4H1R1BCUDyMwSyx/L//QAye1U+A8QNURV2zxDAwPIzBLLH8v/9ADJ7VSAICQFM+BAhgwf0fW+lkVvhUgLbPI4RIG6XMAGDB/RbMJUCgwf0FuKRW+IHA6Ix2zwwAfkAIts8MyX4I7uUXwltf+AmupNfB3DgN1QQZts8bQVzqbQBIW6UXwdtf+AQNRAkEDZGBoDOyMoHFssfFMwSygD0AMo/y/8BzxbJ0H8fLCACkjUC0w/T/9Eh2zww0weAILMSsMBT8qnTHwGCEI6BJ4q68qnT/9M/MEiZ+RHyovgAAqSpOB9VEgPIzBLLH8v/9ADJ7VT4D1jbPDAaGwCmIYIQQ2ZQIbqcMdIf1NFAE4Ag9BUB4CGCEE5Db2S6jhMx1CH7BO1DAtDtHu1TAfEGgvIA4CGCEFBiSyG6lWwh0//R4CGCEE5D7wW6kzHwC+Aw8mACAsUMDQIBICQlAgHNDg8ABqqCWwIBIBARAgFIIiMCAUgSEwAz9oaYOA4Al5ROmP6Y/ph+mHmBBhAHlE33lEwC9QB0NMD+kAwIPpEAaQDcbATsSPHALGSXwTgAtMf0z8ighBOVlNUuo5EMjTU0XH4MyBukjB/lNDXC//iAnADupwxIPAHIfgjvAK8sAHeAY4QgCQB8AEBghDudk9LgEDwCOAwAYIQ7nZPb4BA8AjgMyGCEG5WUFK64wI0IIBQVACU7UTQ1FAzgCD0FcjMAc8Wye1UgAT4xA9s8gEAhoyLC/5xbdPsCghDuVlBSgwaRMuIQI/AIFgLEghBWb3Rluo9MMIMI1xgg0x/TD9P/0QKCEFZvdEW68qUg2zww0weAILMSsMBT8qnTHwGCEI6BJ4q68qnT/9M/MERV+RHyogLbPIIQ1nRSQKASgEDwCOBsMSDAAAGDHrCx8qUaGwL2AdMf1NIAMCKrHZUC+COhAt4h2zwgwv+OFyL4MyBukjBwkvkA4iG9lzCCFx2bnKrejhV5+DNSMIAg9AxvoTGXMIIXMq+RlN7iIddlgwa+lzCCFz2em6reIMH/kmxh4CORMo4UevgzE4Ag9AxvoTGXghc8jZasMt7iIcH/LRcE7pMVXwXgMSGAC/gz2zw0NDVSgLmYXwmCFzqHj5fgUHO2CAODCflBMoMJoBeoBqYCEqgVoFMBqAL4I6DtRNDU0x/T//QE0Sj5AFMBgwf0Dm+h4wIwNlGmoYMduZhfCoIXD56G3ODbPDBzqbQBcG0D+QAQVxBLGkMwKBgfGQHUODk5Bds8Uk29mF8Pghc8jZar4FNYvphfD4IXPpONu+BShqGDDaAZqFHdoYMduZhfDYIXD56G3OAQVkAUUHcDgM7IygcWyx8UzBLKAPQAyj/L/1AEzxZARYMH9EMTA8jMEssfy//0AMntVCwAWoDOyMoHFssfFMwSygD0AMo/y/8XywcUyw9AFoMH9EMSA8jMEssfy//0AMntVAEY2zwyWYAQ9A5voTABHwPE7UTQ1NMf0//0BNFGE1BU2zxUc1QlA8jMEssfy//0AMntVCFukmxRjzh2IaFEQNs8VHJlJgPIzBLLH8v/9ADJ7VQhjpf4DxAjECXbPEQDA8jMEssfy//0AMntVJQQRl8G4uIcHR4E2lMjgwf0Dm+hlF8EbX/h2zwwAfkAAts8Jvgju5pfCwGDB/RbMG1/4FMYvY6MMTIi2zxtBXOptAEVkjc34iVuml8JAYMH9FswbX/gU4GAEPQOb6ExlF8KbX7g+CPIyx9QkoAQ9EMnUIehUgeywv8fLCAhAaoB2zxTJIAg9GogbpIwcJL5AOIhvQHC/7CUXwNwbeB5JIAg9GpSIIAg9AxvoTEhbrCUXwNwbeB6JIAg9GpSIIAg9AxvoTFQA7mTW3Bt4FRhBIAg9BVZLQCCIYH8GbqdbCEgbpIwcJTQ1wv/4uAgbpFb4CGB/Bi6jhQx0NQh+wTtQwLQ7R7tUwHxBoLyAOABgfwXupPQ8AuRMOIALIAi+DMg0NMHAcAS8qiAYNch0z/0BNEBYoAL+DPbPBBHXwcC0wfTB9MHMAPC/xOhUgS8k18DbeClIMEAk18DbeDIywfLB8sHydAoAe6OH1UjgM7IygcWyx8UzBLKAPQAyj/L/wHPFgKDB/RDbXLgIIAL+DPbPBBXXwcE0wfTB9MHMAGkUge+jhBbUFZfBVAjgwf0WzB2WKES4BBFEDQQI0h2gM7IygcWyx8UzBLKAPQAyj/L/xLLBxLLB8sHAoMH9ENtcigAK0cIAYyMsFUAXPFhTLbssfyz/JAfsAgAW1cfgz0NcL//gjghBOQ29kcIIAxP/IyxAUy/+DHfoCE8tqEssfyz8BzxbJcPsAgCASAmJwFpvRwXaiaGppj+n/+gJothjCf7bHTqiJQYP6PzfSkEdGAW2eKQg3gSgBt4EBSJlxANmJczYQwrAV26VF7UTQ10yACwGAIPRqFNs8bERSVLmTXwZ/4FBEtggCgwmgE6gDpgISqBKgAaiCgCASApKgBU0NMHAYEAkbryrAGS1DHe10zQ0wcBwDbyrNMH0wfTB9MH0x/TH9Mf0x/RABG1kv2omhrhY/ABN7YRfaiaGppj+n/+gJothjBg/oHN9DJGDbw7Z5ArAmDbPG2DH44SJYAQ9H5vpTIhlVIDbwIC3gGz5jA00wfTB9MH0QfbPG8DBgcQNRA0bwksLQAk0gcBwM7yrNMf1NIA9ATSP9P/AC7Q0gcBwPPyrNIf9ATSAAGS0/+SfwHi0Q=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif deleted file mode 100644 index 6d3f69fd..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif +++ /dev/null @@ -1,1304 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/config-code.fc` -PROGRAM{ - DECLPROC set_conf_param - DECLPROC load_data - DECLPROC store_data - DECLPROC parse_vote_config - DECLPROC get_vote_config_internal - DECLPROC get_vote_config - DECLPROC check_validator_set - DECLPROC send_answer - DECLPROC send_confirmation - DECLPROC send_error - DECLPROC change_elector_code - 1666 DECLMETHOD after_code_upgrade - DECLPROC perform_action - DECLPROC get_current_vset - DECLPROC get_validator_descr - DECLPROC unpack_validator_descr - DECLPROC parse_config_proposal - DECLPROC accept_proposal - DECLPROC perform_proposed_action - DECLPROC unpack_proposal_status - DECLPROC update_proposal_status - DECLPROC begin_pack_proposal_status - DECLPROC register_vote - DECLPROC proceed_register_vote - DECLPROC scan_proposal - DECLPROC scan_random_proposal - DECLPROC register_voting_proposal - DECLPROC recv_internal - DECLPROC recv_external - DECLPROC run_ticktock - 85143 DECLMETHOD seqno - DECLPROC unpack_proposal - 94347 DECLMETHOD get_proposal - 107394 DECLMETHOD list_proposals - 75077 DECLMETHOD proposal_storage_price - set_conf_param PROC:<{ - // index value - c4 PUSH // index value _3 - CTOS // index value cs - LDREF // index value cfg_dict cs - s3 s3 XCHG2 - 32 PUSHINT // cs value index cfg_dict _9=32 - DICTISETREF // cs cfg_dict - NEWC // cs cfg_dict _11 - STREF // cs _12 - SWAP // _12 cs - STSLICER // _13 - ENDC // _14 - c4 POP - }> - load_data PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - LDREF // _4 cs - 32 LDU // _4 _6 cs - 256 LDU // _4 _6 _9 cs - LDDICT // res res res res cs - ENDS - }> - store_data PROC:<{ - // cfg_dict stored_seqno public_key vote_dict - s0 s3 XCHG - NEWC // vote_dict stored_seqno public_key cfg_dict _4 - STREF // vote_dict stored_seqno public_key _5 - s1 s2 XCHG // vote_dict public_key stored_seqno _5 - 32 STU // vote_dict public_key _7 - 256 STU // vote_dict _9 - STDICT // _10 - ENDC // _11 - c4 POP - }> - parse_vote_config PROC:<{ - // c - CTOS // cs - 8 LDU // _4 cs - SWAP // cs _4 - 54 EQINT // cs _8 - 44 THROWIFNOT - 8 LDU // _11 cs - 8 LDU // _11 _14 cs - 8 LDU // _11 _14 _17 cs - 8 LDU // _11 _14 _17 _20 cs - 32 LDU // _11 _14 _17 _20 _23 cs - 32 LDU // _11 _14 _17 _20 _23 _26 cs - 32 LDU // _11 _14 _17 _20 _23 _26 _29 cs - 32 LDU // res res res res res res res res cs - ENDS - }> - get_vote_config_internal PROCREF:<{ - // critical? cparam11 - CTOS // critical? cs - 8 LDU // critical? _5 cs - SWAP - 145 PUSHINT // critical? cs _5 _8=145 - EQUAL // critical? cs _9 - 44 THROWIFNOT - SWAP // cs critical? - IF:<{ // cs - LDREF // _18 _17 - NIP // cs - }> // cs - PLDREF // _13 - parse_vote_config INLINECALLDICT // _19 _20 _21 _22 _23 _24 _25 _26 - }> - get_vote_config PROC:<{ - // critical? - 11 PUSHINT // critical? _1=11 - CONFIGOPTPARAM // critical? _2 - get_vote_config_internal INLINECALLDICT // _4 _5 _6 _7 _8 _9 _10 _11 - }> - check_validator_set PROC:<{ - // vset - CTOS // cs - 8 LDU // _4 cs - SWAP // cs _4 - 18 EQINT // cs _8 - 9 THROWIFNOT - 32 LDU // utime_since cs - 32 LDU // utime_since utime_until cs - 16 LDU // utime_since utime_until total cs - 16 LDU // utime_since utime_until total _42 _41 - DROP // utime_since utime_until total main - DUP // utime_since utime_until total main main - 0 GTINT // utime_since utime_until total main _28 - 9 THROWIFNOT - GEQ // utime_since utime_until _31 - 9 THROWIFNOT - }> - send_answer PROC:<{ - // addr query_id ans_tag mode - 0 PUSHINT // addr query_id ans_tag mode _4=0 - 24 PUSHINT // addr query_id ans_tag mode _4=0 _5=24 - NEWC // addr query_id ans_tag mode _4=0 _5=24 _6 - 6 STU // addr query_id ans_tag mode _4=0 _8 - s0 s5 XCHG2 // _4=0 query_id ans_tag mode _8 addr - STSLICER // _4=0 query_id ans_tag mode _9 - s1 s4 XCHG // mode query_id ans_tag _4=0 _9 - 111 STU // mode query_id ans_tag _23 - 32 STU // mode query_id _25 - 64 STU // mode _27 - ENDC // mode _28 - SWAP // _28 mode - SENDRAWMSG - }> - send_confirmation PROC:<{ - // addr query_id ans_tag - 64 PUSHINT // addr query_id ans_tag _3=64 - send_answer CALLDICT - }> - send_error PROC:<{ - // addr query_id ans_tag - 64 PUSHINT // addr query_id ans_tag _3=64 - send_answer CALLDICT - }> - change_elector_code PROC:<{ - // cs - 1 PUSHINT // cs _2=1 - CONFIGOPTPARAM // cs _3 - CTOS // cs _4 - 256 PLDU // cs dest_addr - NOW // cs dest_addr query_id - 1313042276 PUSHINT // cs dest_addr query_id _9=1313042276 - 0 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 - 50431 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 - NEWC // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 _12 - 17 STU // cs dest_addr query_id _9=1313042276 _10=0 _14 - s1 s4 XCHG // cs _10=0 query_id _9=1313042276 dest_addr _14 - 256 STU // cs _10=0 query_id _9=1313042276 _16 - 30 PUSHPOW2 // cs _10=0 query_id _9=1313042276 _16 _19 - STGRAMS // cs _10=0 query_id _9=1313042276 _20 - s1 s3 XCHG // cs _9=1313042276 query_id _10=0 _20 - 107 STU // cs _9=1313042276 query_id _34 - s1 s2 XCHG // cs query_id _9=1313042276 _34 - 32 STU // cs query_id _36 - 64 STU // cs _38 - SWAP // _38 cs - STSLICER // _39 - ENDC // _40 - 0 PUSHINT // _40 _41=0 - SENDRAWMSG - }> - after_code_upgrade PROC:<{ - // param old_code - 2DROP // - }> - perform_action PROCREF:<{ - // cfg_dict public_key action cs - OVER - 1130778657 PUSHINT // cfg_dict public_key action cs action _4=1130778657 - EQUAL // cfg_dict public_key action cs _5 - IFJMP:<{ // cfg_dict public_key action cs - NIP // cfg_dict public_key cs - 32 LDI // cfg_dict public_key param_index cs - LDREF // cfg_dict public_key param_index param_value cs - ENDS - s0 s1 s3 XCHG3 - 32 PUSHINT // public_key param_value param_index cfg_dict _15=32 - DICTISETREF // public_key cfg_dict - SWAP // cfg_dict public_key - }> // cfg_dict public_key action cs - OVER - 1313042276 PUSHINT // cfg_dict public_key action cs action _17=1313042276 - EQUAL // cfg_dict public_key action cs _18 - IFJMP:<{ // cfg_dict public_key action cs - NIP // cfg_dict public_key cs - LDREF // cfg_dict public_key new_code cs - OVER // cfg_dict public_key new_code cs new_code - SETCODE - c3 PUSH // cfg_dict public_key new_code cs old_code - s0 s2 XCHG // cfg_dict public_key old_code cs new_code - CTOS // cfg_dict public_key old_code cs _25 - BLESS // cfg_dict public_key old_code cs _26 - c3 POP - SWAP // cfg_dict public_key cs old_code - after_code_upgrade CALLDICT - 0 THROW - }> // cfg_dict public_key action cs - OVER - 1348619041 PUSHINT // cfg_dict public_key action cs action _31=1348619041 - EQUAL // cfg_dict public_key action cs _32 - IFJMP:<{ // cfg_dict public_key action cs - 2 1 BLKDROP2 // cfg_dict cs - 256 LDU // cfg_dict public_key cs - ENDS - }> // cfg_dict public_key action cs - OVER - 1313074949 PUSHINT // cfg_dict public_key action cs action _37=1313074949 - EQUAL // cfg_dict public_key action cs _38 - IFJMP:<{ // cfg_dict public_key action cs - NIP // cfg_dict public_key cs - change_elector_code CALLDICT - }> // cfg_dict public_key action cs - DROP // cfg_dict public_key action - 32 THROWIF - }> - get_current_vset PROCREF:<{ - // - 34 PUSHINT // _1=34 - CONFIGOPTPARAM // vset - DUP // vset vset - CTOS // vset cs - 8 LDU // vset _6 cs - SWAP // vset cs _6 - 18 EQINT // vset cs _10 - 40 THROWIFNOT - 96 PUSHINT // vset cs _19 - SDSKIPFIRST // vset cs - 64 LDU // vset _23 cs - LDDICT // vset total_weight dict cs - ENDS - }> - get_validator_descr PROCREF:<{ - // idx - get_current_vset INLINECALLDICT // idx _9 _10 _11 - s2 POP // idx dict total_weight - -ROT - 16 PUSHINT // total_weight idx dict _7=16 - DICTUGET - NULLSWAPIFNOT // total_weight _12 _13 - DROP // total_weight value - SWAP // value total_weight - }> - unpack_validator_descr PROC:<{ - // cs - 8 LDU // _2 cs - 32 PUSHINT // _2 cs _5=32 - NOT // _2 cs _6 - s1 s2 XCHG // cs _2 _6 - AND // cs _7 - 83 EQINT // cs _9 - 41 THROWIFNOT - 32 LDU // _12 cs - SWAP - 2390828938 PUSHINT // cs _12 _15=2390828938 - EQUAL // cs _16 - 41 THROWIFNOT - 256 LDU // _18 cs - 64 LDU // _18 _31 _30 - DROP // _18 _21 - }> - parse_config_proposal PROCREF:<{ - // c - CTOS // cs - 8 LDI // _4 cs - SWAP // cs _4 - -13 EQINT // cs _10 - 44 THROWIFNOT - 32 LDI // _15 cs - LDOPTREF // _15 _18 cs - 1 LDI // id val hash cs - SWAP // id val cs hash - IF:<{ // id val cs - 256 LDU // id val hash cs - }>ELSE<{ // id val cs - -1 PUSHINT // id val cs hash=-1 - SWAP // id val hash cs - }> - ENDS - }> - accept_proposal PROCREF:<{ - // cfg_dict proposal critical? - SWAP // cfg_dict critical? proposal - parse_config_proposal INLINECALLDICT // cfg_dict critical? param_id param_val req_hash - s2 s4 PUSH2 - 32 PUSHINT // cfg_dict critical? param_id param_val req_hash param_id cfg_dict _8=32 - DICTIGETOPTREF // cfg_dict critical? param_id param_val req_hash cur_val - DUP // cfg_dict critical? param_id param_val req_hash cur_val cur_val - ISNULL // cfg_dict critical? param_id param_val req_hash cur_val _11 - IF:<{ // cfg_dict critical? param_id param_val req_hash cur_val - DROP // cfg_dict critical? param_id param_val req_hash - 0 PUSHINT // cfg_dict critical? param_id param_val req_hash _12=0 - }>ELSE<{ // cfg_dict critical? param_id param_val req_hash cur_val - HASHCU // cfg_dict critical? param_id param_val req_hash _12 - }> // cfg_dict critical? param_id param_val req_hash cur_hash - OVER // cfg_dict critical? param_id param_val req_hash cur_hash req_hash - NEQ // cfg_dict critical? param_id param_val req_hash _15 - SWAP // cfg_dict critical? param_id param_val _15 req_hash - -1 GTINT // cfg_dict critical? param_id param_val _15 _17 - AND // cfg_dict critical? param_id param_val _18 - IFJMP:<{ // cfg_dict critical? param_id param_val - 3 BLKDROP // cfg_dict - 0 PUSHINT // cfg_dict _19=0 - PUSHNULL // cfg_dict _19=0 _20 - }> // cfg_dict critical? param_id param_val - 9 PUSHINT // cfg_dict critical? param_id param_val _22=9 - s4 PUSH - 32 PUSHINT // cfg_dict critical? param_id param_val _22=9 cfg_dict _23=32 - DICTIGETOPTREF // cfg_dict critical? param_id param_val mparams - s2 s(-1) PUXC - 32 PUSHINT // cfg_dict critical? param_id param_val param_id mparams _27=32 - DICTIGET - NULLSWAPIFNOT // cfg_dict critical? param_id param_val _49 _50 - NIP // cfg_dict critical? param_id param_val found? - OVER // cfg_dict critical? param_id param_val found? param_val - ISNULL // cfg_dict critical? param_id param_val found? _29 - AND // cfg_dict critical? param_id param_val _30 - IFJMP:<{ // cfg_dict critical? param_id param_val - 3 BLKDROP // cfg_dict - 0 PUSHINT // cfg_dict _31=0 - PUSHNULL // cfg_dict _31=0 _32 - }> // cfg_dict critical? param_id param_val - 10 PUSHINT // cfg_dict critical? param_id param_val _34=10 - s4 PUSH - 32 PUSHINT // cfg_dict critical? param_id param_val _34=10 cfg_dict _35=32 - DICTIGETOPTREF // cfg_dict critical? param_id param_val cparams - s2 s(-1) PUXC - 32 PUSHINT // cfg_dict critical? param_id param_val param_id cparams _38=32 - DICTIGET - NULLSWAPIFNOT // cfg_dict critical? param_id param_val _51 _52 - NIP // cfg_dict critical? param_id param_val found? - s0 s3 XCHG2 // cfg_dict param_val param_id found? critical? - LESS // cfg_dict param_val param_id _40 - IFJMP:<{ // cfg_dict param_val param_id - 2DROP // cfg_dict - 0 PUSHINT // cfg_dict _41=0 - PUSHNULL // cfg_dict _41=0 _42 - }> // cfg_dict param_val param_id - s1 s(-1) s2 PU2XC - 32 PUSHINT // param_id param_val param_val param_id cfg_dict _44=32 - DICTISETREF // param_id param_val cfg_dict - -ROT // cfg_dict param_id param_val - }> - perform_proposed_action PROCREF:<{ - // cfg_dict public_key param_id param_val - OVER - -999 PUSHINT // cfg_dict public_key param_id param_val param_id _4=-999 - EQUAL // cfg_dict public_key param_id param_val _5 - IFJMP:<{ // cfg_dict public_key param_id param_val - 2 1 BLKDROP2 // cfg_dict param_val - DUP // cfg_dict param_val param_val - ISNULL // cfg_dict param_val _6 - IF:<{ // cfg_dict param_val - DROP // cfg_dict - 0 PUSHINT // cfg_dict _7=0 - }>ELSE<{ // cfg_dict param_val - CTOS // cfg_dict _9 - 256 PLDU // cfg_dict _7 - }> - }> // cfg_dict public_key param_id param_val - DUP // cfg_dict public_key param_id param_val param_val - ISNULL // cfg_dict public_key param_id param_val _12 - IFJMP:<{ // cfg_dict public_key param_id param_val - 2DROP // cfg_dict public_key - }> // cfg_dict public_key param_id param_val - OVER - -1000 PUSHINT // cfg_dict public_key param_id param_val param_id _13=-1000 - EQUAL // cfg_dict public_key param_id param_val _14 - IFJMP:<{ // cfg_dict public_key param_id param_val - NIP // cfg_dict public_key param_val - CTOS // cfg_dict public_key cs - LDREF // cfg_dict public_key new_code cs - OVER // cfg_dict public_key new_code cs new_code - SETCODE - c3 PUSH // cfg_dict public_key new_code cs old_code - s0 s2 XCHG // cfg_dict public_key old_code cs new_code - CTOS // cfg_dict public_key old_code cs _23 - BLESS // cfg_dict public_key old_code cs _24 - c3 POP - SWAP // cfg_dict public_key cs old_code - after_code_upgrade CALLDICT - 0 THROW - }> // cfg_dict public_key param_id param_val - SWAP - -1001 PUSHINT // cfg_dict public_key param_val param_id _29=-1001 - EQUAL // cfg_dict public_key param_val _30 - IF:<{ // cfg_dict public_key param_val - CTOS // cfg_dict public_key cs - change_elector_code CALLDICT - }>ELSE<{ - DROP // cfg_dict public_key - }> - }> - unpack_proposal_status PROCREF:<{ - // cs - 8 LDI // _2 cs - SWAP // cs _2 - -50 EQINT // cs _8 - 44 THROWIFNOT - 32 LDU // _10 cs - LDREF // _10 _13 cs - 1 LDI // _10 _13 _15 cs - LDDICT // _10 _13 _15 _18 cs - 64 LDI // _10 _13 _15 _18 _20 cs - 256 LDU // _10 _13 _15 _18 _20 _23 cs - }> - update_proposal_status PROCREF:<{ - // rest weight_remaining critical? - get_vote_config INLINECALLDICT // rest weight_remaining _43 _44 _45 _46 _47 _48 _49 _50 - s4 s7 XCHG - 7 BLKDROP // rest weight_remaining max_losses - s0 s2 XCHG // max_losses weight_remaining rest - 8 LDU // max_losses weight_remaining _15 rest - 8 LDU // max_losses weight_remaining _15 _18 rest - 8 LDU // max_losses weight_remaining _15 _18 _56 _55 - DROP // max_losses weight_remaining rounds_remaining wins losses - s0 s3 XCHG // max_losses losses rounds_remaining wins weight_remaining - -1 GTINT // max_losses losses rounds_remaining wins _25 - s1 s3 XCHG // max_losses wins rounds_remaining losses _25 - SUB // max_losses wins rounds_remaining losses - s0 s3 PUXC // losses wins rounds_remaining losses max_losses - GREATER // losses wins rounds_remaining _27 - IFJMP:<{ // losses wins rounds_remaining - 3 BLKDROP // - PUSHNULL // _28 - }> // losses wins rounds_remaining - DEC // losses wins rounds_remaining - DUP // losses wins rounds_remaining rounds_remaining - 0 LESSINT // losses wins rounds_remaining _32 - IFJMP:<{ // losses wins rounds_remaining - 3 BLKDROP // - PUSHNULL // _33 - }> // losses wins rounds_remaining - NEWC // losses wins rounds_remaining _34 - 8 STU // losses wins _36 - 8 STU // losses _38 - 8 STU // _40 - ENDC // _41 - CTOS // _42 - }> - begin_pack_proposal_status PROC:<{ - // expires proposal critical? voters weight_remaining vset_id - -50 PUSHINT // expires proposal critical? voters weight_remaining vset_id _8 - NEWC // expires proposal critical? voters weight_remaining vset_id _8 _9 - 8 STI // expires proposal critical? voters weight_remaining vset_id _11 - s1 s6 XCHG // vset_id proposal critical? voters weight_remaining expires _11 - 32 STU // vset_id proposal critical? voters weight_remaining _13 - s1 s4 XCHG // vset_id weight_remaining critical? voters proposal _13 - STREF // vset_id weight_remaining critical? voters _14 - s1 s2 XCHG // vset_id weight_remaining voters critical? _14 - 1 STI // vset_id weight_remaining voters _16 - STDICT // vset_id weight_remaining _17 - 64 STI // vset_id _19 - 256 STU // _21 - }> - register_vote PROCREF:<{ - // vote_dict phash idx weight - s2 s3 PUSH2 - 8 PUSHPOW2 // vote_dict phash idx weight phash vote_dict _6=256 - DICTUGET - NULLSWAPIFNOT // vote_dict phash idx weight pstatus found? - IFNOTJMP:<{ // vote_dict phash idx weight pstatus - 4 BLKDROP // vote_dict - PUSHNULL // vote_dict _8 - -1 PUSHINT // vote_dict _8 _9=-1 - }> // vote_dict phash idx weight pstatus - get_current_vset INLINECALLDICT // vote_dict phash idx weight pstatus _111 _112 _113 - DROP // vote_dict phash idx weight pstatus cur_vset total_weight - SWAP // vote_dict phash idx weight pstatus total_weight cur_vset - HASHCU // vote_dict phash idx weight pstatus total_weight cur_vset_id - s0 s2 XCHG // vote_dict phash idx weight cur_vset_id total_weight pstatus - unpack_proposal_status INLINECALLDICT // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest - s6 PUSH - NOW // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest expires _24 - LEQ // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest _25 - IFJMP:<{ // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest - 11 BLKDROP // vote_dict phash - SWAP - 8 PUSHPOW2 // phash vote_dict _27=256 - DICTUDEL // _121 _122 - DROP // vote_dict - PUSHNULL // vote_dict _29 - -1 PUSHINT // vote_dict _29 _30=-1 - }> // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest - s1 s8 PUSH2 // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest vset_id cur_vset_id - NEQ // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest _31 - IF:<{ // vote_dict phash idx weight cur_vset_id total_weight expires proposal critical? voters weight_remaining vset_id rest - NIP - s2 POP // vote_dict phash idx weight vset_id total_weight expires proposal critical? rest weight_remaining - s2 PUSH // vote_dict phash idx weight vset_id total_weight expires proposal critical? rest weight_remaining critical? - update_proposal_status INLINECALLDICT // vote_dict phash idx weight vset_id total_weight expires proposal critical? rest - PUSHNULL // vote_dict phash idx weight vset_id total_weight expires proposal critical? rest voters - s0 s5 XCHG - 3 PUSHINT // vote_dict phash idx weight vset_id voters expires proposal critical? rest total_weight _34=3 - 2 MULRSHIFT# // vote_dict phash idx weight vset_id voters expires proposal critical? rest weight_remaining - s1 s5 XCHG // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - }>ELSE<{ - s7 POP - s7 POP // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - }> - s5 PUSH // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining rest - ISNULL // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining _37 - IFJMP:<{ // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - 9 BLKDROP // vote_dict phash - SWAP - 8 PUSHPOW2 // phash vote_dict _39=256 - DICTUDEL // _123 _124 - DROP // vote_dict - PUSHNULL // vote_dict _41 - -1 PUSHINT // vote_dict _41 _42=-1 - }> // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - s8 s1 PUSH2 - 16 PUSHINT // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining idx voters _45=16 - DICTUGET - NULLSWAPIFNOT // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining _125 _126 - NIP // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining found? - IFJMP:<{ // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - 10 BLKDROP // vote_dict - PUSHNULL // vote_dict _47 - -2 PUSHINT // vote_dict _47 _48=-2 - }> // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining - NOW // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining _50 - NEWC // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining _50 _51 - 32 STU // vote_dict phash idx weight vset_id rest expires proposal critical? voters weight_remaining _53 - s9 s2 XCHG2 - 16 PUSHINT // vote_dict phash weight_remaining weight vset_id rest expires proposal critical? _53 idx voters _54=16 - DICTUSETB // vote_dict phash weight_remaining weight vset_id rest expires proposal critical? voters - s7 PUSH // vote_dict phash weight_remaining weight vset_id rest expires proposal critical? voters old_wr - s8 s7 XCHG2 // vote_dict phash voters old_wr vset_id rest expires proposal critical? weight_remaining weight - SUB // vote_dict phash voters old_wr vset_id rest expires proposal critical? weight_remaining - s0 s6 PUXC // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? weight_remaining old_wr - XOR // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? _58 - -1 GTINT // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? _60 - IFJMP:<{ // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? - 3 4 BLKSWAP // vote_dict phash rest expires proposal critical? voters weight_remaining vset_id - begin_pack_proposal_status INLINECALLDICT // vote_dict phash rest _62 - SWAP // vote_dict phash _62 rest - STSLICER // vote_dict phash _63 - s0 s2 XCHG - 8 PUSHPOW2 // _63 phash vote_dict _64=256 - DICTUSETB // vote_dict - PUSHNULL // vote_dict _66 - 2 PUSHINT // vote_dict _66 _67=2 - }> // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? - DUP // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? critical? - get_vote_config INLINECALLDICT // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? _127 _128 _129 _130 _131 _132 _133 _134 - s5 s7 XCHG - 7 BLKDROP // vote_dict phash voters weight_remaining vset_id rest expires proposal critical? min_wins - s0 s4 XCHG // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? rest - 8 LDU // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? _80 rest - 8 LDU // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? _80 _83 rest - 8 LDU // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? _80 _83 _140 _139 - DROP // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? rounds_remaining wins losses - SWAP // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? rounds_remaining losses wins - INC // vote_dict phash voters weight_remaining vset_id min_wins expires proposal critical? rounds_remaining losses wins - s0 s6 PUXC // vote_dict phash voters weight_remaining vset_id wins expires proposal critical? rounds_remaining losses wins min_wins - GEQ // vote_dict phash voters weight_remaining vset_id wins expires proposal critical? rounds_remaining losses _91 - IFJMP:<{ // vote_dict phash voters weight_remaining vset_id wins expires proposal critical? rounds_remaining losses - 2DROP - s5 s6 XCHG2 - 5 BLKDROP // vote_dict phash critical? proposal - s2 s3 XCHG2 - 8 PUSHPOW2 // proposal critical? phash vote_dict _93=256 - DICTUDEL // proposal critical? _141 _142 - DROP // proposal critical? vote_dict - 6 PUSHINT - ROT // proposal vote_dict _95=6 critical? - SUB // proposal vote_dict _96 - s1 s2 XCHG // vote_dict proposal _96 - }> // vote_dict phash voters weight_remaining vset_id wins expires proposal critical? rounds_remaining losses - s4 s5 XCHG - s3 s4 XCHG - s2 s3 XCHG - s8 s7 s6 XCHG3 // vote_dict phash wins rounds_remaining losses expires proposal critical? voters weight_remaining vset_id - begin_pack_proposal_status INLINECALLDICT // vote_dict phash wins rounds_remaining losses _98 - s1 s2 XCHG // vote_dict phash wins losses rounds_remaining _98 - 8 STU // vote_dict phash wins losses _100 - s1 s2 XCHG // vote_dict phash losses wins _100 - 8 STU // vote_dict phash losses _102 - 8 STU // vote_dict phash _104 - s0 s2 XCHG - 8 PUSHPOW2 // _104 phash vote_dict _105=256 - DICTUSETB // vote_dict - PUSHNULL // vote_dict _107 - 2 PUSHINT // vote_dict _107 _108=2 - }> - proceed_register_vote PROCREF:<{ - // phash idx weight - load_data INLINECALLDICT // phash idx weight cfg_dict stored_seqno public_key vote_dict - s6 s1 s3 XCHG3 - s5 s4 XCHG2 // stored_seqno public_key cfg_dict vote_dict phash idx weight - register_vote INLINECALLDICT // stored_seqno public_key cfg_dict vote_dict accepted_proposal status - s3 s5 s4 PUSH3 - s5 PUSH // stored_seqno public_key cfg_dict vote_dict accepted_proposal status cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - OVER // stored_seqno public_key cfg_dict vote_dict accepted_proposal status accepted_proposal - ISNULL // stored_seqno public_key cfg_dict vote_dict accepted_proposal status _12 - IFNOT:<{ // stored_seqno public_key cfg_dict vote_dict accepted_proposal status - 6 PUSHINT // stored_seqno public_key cfg_dict vote_dict accepted_proposal status _14=6 - OVER // stored_seqno public_key cfg_dict vote_dict accepted_proposal status _14=6 status - SUB // stored_seqno public_key cfg_dict vote_dict accepted_proposal status critical? - s4 s4 s0 XCHG3 // stored_seqno public_key status vote_dict cfg_dict accepted_proposal critical? - accept_proposal INLINECALLDICT // stored_seqno public_key status vote_dict cfg_dict param_id param_val - s2 s6 s5 PUSH3 - s6 PUSH // stored_seqno public_key status vote_dict cfg_dict param_id param_val cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - OVER // stored_seqno public_key status vote_dict cfg_dict param_id param_val param_id - IF:<{ // stored_seqno public_key status vote_dict cfg_dict param_id param_val - COMMIT - s2 s3 XCHG - s2 s5 XCHG // stored_seqno vote_dict status cfg_dict public_key param_id param_val - perform_proposed_action INLINECALLDICT // stored_seqno vote_dict status cfg_dict public_key - s4 s0 s3 XCHG3 // status cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - }>ELSE<{ - s4 s6 XCHG - 6 BLKDROP // status - }> - }>ELSE<{ - 5 1 BLKDROP2 // status - }> - }> - scan_proposal PROCREF:<{ - // phash pstatus - NIP // pstatus - get_current_vset INLINECALLDICT // pstatus _35 _36 _37 - DROP // pstatus cur_vset total_weight - SWAP // pstatus total_weight cur_vset - HASHCU // pstatus total_weight cur_vset_id - s2 PUSH // pstatus total_weight cur_vset_id pstatus - unpack_proposal_status INLINECALLDICT // pstatus total_weight cur_vset_id _38 _39 _40 _41 _42 _43 _44 - s3 POP // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id - s5 PUSH - NOW // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id expires _16 - LEQ // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id _17 - IFJMP:<{ // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id - 9 BLKDROP // - PUSHNULL // _18 - TRUE // _18 _19 - }> // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id - s6 PUSH // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining vset_id cur_vset_id - EQUAL // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining _20 - IFJMP:<{ // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining - 7 BLKDROP // pstatus - FALSE // pstatus _21 - }> // pstatus total_weight cur_vset_id expires proposal critical? rest weight_remaining - s7 POP // weight_remaining total_weight vset_id expires proposal critical? rest - s0 s6 s6 XC2PU // critical? total_weight vset_id expires proposal rest weight_remaining critical? - update_proposal_status INLINECALLDICT // critical? total_weight vset_id expires proposal rest - PUSHNULL // critical? total_weight vset_id expires proposal rest voters - s0 s5 XCHG - 3 PUSHINT // critical? voters vset_id expires proposal rest total_weight _24=3 - 2 MULRSHIFT# // critical? voters vset_id expires proposal rest weight_remaining - OVER // critical? voters vset_id expires proposal rest weight_remaining rest - ISNULL // critical? voters vset_id expires proposal rest weight_remaining _27 - IFJMP:<{ // critical? voters vset_id expires proposal rest weight_remaining - 7 BLKDROP // - PUSHNULL // _28 - TRUE // _28 _29 - }> // critical? voters vset_id expires proposal rest weight_remaining - s3 s5 XCHG - s2 s4 XCHG - s3 s6 XCHG - s6 s0 s6 XCHG3 // rest expires proposal critical? voters weight_remaining vset_id - begin_pack_proposal_status INLINECALLDICT // rest _30 - SWAP // _30 rest - STSLICER // _31 - ENDC // _32 - CTOS // _33 - TRUE // _33 _34 - }> - scan_random_proposal PROCREF:<{ - // vote_dict - RANDU256 // vote_dict _4 - OVER - 8 PUSHPOW2 // vote_dict _4 vote_dict _5=256 - DICTUGETNEXTEQ - NULLSWAPIFNOT2 // vote_dict pstatus phash found? - IFNOTJMP:<{ // vote_dict pstatus phash - 2DROP // vote_dict - }> // vote_dict pstatus phash - s0 s1 PUXC // vote_dict phash phash pstatus - scan_proposal INLINECALLDICT // vote_dict phash pstatus changed? - IF:<{ // vote_dict phash pstatus - DUP // vote_dict phash pstatus pstatus - ISNULL // vote_dict phash pstatus _9 - IF:<{ // vote_dict phash pstatus - DROP // vote_dict phash - SWAP - 8 PUSHPOW2 // phash vote_dict _11=256 - DICTUDEL // _21 _22 - DROP // vote_dict - }>ELSE<{ // vote_dict phash pstatus - s0 s2 XCHG - 8 PUSHPOW2 // pstatus phash vote_dict _14=256 - DICTUSET // vote_dict - }> - }>ELSE<{ - 2DROP // vote_dict - }> - }> - register_voting_proposal PROCREF:<{ - // cs msg_value - SWAP // msg_value cs - 32 LDU // msg_value _5 cs - LDREF // msg_value _5 _8 cs - 1 LDI // msg_value _5 _8 _156 _155 - DROP // msg_value expire_at proposal critical? - s2 PUSH // msg_value expire_at proposal critical? expire_at - 30 RSHIFT# // msg_value expire_at proposal critical? _14 - IF:<{ // msg_value expire_at proposal critical? - s0 s2 XCHG - NOW // msg_value critical? proposal expire_at _15 - SUB // msg_value critical? proposal expire_at - s0 s2 XCHG // msg_value expire_at proposal critical? - }> // msg_value expire_at proposal critical? - OVER // msg_value expire_at proposal critical? proposal - parse_config_proposal INLINECALLDICT // msg_value expire_at proposal critical? param_id param_val hash - DUP // msg_value expire_at proposal critical? param_id param_val hash hash - -1 GTINT // msg_value expire_at proposal critical? param_id param_val hash _22 - IF:<{ // msg_value expire_at proposal critical? param_id param_val hash - s2 PUSH // msg_value expire_at proposal critical? param_id param_val hash param_id - CONFIGOPTPARAM // msg_value expire_at proposal critical? param_id param_val hash cur_val - DUP // msg_value expire_at proposal critical? param_id param_val hash cur_val cur_val - ISNULL // msg_value expire_at proposal critical? param_id param_val hash cur_val _26 - IF:<{ // msg_value expire_at proposal critical? param_id param_val hash cur_val - DROP // msg_value expire_at proposal critical? param_id param_val hash - 0 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash _27=0 - }>ELSE<{ // msg_value expire_at proposal critical? param_id param_val hash cur_val - HASHCU // msg_value expire_at proposal critical? param_id param_val hash _27 - }> // msg_value expire_at proposal critical? param_id param_val hash cur_hash - OVER // msg_value expire_at proposal critical? param_id param_val hash cur_hash hash - NEQ // msg_value expire_at proposal critical? param_id param_val hash _30 - IF:<{ // msg_value expire_at proposal critical? param_id param_val hash - DROP // msg_value expire_at proposal critical? param_id param_val - -3798229846 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash=-3798229846 - }> // msg_value expire_at proposal critical? param_id param_val hash - }>ELSE<{ // msg_value expire_at proposal critical? param_id param_val hash - 9 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash _33=9 - CONFIGOPTPARAM // msg_value expire_at proposal critical? param_id param_val hash m_params - s3 s(-1) PUXC - 32 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash param_id m_params _37=32 - DICTIGET - NULLSWAPIFNOT // msg_value expire_at proposal critical? param_id param_val hash _160 _161 - NIP // msg_value expire_at proposal critical? param_id param_val hash found? - IF:<{ // msg_value expire_at proposal critical? param_id param_val hash - DROP // msg_value expire_at proposal critical? param_id param_val - -3444600428 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash=-3444600428 - }> // msg_value expire_at proposal critical? param_id param_val hash - }> - OVER // msg_value expire_at proposal critical? param_id param_val hash param_val - CDEPTH // msg_value expire_at proposal critical? param_id param_val hash _40 - 7 PUSHPOW2 // msg_value expire_at proposal critical? param_id param_val hash _40 _41=128 - GEQ // msg_value expire_at proposal critical? param_id param_val hash _42 - IF:<{ // msg_value expire_at proposal critical? param_id param_val hash - DROP // msg_value expire_at proposal critical? param_id param_val - -3261162582 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash=-3261162582 - }> // msg_value expire_at proposal critical? param_id param_val hash - DUP // msg_value expire_at proposal critical? param_id param_val hash hash - -1 LESSINT // msg_value expire_at proposal critical? param_id param_val hash _45 - IFJMP:<{ // msg_value expire_at proposal critical? param_id param_val hash - 6 1 BLKDROP2 // hash - }> // msg_value expire_at proposal critical? param_id param_val hash - s3 PUSH // msg_value expire_at proposal critical? param_id param_val hash critical? - IFNOT:<{ // msg_value expire_at proposal critical? param_id param_val hash - 10 PUSHINT // msg_value expire_at proposal critical? param_id param_val hash _47=10 - CONFIGOPTPARAM // msg_value expire_at proposal critical? param_id param_val hash crit_params - s1 s3 XCHG - 32 PUSHINT // msg_value expire_at proposal critical? hash param_val param_id crit_params _51=32 - DICTIGET - NULLSWAPIFNOT // msg_value expire_at proposal critical? hash param_val _162 _163 - NIP // msg_value expire_at proposal critical? hash param_val found? - IF:<{ // msg_value expire_at proposal critical? hash param_val - -3279055188 PUSHINT - s2 POP // msg_value expire_at proposal critical? hash=-3279055188 param_val - }> // msg_value expire_at proposal critical? hash param_val - }>ELSE<{ - s2 POP // msg_value expire_at proposal critical? hash param_val - }> - OVER // msg_value expire_at proposal critical? hash param_val hash - -1 LESSINT // msg_value expire_at proposal critical? hash param_val _55 - IFJMP:<{ // msg_value expire_at proposal critical? hash param_val - s1 s5 XCHG - 5 BLKDROP // hash - }> // msg_value expire_at proposal critical? hash param_val - NIP // msg_value expire_at proposal critical? param_val - OVER // msg_value expire_at proposal critical? param_val critical? - get_vote_config INLINECALLDICT // msg_value expire_at proposal critical? param_val _172 _173 _174 _175 _176 _177 _178 _179 - s4 POP - s4 POP - s5 POP // msg_value expire_at proposal critical? param_val max_store_sec max_tot_rounds bit_price cell_price min_store_sec - s8 s(-1) PUXC // msg_value expire_at proposal critical? param_val max_store_sec max_tot_rounds bit_price cell_price expire_at min_store_sec - LESS // msg_value expire_at proposal critical? param_val max_store_sec max_tot_rounds bit_price cell_price _66 - IFJMP:<{ // msg_value expire_at proposal critical? param_val max_store_sec max_tot_rounds bit_price cell_price - 9 BLKDROP // - -3313004649 PUSHINT // _67=-3313004649 - }> // msg_value expire_at proposal critical? param_val max_store_sec max_tot_rounds bit_price cell_price - s7 s3 XCHG2 // msg_value bit_price proposal critical? param_val cell_price max_tot_rounds expire_at max_store_sec - MIN // msg_value bit_price proposal critical? param_val cell_price max_tot_rounds expire_at - s0 s3 XCHG - 10 PUSHPOW2 // msg_value bit_price proposal critical? expire_at cell_price max_tot_rounds param_val _72=1024 - CDATASIZE // msg_value bit_price proposal critical? expire_at cell_price max_tot_rounds _180 _181 _182 - s2 POP // msg_value bit_price proposal critical? expire_at cell_price max_tot_rounds refs bits - 10 PUSHPOW2 // msg_value bit_price proposal critical? expire_at cell_price max_tot_rounds refs bits _75=1024 - ADD // msg_value bit_price proposal critical? expire_at cell_price max_tot_rounds refs _76 - s1 s7 XCHG // msg_value refs proposal critical? expire_at cell_price max_tot_rounds bit_price _76 - MUL // msg_value refs proposal critical? expire_at cell_price max_tot_rounds _77 - s0 s6 XCHG // msg_value _77 proposal critical? expire_at cell_price max_tot_rounds refs - 2 ADDCONST // msg_value _77 proposal critical? expire_at cell_price max_tot_rounds _79 - s1 s2 XCHG // msg_value _77 proposal critical? expire_at max_tot_rounds cell_price _79 - MUL // msg_value _77 proposal critical? expire_at max_tot_rounds _80 - s1 s5 XCHG // msg_value max_tot_rounds proposal critical? expire_at _77 _80 - ADD // msg_value max_tot_rounds proposal critical? expire_at pps - s0 s1 PUSH2 // msg_value max_tot_rounds proposal critical? expire_at pps pps expire_at - MUL // msg_value max_tot_rounds proposal critical? expire_at pps price - s0 s2 XCHG - NOW // msg_value max_tot_rounds proposal critical? price pps expire_at _84 - ADD // msg_value max_tot_rounds proposal critical? price pps expire_at - load_data INLINECALLDICT // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict - s8 PUSH // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict proposal - HASHCU // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict phash - s0 s1 PUSH2 - 8 PUSHPOW2 // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict phash phash vote_dict _95=256 - DICTUGET - NULLSWAPIFNOT // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict phash pstatus found? - IFJMP:<{ // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict phash pstatus - s8 POP - s9 POP - s9 POP // msg_value vote_dict phash critical? pstatus pps expire_at cfg_dict stored_seqno public_key - s0 s5 XCHG // msg_value vote_dict phash critical? public_key pps expire_at cfg_dict stored_seqno pstatus - unpack_proposal_status INLINECALLDICT // msg_value vote_dict phash critical? public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id rest - s4 s12 PUXC // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id r_critical? critical? - NEQ // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id _105 - IFJMP:<{ // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id - 15 BLKDROP // - -3279055189 PUSHINT // _106=-3279055189 - }> // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id - s5 s8 PUSH2 // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id expires expire_at - GEQ // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id _107 - IFJMP:<{ // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id - 15 BLKDROP // - -3245109829 PUSHINT // _108=-3245109829 - }> // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno expires r_proposal r_critical? voters weight_remaining vset_id - s8 s5 PUXC // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters weight_remaining expire_at expires - SUB // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters weight_remaining _109 - 14 PUSHPOW2 // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters weight_remaining _109 _110=16384 - ADD // msg_value vote_dict phash rest public_key pps expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters weight_remaining _111 - s1 s9 XCHG // msg_value vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters pps _111 - MUL // msg_value vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters price - s13 s13 XCPU // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters msg_value price - SUB // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters _113 - 30 PUSHPOW2 // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters _113 _116 - LESS // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters _117 - IFJMP:<{ // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters - 13 BLKDROP // - -4032919844 PUSHINT // _118=-4032919844 - }> // price vote_dict phash rest public_key weight_remaining expire_at cfg_dict stored_seqno vset_id r_proposal r_critical? voters - s5 s6 XCHG - s0 s1 s4 XCHG3 - s7 s7 XCHG2 - s0 s3 XCHG // price vote_dict phash rest public_key stored_seqno cfg_dict expire_at r_proposal r_critical? voters weight_remaining vset_id - begin_pack_proposal_status INLINECALLDICT // price vote_dict phash rest public_key stored_seqno cfg_dict _120 - s0 s4 XCHG2 // price vote_dict phash cfg_dict public_key stored_seqno _120 rest - STSLICER // price vote_dict phash cfg_dict public_key stored_seqno _121 - s0 s4 s5 XCHG3 - 8 PUSHPOW2 // price public_key stored_seqno cfg_dict _121 phash vote_dict _122=256 - DICTUSETB // price public_key stored_seqno cfg_dict vote_dict - s1 s3 XCHG // price cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - }> // msg_value max_tot_rounds proposal critical? price pps expire_at cfg_dict stored_seqno public_key vote_dict phash pstatus - DROP - s6 POP // msg_value max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vote_dict - s10 s6 XCPU // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key msg_value price - SUB // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _125 - 30 PUSHPOW2 // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _125 _128 - LESS // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _129 - IFJMP:<{ // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key - 10 BLKDROP // - -4032919844 PUSHINT // _130=-4032919844 - }> // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key - get_current_vset INLINECALLDICT // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _196 _197 _198 - DROP // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vset total_weight - 3 PUSHINT // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vset total_weight _136=3 - 2 MULRSHIFT# // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vset weight_remaining - 0 PUSHINT // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vset weight_remaining _140=0 - PUSHNULL // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key vset weight_remaining _140=0 _141 - s0 s3 XCHG // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _141 weight_remaining _140=0 vset - HASHCU // vote_dict max_tot_rounds proposal critical? price phash expire_at cfg_dict stored_seqno public_key _141 weight_remaining _140=0 _142 - s5 s7 XCHG - s4 s11 XCHG - s1 s10 XCHG - s3 s3 s0 XCHG3 // vote_dict max_tot_rounds public_key _140=0 price phash stored_seqno cfg_dict expire_at proposal critical? _141 weight_remaining _142 - begin_pack_proposal_status INLINECALLDICT // vote_dict max_tot_rounds public_key _140=0 price phash stored_seqno cfg_dict _143 - s1 s7 XCHG // vote_dict cfg_dict public_key _140=0 price phash stored_seqno max_tot_rounds _143 - 8 STU // vote_dict cfg_dict public_key _140=0 price phash stored_seqno _145 - s1 s4 XCHG // vote_dict cfg_dict public_key stored_seqno price phash _140=0 _145 - 16 STU // vote_dict cfg_dict public_key stored_seqno price phash _147 - s0 s1 s6 XCHG3 - 8 PUSHPOW2 // price cfg_dict public_key stored_seqno _147 phash vote_dict _148=256 - DICTUSETB // price cfg_dict public_key stored_seqno vote_dict - s1 s2 XCHG // price cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - }> - recv_internal PROC:<{ - // msg_value in_msg_cell in_msg - SWAP // msg_value in_msg in_msg_cell - CTOS // msg_value in_msg cs - 4 LDU // msg_value in_msg flags cs - LDMSGADDR // msg_value in_msg flags _128 _127 - DROP // msg_value in_msg flags s_addr - DUP // msg_value in_msg flags s_addr s_addr - REWRITESTDADDR // msg_value in_msg flags s_addr src_wc src_addr - SWAP // msg_value in_msg flags s_addr src_addr src_wc - INC // msg_value in_msg flags s_addr src_addr _16 - s0 s3 XCHG - 1 PUSHINT // msg_value in_msg _16 s_addr src_addr flags _17=1 - AND // msg_value in_msg _16 s_addr src_addr _18 - s1 s3 XCHG // msg_value in_msg src_addr s_addr _16 _18 - OR // msg_value in_msg src_addr s_addr _19 - s3 PUSH // msg_value in_msg src_addr s_addr _19 in_msg - SEMPTY // msg_value in_msg src_addr s_addr _19 _20 - OR // msg_value in_msg src_addr s_addr _21 - IFJMP:<{ // msg_value in_msg src_addr s_addr - 4 BLKDROP // - }> // msg_value in_msg src_addr s_addr - s0 s2 XCHG // msg_value s_addr src_addr in_msg - 32 LDU // msg_value s_addr src_addr tag in_msg - 64 LDU // msg_value s_addr src_addr tag query_id in_msg - s2 PUSH - 1314280276 PUSHINT // msg_value s_addr src_addr tag query_id in_msg tag _30=1314280276 - EQUAL // msg_value s_addr src_addr tag query_id in_msg _31 - IFJMP:<{ // msg_value s_addr src_addr tag query_id in_msg - s2 POP - s4 POP // query_id s_addr src_addr in_msg - LDREF // query_id s_addr src_addr vset in_msg - ENDS - 1 PUSHINT // query_id s_addr src_addr vset _37=1 - CONFIGOPTPARAM // query_id s_addr src_addr vset elector_param - DUP // query_id s_addr src_addr vset elector_param elector_param - ISNULL // query_id s_addr src_addr vset elector_param _40 - IF:<{ // query_id s_addr src_addr vset elector_param - DROP // query_id s_addr src_addr vset - -1 PUSHINT // query_id s_addr src_addr vset _41=-1 - }>ELSE<{ // query_id s_addr src_addr vset elector_param - CTOS // query_id s_addr src_addr vset _43 - 256 PLDU // query_id s_addr src_addr vset _41 - }> // query_id s_addr src_addr vset elector_addr - s0 s2 XCHG - FALSE - s0 s3 XCHG // query_id s_addr ok vset src_addr elector_addr - EQUAL // query_id s_addr ok vset _48 - IF:<{ // query_id s_addr ok vset - NIP // query_id s_addr vset - DUP // query_id s_addr vset vset - check_validator_set CALLDICT // query_id s_addr vset t_since t_until - OVER - NOW // query_id s_addr vset t_since t_until t_since t - GREATER // query_id s_addr vset t_since t_until _54 - s0 s2 XCHG // query_id s_addr vset _54 t_until t_since - GREATER // query_id s_addr vset _54 _55 - AND // query_id s_addr vset ok - SWAP // query_id s_addr ok vset - }> // query_id s_addr ok vset - SWAP // query_id s_addr vset ok - IFJMP:<{ // query_id s_addr vset - 36 PUSHINT // query_id s_addr vset _57=36 - SWAP // query_id s_addr _57=36 vset - set_conf_param CALLDICT - SWAP - 4000730955 PUSHINT // s_addr query_id _59=4000730955 - send_confirmation INLINECALLDICT - }> // query_id s_addr vset - DROP // query_id s_addr - SWAP - 4000730991 PUSHINT // s_addr query_id _61=4000730991 - send_error INLINECALLDICT - }> // msg_value s_addr src_addr tag query_id in_msg - s3 POP // msg_value s_addr in_msg tag query_id - OVER - 1851150418 PUSHINT // msg_value s_addr in_msg tag query_id tag _63=1851150418 - EQUAL // msg_value s_addr in_msg tag query_id _64 - IFJMP:<{ // msg_value s_addr in_msg tag query_id - NIP // msg_value s_addr in_msg query_id - s0 s3 XCHG // query_id s_addr in_msg msg_value - register_voting_proposal INLINECALLDICT // query_id s_addr price - 64 PUSHINT // query_id s_addr price mode=64 - OVER // query_id s_addr price mode=64 price - NEGATE // query_id s_addr price mode=64 ans_tag - s2 PUSH // query_id s_addr price mode=64 ans_tag price - -1 GTINT // query_id s_addr price mode=64 ans_tag _72 - IF:<{ // query_id s_addr price mode=64 ans_tag - 2DROP // query_id s_addr price - 4 PUSHINT // query_id s_addr price _73=4 - RAWRESERVE - 3998634066 PUSHINT // query_id s_addr ans_tag=3998634066 - 7 PUSHPOW2 // query_id s_addr ans_tag=3998634066 mode=128 - }>ELSE<{ - s2 POP // query_id s_addr ans_tag mode - }> - s2 s3 XCHG // s_addr query_id ans_tag mode - send_answer CALLDICT - }> // msg_value s_addr in_msg tag query_id - s4 POP // query_id s_addr in_msg tag - DUP - 1450144869 PUSHINT // query_id s_addr in_msg tag tag _78=1450144869 - EQUAL // query_id s_addr in_msg tag _79 - IFJMP:<{ // query_id s_addr in_msg tag - DROP // query_id s_addr in_msg - 9 PUSHPOW2 // query_id s_addr in_msg _82=512 - LDSLICEX // query_id s_addr signature in_msg - DUP // query_id s_addr signature msg_body in_msg - 32 LDU // query_id s_addr signature msg_body _88 in_msg - 16 LDU // query_id s_addr signature msg_body _88 _91 in_msg - 256 LDU // query_id s_addr signature msg_body sign_tag idx phash in_msg - ENDS - s0 s2 XCHG - 1450144837 PUSHINT // query_id s_addr signature msg_body phash idx sign_tag _99=1450144837 - EQUAL // query_id s_addr signature msg_body phash idx _100 - 37 THROWIFNOT - DUP // query_id s_addr signature msg_body phash idx idx - get_validator_descr INLINECALLDICT // query_id s_addr signature msg_body phash idx _147 _148 - DROP // query_id s_addr signature msg_body phash idx vdescr - unpack_validator_descr INLINECALLDICT // query_id s_addr signature msg_body phash idx val_pubkey weight - s4 s5 s5 XCHG3 // query_id s_addr weight idx phash msg_body signature val_pubkey - CHKSIGNS // query_id s_addr weight idx phash _109 - 34 THROWIFNOT - s0 s2 XCHG // query_id s_addr phash idx weight - proceed_register_vote INLINECALLDICT // query_id s_addr res - 3597947456 PUSHINT // query_id s_addr res _113=3597947456 - ADD // query_id s_addr _114 - s1 s2 XCHG // s_addr query_id _114 - send_confirmation INLINECALLDICT - }> // query_id s_addr in_msg tag - 3 1 BLKDROP2 // tag - DUP // tag tag - 0 EQINT // tag _118 - SWAP - 31 PUSHPOW2 // _118 tag _121 - AND // _118 _122 - OR // _123 - 37 THROWIFNOT - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg action cs - 32 LDU // signature in_msg action msg_seqno cs - 32 LDU // signature in_msg action msg_seqno valid_until cs - SWAP - NOW // signature in_msg action msg_seqno cs valid_until _19 - LESS // signature in_msg action msg_seqno cs _20 - 35 THROWIF - DUP // signature in_msg action msg_seqno cs cs - SDEPTH // signature in_msg action msg_seqno cs _23 - 7 PUSHPOW2 // signature in_msg action msg_seqno cs _23 _24=128 - GREATER // signature in_msg action msg_seqno cs _25 - 39 THROWIF - load_data INLINECALLDICT // signature in_msg action msg_seqno cs cfg_dict stored_seqno public_key vote_dict - s5 s2 XCPU // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key msg_seqno stored_seqno - EQUAL // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _33 - 33 THROWIFNOT - s5 PUSH - 1450144869 PUSHINT // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key action _35=1450144869 - EQUAL // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _36 - IFJMP:<{ // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key - s5 POP // signature in_msg public_key vote_dict cs cfg_dict stored_seqno - s0 s2 XCHG // signature in_msg public_key vote_dict stored_seqno cfg_dict cs - 16 LDU // signature in_msg public_key vote_dict stored_seqno cfg_dict _39 cs - 256 LDU // signature in_msg public_key vote_dict stored_seqno cfg_dict idx phash cs - ENDS - OVER // signature in_msg public_key vote_dict stored_seqno cfg_dict idx phash idx - get_validator_descr INLINECALLDICT // signature in_msg public_key vote_dict stored_seqno cfg_dict idx phash _96 _97 - DROP // signature in_msg public_key vote_dict stored_seqno cfg_dict idx phash vdescr - unpack_validator_descr INLINECALLDICT // signature in_msg public_key vote_dict stored_seqno cfg_dict idx phash val_pubkey weight - s8 s9 s9 XCHG3 // weight phash public_key vote_dict stored_seqno cfg_dict idx in_msg signature val_pubkey - CHKSIGNS // weight phash public_key vote_dict stored_seqno cfg_dict idx _53 - 34 THROWIFNOT - ACCEPT - s0 s2 XCHG // weight phash public_key vote_dict idx cfg_dict stored_seqno - INC // weight phash public_key vote_dict idx cfg_dict _57 - 32 MODPOW2# // weight phash public_key vote_dict idx cfg_dict stored_seqno - 2 3 BLKSWAP // weight phash idx cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - COMMIT - ROT // phash idx weight - proceed_register_vote INLINECALLDICT // _64 - DROP // - }> // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key - s0 s6 XCHG // signature public_key action vote_dict cs cfg_dict stored_seqno in_msg - HASHSU // signature public_key action vote_dict cs cfg_dict stored_seqno _66 - s0 s7 s6 XC2PU // stored_seqno public_key action vote_dict cs cfg_dict _66 signature public_key - CHKSIGNU // stored_seqno public_key action vote_dict cs cfg_dict _67 - 34 THROWIFNOT - ACCEPT - s0 s5 XCHG // cfg_dict public_key action vote_dict cs stored_seqno - INC // cfg_dict public_key action vote_dict cs _71 - 32 MODPOW2# // cfg_dict public_key action vote_dict cs stored_seqno - s5 s0 s4 PUSH3 - s5 PUSH // cfg_dict public_key action vote_dict cs stored_seqno cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - COMMIT - s3 s5 XCHG - s4 s5 s5 XCHG3 // stored_seqno vote_dict cfg_dict public_key action cs - perform_action INLINECALLDICT // stored_seqno vote_dict cfg_dict public_key - s3 s0 s3 XCHG3 // cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - }> - run_ticktock PROC:<{ - // is_tock - DROP // - load_data INLINECALLDICT // cfg_dict stored_seqno public_key vote_dict - 32 PUSHINT // cfg_dict stored_seqno public_key vote_dict kl=32 - 36 PUSHINT // cfg_dict stored_seqno public_key vote_dict kl=32 _9=36 - s5 s1 PUSH2 // cfg_dict stored_seqno public_key vote_dict kl=32 _9=36 cfg_dict kl=32 - DICTIGETOPTREF // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset - FALSE // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? - OVER // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? next_vset - ISNULL // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? _13 - IFNOT:<{ // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? - OVER // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? next_vset - CTOS // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? ds - DUP // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? ds ds - SBITS // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? ds _16 - 39 GTINT // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? ds _18 - IF:<{ // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? ds - 8 LDU // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? tag ds - 32 PLDU // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? tag since - NOW // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? tag since _26 - LEQ // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? tag _27 - SWAP // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? _27 tag - 18 EQINT // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? _27 _29 - AND // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? _30 - IF:<{ // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset updated? - DROP // cfg_dict stored_seqno public_key vote_dict kl=32 next_vset - 34 PUSHINT - ROT - s6 s6 XCPU // kl=32 stored_seqno public_key vote_dict next_vset _33=34 cfg_dict kl=32 - DICTISETGETOPTREF // kl=32 stored_seqno public_key vote_dict cfg_dict cur_vset - s5 s1 s0 PUXCPU // kl=32 stored_seqno public_key vote_dict cur_vset _36=32 cfg_dict kl=32 - DICTISETGETOPTREF // kl=32 stored_seqno public_key vote_dict _52 _53 - DROP // kl=32 stored_seqno public_key vote_dict cfg_dict - 36 PUSHINT // kl=32 stored_seqno public_key vote_dict cfg_dict _39=36 - s0 s1 s5 XCHG3 // vote_dict stored_seqno public_key _39=36 cfg_dict kl=32 - DICTIDEL // vote_dict stored_seqno public_key _54 _55 - DROP // vote_dict stored_seqno public_key cfg_dict - s0 s3 XCHG - TRUE // cfg_dict stored_seqno public_key vote_dict updated? - }>ELSE<{ - 2 1 BLKDROP2 // cfg_dict stored_seqno public_key vote_dict updated? - }> - }>ELSE<{ - s1 s3 XCHG - 3 BLKDROP // cfg_dict stored_seqno public_key vote_dict updated? - }> - }>ELSE<{ - 2 1 BLKDROP2 // cfg_dict stored_seqno public_key vote_dict updated? - }> - IFNOT:<{ // cfg_dict stored_seqno public_key vote_dict - scan_random_proposal INLINECALLDICT // cfg_dict stored_seqno public_key vote_dict - }> // cfg_dict stored_seqno public_key vote_dict - store_data INLINECALLDICT - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - unpack_proposal PROCREF:<{ - // pstatus - unpack_proposal_status INLINECALLDICT // expires proposal critical? voters weight_remaining vset_id rest - PUSHNULL // expires proposal critical? voters weight_remaining vset_id rest voters_list - 32 PUSHPOW2 // expires proposal critical? voters weight_remaining vset_id rest voters_list voter_id - UNTIL:<{ - s5 PUSH - 16 PUSHINT // expires proposal critical? voters weight_remaining vset_id rest voters_list voter_id voters _17=16 - DICTUGETPREV - NULLSWAPIFNOT2 // expires proposal critical? voters weight_remaining vset_id rest voters_list _48 _47 _49 - s2 POP // expires proposal critical? voters weight_remaining vset_id rest voters_list f voter_id - OVER // expires proposal critical? voters weight_remaining vset_id rest voters_list f voter_id f - IF:<{ // expires proposal critical? voters weight_remaining vset_id rest voters_list f voter_id - s0 s2 PUXC // expires proposal critical? voters weight_remaining vset_id rest voter_id f voter_id voters_list - CONS // expires proposal critical? voters weight_remaining vset_id rest voter_id f voters_list - s0 s2 XCHG // expires proposal critical? voters weight_remaining vset_id rest voters_list f voter_id - }> // expires proposal critical? voters weight_remaining vset_id rest voters_list f voter_id - SWAP // expires proposal critical? voters weight_remaining vset_id rest voters_list voter_id f - NOT // expires proposal critical? voters weight_remaining vset_id rest voters_list voter_id _20 - }> // expires proposal critical? voters weight_remaining vset_id rest voters_list voter_id - DROP - s4 POP // expires proposal critical? voters_list weight_remaining vset_id rest - 8 LDU // expires proposal critical? voters_list weight_remaining vset_id _24 rest - 8 LDU // expires proposal critical? voters_list weight_remaining vset_id _24 _27 rest - 8 LDU // expires proposal critical? voters_list weight_remaining vset_id rounds_remaining losses wins rest - ENDS - s0 s7 XCHG // expires wins critical? voters_list weight_remaining vset_id rounds_remaining losses proposal - parse_config_proposal INLINECALLDICT // expires wins critical? voters_list weight_remaining vset_id rounds_remaining losses param_id param_val param_hash - TRIPLE // expires wins critical? voters_list weight_remaining vset_id rounds_remaining losses _39 - s0 s6 XCHG - s0 s7 XCHG - s3 s5 XCHG - s3 s4 XCHG // expires critical? _39 vset_id voters_list weight_remaining rounds_remaining losses wins - 9 TUPLE // _38 - }> - get_proposal PROC:<{ - // phash - load_data INLINECALLDICT // phash _12 _13 _14 _15 - 3 1 BLKDROP2 // phash vote_dict - 8 PUSHPOW2 // phash vote_dict _8=256 - DICTUGET - NULLSWAPIFNOT // pstatus found? - IFNOTJMP:<{ // pstatus - DROP // - PUSHNULL // _10 - }> // pstatus - unpack_proposal INLINECALLDICT // _11 - }> - list_proposals PROC:<{ - // - load_data INLINECALLDICT // _25 _26 _27 _28 - 3 1 BLKDROP2 // vote_dict - 256 PUSHPOW2DEC // vote_dict phash - PUSHNULL // vote_dict phash list - UNTIL:<{ - s1 s2 XCPU - 8 PUSHPOW2 // vote_dict list phash vote_dict _19=256 - DICTUGETPREV - NULLSWAPIFNOT2 // vote_dict list pstatus phash f - DUP // vote_dict list pstatus phash f f - IF:<{ // vote_dict list pstatus phash f - s0 s2 XCHG // vote_dict list f phash pstatus - unpack_proposal INLINECALLDICT // vote_dict list f phash _22 - s1 s(-1) PUXC // vote_dict list f phash phash _22 - PAIR // vote_dict list f phash _21 - s0 s3 XCHG2 // vote_dict phash f _21 list - CONS // vote_dict phash f list - s0 s2 XCHG // vote_dict list f phash - }>ELSE<{ - s2 POP // vote_dict list f phash - }> - SWAP // vote_dict list phash f - NOT // vote_dict list phash _24 - s1 s2 XCHG // vote_dict phash list _24 - }> // vote_dict phash list - 2 1 BLKDROP2 // list - }> - proposal_storage_price PROC:<{ - // critical? seconds bits refs - c4 PUSH // critical? seconds bits refs _5 - CTOS // critical? seconds bits refs _6 - PLDREF // critical? seconds bits refs cfg_dict - 11 PUSHINT // critical? seconds bits refs cfg_dict _9=11 - SWAP - 32 PUSHINT // critical? seconds bits refs _9=11 cfg_dict _10=32 - DICTIGETOPTREF // critical? seconds bits refs cparam11 - s1 s4 XCHG // refs seconds bits critical? cparam11 - get_vote_config_internal INLINECALLDICT // refs seconds bits _32 _33 _34 _35 _36 _37 _38 _39 - 4 4 BLKDROP2 // refs seconds bits min_store_sec max_store_sec bit_price cell_price - s5 s3 PUXC // refs seconds bits cell_price max_store_sec bit_price seconds min_store_sec - LESS // refs seconds bits cell_price max_store_sec bit_price _21 - IFJMP:<{ // refs seconds bits cell_price max_store_sec bit_price - 6 BLKDROP // - -1 PUSHINT // _22=-1 - }> // refs seconds bits cell_price max_store_sec bit_price - s4 s4 XCHG2 // refs bit_price bits cell_price seconds max_store_sec - MIN // refs bit_price bits cell_price seconds - s0 s2 XCHG - 10 PUSHPOW2 // refs bit_price seconds cell_price bits _24=1024 - ADD // refs bit_price seconds cell_price _25 - s1 s3 XCHG // refs cell_price seconds bit_price _25 - MUL // refs cell_price seconds _26 - s0 s3 XCHG // _26 cell_price seconds refs - 2 ADDCONST // _26 cell_price seconds _28 - s1 s2 XCHG // _26 seconds cell_price _28 - MUL // _26 seconds _29 - s1 s2 XCHG // seconds _26 _29 - ADD // seconds _30 - SWAP // _30 seconds - MUL // _31 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.cpp deleted file mode 100644 index 91737ceb..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("dns-auto", "te6ccgECLgEABhcAART/APSkE/S88sgLAQIBIAIDAgFIBAUBIvIw2zwxmPgAhB/4I/AD4V8ELQICzQYHAgEgGRoCASAICQIBIBMUAvdCDXScEgkl8D4AHQ0wMBcbCSXwPg+kAwIPpEA9MfIZJfBuFwIddJwj+UMNM/Ad5UFAJvA/hhIIMesJJfBeAgqxfAQ46ENFnbPOAgghByZWdkuiGCEHByb2y6qgCgIYIQdXBkZLqqAaABghBnb2djuqoCoCCWXwWEH/AF4YCgsARVAm8kCMjMF/QAFfQAyx1QA/oCUAP6AlAD+gISyx/LH8ntVIA/bbPCXQ0gcKvQnT/zBQCL0YsZpfCIIQ7m93bvAF4CeCEENoUHK6jhcwNgLTH/oA+gD6ANFvBEBEBQPwA3DwBuA0NAWCEENEZWy6jq8kbpJfBZYEA3F/8Afi2zwQRV8FbpiCEO50ZW3wBeH4QW8jghDva2F5WXCBAKDwBOAtLQwD/qPbPCbACI4ZMDU1NjYD0h8wEDUQNHEB8AeCEO9rYXnwBeAI9AQhbpsx0wUhwAACqgLXGJ0B0CDXSwGm+ICHsLEC4iKZMiB41yLXCwcC3wKaXwyCEO5vXDDwBeD4I20gcFRwBCDXSak2AorkMAHCBJtfD1uCEO92XDDwBeAswwEtDQ4ADF8FhB/wBQCEbTbTBwHAAFEzoQOONDMi10lScNcj+QKrH1MMgQDg9A5voY4ZbBLTH1MXvp3U0X4BgBD0DZE1kTDikTDiAZEw4gPeBP4kBE8TEREB2zwglGzh8AXgMCnDAo49A9QwIG6ONX4hgBD0DY4V0CDXSYEBG77yn9cLEoIIBP6cuvKfkTDiIIAQ9IRvpWwhIYAQ9IxvpWwhsPKf35IzIuIlbyQjnF8PXwOCENNPRkbwBeEkEDdZ2zwrwwQVsBSgDoMdoS654wIpDyoQEQCsBG5SQLCYXwSCEO5vdGbgIm6ZXwOCEO5vLTKw4DOCEOJhZDIC0CDXSYEBG7mUECNfA+DTEgGCCAT+nL2UECNfA+BsEtIH1wv/Ar0CvbGWghDub3du4HAAFF8OghDncjxw8AUB3MACjkUzOFF3oFKAvJpfC4IQ82Vyb/AF4FN2oMjLH8xUIJWBAOD0Qwaq31AIoASq31JAoFBEgwf0WzDIQESDB/RDA0VUcfAH8AbgKcAB4wJsMQbABI4VBsjLHxXMUHKBAOD0Q1BUE3HwB/AG4F8KEgBwOTkBbppfC4IQ4WxyZfAF4RegIMjLHxbMVCCEgQDg9EMkqt9QCLHIAoMH9ENQQ7YIFUMEcfAH8AYCASAVFgIBIBcYAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAXPhBbyMQI3CAQPAEgACcdPsC+EFvI4IQ72theVlwgwbwBIADxPgjIqY8UkC2CVIQuZNb8APgMiSDB/SGb6Uyk1ESsI5UMyKr31MCuY4/MCKpON9TBoEA4PQOb6GOEtcLHyO7mVAGgQDg9FswBZEw4pFb4lAkgwf0WzAggwf0hm+lMiGTIKvfkoQf4gallUUVA3AC4hA2EDRZ6FvwA4AIBIBscAgEgHyABDbh1rbPF8DgpAgFIHR4CGbOxNs8MxA0RATbPKCApKgENsWa2zxfA4CsCAVghIgE9ujDAH4I9s8A5RfBHBt4ZJ/M98B10kilVmAEPRq4DKCsCAVgjJAIBaicoAgEgJSYBEKvu+CPbPF8DKwENp4W2eCa+BykBD6eltnggRr4HKQELp8e2eNhjKQIPpTG2eNhFtnkpKgAo7UTQ1DH0BDH0BDHTHfoA+gD6ADAAMAKAZPlBMgTXSaoAgQDAoBSgA6YCqAKooAH2IddLIXewsfJeIJZfA3BtIW3hInjXItcLB55wyFAEzxYTywfJ0AKmCN4gwAiWXwNwbSFt4O1E0NQx9AQwbX8lBKsCjjID0wcBwACOKCDXSVJg1yP5AqsfI4EA4PQOb6GOECDXCx8mvpYyMyLXSQORMOKRMOLeA+RsIjIgLAAsbpZfA3BtIW3g0x/UMCLAAFBD1yNDMAA07UTQ1PQE9ATTHfoA+gD6AFUwbwQB0x/THzA="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.fif deleted file mode 100644 index 1b423e5d..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-auto-code.fif +++ /dev/null @@ -1,946 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/dns-auto-code.fc` -PROGRAM{ - DECLPROC load_data - DECLPROC load_prices - DECLPROC store_data - DECLPROC send_message - DECLPROC send_error - DECLPROC send_ok - DECLPROC housekeeping - DECLPROC calcprice_internal - DECLPROC check_owner - DECLPROC perform_ctl_op - DECLPROC recv_internal - DECLPROC recv_external - DECLPROC dnsdictlookup - 123660 DECLMETHOD dnsresolve - 87450 DECLMETHOD getexpirationx - 110574 DECLMETHOD getexpiration - 67418 DECLMETHOD getstdperiod - 109522 DECLMETHOD getppr - 108994 DECLMETHOD getppc - 113123 DECLMETHOD getppb - 113304 DECLMETHOD calcprice - 85700 DECLMETHOD calcregprice - DECLGLOBVAR query_info - load_data PROCREF:<{ - // - c4 PUSH // _1 - CTOS // cs - LDREF // _3 cs - LDDICT // _3 _5 cs - LDDICT // _3 _5 _7 cs - 30 LDU // _3 _5 _7 _10 cs - LDGRAMS // _3 _5 _7 _10 _13 cs - LDGRAMS // _3 _5 _7 _10 _13 _15 cs - LDGRAMS // _3 _5 _7 _10 _13 _15 _17 cs - 4 -ROLL // _3 _5 _7 cs _10 _13 _15 _17 - 4 TUPLE // _3 _5 _7 cs _9 - SWAP // _3 _5 _7 _9 cs - 32 LDU // _3 _5 _7 _9 _19 cs - 32 LDU // _3 _5 _7 _9 _19 _42 _41 - DROP // _3 _5 _7 _9 _19 _22 - }> - load_prices PROCREF:<{ - // - c4 PUSH // _1 - CTOS // cs - LDREF // _19 _18 - NIP // cs - LDDICT // _21 _20 - NIP // cs - LDDICT // _23 _22 - NIP // cs - 30 LDU // _9 cs - LDGRAMS // _9 _12 cs - LDGRAMS // _9 _12 _14 cs - LDGRAMS // _9 _12 _14 _31 _30 - DROP // _9 _12 _14 _16 - }> - store_data PROC:<{ - // ctl dd gc prices nhk lhk - s0 s2 XCHG // ctl dd gc lhk nhk prices - 4 UNTUPLE // ctl dd gc lhk nhk sp ppr ppc ppb - s0 s8 XCHG - NEWC // ppb dd gc lhk nhk sp ppr ppc ctl _11 - STREF // ppb dd gc lhk nhk sp ppr ppc _12 - s1 s7 XCHG // ppb ppc gc lhk nhk sp ppr dd _12 - STDICT // ppb ppc gc lhk nhk sp ppr _13 - s1 s5 XCHG // ppb ppc ppr lhk nhk sp gc _13 - STDICT // ppb ppc ppr lhk nhk sp _14 - 30 STU // ppb ppc ppr lhk nhk _16 - s0 s3 XCHG2 // ppb ppc nhk lhk _16 ppr - STGRAMS // ppb ppc nhk lhk _17 - s0 s3 XCHG2 // ppb lhk nhk _17 ppc - STGRAMS // ppb lhk nhk _18 - s0 s3 XCHG2 // nhk lhk _18 ppb - STGRAMS // nhk lhk _19 - s1 s2 XCHG // lhk nhk _19 - 32 STU // lhk _21 - 32 STU // _23 - ENDC // _24 - c4 POP - }> - send_message PROC:<{ - // addr tag query_id body grams mode - 0 PUSHINT // addr tag query_id body grams mode _7=0 - 24 PUSHINT // addr tag query_id body grams mode _7=0 _8=24 - NEWC // addr tag query_id body grams mode _7=0 _8=24 _9 - 6 STU // addr tag query_id body grams mode _7=0 _11 - s0 s7 XCHG2 // _7=0 tag query_id body grams mode _11 addr - STSLICER // _7=0 tag query_id body grams mode _12 - ROT // _7=0 tag query_id body mode _12 grams - STGRAMS // _7=0 tag query_id body mode _13 - s1 s5 XCHG // mode tag query_id body _7=0 _13 - 107 STU // mode tag query_id body _27 - s1 s3 XCHG // mode body query_id tag _27 - 32 STU // mode body query_id _29 - 64 STU // mode body msg - OVER // mode body msg body - -1 GTINT // mode body msg _33 - IF:<{ // mode body msg - 32 STU // mode msg - }>ELSE<{ - NIP // mode msg - }> - ENDC // mode _37 - SWAP // _37 mode - SENDRAWMSG - }> - send_error PROC:<{ - // error_code - query_info GETGLOB - UNTRIPLE // error_code addr query_id op - s2 s3 XCHG - 0 PUSHINT - 64 PUSHINT // addr error_code query_id op _5=0 _6=64 - send_message CALLDICT - }> - send_ok PROC:<{ - // price - 4 PUSHINT // price _1=4 - RAWRESERVE - query_info GETGLOB - UNTRIPLE // addr query_id op - 4016791929 PUSHINT // addr query_id op _7=4016791929 - -ROT - 0 PUSHINT - 7 PUSHPOW2 // addr _7=4016791929 query_id op _8=0 _9=128 - send_message CALLDICT - }> - housekeeping PROC:<{ - // ctl dd gc prices nhk lhk max_steps - NOW // ctl dd gc prices nhk lhk max_steps n - s2 PUSH // ctl dd gc prices nhk lhk max_steps n lhk - 60 ADDCONST // ctl dd gc prices nhk lhk max_steps n _10 - s4 s(-1) PUXC // ctl dd gc prices nhk lhk max_steps n nhk _10 - MAX // ctl dd gc prices nhk lhk max_steps n _11 - s1 s(-1) PUXC // ctl dd gc prices nhk lhk max_steps n n _11 - LESS // ctl dd gc prices nhk lhk max_steps n _12 - IFJMP:<{ // ctl dd gc prices nhk lhk max_steps n - 2DROP // ctl dd gc prices nhk lhk - store_data CALLDICT - }> // ctl dd gc prices nhk lhk max_steps n - s2 POP // ctl dd gc prices nhk n max_steps - s4 PUSH - 8 PUSHPOW2 // ctl dd gc prices nhk n max_steps gc _17=256 - DICTUMIN - NULLSWAPIFNOT2 // ctl dd gc prices nhk n max_steps _63 _62 _64 - s2 POP // ctl dd gc prices nhk n max_steps found? mkey - WHILE:<{ - s1 s2 XCPU // ctl dd gc prices nhk n max_steps mkey found? max_steps - AND // ctl dd gc prices nhk n max_steps mkey _19 - }>DO<{ // ctl dd gc prices nhk n max_steps mkey - s3 POP // ctl dd gc prices mkey n max_steps - s2 PUSH // ctl dd gc prices mkey n max_steps mkey - 224 RSHIFT# // ctl dd gc prices mkey n max_steps nhk - s0 s2 PUSH2 // ctl dd gc prices mkey n max_steps nhk nhk n - LESS // ctl dd gc prices mkey n max_steps nhk _24 - IF:<{ // ctl dd gc prices mkey n max_steps nhk - DROP // ctl dd gc prices mkey n max_steps - s2 PUSH // ctl dd gc prices mkey n max_steps mkey - 224 MODPOW2# // ctl dd gc prices mkey n max_steps key - s0 s6 PUSH2 - 224 PUSHINT // ctl dd gc prices mkey n max_steps key key dd _35 - DICTUGET - NULLSWAPIFNOT // ctl dd gc prices mkey n max_steps key val found? - IF:<{ // ctl dd gc prices mkey n max_steps key val - 32 PLDU // ctl dd gc prices mkey n max_steps key exp - s3 PUSH // ctl dd gc prices mkey n max_steps key exp n - LEQ // ctl dd gc prices mkey n max_steps key _40 - IF:<{ // ctl dd gc prices mkey n max_steps key - s0 s6 XCHG2 - 224 PUSHINT // ctl max_steps gc prices mkey n key dd _44 - DICTUDEL // ctl max_steps gc prices mkey n _67 _68 - DROP // ctl max_steps gc prices mkey n dd - s0 s5 XCHG // ctl dd gc prices mkey n max_steps - }>ELSE<{ - DROP // ctl dd gc prices mkey n max_steps - }> - }>ELSE<{ - 2DROP // ctl dd gc prices mkey n max_steps - }> - s2 s4 XCHG2 - 8 PUSHPOW2 // ctl dd max_steps prices n mkey gc _47=256 - DICTUDEL // ctl dd max_steps prices n _69 _70 - DROP // ctl dd max_steps prices n gc - DUP - 8 PUSHPOW2 // ctl dd max_steps prices n gc gc _50=256 - DICTUMIN - NULLSWAPIFNOT2 // ctl dd max_steps prices n gc _72 _71 _73 - s2 POP // ctl dd max_steps prices n gc found? mkey - OVER // ctl dd max_steps prices n gc found? mkey found? - IF:<{ // ctl dd max_steps prices n gc found? mkey - DUP // ctl dd max_steps prices n gc found? mkey mkey - 224 RSHIFT# // ctl dd max_steps prices n gc found? mkey _52 - }>ELSE<{ // ctl dd max_steps prices n gc found? mkey - 32 PUSHPOW2DEC // ctl dd max_steps prices n gc found? mkey _52=4294967295 - }> // ctl dd max_steps prices n gc found? mkey nhk - s0 s6 XCHG // ctl dd nhk prices n gc found? mkey max_steps - DEC // ctl dd nhk prices n gc found? mkey max_steps - }>ELSE<{ // ctl dd gc prices mkey n max_steps nhk - s5 s1 s5 XCHG3 - s0 s3 XCHG - FALSE - s0 s2 XCHG // ctl dd nhk prices n gc found? mkey max_steps - }> - s3 s6 XCHG - s3 s4 XCHG - -ROT // ctl dd gc prices nhk n max_steps found? mkey - }> // ctl dd gc prices nhk n max_steps mkey - 2DROP // ctl dd gc prices nhk n - store_data CALLDICT - }> - calcprice_internal PROCREF:<{ - // domain data ppc ppb - s0 s2 XCHG - 100 PUSHINT // domain ppb ppc data _7=100 - CDATASIZE // domain ppb ppc _24 _25 _26 - s2 POP // domain ppb ppc refs bits - s0 s4 XCHG // bits ppb ppc refs domain - SBITS // bits ppb ppc refs _9 - 1 LSHIFT# // bits ppb ppc refs _11 - 192 PUSHINT // bits ppb ppc refs _11 _16 - ADD // bits ppb ppc refs _17 - s1 s4 XCHG // refs ppb ppc bits _17 - ADD // refs ppb ppc bits - s0 s3 XCHG // bits ppb ppc refs - 2 ADDCONST // bits ppb ppc _20 - MUL // bits ppb _21 - s0 s2 XCHG // _21 ppb bits - MUL // _21 _22 - ADD // _23 - }> - check_owner PROCREF:<{ - // cat_table owner_info src_wc src_addr strict - s0 s4 XCHG // strict owner_info src_wc src_addr cat_table - ISNULL // strict owner_info src_wc src_addr _5 - s4 s(-1) PUXC // strict owner_info src_wc src_addr strict _5 - AND // strict owner_info src_wc src_addr _6 - IFJMP:<{ // strict owner_info src_wc src_addr - 4 BLKDROP // - 4000281702 PUSHINT // _7=4000281702 - }> // strict owner_info src_wc src_addr - s2 PUSH // strict owner_info src_wc src_addr owner_info - ISNULL // strict owner_info src_wc src_addr _8 - IFJMP:<{ // strict owner_info src_wc src_addr - 3 BLKDROP // strict - 4000263474 PUSHINT // strict _9=4000263474 - AND // _10 - }> // strict owner_info src_wc src_addr - s3 POP // src_addr owner_info src_wc - 3798033458 PUSHINT // src_addr owner_info src_wc ERR_BAD2=3798033458 - s0 s2 XCHG // src_addr ERR_BAD2=3798033458 src_wc owner_info - CTOS // src_addr ERR_BAD2=3798033458 src_wc sown - DUP // src_addr ERR_BAD2=3798033458 src_wc sown sown - SBITS // src_addr ERR_BAD2=3798033458 src_wc sown _15 - 283 PUSHINT // src_addr ERR_BAD2=3798033458 src_wc sown _15 _22 - LESS // src_addr ERR_BAD2=3798033458 src_wc sown _23 - IFJMP:<{ // src_addr ERR_BAD2=3798033458 src_wc sown - s2 s3 XCHG - 3 BLKDROP // ERR_BAD2=3798033458 - }> // src_addr ERR_BAD2=3798033458 src_wc sown - 19 LDU // src_addr ERR_BAD2=3798033458 src_wc _24 sown - SWAP - 327324 PUSHINT // src_addr ERR_BAD2=3798033458 src_wc sown _24 _33 - NEQ // src_addr ERR_BAD2=3798033458 src_wc sown _34 - IFJMP:<{ // src_addr ERR_BAD2=3798033458 src_wc sown - s2 s3 XCHG - 3 BLKDROP // ERR_BAD2=3798033458 - }> // src_addr ERR_BAD2=3798033458 src_wc sown - 1 2 BLKDROP2 // src_addr src_wc sown - 8 LDI // src_addr src_wc _37 sown - 256 PLDU // src_addr src_wc owner_wc owner_addr - s0 s2 XCHG // src_addr owner_addr owner_wc src_wc - NEQ // src_addr owner_addr _42 - s0 s2 XCHG // _42 owner_addr src_addr - NEQ // _42 _43 - OR // _44 - IFJMP:<{ // - 4000282478 PUSHINT // _45=4000282478 - }> // - 0 PUSHINT // _46=0 - }> - perform_ctl_op PROCREF:<{ - // op src_wc src_addr in_msg - load_data INLINECALLDICT // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk - s5 PUSH // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk ctl - CTOS // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk cs - 8 LDI // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk _13 cs - s0 s10 XCHG // op cs src_addr in_msg ctl domdata gc prices nhk lhk _13 src_wc - NEQ // op cs src_addr in_msg ctl domdata gc prices nhk lhk _16 - s0 s9 XCHG // op _16 src_addr in_msg ctl domdata gc prices nhk lhk cs - 256 LDU // op _16 src_addr in_msg ctl domdata gc prices nhk lhk _75 _74 - DROP // op _16 src_addr in_msg ctl domdata gc prices nhk lhk _17 - s0 s8 XCHG2 // op _16 lhk in_msg ctl domdata gc prices nhk _17 src_addr - NEQ // op _16 lhk in_msg ctl domdata gc prices nhk _20 - s1 s8 XCHG // op nhk lhk in_msg ctl domdata gc prices _16 _20 - OR // op nhk lhk in_msg ctl domdata gc prices _21 - IFJMP:<{ // op nhk lhk in_msg ctl domdata gc prices - 8 BLKDROP // - 4000282478 PUSHINT // _22=4000282478 - send_error CALLDICT - }> // op nhk lhk in_msg ctl domdata gc prices - s7 PUSH - 1130909810 PUSHINT // op nhk lhk in_msg ctl domdata gc prices op _24=1130909810 - EQUAL // op nhk lhk in_msg ctl domdata gc prices _25 - IFJMP:<{ // op nhk lhk in_msg ctl domdata gc prices - DROP - s6 POP // gc nhk lhk in_msg ctl domdata - s0 s2 XCHG // gc nhk lhk domdata ctl in_msg - 32 LDU // gc nhk lhk domdata ctl _30 in_msg - LDGRAMS // gc nhk lhk domdata ctl _30 _33 in_msg - LDGRAMS // gc nhk lhk domdata ctl _30 _33 _35 in_msg - LDGRAMS // gc nhk lhk domdata ctl stdper ppr ppc ppb in_msg - ENDS - 4 TUPLE // gc nhk lhk domdata ctl _40 - s0 s4 s4 XCHG3 - s0 s5 XCHG - s0 s3 XCHG // ctl domdata gc _40 nhk lhk - store_data CALLDICT - 0 PUSHINT // _42=0 - send_ok CALLDICT - }> // op nhk lhk in_msg ctl domdata gc prices - s4 POP - s4 POP // op nhk gc prices ctl domdata - s0 s5 XCHG - 1128555884 PUSHINT // domdata nhk gc prices ctl op _44=1128555884 - EQUAL // domdata nhk gc prices ctl _45 - IFJMP:<{ // domdata nhk gc prices ctl - s4 PUSH // domdata nhk gc prices ctl domdata - ISNULL // domdata nhk gc prices ctl _46 - IFNOT:<{ // domdata nhk gc prices ctl - s0 s4 XCHG - s0 s3 XCHG - 1 PUSHINT - -1 PUSHINT // ctl domdata gc prices nhk _47=1 _48=-1 - housekeeping CALLDICT - }>ELSE<{ - 5 BLKDROP // - }> - load_data INLINECALLDICT // _84 _85 _86 _87 _88 _89 - s4 s5 XCHG - 5 BLKDROP // domdata - ISNULL // _51 - IFNOTJMP:<{ // - 4000605549 PUSHINT // _52=4000605549 - send_error CALLDICT - }> // - query_info GETGLOB - UNTRIPLE // addr query_id op - 4016791929 PUSHINT // addr query_id op _58=4016791929 - -ROT - 0 PUSHINT - 160 PUSHINT // addr _58=4016791929 query_id op _59=0 _62 - send_message CALLDICT - }> // domdata nhk gc prices ctl - 5 BLKDROP // - 32 PUSHPOW2DEC // _64=4294967295 - send_error CALLDICT - }> - recv_internal PROC:<{ - // msg_value in_msg_cell in_msg - DUP // msg_value in_msg_cell in_msg in_msg - SBITS // msg_value in_msg_cell in_msg _3 - 32 LESSINT // msg_value in_msg_cell in_msg _5 - IFJMP:<{ // msg_value in_msg_cell in_msg - 3 BLKDROP // - }> // msg_value in_msg_cell in_msg - SWAP // msg_value in_msg in_msg_cell - CTOS // msg_value in_msg cs - 4 LDU // msg_value in_msg flags cs - SWAP - 1 PUSHINT // msg_value in_msg cs flags _12=1 - AND // msg_value in_msg cs _13 - IFJMP:<{ // msg_value in_msg cs - 3 BLKDROP // - }> // msg_value in_msg cs - LDMSGADDR // msg_value in_msg _327 _326 - DROP // msg_value in_msg s_addr - DUP // msg_value in_msg s_addr s_addr - REWRITESTDADDR // msg_value in_msg s_addr src_wc src_addr - s0 s3 XCHG // msg_value src_addr s_addr src_wc in_msg - 32 LDU // msg_value src_addr s_addr src_wc op in_msg - OVER // msg_value src_addr s_addr src_wc op in_msg op - IFNOTJMP:<{ // msg_value src_addr s_addr src_wc op in_msg - 6 BLKDROP // - }> // msg_value src_addr s_addr src_wc op in_msg - 0 PUSHINT // msg_value src_addr s_addr src_wc op in_msg query_id=0 - OVER // msg_value src_addr s_addr src_wc op in_msg query_id=0 in_msg - SBITS // msg_value src_addr s_addr src_wc op in_msg query_id=0 _26 - 63 GTINT // msg_value src_addr s_addr src_wc op in_msg query_id=0 _28 - IF:<{ // msg_value src_addr s_addr src_wc op in_msg query_id=0 - DROP // msg_value src_addr s_addr src_wc op in_msg - 64 LDU // msg_value src_addr s_addr src_wc op query_id in_msg - SWAP // msg_value src_addr s_addr src_wc op in_msg query_id - }> // msg_value src_addr s_addr src_wc op in_msg query_id - s4 s0 s2 XC2PU // msg_value src_addr in_msg src_wc op s_addr query_id op - TRIPLE - query_info SETGLOB - DUP - 31 PUSHPOW2 // msg_value src_addr in_msg src_wc op op _34 - AND // msg_value src_addr in_msg src_wc op _35 - IFJMP:<{ // msg_value src_addr in_msg src_wc op - 5 BLKDROP // - }> // msg_value src_addr in_msg src_wc op - DUP // msg_value src_addr in_msg src_wc op op - 24 RSHIFT# // msg_value src_addr in_msg src_wc op _37 - 67 EQINT // msg_value src_addr in_msg src_wc op _39 - IFJMP:<{ // msg_value src_addr in_msg src_wc op - s4 POP // op src_addr in_msg src_wc - -ROT // op src_wc src_addr in_msg - perform_ctl_op INLINECALLDICT - }> // msg_value src_addr in_msg src_wc op - DUP - 1919248228 PUSHINT // msg_value src_addr in_msg src_wc op op _42=1919248228 - EQUAL // msg_value src_addr in_msg src_wc op _45 - OVER - 1886547820 PUSHINT // msg_value src_addr in_msg src_wc op _45 op _46=1886547820 - EQUAL // msg_value src_addr in_msg src_wc op _45 _47 - 1 LSHIFT# // msg_value src_addr in_msg src_wc op _45 _49 - ADD // msg_value src_addr in_msg src_wc op _50 - OVER - 1970300004 PUSHINT // msg_value src_addr in_msg src_wc op _50 op _51=1970300004 - EQUAL // msg_value src_addr in_msg src_wc op _50 _52 - 2 LSHIFT# // msg_value src_addr in_msg src_wc op _50 _54 - ADD // msg_value src_addr in_msg src_wc op _55 - SWAP - 1735354211 PUSHINT // msg_value src_addr in_msg src_wc _55 op _56=1735354211 - EQUAL // msg_value src_addr in_msg src_wc _55 _57 - 3 LSHIFT# // msg_value src_addr in_msg src_wc _55 _59 - ADD // msg_value src_addr in_msg src_wc qt - DUP // msg_value src_addr in_msg src_wc qt qt - IFNOTJMP:<{ // msg_value src_addr in_msg src_wc qt - 5 BLKDROP // - 32 PUSHPOW2DEC // _61=4294967295 - send_error CALLDICT - }> // msg_value src_addr in_msg src_wc qt - NEGATE // msg_value src_addr in_msg src_wc qt - load_data INLINECALLDICT // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk - s6 PUSH // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk qt - 8 EQINT // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk _72 - IFJMP:<{ // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk - DROP - s5 POP - s5 POP - s6 POP - s6 POP // domdata gc in_msg prices nhk ctl - s0 s3 XCHG // domdata gc ctl prices nhk in_msg - 32 LDI // domdata gc ctl prices nhk _341 _340 - DROP // domdata gc ctl prices nhk max_steps - s3 s5 XCHG - s3 s4 XCHG - 1 PUSHINT - SWAP // ctl domdata gc prices nhk _77=1 max_steps - housekeeping CALLDICT - 4016791929 PUSHINT // _79=4016791929 - send_error CALLDICT - }> // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk - s0 s8 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg - LDOPTREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg - OVER // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg domain_cell - ISNULL // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg _88 - IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg - NIP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg - 6 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg - OVER // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg bytes - 0 EQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg fail - s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail in_msg bytes - 3 LSHIFT# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail in_msg _97 - LDSLICEX // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg - }>ELSE<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg - SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain_cell - CTOS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain - DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain domain - SBITREFS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain bits refs - SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs bits - -8 ADDCONST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _104 - -121 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _104 _107 - AND // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _108 - OR // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail - s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg - }> - s2 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg fail - IFNOT:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg - s2 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain - DUP - 8 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain domain _110=8 - SDCUTLAST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain _111 - 8 PLDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail - s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg - }> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg - s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail - IFJMP:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain - 12 BLKDROP // - 4000275504 PUSHINT // _114=4000275504 - send_error CALLDICT - }> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain - NOW // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n - PUSHNULL // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n _120 - DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info - 0 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info _124=0 - s0 s0 s4 PUSH3 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail - DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail tail - SBITS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail _126 - 3 RSHIFTC# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail _128 - REPEAT:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail - PUSHNULL - s6 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail - 8 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp _131 tail - SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail _131 - 0 EQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail z - s3 s3 XCPU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key z exp tail zeros z - SUB // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key z exp tail zeros - s0 s3 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail z - IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail - s3 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp - s2 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp tail - SBITS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _137 - s7 s(-1) PUXC // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp domain _137 - SDSKIPLAST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _138 - SHA256U // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _139 - 32 RSHIFT# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key - s0 s12 PUSH2 - 224 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key key domdata _146 - DICTUGET - NULLSWAPIFNOT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key val found? - IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key val - 1 2 BLKDROP2 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key val - 32 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val - s1 s7 PUSH2 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val exp n - GEQ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val _151 - IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val - LDREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cat_table val - ENDS - -2 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cat_table _158=-2 - SWAP - 16 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp _158=-2 cat_table _159=16 - DICTIGETREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cown ok - IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cown - s5 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp - }>ELSE<{ - DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp - }> - }>ELSE<{ - DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp - }> - SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key - }>ELSE<{ - DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key - }> - s0 s3 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail - }> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail - }> - DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp - SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp zeros - 4 GTINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp _162 - IFJMP:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp - 15 BLKDROP - 2DROP // - 4017511472 PUSHINT // _163=4017511472 - send_error CALLDICT - }> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp - s12 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp qt - 1 NEQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp _167 - s4 PUSH - s0 s4 XCHG - s15 s1 s3 XCHG3 - s0 17 s() XCHG - SWAP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table cat_table owner_info src_wc src_addr _167 - check_owner INLINECALLDICT // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err - DUP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err err - IFJMP:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err - 14 1 BLKDROP2 // err - send_error CALLDICT - }> // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err - DROP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table - s9 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table qt - 2 NEQINT // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table _173 - IF:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table - s0 s3 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n in_msg - LDREF // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n _361 _360 - DROP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data - DUP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data data - DICTEMPTY // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _176 - IFNOT:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data - -2 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _179=-2 - OVER - 16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _179=-2 data _180=16 - DICTIGETREF // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data oinfo ok - IF:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data oinfo - CTOS // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs - DUP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs cs - SBITS // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _185 - 283 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _185 _192 - GEQ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _193 - 31 THROWIFNOT - 19 PLDU // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _197 - 327324 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _197 _202 - EQUAL // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _203 - 31 THROWIFNOT - }>ELSE<{ - DROP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data - }> - DUP - 16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data data _208=16 - DICTIMIN - NULLSWAPIFNOT2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _365 _364 _366 - 2 1 BLKDROP2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok - OVER - 16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok data _213=16 - DICTIMAX - NULLSWAPIFNOT2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok _368 _367 _369 - 2 1 BLKDROP2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok maxok - AND // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _216 - 31 THROWIFNOT - }> // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data - }>ELSE<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table - s3 POP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n - s2 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data - }> - s5 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data prices - 4 UNTUPLE // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb - s3 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb stdper - IFNOTJMP:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb - 15 BLKDROP - 3 BLKDROP // - 3545187910 PUSHINT // _223=3545187910 - send_error CALLDICT - }> // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb - s4 PUSH - s3 s7 XCHG - -ROT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper domain data ppc ppb - calcprice_internal INLINECALLDICT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226 - s11 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226 qt - 4 NEQINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226 _228 - s1 s5 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table _226 n data stdper ppr _228 - AND // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table _226 n data stdper _229 - s1 s4 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _226 _229 - ADD // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data price - s0 s14 XCHG - 30 PUSHPOW2 // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data msg_value _233 - SUB // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _234 - s14 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _234 price - LESS // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _235 - IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - 14 BLKDROP // - 3883023472 PUSHINT // _236=3883023472 - send_error CALLDICT - }> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - s9 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data qt - 2 EQINT // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _243 - IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - s3 POP - s8 POP // price key lhk exp n ctl domdata gc prices nhk data stdper - s7 s7 XCPU // price key lhk exp stdper ctl domdata gc prices nhk data n stdper - ADD // price key lhk exp stdper ctl domdata gc prices nhk data _244 - s8 s(-1) PUXC // price key lhk exp stdper ctl domdata gc prices nhk data exp _244 - GREATER // price key lhk exp stdper ctl domdata gc prices nhk data _245 - IFJMP:<{ // price key lhk exp stdper ctl domdata gc prices nhk data - 11 BLKDROP // - 4083511919 PUSHINT // _246=4083511919 - send_error CALLDICT - }> // price key lhk exp stdper ctl domdata gc prices nhk data - s7 s6 PUSH2 // price key lhk exp stdper ctl domdata gc prices nhk data exp stdper - ADD // price key lhk exp stdper ctl domdata gc prices nhk data _249 - NEWC // price key lhk exp stdper ctl domdata gc prices nhk data _249 _250 - 32 STU // price key lhk exp stdper ctl domdata gc prices nhk data _252 - STREF // price key lhk exp stdper ctl domdata gc prices nhk _253 - s0 s9 s4 XCPUXC - 224 PUSHINT // price key lhk exp stdper ctl nhk gc prices _253 key domdata _256 - DICTUSETB // price key lhk exp stdper ctl nhk gc prices domdata - s0 s6 XCHG // price key lhk domdata stdper ctl nhk gc prices exp - 224 LSHIFT# // price key lhk domdata stdper ctl nhk gc prices _262 - s0 s8 XCHG2 // price prices lhk domdata stdper ctl nhk gc _262 key - ADD // price prices lhk domdata stdper ctl nhk gc gckeyO - s0 s4 XCHG // price prices lhk domdata gckeyO ctl nhk gc stdper - 224 LSHIFT# // price prices lhk domdata gckeyO ctl nhk gc _268 - s4 s(-1) PUXC // price prices lhk domdata gckeyO ctl nhk gc gckeyO _268 - ADD // price prices lhk domdata gckeyO ctl nhk gc gckeyN - s4 s4 XCHG2 - 8 PUSHPOW2 // price prices lhk domdata gckeyN ctl nhk gckeyO gc _271=256 - DICTUDEL // price prices lhk domdata gckeyN ctl nhk _376 _377 - DROP // price prices lhk domdata gckeyN ctl nhk gc - NEWC // price prices lhk domdata gckeyN ctl nhk gc _274 - s0 s4 s4 XCHG3 - 8 PUSHPOW2 // price prices lhk domdata nhk ctl _274 gckeyN gc _275=256 - DICTUSETB // price prices lhk domdata nhk ctl gc - s0 s3 XCHG - s5 s5 s4 XCHG3 - 1 PUSHINT // price ctl domdata gc prices nhk lhk _277=1 - housekeeping CALLDICT - send_ok CALLDICT - }> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - s9 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data qt - 1 EQINT // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _281 - IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - s9 POP - s9 POP // price key lhk n data ctl domdata gc prices nhk cat_table stdper - SWAP // price key lhk n data ctl domdata gc prices nhk stdper cat_table - ISNULL // price key lhk n data ctl domdata gc prices nhk stdper _282 - IFNOTJMP:<{ // price key lhk n data ctl domdata gc prices nhk stdper - 11 BLKDROP // - 3781980773 PUSHINT // _283=3781980773 - send_error CALLDICT - }> // price key lhk n data ctl domdata gc prices nhk stdper - s1 s7 XCHG // price key lhk nhk data ctl domdata gc prices n stdper - ADD // price key lhk nhk data ctl domdata gc prices expires_at - DUP - NEWC // price key lhk nhk data ctl domdata gc prices expires_at expires_at _288 - 32 STU // price key lhk nhk data ctl domdata gc prices expires_at _290 - s1 s6 XCHG // price key lhk nhk expires_at ctl domdata gc prices data _290 - STREF // price key lhk nhk expires_at ctl domdata gc prices _291 - s0 s8 s3 XCPUXC - 224 PUSHINT // price key lhk nhk expires_at ctl prices gc _291 key domdata _294 - DICTUSETB // price key lhk nhk expires_at ctl prices gc domdata - s4 PUSH // price key lhk nhk expires_at ctl prices gc domdata expires_at - 224 LSHIFT# // price key lhk nhk expires_at ctl prices gc domdata _300 - s0 s8 XCHG2 // price domdata lhk nhk expires_at ctl prices gc _300 key - OR // price domdata lhk nhk expires_at ctl prices gc gckey - NEWC // price domdata lhk nhk expires_at ctl prices gc gckey _303 - s0 s2 XCHG - 8 PUSHPOW2 // price domdata lhk nhk expires_at ctl prices _303 gckey gc _304=256 - DICTUSETB // price domdata lhk nhk expires_at ctl prices gc - s4 s3 XCHG2 // price domdata lhk prices gc ctl nhk expires_at - MIN // price domdata lhk prices gc ctl _306 - s1 s5 XCHG - s3 s0 s4 XCHG3 - 1 PUSHINT // price ctl domdata gc prices _306 lhk _307=1 - housekeeping CALLDICT - send_ok CALLDICT - }> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data - 3 1 BLKDROP2 // price key lhk exp qt ctl domdata gc prices nhk data - s0 s6 XCHG // price key lhk exp data ctl domdata gc prices nhk qt - 4 EQINT // price key lhk exp data ctl domdata gc prices nhk _311 - IFJMP:<{ // price key lhk exp data ctl domdata gc prices nhk - s0 s6 XCHG - NEWC // price key lhk nhk data ctl domdata gc prices exp _313 - 32 STU // price key lhk nhk data ctl domdata gc prices _315 - s1 s5 XCHG // price key lhk nhk prices ctl domdata gc data _315 - STREF // price key lhk nhk prices ctl domdata gc _316 - s7 s2 XCHG2 - 224 PUSHINT // price gc lhk nhk prices ctl _316 key domdata _319 - DICTUSETB // price gc lhk nhk prices ctl domdata - s5 s4 XCHG2 - s1 s3 XCHG - 1 PUSHINT // price ctl domdata gc prices nhk lhk _321=1 - housekeeping CALLDICT - send_ok CALLDICT - }> // price key lhk exp data ctl domdata gc prices nhk - 10 BLKDROP // - }> - recv_external PROC:<{ - // in_msg - DROP // - load_data INLINECALLDICT // _12 _13 _14 _15 _16 _17 - NIP // ctl dd gc prices lhk - IFNOTJMP:<{ // ctl dd gc prices - ACCEPT - 32 PUSHPOW2DEC // ctl dd gc prices _9=4294967295 - NOW // ctl dd gc prices _9=4294967295 _10 - store_data CALLDICT - }> // ctl dd gc prices - 4 BLKDROP // - }> - dnsdictlookup PROCREF:<{ - // domain nowtime - OVER // domain nowtime domain - SBITREFS // domain nowtime bits refs - OVER - 7 PUSHINT // domain nowtime bits refs bits _6=7 - AND // domain nowtime bits refs _7 - OR // domain nowtime bits _8 - 30 THROWIF - DUP // domain nowtime bits bits - IFNOTJMP:<{ // domain nowtime bits - 3 BLKDROP // - 0 PUSHINT // _10=0 - PUSHNULL // _10=0 _11 - OVER // _10=0 _11 _12=0 - PUSHNULL // _10=0 _11 _12=0 _13 - }> // domain nowtime bits - s2 PUSH - 8 PUSHINT // domain nowtime bits domain _15=8 - SDCUTLAST // domain nowtime bits _16 - 8 PLDU // domain nowtime bits domain_last_byte - IF:<{ // domain nowtime bits - 0 PUSHINT // domain nowtime bits _19=0 - NEWC // domain nowtime bits _19=0 _20 - s0 s4 XCHG2 // _19=0 nowtime bits _20 domain - STSLICER // _19=0 nowtime bits _21 - s1 s3 XCHG // bits nowtime _19=0 _21 - 8 STU // bits nowtime _23 - ENDC // bits nowtime _24 - CTOS // bits nowtime domain - s0 s2 XCHG // domain nowtime bits - 8 ADDCONST // domain nowtime bits - }> // domain nowtime bits - DUP // domain nowtime bits bits - 8 EQINT // domain nowtime bits _29 - IFJMP:<{ // domain nowtime bits - 3 BLKDROP // - 0 PUSHINT // _30=0 - PUSHNULL // _30=0 _31 - OVER // _30=0 _31 _32=0 - PUSHNULL // _30=0 _31 _32=0 _33 - }> // domain nowtime bits - c4 PUSH // domain nowtime bits _35 - CTOS // domain nowtime bits ds - LDREF // domain nowtime bits _87 _86 - NIP // domain nowtime bits ds - LDDICT // domain nowtime bits _89 _88 - DROP // domain nowtime bits root - PUSHNULL // domain nowtime bits root val - -1 PUSHINT // domain nowtime bits root val tail_bits=-1 - s5 PUSH // domain nowtime bits root val tail_bits=-1 tail - s0 s4 XCHG // domain nowtime tail root val tail_bits=-1 bits - 3 RSHIFT# // domain nowtime tail root val tail_bits=-1 _49 - REPEAT:<{ // domain nowtime tail root val tail_bits - s0 s3 XCHG // domain nowtime tail_bits root val tail - 8 LDU // domain nowtime tail_bits root val _50 tail - SWAP // domain nowtime tail_bits root val tail _50 - 0 EQINT // domain nowtime tail_bits root val tail _54 - IF:<{ // domain nowtime tail_bits root val tail - DUP // domain nowtime tail_bits root val tail tail - SBITS // domain nowtime tail_bits root val tail _56 - s6 s(-1) PUXC // domain nowtime tail_bits root val tail domain _56 - SDSKIPLAST // domain nowtime tail_bits root val tail _57 - SHA256U // domain nowtime tail_bits root val tail _58 - 32 RSHIFT# // domain nowtime tail_bits root val tail key - s3 PUSH - 224 PUSHINT // domain nowtime tail_bits root val tail key root _65 - DICTUGET - NULLSWAPIFNOT // domain nowtime tail_bits root val tail v found? - IF:<{ // domain nowtime tail_bits root val tail v - DUP // domain nowtime tail_bits root val tail v v - 32 PLDU // domain nowtime tail_bits root val tail v _68 - s6 PUSH // domain nowtime tail_bits root val tail v _68 nowtime - GEQ // domain nowtime tail_bits root val tail v _69 - IF:<{ // domain nowtime tail_bits root val tail v - s2 POP - s3 POP // domain nowtime tail root val - s2 PUSH // domain nowtime tail root val tail - SBITS // domain nowtime tail root val tail_bits - s0 s3 XCHG // domain nowtime tail_bits root val tail - }>ELSE<{ - DROP // domain nowtime tail_bits root val tail - }> - }>ELSE<{ - DROP // domain nowtime tail_bits root val tail - }> - }> // domain nowtime tail_bits root val tail - s0 s3 XCHG // domain nowtime tail root val tail_bits - }> - 2 2 BLKDROP2 - s2 POP // domain tail_bits val - DUP // domain tail_bits val val - ISNULL // domain tail_bits val _71 - IFJMP:<{ // domain tail_bits val - 3 BLKDROP // - 0 PUSHINT // _72=0 - PUSHNULL // _72=0 _73 - OVER // _72=0 _73 _74=0 - PUSHNULL // _72=0 _73 _74=0 _75 - }> // domain tail_bits val - 32 LDU // domain tail_bits _76 val - LDREF // domain tail_bits _76 _97 _96 - DROP // domain tail_bits _76 _79 - s2 PUSH // domain tail_bits _76 _79 tail_bits - 0 EQINT // domain tail_bits _76 _79 _82 - s4 s3 XCHG2 // _79 _82 _76 domain tail_bits - SDSKIPLAST // _79 _82 _76 _83 - s3 s3 s0 XCHG3 // _76 _79 _82 _83 - }> - dnsresolve PROC:<{ - // domain category - SWAP - NOW // category domain _6 - dnsdictlookup INLINECALLDICT // category exp cat_table exact? pfx - s0 s3 XCHG // category pfx cat_table exact? exp - IFNOTJMP:<{ // category pfx cat_table exact? - 4 BLKDROP // - 0 PUSHINT // _8=0 - PUSHNULL // _8=0 _9 - }> // category pfx cat_table exact? - IFNOT:<{ // category pfx cat_table - -1 PUSHINT - s3 POP // category=-1 pfx cat_table - }> // category pfx cat_table - SWAP // category cat_table pfx - SBITS // category cat_table pfx_bits - s2 PUSH // category cat_table pfx_bits category - IFJMP:<{ // category cat_table pfx_bits - -ROT - 16 PUSHINT // pfx_bits category cat_table _14=16 - DICTIGETOPTREF // pfx_bits cat_found - }> // category cat_table pfx_bits - s2 POP // pfx_bits cat_table - }> - getexpirationx PROC:<{ - // domain nowtime - dnsdictlookup INLINECALLDICT // _7 _8 _9 _10 - 3 BLKDROP // exp - }> - getexpiration PROC:<{ - // domain - NOW // domain _1 - getexpirationx INLINECALLDICT // _2 - }> - getstdperiod PROC:<{ - // - load_prices INLINECALLDICT // _5 _6 _7 _8 - 3 BLKDROP // stdper - }> - getppr PROC:<{ - // - load_prices INLINECALLDICT // _5 _6 _7 _8 - s2 s3 XCHG - 3 BLKDROP // ppr - }> - getppc PROC:<{ - // - load_prices INLINECALLDICT // _5 _6 _7 _8 - s1 s3 XCHG - 3 BLKDROP // ppc - }> - getppb PROC:<{ - // - load_prices INLINECALLDICT // _5 _6 _7 _8 - 3 1 BLKDROP2 // ppb - }> - calcprice PROC:<{ - // domain val - load_prices INLINECALLDICT // domain val _8 _9 _10 _11 - 2 2 BLKDROP2 // domain val ppc ppb - calcprice_internal INLINECALLDICT // _7 - }> - calcregprice PROC:<{ - // domain val - load_prices INLINECALLDICT // domain val _9 _10 _11 _12 - s3 POP // domain val ppb ppr ppc - s3 s4 XCHG - s4 s0 s4 XCHG3 // ppr domain val ppc ppb - calcprice_internal INLINECALLDICT // ppr _7 - ADD // _8 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.cpp deleted file mode 100644 index a7d52587..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("dns-manual", "te6ccgECGAEAAswAART/APSkE/S88sgLAQIBIAIDAgFIBAUC6vLbPAWDCNcYIPkBAdMf0z/4I6ofUyC58mNTKoBA9A5voTHyYFKUuvKiVBNG+RDyo/gAItcLBcAzmDQBdtch0/8wjoVa2zxAA+IDgyWhyEAHgED0Q44aIIBA9JZvpWwSIJQwUwe53iCTMzUBkmwh4rPmbBXwBBESAgLFBgcCASAMDQIBzwgJAAiqgl8DAgFICgsAIdAmRlj4nln+X/+gB6AGT2qkAAUXwOAAFzI9ADJ0EEz9HDyoYAAXvZznaiaGmvmOuF/8AgEgDg8AEbs3PtRNDXCx+AP5ujDCHXSSCUXwNwbeEgd7DyXiJ41yLXCweecMhQBM8WE8sHydACpgjeIMAIlF8DcG3g2zwUXwQjcAOrApjTBwHAABOhAuQgbY6bXwMhyMsGJM8WydCECSIC2zwFpRWyIMEBFUMw5jM1IpRfBXBt4WwSxwCSfzLfAtdJpvkhgRFRAAFsAAkjEB4AKAEPRqABztRNDTH9M/0//0BPQE0QE0cFmOk9s8IMcBmyDXSpPUMNCSfzPi3iLmMDETBPbTBSHBCo4sIZEx4SHAAZcx0wfUAvsA4AHACY4U1CH7BO1DAtDtHu1TVGID8QaC8gDg8i3gcCLBFJQw0g8B3m1tJMEe4wAkwRSOkSWECSPbPDMClTLHAPKjkVvi3iTAC44TNAL0BFAkgBD0bjAQI4QJWfABAeAkwAzjAjAUFRYXAIQxAtMAAcABk9QB0JjTBQGqAtcYAeIg10nCD/KmIHjXItcLB/JocFMR10mpNgKY0wcBwAASoQHkMMjLBgHPFsnQUAMAIFn0qG+lIJQC9AQwkjJt4gIAKDQDgBD0WpkQI4QJQETwAQGSMDHiAGYxIsAVnDL0BBAjhAlQQvABAeAiwBaYMgKECfRzMAHgMDIgwB+TMPQE4MAgkm0B4PIsbQE="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.fif deleted file mode 100644 index 1f15c315..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/dns-manual-code.fif +++ /dev/null @@ -1,477 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/dns-manual-code.fc` -PROGRAM{ - DECLPROC pfxdict_set_ref - DECLPROC pfxdict_get_ref - DECLPROC load_data - DECLPROC store_data - DECLPROC recv_internal - 1666 DECLMETHOD after_code_upgrade - DECLPROC process_op - DECLPROC process_ops - DECLPROC recv_external - 111475 DECLMETHOD get_contract_id - 78748 DECLMETHOD get_public_key - 123660 DECLMETHOD dnsresolve - pfxdict_set_ref PROC:<{ - // dict key_len key value - NEWC // dict key_len key value _6 - STOPTREF // dict key_len key _7 - ENDC // dict key_len key _8 - CTOS // dict key_len key _9 - s1 s3 s3 XCHG3 // _9 key dict key_len - PFXDICTSET // dict _5 - 33 THROWIFNOT - }> - pfxdict_get_ref PROCREF:<{ - // dict key_len key - -ROT // key dict key_len - PFXDICTGETQ - NULLSWAPIFNOT2 // pfx val tail succ - DUP // pfx val tail succ succ - IF:<{ // pfx val tail succ - s0 s2 XCHG // pfx succ tail val - LDOPTREF // pfx succ tail _18 _17 - DROP // pfx succ tail _9 - }>ELSE<{ // pfx val tail succ - s2 POP // pfx succ tail - PUSHNULL // pfx succ tail _9 - }> // pfx succ tail res - s0 s2 XCHG // pfx res tail succ - }> - load_data PROCREF:<{ - // - c4 PUSH // _1 - CTOS // cs - 32 LDU // _4 cs - 64 LDU // _4 _7 cs - 256 LDU // _4 _7 _10 cs - LDDICT // _4 _7 _10 _13 cs - LDDICT // res res res res res cs - ENDS - }> - store_data PROC:<{ - // contract_id last_cleaned public_key root old_queries - s0 s4 XCHG - NEWC // old_queries last_cleaned public_key root contract_id _5 - 32 STU // old_queries last_cleaned public_key root _7 - s1 s3 XCHG // old_queries root public_key last_cleaned _7 - 64 STU // old_queries root public_key _9 - 256 STU // old_queries root _11 - STDICT // old_queries _12 - STDICT // _13 - ENDC // _14 - c4 POP - }> - recv_internal PROC:<{ - // msg_value in_msg_cell in_msg - 3 BLKDROP // - }> - after_code_upgrade PROC:<{ - // root ops old_code - 3 BLKDROP // - }> - process_op PROCREF:<{ - // root ops - 6 LDU // root op ops - OVER // root op ops op - 10 LESSINT // root op ops _7 - IFJMP:<{ // root op ops - OVER // root op ops op - IFNOTJMP:<{ // root op ops - NIP // root ops - }> // root op ops - OVER // root op ops op - 1 EQINT // root op ops _9 - IFJMP:<{ // root op ops - NIP // root ops - 8 LDU // root mode ops - LDREF // root mode _14 ops - s0 s2 XCHG // root ops _14 mode - SENDRAWMSG - }> // root op ops - SWAP // root ops op - 9 EQINT // root ops _18 - IFJMP:<{ // root ops - LDREF // root new_code ops - OVER // root new_code ops new_code - SETCODE - c3 PUSH // root new_code ops old_code - s0 s2 XCHG // root old_code ops new_code - CTOS // root old_code ops _25 - BLESS // root old_code ops _26 - c3 POP - s2 s(-1) s1 PU2XC // root ops root ops old_code - after_code_upgrade CALLDICT - 0 THROW - }> // root ops - 45 THROW - }> // root op ops - 0 PUSHINT // root op ops cat=0 - s2 PUSH // root op ops cat=0 op - 20 LESSINT // root op ops cat=0 _36 - IF:<{ // root op ops cat=0 - DROP // root op ops - 16 LDI // root op cat ops - SWAP // root op ops cat - }> // root op ops cat - PUSHNULL // root op ops cat name - PUSHNULL // root op ops cat name cat_table - s4 PUSH // root op ops cat name cat_table op - 30 LESSINT // root op ops cat name cat_table _45 - IF:<{ // root op ops cat name cat_table - NIP // root op ops cat cat_table - s0 s2 XCHG // root op cat_table cat ops - 1 LDU // root op cat_table cat _47 ops - SWAP // root op cat_table cat ops _47 - 1 EQINT // root op cat_table cat ops is_name_ref - IF:<{ // root op cat_table cat ops - LDREF // root op cat_table cat _52 ops - SWAP // root op cat_table cat ops _52 - CTOS // root op cat_table cat ops name - }>ELSE<{ // root op cat_table cat ops - 6 LDU // root op cat_table cat _56 ops - SWAP // root op cat_table cat ops _56 - 3 LSHIFT# // root op cat_table cat ops name_len - LDSLICEX // root op cat_table cat name ops - SWAP // root op cat_table cat ops name - }> - DUP // root op cat_table cat ops name name - SBITS // root op cat_table cat ops name _64 - 15 GTINT // root op cat_table cat ops name _66 - 38 THROWIFNOT - DUP - 8 PUSHINT // root op cat_table cat ops name name _69=8 - SDCUTLAST // root op cat_table cat ops name _70 - 8 PLDU // root op cat_table cat ops name name_last_byte - 40 THROWIF - 0 PUSHINT // root op cat_table cat ops name zeros=0 - s1 s1 PUSH2 // root op cat_table cat ops name zeros=0 cname cname - SBITS // root op cat_table cat ops name zeros=0 cname _78 - 3 RSHIFTC# // root op cat_table cat ops name zeros=0 cname _80 - REPEAT:<{ // root op cat_table cat ops name zeros cname - 8 LDU // root op cat_table cat ops name zeros c cname - SWAP // root op cat_table cat ops name zeros cname c - 0 EQINT // root op cat_table cat ops name zeros cname _86 - s1 s2 XCHG // root op cat_table cat ops name cname zeros _86 - SUB // root op cat_table cat ops name cname zeros - SWAP // root op cat_table cat ops name zeros cname - }> - DROP // root op cat_table cat ops name zeros - NEWC // root op cat_table cat ops name zeros _88 - 7 STU // root op cat_table cat ops name _90 - SWAP // root op cat_table cat ops _90 name - STSLICER // root op cat_table cat ops _91 - ENDC // root op cat_table cat ops _92 - CTOS // root op cat_table cat ops name - s0 s3 XCHG2 // root op ops cat name cat_table - }> // root op ops cat name cat_table - s4 PUSH // root op ops cat name cat_table op - 20 LESSINT // root op ops cat name cat_table _95 - IF:<{ // root op ops cat name cat_table - s5 PUSH - 10 PUSHPOW2DEC - s3 PUSH // root op ops cat name cat_table root _100=1023 name - pfxdict_get_ref INLINECALLDICT // root op ops cat name cat_table _168 _169 _170 _171 - s3 POP // root op ops cat name cat_table succ val tail - s0 s2 XCHG // root op ops cat name cat_table tail val succ - IF:<{ // root op ops cat name cat_table tail val - s2 POP // root op ops cat name val tail - SEMPTY // root op ops cat name val _103 - 35 THROWIFNOT // root op ops cat name cat_table - }>ELSE<{ - 2DROP // root op ops cat name cat_table - }> - }> // root op ops cat name cat_table - s4 PUSH // root op ops cat name cat_table op - 11 EQINT // root op ops cat name cat_table _106 - IFJMP:<{ // root op ops cat name cat_table - s4 POP // root cat_table ops cat name - s0 s2 XCHG // root cat_table name cat ops - LDOPTREF // root cat_table name cat new_value ops - s2 s4 XCHG2 - 16 PUSHINT // root ops name new_value cat cat_table _111=16 - DICTISETGETOPTREF // root ops name _174 _175 - DROP // root ops name cat_table - s2 s3 XCHG - 10 PUSHPOW2DEC - -ROT // ops root _114=1023 name cat_table - pfxdict_set_ref CALLDICT // ops root - SWAP // root ops - }> // root op ops cat name cat_table - s4 PUSH // root op ops cat name cat_table op - 12 EQINT // root op ops cat name cat_table _117 - IFJMP:<{ // root op ops cat name cat_table - s4 POP // root cat_table ops cat name - s0 s3 XCHG - 16 PUSHINT // root name ops cat cat_table _119=16 - DICTIDEL // root name ops cat_table _118 - IF:<{ // root name ops cat_table - s2 s3 XCHG - 10 PUSHPOW2DEC - s0 s4 s4 XCHG3 // ops root _122=1023 name cat_table - pfxdict_set_ref CALLDICT // ops root - SWAP // root ops - }>ELSE<{ - DROP - NIP // root ops - }> - }> // root op ops cat name cat_table - DROP - NIP // root op ops name - s2 PUSH // root op ops name op - 21 EQINT // root op ops name _125 - IFJMP:<{ // root op ops name - s2 POP // root name ops - LDOPTREF // root name new_cat_table ops - s2 s3 XCHG - 10 PUSHPOW2DEC - s4 s2 XCHG2 // ops root _130=1023 name new_cat_table - pfxdict_set_ref CALLDICT // ops root - SWAP // root ops - }> // root op ops name - s2 PUSH // root op ops name op - 22 EQINT // root op ops name _133 - IFJMP:<{ // root op ops name - s2 POP // root name ops - s0 s2 XCHG - 10 PUSHPOW2DEC // ops name root _135=1023 - PFXDICTDEL // ops _180 _181 - DROP // ops root - SWAP // root ops - }> // root op ops name - DROP - s2 POP // ops op - DUP // ops op op - 31 EQINT // ops op _138 - IFJMP:<{ // ops op - DROP // ops - LDOPTREF // new_tree_root ops - }> // ops op - 32 EQINT // ops _143 - IFJMP:<{ // ops - PUSHNULL // ops _144 - SWAP // _144 ops - }> // ops - 44 THROW - PUSHNULL // ops _147 - SWAP // _147 ops - }> - process_ops PROCREF:<{ - // root ops - FALSE // root ops stop - -ROT // stop root ops - UNTIL:<{ - process_op INLINECALLDICT // stop root ops - DUP // stop root ops ops - SDEMPTY // stop root ops _9 - IF:<{ // stop root ops - DUP // stop root ops ops - SREFS // stop root ops _10 - IF:<{ // stop root ops - LDREF // stop root _18 _17 - DROP // stop root _11 - CTOS // stop root ops - }>ELSE<{ // stop root ops - TRUE - s3 POP // stop root ops - }> - }> // stop root ops - s2 PUSH // stop root ops stop - }> // stop root ops - DROP - NIP // root - }> - recv_external PROC:<{ - // in_msg - load_data INLINECALLDICT // in_msg contract_id last_cleaned public_key root old_queries - s0 s5 XCHG - 9 PUSHPOW2 // old_queries contract_id last_cleaned public_key root in_msg _9=512 - LDSLICEX // old_queries contract_id last_cleaned public_key root signature in_msg - DUP // old_queries contract_id last_cleaned public_key root signature in_msg in_msg - HASHSU // old_queries contract_id last_cleaned public_key root signature in_msg shash - SWAP // old_queries contract_id last_cleaned public_key root signature shash in_msg - 32 LDU // old_queries contract_id last_cleaned public_key root signature shash _15 in_msg - 64 LDU // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg - NOW // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg _22 - 32 LSHIFT# // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound - s2 s0 PUSH2 // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound query_id bound - LESS // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound _26 - 35 THROWIF - s2 s10 PUSH2 - 64 PUSHINT // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound query_id old_queries _30=64 - DICTUGET - NULLSWAPIFNOT // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound _84 _85 - NIP // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound found? - 32 THROWIF - s9 s3 PUXC // old_queries contract_id last_cleaned public_key root signature shash bound query_id in_msg contract_id query_contract - EQUAL // old_queries contract_id last_cleaned public_key root signature shash bound query_id in_msg _35 - 34 THROWIFNOT - s3 s4 s6 XC2PU // old_queries contract_id last_cleaned public_key root in_msg query_id bound shash signature public_key - CHKSIGNU // old_queries contract_id last_cleaned public_key root in_msg query_id bound _38 - 35 THROWIFNOT - ACCEPT - s2 PUSH // old_queries contract_id last_cleaned public_key root in_msg query_id bound in_msg - 6 PLDU // old_queries contract_id last_cleaned public_key root in_msg query_id bound op - 51 EQINT // old_queries contract_id last_cleaned public_key root in_msg query_id bound _45 - IF:<{ // old_queries contract_id last_cleaned public_key root in_msg query_id bound - s4 POP // old_queries contract_id last_cleaned bound root in_msg query_id - SWAP - 6 PUSHINT // old_queries contract_id last_cleaned bound root query_id in_msg _47=6 - SDSKIPFIRST // old_queries contract_id last_cleaned bound root query_id in_msg - 256 LDU // old_queries contract_id last_cleaned bound root query_id _87 _86 - DROP // old_queries contract_id last_cleaned bound root query_id public_key - }>ELSE<{ // old_queries contract_id last_cleaned public_key root in_msg query_id bound - 2SWAP // old_queries contract_id last_cleaned public_key query_id bound root in_msg - process_ops INLINECALLDICT // old_queries contract_id last_cleaned public_key query_id bound root - s0 s0 s3 XCHG3 // old_queries contract_id last_cleaned bound root query_id public_key - }> - s0 s3 XCHG - 38 PUSHPOW2 // old_queries contract_id last_cleaned public_key root query_id bound _55 - SUB // old_queries contract_id last_cleaned public_key root query_id bound - NEWC // old_queries contract_id last_cleaned public_key root query_id bound _58 - s0 s0 s7 XCHG3 - 64 PUSHINT // bound contract_id last_cleaned public_key root _58 query_id old_queries _59=64 - DICTUSETB // bound contract_id last_cleaned public_key root old_queries - UNTIL:<{ - DUP - 64 PUSHINT // bound contract_id last_cleaned public_key root old_queries old_queries _66=64 - DICTUREMMIN - NULLSWAPIFNOT2 // bound contract_id last_cleaned public_key root old_queries _88 _90 _89 _91 - 1 2 BLKDROP2 // bound contract_id last_cleaned public_key root old_queries old_queries' i f - DUP // bound contract_id last_cleaned public_key root old_queries old_queries' i f f - IF:<{ // bound contract_id last_cleaned public_key root old_queries old_queries' i f - DROP // bound contract_id last_cleaned public_key root old_queries old_queries' i - s0 s7 PUSH2 // bound contract_id last_cleaned public_key root old_queries old_queries' i i bound - LESS // bound contract_id last_cleaned public_key root old_queries old_queries' i f - }> // bound contract_id last_cleaned public_key root old_queries old_queries' i f - DUP // bound contract_id last_cleaned public_key root old_queries old_queries' i f f - IF:<{ // bound contract_id last_cleaned public_key root old_queries old_queries' i f - s3 POP - s5 POP // bound contract_id last_cleaned public_key root f old_queries - SWAP // bound contract_id last_cleaned public_key root old_queries f - }>ELSE<{ - 2 1 BLKDROP2 // bound contract_id last_cleaned public_key root old_queries f - }> - NOT // bound contract_id last_cleaned public_key root old_queries _71 - }> // bound contract_id last_cleaned public_key root old_queries - 1 5 BLKDROP2 // contract_id last_cleaned public_key root old_queries - store_data CALLDICT - }> - get_contract_id PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 96 LDU // _11 _10 - NIP // cs - 256 PLDU // _9 - }> - dnsresolve PROC:<{ - // subdomain category - OVER // subdomain category subdomain - SBITS // subdomain category bits - DUP // subdomain category bits bits - IFNOTJMP:<{ // subdomain category bits - 3 BLKDROP // - 0 PUSHINT // _4=0 - PUSHNULL // _4=0 _5 - }> // subdomain category bits - DUP - 7 PUSHINT // subdomain category bits bits _7=7 - AND // subdomain category bits _8 - 30 THROWIF - s2 PUSH - 8 PUSHINT // subdomain category bits subdomain _11=8 - SDCUTLAST // subdomain category bits _12 - 8 PLDU // subdomain category bits name_last_byte - IF:<{ // subdomain category bits - 0 PUSHINT // subdomain category bits _15=0 - NEWC // subdomain category bits _15=0 _16 - s0 s4 XCHG2 // _15=0 category bits _16 subdomain - STSLICER // _15=0 category bits _17 - s1 s3 XCHG // bits category _15=0 _17 - 8 STU // bits category _19 - ENDC // bits category _20 - CTOS // bits category subdomain - s0 s2 XCHG // subdomain category bits - 8 ADDCONST // subdomain category bits - }> // subdomain category bits - DUP // subdomain category bits bits - 8 EQINT // subdomain category bits _25 - IFJMP:<{ // subdomain category bits - 3 BLKDROP // - 0 PUSHINT // _26=0 - PUSHNULL // _26=0 _27 - }> // subdomain category bits - load_data INLINECALLDICT // subdomain category bits _80 _81 _82 _83 _84 - s1 s4 XCHG - 4 BLKDROP // subdomain category bits root - s3 PUSH // subdomain category bits root cname - 0 PUSHINT // subdomain category bits root cname zeros=0 - s0 s3 XCHG // subdomain category zeros=0 root cname bits - 3 RSHIFT# // subdomain category zeros=0 root cname _38 - REPEAT:<{ // subdomain category zeros root cname - 8 LDU // subdomain category zeros root c cname - SWAP // subdomain category zeros root cname c - 0 EQINT // subdomain category zeros root cname _44 - s1 s3 XCHG // subdomain category cname root zeros _44 - SUB // subdomain category cname root zeros - s0 s2 XCHG // subdomain category zeros root cname - }> - DUP // subdomain category zeros root cname pfx - PUSHNULL // subdomain category zeros root tail pfx val - UNTIL:<{ - 3 BLKDROP // subdomain category zeros root - OVER - NEWC // subdomain category zeros root zeros _51 - 7 STU // subdomain category zeros root _53 - s4 PUSH // subdomain category zeros root _53 subdomain - STSLICER // subdomain category zeros root _54 - ENDC // subdomain category zeros root _55 - CTOS // subdomain category zeros root pfxname - 10 PUSHPOW2DEC // subdomain category zeros root pfxname _58=1023 - s2 PUSH - s0 s2 XCHG // subdomain category zeros root root _58=1023 pfxname - pfxdict_get_ref INLINECALLDICT // subdomain category zeros root pfx val tail succ - s0 s5 XCHG // subdomain category succ root pfx val tail zeros - DEC // subdomain category succ root pfx val tail _61 - s1 s5 XCHG // subdomain category tail root pfx val succ _61 - XOR // subdomain category tail root pfx val zeros - DUP // subdomain category tail root pfx val zeros zeros - 1 LESSINT // subdomain category tail root pfx val zeros _64 - s1 s5 XCHG - s3 s3 s0 XCHG3 // subdomain category zeros root tail pfx val _64 - }> // subdomain category zeros root tail pfx val - s3 POP - s5 POP // pfx category zeros val tail - s2 PUSH // pfx category zeros val tail zeros - IFNOTJMP:<{ // pfx category zeros val tail - 5 BLKDROP // - 0 PUSHINT // _65=0 - PUSHNULL // _65=0 _66 - }> // pfx category zeros val tail - 1 2 BLKDROP2 // pfx category val tail - SEMPTY // pfx category val _68 - IFNOT:<{ // pfx category val - -1 PUSHINT - s2 POP // pfx category=-1 val - }> // pfx category val - s0 s2 XCHG // val category pfx - SBITS // val category _71 - -7 ADDCONST // cat_table category pfx_bits - OVER // cat_table category pfx_bits category - 0 EQINT // cat_table category pfx_bits _76 - IFJMP:<{ // cat_table category pfx_bits - NIP // cat_table pfx_bits - SWAP // pfx_bits cat_table - }> // cat_table category pfx_bits - s0 s2 XCHG - 16 PUSHINT // pfx_bits category cat_table _78=16 - DICTIGETOPTREF // pfx_bits cat_found - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp deleted file mode 100644 index b06c95a9..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("elector-code", "te6ccgECZAEADwkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgVeSBOKjgQ+BL5ICz4FHkgcXgTeSB4FJhAAgLFBgcCASBGRwIByQgJASqqgjGCEE5Db2SCEM5Db2RZcIBA2zwoAgEgCgsCAUgpKgIBIAwNBOOnAX0iANJJr4G/8BDrskGDX0mvgb7wbZ4IGq+CgWmPqYnAEHoHN9DJr4M/cJBrhY/8EdCQYIDJr4O+cBFtnjYRGfwR7Z4FwYX8oZlBhNAsVADTASgF1A1QKAPUKARQEEGO0CgGXMmvhb3wKgoBqhzbk8BgUl0TBH/YDoaYGAuNhJL4HwfSAYEOOAR0IYgO2ecADpj5DgAEdCLYDtnnBpn5FBCCc5uiXdR0KZCBHtnnARQQgjsroSXUDg4PEAAduwAf8GehpD+kP6Q/rhQ/BFTbPAf6RAGksSHAALGOiAWgEDVVEts84FMCgCD0Dm+hlDAFoAHjDRA1QUNgQRESBMQj+kTtRND0BCFuBKQUsY6HEDVfBXDbPOAE0//TH9Mf0//UAdCDCNcZAdGCEGVMUHTIyx9SQMsfUjDLH1Jgy/9SIMv/ydBRFfkRjocQaF8Icds84SGDD7mOhxBoXwh22zzgBxgYGBYEeo6ENBPbPOAighBOQ29kuo8YNFRSRNs8loIQzkNvZJKEH+JAM3CAQNs84CKCEO52T0u6I4IQ7nZPb7pSELEbHCgdAiDbPAygVQUL2zxUIFOAIPRDWjkBBNs8QQSk2zzJAts8UbODB/QOb6GUXw6A+uGBAUDXIfoAMFIIqbQfGaBSB7yUXwyA+eBRW7uUXwuA+OBtcFMHVSDbPAb5AEYJgwf0U5RfCoD34UZQEDcQJxRaJhUANIC8yMoHGMv/FswUyx8SywfL/wH6AgH6AssfAyLbPAKAIPRD2zwzEEUQNFjbPDlgQQRW2zwxDYIQO5rKAKEgqgsjuY6HEL1fDXLbPOBRIqBRdb2OhxCsXwxz2zzgDGMYGBcEwI6HEJtfC3DbPOBTa4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHijocQm18LdNs84FMBuY6HEJtfC3XbPOAg8qz4APgjyFj6AssfFMsfFsv/GMv/QDiDB/RDEEVBMBZwcBgYGBkBGIIQ7m9FTFlwgEDbPCgCJts8yPQAWM8Wye1UII6DcNs84FtFGgEgghDzdEhMWYIQO5rKAHLbPCgC1jEh+kQBpI6OMIIQ/////kATcIBA2zzg7UTQ9AT0BFAzgwf0Zm+hjo9fBIIQ/////kATcIBA2zzhNgX6ANEByPQAFfQAAc8Wye1UghD5b3MkcIAYyMsFUATPFlAE+gISy2oSyx/LP8mAQPsAKCgAbnD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwScAdDtHu1TAfEGgvIA4n8Elo6GMzRDANs84DAighBSZ0Nwuo6mVEMV8B6AQCGjIsL/l1t0+wJwgwaRMuIBghDyZ2NQoANERHAB2zzgNCGCEFZ0Q3C64wIzIIMesB4oHyACoDIC+kRw+DPQ1wv/7UTQ9AQEpFq9sSFusZJfBODbPGxRUhW9BLMUsZJfA+D4AAGRW46d9AT0BPoAQzTbPHDIygAT9AD0AFmg+gIBzxbJ7VTiY0ADogODCNcYINMf0w/TH9P/0QOCEFZ0Q1C68qUh2zww0weAILMSsMBT8qnTHwGCEI6BJ4q68qnT/9M/MEVm+RHyolUC2zyCENZ0UkCgQDNwgEDbPCEiKAEcjomEH0AzcIBA2zzhXwMoARjbPDJZgBD0Dm+hMAElBFDbPFOTgCD0Dm+hOwqTXwp+4QnbPDRbbCJJNxjbPDIhwQGTGF8I4CBuYFojJAO+UyODB/QOb6GUXwRtf+HbPDAB+QAC2zxTFb2ZXwNtAnOp1AACkjQ04lNQgBD0Dm+hMZRfB21w4PgjyMsfQGaAEPRDVCAEoVEzsiRQMwTbPEA0gwf0QwHC/5MxbXHgAXIlUSYCKpIwNI6JQ1DbPDEVoFBE4kUTREbbPCdBACyAIvgzINDTBwHAEvKogGDXIdM/9ATRAByALcjLBxTMEvQAy//KPwKa0Ns8NDQ0U0WDB/QOb6GTXwZw4dP/0z/6ANIA0VIWqbQfFqBSULYIUVWhAsjL/8s/AfoCEsoAQEWDB/RDI6sCAqoCErYIUTOhREPbPFlSRABEcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AAIBICssAgFIOzwAA2nCAgEgLS4CASAvMAOnTbPIAi+DP5AFMBupNfB3DgIo4vUySAIPQOb6GOINMfMSDTH9P/MFAEuvK5+CNQA6DIyx9YzxZABIAg9EMCkxNfA+KSbCHif4rmIG6SMHDeAds8f4YDpBA/cgBD4M9DTD9MPMdMP0XG2CXBtf45BKYMH9HxvpSCOMgL6ANMf0x/T/9P/0QOjBMjLfxTKH1JAy//J0FEatgjIyx8Ty//L/0AUgQGg9EEDpEMTkTLiAbPmMDRYtghTAbmXXwdtcG1TEeBtiuYzNKVckm8R5HAgiuY2NlsigMTIzA/UAds8NPgjJbmTXwhw4HD4M26UXwjwIuCAEfgz0PoA+gD6ANMf0VNhuZRfDPAi4ASUXwvwIuAGk18KcOAjEElRMlB38CQgwAAgsysGEFsQShA5Td3bPCOOEDFsUsj0APQAAc8Wye1U8CLh8A0y+CMBoKbEKbYJgBD4M9CBjRTcAZAOBAaD0km+lII4hAdN/URm2CAHTHzHXC/8D0x/T/zHXC/9BMBRvBFAFbwIEkmwh4rMUAUgCbyIBbxAEpFNIvo6QVGUG2zxTAryUbCIiApEw4pE04lM2vhM0AV7AAFJDuRKxl18EbXBtUxHgUwGlkm8R5G8QbxBwUwBtbYrmNDQ0NlJVuvKxUERDEzUANHACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxAf4GbyIBbyRTHYMH9A5vofK9+gAx0z8x1wv/U5y5jl1ROqirD1JAtghRRKEkqjsuqQRRlaBRiaCCEI6BJ4ojkoBzkoBT4sjLB8sfUkDL/1Kgyz8jlBPL/wKRM+JUIqiAEPRDcCTIy/8ayz9QBfoCGMoAQBqDB/RDCBBFExSSbDHiNgEiIY6FTADbPAqRW+IEpCRuFRdEArqAENch1wsPUnC2CFMToIASyMsHUjDLH8sfGMsPF8sPGss/E/QAyXD4M9DXC/9TGNs8CfQEUFOgKKAJ+QAQSRA4QGVwbds8QDWAIPRDA8j0ABL0ABL0AAHPFsntVH84OQBGghBOVlNUcIIAxP/IyxAVy/+DHfoCFMtqE8sfEss/zMlx+wAAKAbIyx8Vyx8Ty//0AAH6AgH6AvQAAJYjgCD0fG+lII48AtM/0/9TFbqOLjQD9AT6APoAKKsCUZmhUCmgBMjLPxbL/xL0AAH6AgH6AljPFlQgBYAg9EMDcAGSXwPikTLiAbMCASA9PgHdQxgCT4M26SW3Dhcfgz0NcL//go+kQBpAK9sZJbcOCAIvgzIG6TXwNw4PANMDIC0IAo1yHXCx/4I1EToVy5k18GcOBcocE8kTGRMOKAEfgz0PoAMAOgUgKhcG0QNBAjcHDbPMj0APQAAc8Wye1Uf4RQOTAHbPGxRk18DcOEC9ARRMYAg9A5voZNfBHDhgEDXIdcL/4Ai+DMh2zyAJPgzWNs8sY4TcMjKABL0APQAAc8Wye1U8CYwf+BfA3CBjPz8DeTbPH+PMiSAIPR8b6UgjyMC0x8w+CO7UxS9sI8VMVQVRNs8FKBUdhNUc1jbPANQVHAB3pEy4gGz5mxhbrOBgQEEAGCFukltwlQH5AAG64gNEAYAg9GZvoZIwcOHbPDBsMyDCAI6EEDTbPI6FMBAj2zziElpCQwAoBcj0ABT0ABL0AAH6Assfy//J7VQBmHBTAH+OtyaDB/R8b6UgjqgC0//TPzH6ANIA0ZQxUTOgjpFUdwiphFFmoFIXoEuw2zwJA+JQU6AEkTLiAbPmMDUDulMhu7DyuxKgAaFEAXJwIH+OrSSDB/R8b6Ugjp4C0//TPzH6ANIA0ZQxUTOgjodUGIjbPAcD4lBDoAORMuIBs+YwMwG68rtEADJTEoMH9A5voZT6ADCgkTDiyAH6AgKDB/RDACoGyMsfFcsfUAP6AgH6AvQAygDKAMkCASBISQIBIF5fAgEgSksCASBTVAJTtkhbZ5Cf7bHTqiJQYP6PzfSkEdGAW2eKQg3gSgBt4EBSJlxANmJczYQwWVACASBMTQJhsKI2zwQNV8Fgx9tjqBREoAg9H5vpSCOjwLbPF8EI0MTbwRQA28CApEy4gGzEuZsIYGBaAgEgTk8CJ6wOgO2eQYP6BzfQx0FtnkkYNvFAWVACXa9LbZ4IGq+CwY+2x08oiUAQej830pBHRoFtnhOqsDeEKAG3gQFImXEA2YlzNhDAYFoCSts8bYMfjhIkgBD0fm+lMiGVUgNvAgLeAbPmMDMD0Ns8bwgDbwRRUgAe0wcBwC3yidT0BNP/0j/RAC7SBwHAvPKJ0//U0x/TB9P/+gD6ANMf0QIBalVWATO30/tngLBhNAA1AHTASgCVAlQANQA0EGO0EF0CASBXWAFCqyztRND0BSBukltw4Ns8ECZfBoMH9A5voZP6ADCSMHDiYwEDp8lZAgFIW1wCKNs8EDVfBYAg9A5voZIwbeHbPGxhYFoAHtMf0x/T//QE+gD6APQE0QAjuH7UTQ9AUgbpIwcJTQ1wsf4oAYe6rtRND0BSBumDBwVHAAbVMR4Ns8bYT/jickgwf0fm+lII4YAvoA0x8x0x/T/9P/0W8EUhBvAlADbwICkTLiAbPmMDOGMAPIAN+DMgbpYwgyNxgwif0NMHAcAa8on6APoA+gDR4gFJuYdds8EDVfBYMfbY4UURKAIPR+b6UyIZVSA28CAt4BsxLmbCGGACAVhhYgAg7UTQ9AT0BPQE+gDTH9P/0QFtsKV7UTQ9AUgbpIwbeDbPBAmXwZthP+OGyKDB/R+b6UgnQL6ADBSEG8CUANvAgKRMuIBs+YwMYGMAM7PgO1E0PQEMfQEMIMH9A5voZP6ADCSMHDigACDQ0x/TH/oA+gD0BNIA0gDR"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif deleted file mode 100644 index 39f7fa56..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif +++ /dev/null @@ -1,2436 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/elector-code.fc` -PROGRAM{ - DECLPROC load_data - DECLPROC store_data - DECLPROC unpack_elect - DECLPROC pack_elect - DECLPROC unpack_past_election - DECLPROC pack_past_election - DECLPROC unpack_complaint_status - DECLPROC pack_complaint_status - DECLPROC unpack_complaint - DECLPROC pack_complaint - DECLPROC parse_complaint_prices - DECLPROC get_complaint_prices - DECLPROC get_validator_conf - DECLPROC get_current_vset - DECLPROC get_validator_descr - DECLPROC unpack_validator_descr - DECLPROC send_message_back - DECLPROC return_stake - DECLPROC send_confirmation - DECLPROC send_validator_set_to_config - DECLPROC ~credit_to - DECLPROC process_new_stake - DECLPROC unfreeze_without_bonuses - DECLPROC unfreeze_with_bonuses - DECLPROC unfreeze_all - DECLPROC config_set_confirmed - DECLPROC process_simple_transfer - DECLPROC recover_stake - 1666 DECLMETHOD after_code_upgrade - DECLPROC upgrade_code - DECLPROC register_complaint - DECLPROC punish - DECLPROC register_vote - DECLPROC proceed_register_vote - DECLPROC recv_internal - DECLPROC postpone_elections - DECLPROC compute_total_stake - DECLPROC try_elect - DECLPROC conduct_elections - DECLPROC update_active_vset_id - DECLPROC cell_hash_eq? - DECLPROC validator_set_installed - DECLPROC check_unfreeze - DECLPROC announce_new_elections - DECLPROC run_ticktock - 86535 DECLMETHOD active_election_id - 87852 DECLMETHOD participates_in - 123541 DECLMETHOD participant_list - 86698 DECLMETHOD participant_list_extended - 130944 DECLMETHOD compute_returned_stake - 104565 DECLMETHOD past_election_ids - 81558 DECLMETHOD past_elections - 74376 DECLMETHOD past_elections_list - DECLPROC complete_unpack_complaint - 86500 DECLMETHOD get_past_complaints - 77853 DECLMETHOD show_complaint - 70210 DECLMETHOD list_complaints - 97951 DECLMETHOD complaint_storage_price - load_data PROCREF:<{ - // - c4 PUSH // _1 - CTOS // cs - LDDICT // _4 cs - LDDICT // _4 _6 cs - LDDICT // _4 _6 _8 cs - LDGRAMS // _4 _6 _8 _10 cs - 32 LDU // _4 _6 _8 _10 _12 cs - 256 LDU // res res res res res res cs - ENDS - }> - store_data PROCREF:<{ - // elect credits past_elections grams active_id active_hash - s0 s5 XCHG - NEWC // active_hash credits past_elections grams active_id elect _6 - STDICT // active_hash credits past_elections grams active_id _7 - s1 s4 XCHG // active_hash active_id past_elections grams credits _7 - STDICT // active_hash active_id past_elections grams _8 - s1 s2 XCHG // active_hash active_id grams past_elections _8 - STDICT // active_hash active_id grams _9 - SWAP // active_hash active_id _9 grams - STGRAMS // active_hash active_id _10 - 32 STU // active_hash _12 - 256 STU // _14 - ENDC // _15 - c4 POP - }> - unpack_elect PROCREF:<{ - // elect - CTOS // es - 32 LDU // _4 es - 32 LDU // _4 _7 es - LDGRAMS // _4 _7 _10 es - LDGRAMS // _4 _7 _10 _12 es - LDDICT // _4 _7 _10 _12 _14 es - 1 LDI // _4 _7 _10 _12 _14 _16 es - 1 LDI // res res res res res res res es - ENDS - }> - pack_elect PROCREF:<{ - // elect_at elect_close min_stake total_stake members failed finished - s0 s6 XCHG - NEWC // finished elect_close min_stake total_stake members failed elect_at _7 - 32 STU // finished elect_close min_stake total_stake members failed _9 - s1 s5 XCHG // finished failed min_stake total_stake members elect_close _9 - 32 STU // finished failed min_stake total_stake members _11 - s0 s3 XCHG2 // finished failed members total_stake _11 min_stake - STGRAMS // finished failed members total_stake _12 - SWAP // finished failed members _12 total_stake - STGRAMS // finished failed members _13 - STDICT // finished failed _14 - 1 STI // finished _16 - 1 STI // _18 - ENDC // _19 - }> - unpack_past_election PROCREF:<{ - // fs - 32 LDU // _2 fs - 32 LDU // _2 _5 fs - 256 LDU // _2 _5 _8 fs - LDDICT // _2 _5 _8 _11 fs - LDGRAMS // _2 _5 _8 _11 _13 fs - LDGRAMS // _2 _5 _8 _11 _13 _15 fs - LDDICT // res res res res res res res fs - ENDS - }> - pack_past_election PROCREF:<{ - // unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses complaints - s0 s6 XCHG - NEWC // complaints stake_held vset_hash frozen_dict total_stake bonuses unfreeze_at _7 - 32 STU // complaints stake_held vset_hash frozen_dict total_stake bonuses _9 - s1 s5 XCHG // complaints bonuses vset_hash frozen_dict total_stake stake_held _9 - 32 STU // complaints bonuses vset_hash frozen_dict total_stake _11 - s1 s3 XCHG // complaints bonuses total_stake frozen_dict vset_hash _11 - 256 STU // complaints bonuses total_stake frozen_dict _13 - STDICT // complaints bonuses total_stake _14 - SWAP // complaints bonuses _14 total_stake - STGRAMS // complaints bonuses _15 - SWAP // complaints _15 bonuses - STGRAMS // complaints _16 - STDICT // _17 - }> - unpack_complaint_status PROCREF:<{ - // cs - 8 LDU // _2 cs - SWAP // cs _2 - 45 EQINT // cs _6 - 9 THROWIFNOT - LDREF // _9 cs - LDDICT // _9 _11 cs - 256 LDU // _9 _11 _13 cs - 64 LDI // res res res res cs - ENDS - }> - pack_complaint_status PROCREF:<{ - // complaint voters vset_id weight_remaining - 45 PUSHINT // complaint voters vset_id weight_remaining _4=45 - NEWC // complaint voters vset_id weight_remaining _4=45 _5 - 8 STU // complaint voters vset_id weight_remaining _7 - s1 s4 XCHG // weight_remaining voters vset_id complaint _7 - STREF // weight_remaining voters vset_id _8 - s1 s2 XCHG // weight_remaining vset_id voters _8 - STDICT // weight_remaining vset_id _9 - 256 STU // weight_remaining _11 - 64 STI // _13 - }> - unpack_complaint PROCREF:<{ - // cs - 8 LDI // _2 cs - SWAP // cs _2 - -68 EQINT // cs _8 - 9 THROWIFNOT - 256 LDU // _11 cs - LDREF // _11 _14 cs - 32 LDU // _11 _14 _16 cs - 8 LDU // _11 _14 _16 _19 cs - 256 LDU // _11 _14 _16 _19 _22 cs - LDGRAMS // _11 _14 _16 _19 _22 _25 cs - LDGRAMS // _11 _14 _16 _19 _22 _25 _27 cs - 32 LDU // res res res res res res res res cs - ENDS - }> - pack_complaint PROCREF:<{ - // validator_pubkey description created_at severity reward_addr paid suggested_fine suggested_fine_part - -68 PUSHINT // validator_pubkey description created_at severity reward_addr paid suggested_fine suggested_fine_part _10 - NEWC // validator_pubkey description created_at severity reward_addr paid suggested_fine suggested_fine_part _10 _11 - 8 STI // validator_pubkey description created_at severity reward_addr paid suggested_fine suggested_fine_part _13 - s1 s8 XCHG // suggested_fine_part description created_at severity reward_addr paid suggested_fine validator_pubkey _13 - 256 STU // suggested_fine_part description created_at severity reward_addr paid suggested_fine _15 - s1 s6 XCHG // suggested_fine_part suggested_fine created_at severity reward_addr paid description _15 - STREF // suggested_fine_part suggested_fine created_at severity reward_addr paid _16 - s1 s4 XCHG // suggested_fine_part suggested_fine paid severity reward_addr created_at _16 - 32 STU // suggested_fine_part suggested_fine paid severity reward_addr _18 - s1 s2 XCHG // suggested_fine_part suggested_fine paid reward_addr severity _18 - 8 STU // suggested_fine_part suggested_fine paid reward_addr _20 - 256 STU // suggested_fine_part suggested_fine paid _22 - SWAP // suggested_fine_part suggested_fine _22 paid - STGRAMS // suggested_fine_part suggested_fine _23 - SWAP // suggested_fine_part _23 suggested_fine - STGRAMS // suggested_fine_part _24 - 32 STU // _26 - }> - parse_complaint_prices PROC:<{ - // info - CTOS // cs - 8 LDU // _4 cs - SWAP // cs _4 - 26 EQINT // cs _8 - 9 THROWIFNOT - LDGRAMS // _11 cs - LDGRAMS // _11 _13 cs - LDGRAMS // res res res cs - ENDS - }> - get_complaint_prices PROCREF:<{ - // - 13 PUSHINT // _1=13 - CONFIGOPTPARAM // info - DUP // info info - ISNULL // info _3 - IF:<{ // info - DROP // - 36 PUSHPOW2 // _7 - 1 PUSHINT // _7 _8=1 - 9 PUSHPOW2 // _11 _12=1 _13=512 - }>ELSE<{ // info - parse_complaint_prices INLINECALLDICT // _11 _12 _13 - }> - }> - get_validator_conf PROC:<{ - // - 15 PUSHINT // _1=15 - CONFIGOPTPARAM // _2 - CTOS // cs - 32 LDI // _4 cs - 32 LDI // _4 _7 cs - 32 LDI // _4 _7 _10 cs - 32 PLDI // _4 _7 _10 _14 - }> - get_current_vset PROCREF:<{ - // - 34 PUSHINT // _1=34 - CONFIGOPTPARAM // vset - DUP // vset vset - CTOS // vset cs - 8 LDU // vset _6 cs - SWAP // vset cs _6 - 18 EQINT // vset cs _10 - 40 THROWIFNOT - 96 PUSHINT // vset cs _19 - SDSKIPFIRST // vset cs - 64 LDU // vset _23 cs - LDDICT // vset total_weight dict cs - ENDS - }> - get_validator_descr PROCREF:<{ - // idx - get_current_vset INLINECALLDICT // idx _9 _10 _11 - s2 POP // idx dict total_weight - -ROT - 16 PUSHINT // total_weight idx dict _7=16 - DICTUGET - NULLSWAPIFNOT // total_weight _12 _13 - DROP // total_weight value - SWAP // value total_weight - }> - unpack_validator_descr PROC:<{ - // cs - 8 LDU // _2 cs - 32 PUSHINT // _2 cs _5=32 - NOT // _2 cs _6 - s1 s2 XCHG // cs _2 _6 - AND // cs _7 - 83 EQINT // cs _9 - 41 THROWIFNOT - 32 LDU // _12 cs - SWAP - 2390828938 PUSHINT // cs _12 _15=2390828938 - EQUAL // cs _16 - 41 THROWIFNOT - 256 LDU // _18 cs - 64 LDU // _18 _31 _30 - DROP // _18 _21 - }> - send_message_back PROCREF:<{ - // addr ans_tag query_id body grams mode - 0 PUSHINT // addr ans_tag query_id body grams mode _7=0 - 24 PUSHINT // addr ans_tag query_id body grams mode _7=0 _8=24 - NEWC // addr ans_tag query_id body grams mode _7=0 _8=24 _9 - 6 STU // addr ans_tag query_id body grams mode _7=0 _11 - s0 s7 XCHG2 // _7=0 ans_tag query_id body grams mode _11 addr - STSLICER // _7=0 ans_tag query_id body grams mode _12 - ROT // _7=0 ans_tag query_id body mode _12 grams - STGRAMS // _7=0 ans_tag query_id body mode _13 - s1 s5 XCHG // mode ans_tag query_id body _7=0 _13 - 107 STU // mode ans_tag query_id body _27 - s1 s3 XCHG // mode body query_id ans_tag _27 - 32 STU // mode body query_id _29 - 64 STU // mode body msg - OVER // mode body msg body - -1 GTINT // mode body msg _33 - IF:<{ // mode body msg - 32 STU // mode msg - }>ELSE<{ - NIP // mode msg - }> - ENDC // mode _37 - SWAP // _37 mode - SENDRAWMSG - }> - return_stake PROCREF:<{ - // addr query_id reason - 4000269644 PUSHINT // addr query_id reason _3=4000269644 - -ROT - 0 PUSHINT - 64 PUSHINT // addr _3=4000269644 query_id reason _4=0 _5=64 - send_message_back INLINECALLDICT - }> - send_confirmation PROCREF:<{ - // addr query_id comment - 4084484172 PUSHINT // addr query_id comment _3=4084484172 - -ROT - 1000000000 PUSHINT - 2 PUSHINT // addr _3=4084484172 query_id comment _4=1000000000 _5=2 - send_message_back INLINECALLDICT - }> - send_validator_set_to_config PROCREF:<{ - // config_addr vset query_id - 1314280276 PUSHINT // config_addr vset query_id _4=1314280276 - 0 PUSHINT // config_addr vset query_id _4=1314280276 _5=0 - 50431 PUSHINT // config_addr vset query_id _4=1314280276 _5=0 _6=50431 - NEWC // config_addr vset query_id _4=1314280276 _5=0 _6=50431 _7 - 17 STU // config_addr vset query_id _4=1314280276 _5=0 _9 - s1 s5 XCHG // _5=0 vset query_id _4=1314280276 config_addr _9 - 256 STU // _5=0 vset query_id _4=1314280276 _11 - 30 PUSHPOW2 // _5=0 vset query_id _4=1314280276 _11 _14 - STGRAMS // _5=0 vset query_id _4=1314280276 _15 - s1 s4 XCHG // _4=1314280276 vset query_id _5=0 _15 - 107 STU // _4=1314280276 vset query_id _29 - s1 s3 XCHG // query_id vset _4=1314280276 _29 - 32 STU // query_id vset _31 - s1 s2 XCHG // vset query_id _31 - 64 STU // vset _33 - STREF // msg - ENDC // _35 - 1 PUSHINT // _35 _36=1 - SENDRAWMSG - }> - ~credit_to PROCREF:<{ - // credits addr amount - s1 s2 PUSH2 - 8 PUSHPOW2 // credits addr amount addr credits _5=256 - DICTUGET - NULLSWAPIFNOT // credits addr amount val f - IF:<{ // credits addr amount val - LDGRAMS // credits addr amount _18 _17 - DROP // credits addr amount _7 - ADD // credits addr amount - }>ELSE<{ - DROP // credits addr amount - }> - NEWC // credits addr amount _11 - SWAP // credits addr _11 amount - STGRAMS // credits addr _12 - s0 s2 XCHG - 8 PUSHPOW2 // _12 addr credits _13=256 - DICTUSETB // credits - }> - process_new_stake PROCREF:<{ - // s_addr msg_value cs query_id - s3 PUSH // s_addr msg_value cs query_id s_addr - REWRITESTDADDR // s_addr msg_value cs query_id src_wc src_addr - c4 PUSH // s_addr msg_value cs query_id src_wc src_addr _8 - CTOS // s_addr msg_value cs query_id src_wc src_addr ds - LDDICT // s_addr msg_value cs query_id src_wc src_addr elect ds - OVER // s_addr msg_value cs query_id src_wc src_addr elect ds elect - ISNULL // s_addr msg_value cs query_id src_wc src_addr elect ds _13 - s0 s4 XCHG // s_addr msg_value cs query_id _13 src_addr elect ds src_wc - INC // s_addr msg_value cs query_id _13 src_addr elect ds _15 - s1 s4 XCHG // s_addr msg_value cs query_id ds src_addr elect _13 _15 - OR // s_addr msg_value cs query_id ds src_addr elect _16 - IFJMP:<{ // s_addr msg_value cs query_id ds src_addr elect - s3 s5 XCHG - 5 BLKDROP // s_addr query_id - 0 PUSHINT // s_addr query_id _17=0 - return_stake INLINECALLDICT - }> // s_addr msg_value cs query_id ds src_addr elect - s0 s4 XCHG // s_addr msg_value elect query_id ds src_addr cs - 256 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey cs - 32 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at cs - 32 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor cs - 256 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs - LDREF // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _36 cs - SWAP // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _36 - CTOS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _38 - 9 PUSHPOW2 // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _38 _39=512 - PLDSLICEX // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs signature - SWAP // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature cs - ENDS - 1699500148 PUSHINT // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _42=1699500148 - NEWC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _42=1699500148 _43 - 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _45 - s4 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature stake_at _45 - 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _47 - s3 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature max_factor _47 - 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _49 - s6 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature src_addr _49 - 256 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _51 - s2 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature adnl_addr _51 - 256 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _53 - ENDC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _54 - CTOS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _55 - s1 s5 XCPU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _55 signature validator_pubkey - CHKSIGNS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _56 - IFNOTJMP:<{ // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr - s6 s8 XCHG - 8 BLKDROP // s_addr query_id - 1 PUSHINT // s_addr query_id _57=1 - return_stake INLINECALLDICT - }> // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr - OVER - 16 PUSHPOW2 // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr max_factor _59=65536 - LESS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _60 - IFJMP:<{ // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr - s6 s8 XCHG - 8 BLKDROP // s_addr query_id - 6 PUSHINT // s_addr query_id _61=6 - return_stake INLINECALLDICT - }> // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr - s0 s7 XCHG // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect - unpack_elect INLINECALLDICT // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor _144 _145 _146 _147 _148 _149 _150 - NIP // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members finished - s0 s13 XCHG - 1000000000 PUSHINT // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value _71=1000000000 - SUB // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value - DUP // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value msg_value - 12 LSHIFT# // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value _74 - s3 PUSH // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value _74 total_stake - LESS // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value _75 - IFJMP:<{ // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value - s11 s13 XCHG - 13 BLKDROP // s_addr query_id - 2 PUSHINT // s_addr query_id _76=2 - return_stake INLINECALLDICT - }> // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members msg_value - s2 s2 XCPU // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake msg_value members total_stake msg_value - ADD // s_addr finished adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake msg_value members total_stake - s7 s5 XCPU // s_addr finished adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value members stake_at elect_at - NEQ // s_addr finished adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value members _79 - IFJMP:<{ // s_addr finished adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value members - s10 s12 XCHG - 12 BLKDROP // s_addr query_id - 3 PUSHINT // s_addr query_id _80=3 - return_stake INLINECALLDICT - }> // s_addr finished adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value members - s0 s12 XCHG // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value finished - IFJMP:<{ // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - s9 s11 XCHG - 11 BLKDROP // s_addr query_id - 0 PUSHINT // s_addr query_id _82=0 - return_stake INLINECALLDICT - }> // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - s6 s11 PUSH2 - 8 PUSHPOW2 // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value validator_pubkey members _86=256 - DICTUGET - NULLSWAPIFNOT // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem found - DUP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem found found - IF:<{ // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem found - DROP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem - LDGRAMS // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _88 mem - -ROT // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake mem msg_value _88 - ADD // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake mem msg_value - SWAP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem - 64 LDU // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _156 _155 - NIP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value mem - 256 LDU // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _158 _157 - DROP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _94 - s8 s(-1) PUXC // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value src_addr _94 - NEQ // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value found - }>ELSE<{ - NIP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value found - }> - IFJMP:<{ // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - s9 s11 XCHG - 11 BLKDROP // s_addr query_id - 4 PUSHINT // s_addr query_id _98=4 - return_stake INLINECALLDICT - }> // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - s0 s1 PUSH2 // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value msg_value min_stake - LESS // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _100 - IFJMP:<{ // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - s9 s11 XCHG - 11 BLKDROP // s_addr query_id - 5 PUSHINT // s_addr query_id _101=5 - return_stake INLINECALLDICT - }> // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value - DUP // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value msg_value - 44 THROWIFNOT - ACCEPT - NOW // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake msg_value _107 - NEWC - ROT // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake _107 _108 msg_value - STGRAMS // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake _107 _109 - 32 STU // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor elect_at elect_close min_stake _111 - s1 s4 XCHG // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake min_stake elect_at elect_close max_factor _111 - 32 STU // s_addr members adnl_addr query_id ds src_addr validator_pubkey total_stake min_stake elect_at elect_close _113 - s1 s6 XCHG // s_addr members adnl_addr query_id ds elect_close validator_pubkey total_stake min_stake elect_at src_addr _113 - 256 STU // s_addr members adnl_addr query_id ds elect_close validator_pubkey total_stake min_stake elect_at _115 - s1 s8 XCHG // s_addr members elect_at query_id ds elect_close validator_pubkey total_stake min_stake adnl_addr _115 - 256 STU // s_addr members elect_at query_id ds elect_close validator_pubkey total_stake min_stake _117 - s0 s3 s8 XCHG3 - 8 PUSHPOW2 // s_addr total_stake elect_at query_id ds elect_close min_stake _117 validator_pubkey members _118=256 - DICTUSETB // s_addr total_stake elect_at query_id ds elect_close min_stake members - s4 s5 XCHG - s1 s3 s0 XCHG3 - s1 s6 XCHG - FALSE - FALSE // s_addr ds query_id elect_at elect_close min_stake total_stake members _120 _121 - pack_elect INLINECALLDICT // s_addr ds query_id elect - NEWC // s_addr ds query_id elect _123 - STDICT // s_addr ds query_id _124 - ROT // s_addr query_id _124 ds - STSLICER // s_addr query_id _125 - ENDC // s_addr query_id _126 - c4 POP - DUP // s_addr query_id query_id - IFJMP:<{ // s_addr query_id - 0 PUSHINT // s_addr query_id _128=0 - send_confirmation INLINECALLDICT - }> // s_addr query_id - 2DROP // - }> - unfreeze_without_bonuses PROCREF:<{ - // credits freeze_dict tot_stakes - 0 PUSHINT // credits freeze_dict tot_stakes _5=0 - DUP // credits freeze_dict tot_stakes total=0 recovered=0 - -1 PUSHINT // credits freeze_dict tot_stakes total=0 recovered=0 pubkey=-1 - UNTIL:<{ - s4 PUSH - 8 PUSHPOW2 // credits freeze_dict tot_stakes total recovered pubkey freeze_dict _10=256 - DICTUGETNEXT - NULLSWAPIFNOT2 // credits freeze_dict tot_stakes total recovered cs pubkey f - DUP // credits freeze_dict tot_stakes total recovered cs pubkey f f - IF:<{ // credits freeze_dict tot_stakes total recovered cs pubkey f - s0 s2 XCHG // credits freeze_dict tot_stakes total recovered f pubkey cs - 256 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 cs - 64 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 _42 _41 - NIP // credits freeze_dict tot_stakes total recovered f pubkey _16 cs - LDGRAMS // credits freeze_dict tot_stakes total recovered f pubkey _16 _22 cs - 1 LDI // credits freeze_dict tot_stakes total recovered f pubkey addr stake banned cs - ENDS - IF:<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake - NIP // credits freeze_dict tot_stakes total recovered f pubkey stake - s3 s3 XCPU // credits freeze_dict tot_stakes total stake f pubkey recovered stake - ADD // credits freeze_dict tot_stakes total stake f pubkey recovered - }>ELSE<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake - s8 s8 s8 XC2PU // stake freeze_dict tot_stakes total recovered f pubkey credits addr stake - ~credit_to INLINECALLDICT // stake freeze_dict tot_stakes total recovered f pubkey credits - s0 s7 XCHG - s0 s3 XCHG // credits freeze_dict tot_stakes total stake f pubkey recovered - }> - s4 s3 XCHG2 // credits freeze_dict tot_stakes pubkey recovered f total stake - ADD // credits freeze_dict tot_stakes pubkey recovered f total - s0 s3 XCHG // credits freeze_dict tot_stakes total recovered f pubkey - }>ELSE<{ - s2 POP // credits freeze_dict tot_stakes total recovered f pubkey - }> - SWAP // credits freeze_dict tot_stakes total recovered pubkey f - NOT // credits freeze_dict tot_stakes total recovered pubkey _32 - }> // credits freeze_dict tot_stakes total recovered pubkey - DROP - s3 POP // credits recovered tot_stakes total - SWAP // credits recovered total tot_stakes - EQUAL // credits recovered _34 - 59 THROWIFNOT - }> - unfreeze_with_bonuses PROCREF:<{ - // credits freeze_dict tot_stakes tot_bonuses - 0 PUSHINT // credits freeze_dict tot_stakes tot_bonuses _7=0 - s0 s0 PUSH2 // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 - -1 PUSHINT // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 pubkey=-1 - UNTIL:<{ - s6 PUSH - 8 PUSHPOW2 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey freeze_dict _12=256 - DICTUGETNEXT - NULLSWAPIFNOT2 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f - DUP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f f - IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f - s0 s2 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey cs - 256 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs - 64 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _52 _51 - NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs - LDGRAMS // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _24 cs - 1 LDI // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake banned cs - ENDS - IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake - NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey stake - s3 s3 XCPU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered stake - ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered - }>ELSE<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake - s7 s0 s8 PUSH3 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake tot_bonuses stake tot_stakes - MULDIV // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake bonus - s6 s6 XCPU // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses bonus - ADD // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses - s1 s6 PUXC // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake stake bonus - ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake _35 - s11 s11 s0 XCHG3 // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits addr _35 - ~credit_to INLINECALLDICT // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits - s0 s9 XCHG - s0 s3 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered - }> - s5 s3 XCHG2 // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total stake - ADD // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total - s0 s4 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey - }>ELSE<{ - s2 POP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey - }> - SWAP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey f - NOT // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey _38 - }> // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey - DROP - s5 POP // credits recovered tot_stakes tot_bonuses total returned_bonuses - s0 s3 XCHG // credits recovered returned_bonuses tot_bonuses total tot_stakes - EQUAL // credits recovered returned_bonuses tot_bonuses _40 - s2 s1 PUSH2 // credits recovered returned_bonuses tot_bonuses _40 returned_bonuses tot_bonuses - LEQ // credits recovered returned_bonuses tot_bonuses _40 _41 - AND // credits recovered returned_bonuses tot_bonuses _42 - 59 THROWIFNOT - s1 s2 XCHG // credits returned_bonuses recovered tot_bonuses - ADD // credits returned_bonuses _44 - SWAP // credits _44 returned_bonuses - SUB // credits _45 - }> - unfreeze_all PROCREF:<{ - // credits past_elections elect_id - SWAP - 32 PUSHINT // credits elect_id past_elections _6=32 - DICTUDELGET - NULLSWAPIFNOT // credits past_elections fs f - IFNOTJMP:<{ // credits past_elections fs - DROP // credits past_elections - 0 PUSHINT // credits past_elections _8=0 - }> // credits past_elections fs - unpack_past_election INLINECALLDICT // credits past_elections _30 _31 _32 _33 _34 _35 _36 - DROP - 3 3 BLKDROP2 // credits past_elections fdict tot_stakes bonuses - DUP // credits past_elections fdict tot_stakes bonuses bonuses - 0 GTINT // credits past_elections fdict tot_stakes bonuses _19 - IF:<{ // credits past_elections fdict tot_stakes bonuses - s3 s4 XCHG // past_elections credits fdict tot_stakes bonuses - unfreeze_with_bonuses INLINECALLDICT // past_elections credits _20 - }>ELSE<{ // credits past_elections fdict tot_stakes bonuses - DROP // credits past_elections fdict tot_stakes - s2 s3 XCHG // past_elections credits fdict tot_stakes - unfreeze_without_bonuses INLINECALLDICT // past_elections credits _20 - }> // past_elections credits unused_prizes - s1 s2 XCHG // credits past_elections unused_prizes - }> - config_set_confirmed PROCREF:<{ - // s_addr cs query_id ok - s2 POP // s_addr ok query_id - s0 s2 XCHG // query_id ok s_addr - REWRITESTDADDR // query_id ok src_wc src_addr - 0 PUSHINT // query_id ok src_wc src_addr _8=0 - CONFIGOPTPARAM // query_id ok src_wc src_addr _9 - CTOS // query_id ok src_wc src_addr _10 - 256 PLDU // query_id ok src_wc src_addr config_addr - c4 PUSH // query_id ok src_wc src_addr config_addr _14 - CTOS // query_id ok src_wc src_addr config_addr ds - LDDICT // query_id ok src_wc src_addr config_addr elect ds - s0 s4 XCHG // query_id ok ds src_addr config_addr elect src_wc - INC // query_id ok ds src_addr config_addr elect _20 - 2SWAP // query_id ok ds elect _20 src_addr config_addr - NEQ // query_id ok ds elect _20 _21 - OR // query_id ok ds elect _22 - OVER // query_id ok ds elect _22 elect - ISNULL // query_id ok ds elect _22 _23 - OR // query_id ok ds elect _24 - IFJMP:<{ // query_id ok ds elect - 4 BLKDROP // - }> // query_id ok ds elect - unpack_elect INLINECALLDICT // query_id ok ds _63 _64 _65 _66 _67 _68 _69 - 5 1 BLKDROP2 // query_id ok ds elect_at finished - s1 s4 PUXC // finished ok ds elect_at elect_at query_id - NEQ // finished ok ds elect_at _33 - s0 s4 XCHG // _33 ok ds elect_at finished - NOT // _33 ok ds elect_at _34 - s1 s4 XCHG // elect_at ok ds _33 _34 - OR // elect_at ok ds _35 - IFJMP:<{ // elect_at ok ds - 3 BLKDROP // - }> // elect_at ok ds - ACCEPT - SWAP // elect_at ds ok - IFNOT:<{ // elect_at ds - LDDICT // elect_at _40 ds - LDDICT // elect_at _40 _42 ds - LDGRAMS // elect_at credits past_elections grams ds - s3 s3 s4 XCHG3 // ds grams credits past_elections elect_at - unfreeze_all INLINECALLDICT // ds grams credits past_elections unused_prizes - FALSE // ds grams credits past_elections unused_prizes _48 - NEWC // ds grams credits past_elections unused_prizes _48 _49 - 1 STI // ds grams credits past_elections unused_prizes _51 - s1 s3 XCHG // ds grams unused_prizes past_elections credits _51 - STDICT // ds grams unused_prizes past_elections _52 - STDICT // ds grams unused_prizes _53 - -ROT // ds _53 grams unused_prizes - ADD // ds _53 _54 - STGRAMS // ds _55 - SWAP // _55 ds - STSLICER // _56 - ENDC // _57 - c4 POP - }>ELSE<{ - 2DROP // - }> - }> - process_simple_transfer PROCREF:<{ - // s_addr msg_value - load_data INLINECALLDICT // s_addr msg_value elect credits past_elections grams active_id active_hash - s0 s7 XCHG // active_hash msg_value elect credits past_elections grams active_id s_addr - REWRITESTDADDR // active_hash msg_value elect credits past_elections grams active_id src_wc src_addr - SWAP // active_hash msg_value elect credits past_elections grams active_id src_addr src_wc - INC // active_hash msg_value elect credits past_elections grams active_id src_addr _13 - OR // active_hash msg_value elect credits past_elections grams active_id _14 - OVER // active_hash msg_value elect credits past_elections grams active_id _14 active_id - 0 EQINT // active_hash msg_value elect credits past_elections grams active_id _14 _16 - OR // active_hash msg_value elect credits past_elections grams active_id _17 - IFJMP:<{ // active_hash msg_value elect credits past_elections grams active_id - s0 s5 XCHG // active_hash active_id elect credits past_elections grams msg_value - ADD // active_hash active_id elect credits past_elections grams - s3 s5 XCHG - 2 3 BLKSWAP // elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - }> // active_hash msg_value elect credits past_elections grams active_id - s0 s2 PUSH2 - 32 PUSHINT // active_hash msg_value elect credits past_elections grams active_id active_id past_elections _22=32 - DICTUGET - NULLSWAPIFNOT // active_hash msg_value elect credits past_elections grams active_id fs f - IF:<{ // active_hash msg_value elect credits past_elections grams active_id fs - unpack_past_election INLINECALLDICT // active_hash msg_value elect credits past_elections grams active_id unfreeze_at stake_held hash dict total_stake bonuses complaints - s0 s12 XCHG // active_hash complaints elect credits past_elections grams active_id unfreeze_at stake_held hash dict total_stake bonuses msg_value - ADD // active_hash complaints elect credits past_elections grams active_id unfreeze_at stake_held hash dict total_stake bonuses - 6 ROLL - s0 s11 XCHG // active_hash active_id elect credits past_elections grams unfreeze_at stake_held hash dict total_stake bonuses complaints - pack_past_election INLINECALLDICT // active_hash active_id elect credits past_elections grams _35 - s0 s5 s2 XCPUXC - 32 PUSHINT // active_hash active_id elect credits grams _35 active_id past_elections _36=32 - DICTUSETB // active_hash active_id elect credits grams past_elections - }>ELSE<{ // active_hash msg_value elect credits past_elections grams active_id fs - DROP // active_hash msg_value elect credits past_elections grams active_id - s0 s5 XCHG // active_hash active_id elect credits past_elections grams msg_value - ADD // active_hash active_id elect credits past_elections grams - SWAP // active_hash active_id elect credits grams past_elections - }> - s3 s5 XCHG - s1 s4 s3 XCHG3 // elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - }> - recover_stake PROCREF:<{ - // op s_addr cs query_id - NIP // op s_addr query_id - OVER // op s_addr query_id s_addr - REWRITESTDADDR // op s_addr query_id src_wc src_addr - SWAP // op s_addr query_id src_addr src_wc - INC // op s_addr query_id src_addr _8 - IFJMP:<{ // op s_addr query_id src_addr - DROP // op s_addr query_id - 4294967294 PUSHINT // op s_addr query_id _9=4294967294 - s0 s1 s3 XCHG3 - 0 PUSHINT - 64 PUSHINT // s_addr _9=4294967294 query_id op _10=0 _11=64 - send_message_back INLINECALLDICT - }> // op s_addr query_id src_addr - c4 PUSH // op s_addr query_id src_addr _14 - CTOS // op s_addr query_id src_addr ds - LDDICT // op s_addr query_id src_addr _18 ds - LDDICT // op s_addr query_id src_addr elect credits ds - s3 s3 XCHG2 - 8 PUSHPOW2 // op s_addr query_id ds elect src_addr credits _25=256 - DICTUDELGET - NULLSWAPIFNOT // op s_addr query_id ds elect credits cs f - IFNOTJMP:<{ // op s_addr query_id ds elect credits cs - 4 BLKDROP // op s_addr query_id - 4294967294 PUSHINT // op s_addr query_id _27=4294967294 - s0 s1 s3 XCHG3 - 0 PUSHINT - 64 PUSHINT // s_addr _27=4294967294 query_id op _28=0 _29=64 - send_message_back INLINECALLDICT - }> // op s_addr query_id ds elect credits cs - s6 POP // cs s_addr query_id ds elect credits - s0 s5 XCHG // credits s_addr query_id ds elect cs - LDGRAMS // credits s_addr query_id ds elect amount cs - ENDS - SWAP - NEWC // credits s_addr query_id ds amount elect _35 - STDICT // credits s_addr query_id ds amount _36 - s1 s5 XCHG // amount s_addr query_id ds credits _36 - STDICT // amount s_addr query_id ds _37 - SWAP // amount s_addr query_id _37 ds - STSLICER // amount s_addr query_id _38 - ENDC // amount s_addr query_id _39 - c4 POP - 4184830756 PUSHINT // amount s_addr query_id _41=4184830756 - 0 PUSHINT // amount s_addr query_id _41=4184830756 _42=0 - 24 PUSHINT // amount s_addr query_id _41=4184830756 _42=0 _43=24 - NEWC // amount s_addr query_id _41=4184830756 _42=0 _43=24 _44 - 6 STU // amount s_addr query_id _41=4184830756 _42=0 _46 - s0 s4 XCHG2 // amount _42=0 query_id _41=4184830756 _46 s_addr - STSLICER // amount _42=0 query_id _41=4184830756 _47 - s0 s4 XCHG2 // _41=4184830756 _42=0 query_id _47 amount - STGRAMS // _41=4184830756 _42=0 query_id _48 - s1 s2 XCHG // _41=4184830756 query_id _42=0 _48 - 107 STU // _41=4184830756 query_id _62 - s1 s2 XCHG // query_id _41=4184830756 _62 - 32 STU // query_id _64 - 64 STU // _66 - ENDC // _67 - 64 PUSHINT // _67 _68=64 - SENDRAWMSG - }> - after_code_upgrade PROC:<{ - // s_addr cs query_id - NIP // s_addr query_id - 1313042276 PUSHINT // s_addr query_id op=1313042276 - 3460525924 PUSHINT // s_addr query_id op=1313042276 _5=3460525924 - -ROT - 0 PUSHINT - 64 PUSHINT // s_addr _5=3460525924 query_id op=1313042276 _6=0 _7=64 - send_message_back INLINECALLDICT - }> - upgrade_code PROCREF:<{ - // s_addr cs query_id - 0 PUSHINT // s_addr cs query_id _4=0 - CONFIGOPTPARAM // s_addr cs query_id c_addr - DUP // s_addr cs query_id c_addr c_addr - ISNULL // s_addr cs query_id c_addr _6 - IFJMP:<{ // s_addr cs query_id c_addr - 4 BLKDROP // - FALSE // _7 - }> // s_addr cs query_id c_addr - CTOS // s_addr cs query_id _9 - 256 PLDU // s_addr cs query_id config_addr - s3 PUSH // s_addr cs query_id config_addr s_addr - REWRITESTDADDR // s_addr cs query_id config_addr src_wc src_addr - SWAP // s_addr cs query_id config_addr src_addr src_wc - INC // s_addr cs query_id config_addr src_addr _16 - s0 s2 XCHG // s_addr cs query_id _16 src_addr config_addr - NEQ // s_addr cs query_id _16 _17 - OR // s_addr cs query_id _18 - IFJMP:<{ // s_addr cs query_id - 3 BLKDROP // - FALSE // _19 - }> // s_addr cs query_id - ACCEPT - SWAP // s_addr query_id cs - LDREF // s_addr query_id code cs - OVER // s_addr query_id code cs code - SETCODE - DUP // s_addr query_id code cs cs - SEMPTY // s_addr query_id code cs _25 - IFNOT:<{ // s_addr query_id code cs - SWAP // s_addr query_id cs code - CTOS // s_addr query_id cs _26 - BLESS // s_addr query_id cs _27 - c3 POP - SWAP // s_addr cs query_id - after_code_upgrade CALLDICT - 0 THROW - }>ELSE<{ - 4 BLKDROP // - }> - TRUE // _32 - }> - register_complaint PROC:<{ - // s_addr complaint msg_value - s0 s2 XCHG // msg_value complaint s_addr - REWRITESTDADDR // msg_value complaint src_wc src_addr - SWAP // msg_value complaint src_addr src_wc - INC // msg_value complaint src_addr _7 - IFJMP:<{ // msg_value complaint src_addr - 3 BLKDROP // - -1 PUSHINT // _8=-1 - }> // msg_value complaint src_addr - OVER // msg_value complaint src_addr complaint - SDEPTH // msg_value complaint src_addr _9 - 7 PUSHPOW2 // msg_value complaint src_addr _9 _10=128 - GEQ // msg_value complaint src_addr _11 - IFJMP:<{ // msg_value complaint src_addr - 3 BLKDROP // - -3 PUSHINT // _12=-3 - }> // msg_value complaint src_addr - load_data INLINECALLDICT // msg_value complaint src_addr _131 _132 _133 _134 _135 _136 - s3 s5 XCHG - 5 BLKDROP // msg_value complaint src_addr past_elections - s0 s2 XCHG // msg_value past_elections src_addr complaint - 32 LDU // msg_value past_elections src_addr election_id complaint - s1 s3 PUSH2 - 32 PUSHINT // msg_value past_elections src_addr election_id complaint election_id past_elections _26=32 - DICTUGET - NULLSWAPIFNOT // msg_value past_elections src_addr election_id complaint fs f - IFNOTJMP:<{ // msg_value past_elections src_addr election_id complaint fs - 6 BLKDROP // - -2 PUSHINT // _28=-2 - }> // msg_value past_elections src_addr election_id complaint fs - DUP // msg_value past_elections src_addr election_id complaint fs fs - 32 PLDU // msg_value past_elections src_addr election_id complaint fs _31 - NOW // msg_value past_elections src_addr election_id complaint fs _31 _32 - SUB // msg_value past_elections src_addr election_id complaint fs expire_in - DUP // msg_value past_elections src_addr election_id complaint fs expire_in expire_in - 1 LESSINT // msg_value past_elections src_addr election_id complaint fs expire_in _35 - IFJMP:<{ // msg_value past_elections src_addr election_id complaint fs expire_in - 7 BLKDROP // - -4 PUSHINT // _36=-4 - }> // msg_value past_elections src_addr election_id complaint fs expire_in - s2 PUSH // msg_value past_elections src_addr election_id complaint fs expire_in complaint - unpack_complaint INLINECALLDICT // msg_value past_elections src_addr election_id complaint fs expire_in _141 _142 _143 _144 _145 _146 _147 _148 - 2 2 BLKDROP2 - s3 POP // msg_value past_elections reward_addr election_id complaint fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine - NOW // msg_value past_elections reward_addr election_id complaint fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at - get_complaint_prices INLINECALLDICT // msg_value past_elections reward_addr election_id complaint fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price cell_price - s0 s11 XCHG - 12 PUSHPOW2 // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price complaint _54=4096 - SDATASIZE // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price _152 _153 _154 - s2 POP // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price refs bits - 10 PUSHPOW2 // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price refs bits _57=1024 - ADD // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit bit_price refs _58 - ROT // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit refs _58 bit_price - MUL // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit refs _59 - SWAP // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit _59 refs - 2 ADDCONST // msg_value past_elections reward_addr election_id cell_price fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit _59 _61 - s0 s11 XCHG2 // msg_value past_elections reward_addr election_id _59 fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit _61 cell_price - MUL // msg_value past_elections reward_addr election_id _59 fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at deposit _62 - s1 s10 XCHG // msg_value past_elections reward_addr election_id deposit fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at _59 _62 - ADD // msg_value past_elections reward_addr election_id deposit fs expire_in validator_pubkey description suggested_fine_part severity suggested_fine created_at pps - s0 s7 XCHG2 // msg_value past_elections reward_addr election_id deposit fs created_at validator_pubkey description suggested_fine_part severity suggested_fine pps expire_in - MUL // msg_value past_elections reward_addr election_id deposit fs created_at validator_pubkey description suggested_fine_part severity suggested_fine _64 - s0 s8 XCHG2 // msg_value past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity _64 deposit - ADD // msg_value past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity paid - DUP - 30 PUSHPOW2 // msg_value past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity paid paid _68 - ADD // msg_value past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity paid _69 - s0 s12 XCHG2 // paid past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity _69 msg_value - LESS // paid past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity _70 - IFJMP:<{ // paid past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity - 11 BLKDROP // - -5 PUSHINT // _71=-5 - }> // paid past_elections reward_addr election_id suggested_fine fs created_at validator_pubkey description suggested_fine_part severity - s4 s0 s3 XC2PU - s9 s11 s7 XCPU2 - s7 PUSH // paid past_elections validator_pubkey election_id suggested_fine fs suggested_fine_part validator_pubkey description created_at severity reward_addr paid suggested_fine suggested_fine_part - pack_complaint INLINECALLDICT // paid past_elections validator_pubkey election_id suggested_fine fs suggested_fine_part _73 - ENDC // paid past_elections validator_pubkey election_id suggested_fine fs suggested_fine_part complaint - s0 s2 XCHG // paid past_elections validator_pubkey election_id suggested_fine complaint suggested_fine_part fs - unpack_past_election INLINECALLDICT // paid past_elections validator_pubkey election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses complaints - s11 s3 XCPU - 8 PUSHPOW2 // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses validator_pubkey frozen_dict _85=256 - DICTUGET - NULLSWAPIFNOT // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses fs f - IFNOTJMP:<{ // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses fs - 14 BLKDROP // - -6 PUSHINT // _87=-6 - }> // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses fs - 320 PUSHINT // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses fs _91 - SDSKIPFIRST // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses fs - LDGRAMS // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses _165 _164 - DROP // paid past_elections complaints election_id suggested_fine complaint suggested_fine_part unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses validator_stake - s0 s7 PUXC // paid past_elections complaints election_id suggested_fine complaint validator_stake unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses validator_stake suggested_fine_part - 32 MULRSHIFT# // paid past_elections complaints election_id suggested_fine complaint validator_stake unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses _100 - s1 s9 XCHG // paid past_elections complaints election_id bonuses complaint validator_stake unfreeze_at stake_held vset_hash frozen_dict total_stake suggested_fine _100 - ADD // paid past_elections complaints election_id bonuses complaint validator_stake unfreeze_at stake_held vset_hash frozen_dict total_stake fine - s0 s6 PUXC // paid past_elections complaints election_id bonuses complaint fine unfreeze_at stake_held vset_hash frozen_dict total_stake fine validator_stake - GREATER // paid past_elections complaints election_id bonuses complaint fine unfreeze_at stake_held vset_hash frozen_dict total_stake _102 - IFJMP:<{ // paid past_elections complaints election_id bonuses complaint fine unfreeze_at stake_held vset_hash frozen_dict total_stake - 12 BLKDROP // - -7 PUSHINT // _103=-7 - }> // paid past_elections complaints election_id bonuses complaint fine unfreeze_at stake_held vset_hash frozen_dict total_stake - s5 s11 XCPU // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict fine paid - LEQ // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict _104 - IFJMP:<{ // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict - 11 BLKDROP // - -8 PUSHINT // _105=-8 - }> // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict - PUSHNULL // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict _107 - 0 PUSHINT // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict _107 _108=0 - s0 s7 PUSH2 - 3 -ROLL // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict complaint _107 _108=0 _109=0 - pack_complaint_status INLINECALLDICT // paid past_elections complaints election_id bonuses complaint total_stake unfreeze_at stake_held vset_hash frozen_dict cstatus - s0 s6 XCHG // paid past_elections complaints election_id bonuses cstatus total_stake unfreeze_at stake_held vset_hash frozen_dict complaint - HASHCU // paid past_elections complaints election_id bonuses cstatus total_stake unfreeze_at stake_held vset_hash frozen_dict cpl_id - s6 s0 s9 XCHG3 - 8 PUSHPOW2 // paid past_elections frozen_dict election_id bonuses vset_hash total_stake unfreeze_at stake_held cstatus cpl_id complaints _114=256 - DICTUADDB // paid past_elections frozen_dict election_id bonuses vset_hash total_stake unfreeze_at stake_held complaints _113 - IFNOTJMP:<{ // paid past_elections frozen_dict election_id bonuses vset_hash total_stake unfreeze_at stake_held complaints - 10 BLKDROP // - -9 PUSHINT // _116=-9 - }> // paid past_elections frozen_dict election_id bonuses vset_hash total_stake unfreeze_at stake_held complaints - s6 s5 s0 XCHG3 - s3 s7 XCHG - s2 s7 XCHG // paid past_elections election_id unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses complaints - pack_past_election INLINECALLDICT // paid past_elections election_id _118 - s0 s2 XCHG - 32 PUSHINT // paid _118 election_id past_elections _119=32 - DICTUSETB // paid past_elections - load_data INLINECALLDICT // paid past_elections _168 _169 _170 _171 _172 _173 - s3 POP // paid past_elections elect credits active_hash grams active_id - s4 s5 XCHG - s3 s4 XCHG - ROT // paid elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - }> - punish PROCREF:<{ - // credits frozen complaint - CTOS // credits frozen _11 - unpack_complaint INLINECALLDICT // credits frozen _62 _63 _64 _65 _66 _67 _68 _69 - s4 POP - s4 POP - s4 POP // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr - s4 s5 PUSH2 - 8 PUSHPOW2 // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr validator_pubkey frozen _15=256 - DICTUGET - NULLSWAPIFNOT // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr cs f - IFNOTJMP:<{ // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr cs - 6 BLKDROP // credits frozen - 0 PUSHINT // credits frozen _17=0 - }> // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr cs - 256 LDU // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr _22 cs - 64 LDU // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr _22 _25 cs - LDGRAMS // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr _22 _25 _28 cs - 1 LDI // credits frozen validator_pubkey paid suggested_fine suggested_fine_part reward_addr addr weight stake banned cs - ENDS - s1 s5 PUXC // credits frozen validator_pubkey paid suggested_fine banned reward_addr addr weight stake stake suggested_fine_part - 32 MULRSHIFT# // credits frozen validator_pubkey paid suggested_fine banned reward_addr addr weight stake _38 - s1 s6 XCHG // credits frozen validator_pubkey paid stake banned reward_addr addr weight suggested_fine _38 - ADD // credits frozen validator_pubkey paid stake banned reward_addr addr weight _39 - s5 s(-1) PUXC // credits frozen validator_pubkey paid stake banned reward_addr addr weight stake _39 - MIN // credits frozen validator_pubkey paid stake banned reward_addr addr weight fine - s5 s5 XCPU // credits frozen validator_pubkey paid fine banned reward_addr addr weight stake fine - SUB // credits frozen validator_pubkey paid fine banned reward_addr addr weight stake - s0 s2 XCHG - NEWC // credits frozen validator_pubkey paid fine banned reward_addr stake weight addr _43 - 256 STU // credits frozen validator_pubkey paid fine banned reward_addr stake weight _45 - 64 STU // credits frozen validator_pubkey paid fine banned reward_addr stake _47 - SWAP // credits frozen validator_pubkey paid fine banned reward_addr _47 stake - STGRAMS // credits frozen validator_pubkey paid fine banned reward_addr _48 - s1 s2 XCHG // credits frozen validator_pubkey paid fine reward_addr banned _48 - 1 STI // credits frozen validator_pubkey paid fine reward_addr _50 - s0 s4 s5 XCHG3 - 8 PUSHPOW2 // credits fine reward_addr paid _50 validator_pubkey frozen _51=256 - DICTUSETB // credits fine reward_addr paid frozen - s3 PUSH // credits fine reward_addr paid frozen fine - 3 RSHIFT# // credits fine reward_addr paid frozen _55 - s0 s2 XCHG // credits fine reward_addr _55 frozen paid - 3 LSHIFT# // credits fine reward_addr _55 frozen _57 - s1 s2 XCHG // credits fine reward_addr frozen _55 _57 - MIN // credits fine reward_addr frozen reward - s3 s3 XCPU // credits reward reward_addr frozen fine reward - SUB // credits reward reward_addr frozen fine - s4 s4 s3 XCHG3 // frozen fine credits reward_addr reward - ~credit_to INLINECALLDICT // frozen fine credits - -ROT // credits frozen fine - }> - register_vote PROCREF:<{ - // complaints chash idx weight - s2 s3 PUSH2 - 8 PUSHPOW2 // complaints chash idx weight chash complaints _6=256 - DICTUGET - NULLSWAPIFNOT // complaints chash idx weight cstatus found? - IFNOTJMP:<{ // complaints chash idx weight cstatus - 4 BLKDROP // complaints - PUSHNULL // complaints _8 - -1 PUSHINT // complaints _8 _9=-1 - }> // complaints chash idx weight cstatus - get_current_vset INLINECALLDICT // complaints chash idx weight cstatus _53 _54 _55 - DROP // complaints chash idx weight cstatus cur_vset total_weight - SWAP // complaints chash idx weight cstatus total_weight cur_vset - HASHCU // complaints chash idx weight cstatus total_weight cur_vset_id - s0 s2 XCHG // complaints chash idx weight cur_vset_id total_weight cstatus - unpack_complaint_status INLINECALLDICT // complaints chash idx weight cur_vset_id total_weight complaint voters vset_id weight_remaining - s1 s5 PUSH2 // complaints chash idx weight cur_vset_id total_weight complaint voters vset_id weight_remaining vset_id cur_vset_id - NEQ // complaints chash idx weight cur_vset_id total_weight complaint voters vset_id weight_remaining _21 - IF:<{ // complaints chash idx weight cur_vset_id total_weight complaint voters vset_id weight_remaining - 3 BLKDROP // complaints chash idx weight vset_id total_weight complaint - PUSHNULL // complaints chash idx weight vset_id total_weight complaint voters - s0 s2 XCHG - 3 PUSHINT // complaints chash idx weight vset_id voters complaint total_weight _24=3 - 1 LSHIFT#DIV // complaints chash idx weight vset_id voters complaint weight_remaining - s0 s2 XCHG // complaints chash idx weight vset_id weight_remaining complaint voters - }>ELSE<{ - s4 POP - s4 POP // complaints chash idx weight vset_id weight_remaining complaint voters - }> - s5 s0 PUSH2 - 16 PUSHINT // complaints chash idx weight vset_id weight_remaining complaint voters idx voters _28=16 - DICTUGET - NULLSWAPIFNOT // complaints chash idx weight vset_id weight_remaining complaint voters _60 _61 - NIP // complaints chash idx weight vset_id weight_remaining complaint voters found? - IFJMP:<{ // complaints chash idx weight vset_id weight_remaining complaint voters - 7 BLKDROP // complaints - PUSHNULL // complaints _30 - 0 PUSHINT // complaints _30 _31=0 - }> // complaints chash idx weight vset_id weight_remaining complaint voters - NOW // complaints chash idx weight vset_id weight_remaining complaint voters _33 - NEWC // complaints chash idx weight vset_id weight_remaining complaint voters _33 _34 - 32 STU // complaints chash idx weight vset_id weight_remaining complaint voters _36 - s0 s6 s6 XCHG3 - 16 PUSHINT // complaints chash complaint weight vset_id weight_remaining _36 idx voters _37=16 - DICTUSETB // complaints chash complaint weight vset_id weight_remaining voters - s0 s0 s3 XCPUXC // complaints chash complaint old_wr vset_id voters weight_remaining weight - SUB // complaints chash complaint old_wr vset_id voters weight_remaining - s3 s3 XCPU // complaints chash complaint weight_remaining vset_id voters old_wr weight_remaining - XOR // complaints chash complaint weight_remaining vset_id voters old_wr - s4 PUSH - s3 s3 XCHG2 - s0 s4 XCHG // complaints chash complaint old_wr complaint voters vset_id weight_remaining - pack_complaint_status INLINECALLDICT // complaints chash complaint old_wr _43 - s0 s3 s4 XCHG3 - 8 PUSHPOW2 // complaint old_wr _43 chash complaints _44=256 - DICTUSETB // complaint old_wr complaints - SWAP // complaint complaints old_wr - -1 GTINT // complaint complaints _47 - IFJMP:<{ // complaint complaints - NIP // complaints - PUSHNULL // complaints _48 - 1 PUSHINT // complaints _48 _49=1 - }> // complaint complaints - SWAP - 2 PUSHINT // complaints complaint _50=2 - }> - proceed_register_vote PROCREF:<{ - // election_id chash idx weight - load_data INLINECALLDICT // election_id chash idx weight elect credits past_elections grams active_id active_hash - s9 s3 PUSH2 - 32 PUSHINT // election_id chash idx weight elect credits past_elections grams active_id active_hash election_id past_elections _13=32 - DICTUGET - NULLSWAPIFNOT // election_id chash idx weight elect credits past_elections grams active_id active_hash _43 _44 - s11 POP // f chash idx weight elect credits past_elections grams active_id active_hash fs - s0 s10 XCHG // fs chash idx weight elect credits past_elections grams active_id active_hash f - IFNOTJMP:<{ // fs chash idx weight elect credits past_elections grams active_id active_hash - 10 BLKDROP // - -2 PUSHINT // _15=-2 - }> // fs chash idx weight elect credits past_elections grams active_id active_hash - s0 s9 XCHG // active_hash chash idx weight elect credits past_elections grams active_id fs - unpack_past_election INLINECALLDICT // active_hash chash idx weight elect credits past_elections grams active_id _45 _46 _47 _48 _49 _50 _51 - s4 POP - 2DROP - 2 2 BLKDROP2 // active_hash chash idx weight elect credits past_elections grams active_id complaints frozen_dict - s9 s3 s7 XCHG3 - s1 s8 XCHG // active_hash active_id grams frozen_dict elect credits past_elections complaints chash idx weight - register_vote INLINECALLDICT // active_hash active_id grams frozen_dict elect credits past_elections _52 _53 _54 - s2 POP // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint - OVER // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint status - 1 LESSINT // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint _28 - IFJMP:<{ // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint - s1 s8 XCHG - 8 BLKDROP // status - }> // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint - DUP // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint accepted_complaint - ISNULL // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint _29 - IFNOT:<{ // active_hash active_id grams frozen_dict elect credits past_elections status accepted_complaint - s3 s5 s0 XCHG3 // active_hash active_id grams status elect past_elections credits frozen_dict accepted_complaint - punish INLINECALLDICT // active_hash active_id grams status elect past_elections _55 _56 _57 - NIP // active_hash active_id grams status elect past_elections credits fine - s1 s5 XCHG // active_hash active_id credits status elect past_elections grams fine - ADD // active_hash active_id credits status elect past_elections grams - s4 s4 XCHG2 // active_hash active_id grams status elect credits past_elections - }>ELSE<{ - DROP - s4 POP // active_hash active_id grams status elect credits past_elections - }> - s5 s1 s3 XCHG3 - s4 s4 s6 XCHG3 // status elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - }> - recv_internal PROC:<{ - // msg_value in_msg_cell in_msg - SWAP // msg_value in_msg in_msg_cell - CTOS // msg_value in_msg cs - 4 LDU // msg_value in_msg flags cs - SWAP - 1 PUSHINT // msg_value in_msg cs flags _9=1 - AND // msg_value in_msg cs _10 - IFJMP:<{ // msg_value in_msg cs - 3 BLKDROP // - }> // msg_value in_msg cs - LDMSGADDR // msg_value in_msg _123 _122 - DROP // msg_value in_msg s_addr - OVER // msg_value in_msg s_addr in_msg - SEMPTY // msg_value in_msg s_addr _14 - IFJMP:<{ // msg_value in_msg s_addr - NIP // msg_value s_addr - SWAP // s_addr msg_value - process_simple_transfer INLINECALLDICT - }> // msg_value in_msg s_addr - SWAP // msg_value s_addr in_msg - 32 LDU // msg_value s_addr op in_msg - OVER // msg_value s_addr op in_msg op - 0 EQINT // msg_value s_addr op in_msg _21 - IFJMP:<{ // msg_value s_addr op in_msg - 2DROP // msg_value s_addr - SWAP // s_addr msg_value - process_simple_transfer INLINECALLDICT - }> // msg_value s_addr op in_msg - 64 LDU // msg_value s_addr op query_id in_msg - s2 PUSH - 1316189259 PUSHINT // msg_value s_addr op query_id in_msg op _27=1316189259 - EQUAL // msg_value s_addr op query_id in_msg _28 - IFJMP:<{ // msg_value s_addr op query_id in_msg - s2 POP // msg_value s_addr in_msg query_id - s2 s3 XCHG // s_addr msg_value in_msg query_id - process_new_stake INLINECALLDICT - }> // msg_value s_addr op query_id in_msg - s2 PUSH - 1197831204 PUSHINT // msg_value s_addr op query_id in_msg op _30=1197831204 - EQUAL // msg_value s_addr op query_id in_msg _31 - IFJMP:<{ // msg_value s_addr op query_id in_msg - s4 POP // in_msg s_addr op query_id - s1 s3 XCHG // op s_addr in_msg query_id - recover_stake INLINECALLDICT - }> // msg_value s_addr op query_id in_msg - s2 PUSH - 1313042276 PUSHINT // msg_value s_addr op query_id in_msg op _33=1313042276 - EQUAL // msg_value s_addr op query_id in_msg _34 - IFJMP:<{ // msg_value s_addr op query_id in_msg - s4 POP // in_msg s_addr op query_id - s2 s3 s3 PUXCPU // query_id s_addr op s_addr in_msg query_id - upgrade_code INLINECALLDICT // query_id s_addr op ok - IF:<{ // query_id s_addr op - 3460525924 PUSHINT // query_id s_addr op _37=3460525924 - }>ELSE<{ // query_id s_addr op - 32 PUSHPOW2DEC // query_id s_addr op _37=4294967295 - }> - s0 s3 s3 XCHG3 - 0 PUSHINT - 64 PUSHINT // s_addr _37 query_id op _40=0 _41=64 - send_message_back INLINECALLDICT - }> // msg_value s_addr op query_id in_msg - s2 PUSH - 4000730955 PUSHINT // msg_value s_addr op query_id in_msg op _44=4000730955 - EQUAL // msg_value s_addr op query_id in_msg cfg_ok - s3 PUSH - 4000730991 PUSHINT // msg_value s_addr op query_id in_msg cfg_ok op _46=4000730991 - EQUAL // msg_value s_addr op query_id in_msg cfg_ok _47 - s1 s(-1) PUXC // msg_value s_addr op query_id in_msg cfg_ok cfg_ok _47 - OR // msg_value s_addr op query_id in_msg cfg_ok _48 - IFJMP:<{ // msg_value s_addr op query_id in_msg cfg_ok - s3 POP - s4 POP // in_msg s_addr cfg_ok query_id - s3 s0 s0 XCHG3 // s_addr in_msg query_id cfg_ok - config_set_confirmed INLINECALLDICT - }> // msg_value s_addr op query_id in_msg cfg_ok - DROP // msg_value s_addr op query_id in_msg - s2 PUSH - 1382499184 PUSHINT // msg_value s_addr op query_id in_msg op _50=1382499184 - EQUAL // msg_value s_addr op query_id in_msg _51 - IFJMP:<{ // msg_value s_addr op query_id in_msg - s3 s0 s4 PUXC2 // query_id s_addr op s_addr in_msg msg_value - register_complaint CALLDICT // query_id s_addr op price - 64 PUSHINT // query_id s_addr op price mode=64 - OVER // query_id s_addr op price mode=64 price - NEGATE // query_id s_addr op price mode=64 ans_tag - s2 PUSH // query_id s_addr op price mode=64 ans_tag price - -1 GTINT // query_id s_addr op price mode=64 ans_tag _59 - IF:<{ // query_id s_addr op price mode=64 ans_tag - 2DROP // query_id s_addr op price - 4 PUSHINT // query_id s_addr op price _60=4 - RAWRESERVE - 0 PUSHINT // query_id s_addr op ans_tag=0 - 7 PUSHPOW2 // query_id s_addr op ans_tag=0 mode=128 - }>ELSE<{ - s2 POP // query_id s_addr op ans_tag mode - }> - SWAP - 4066861904 PUSHINT // query_id s_addr op mode ans_tag _64=4066861904 - ADD // query_id s_addr op mode _65 - s0 s3 XCHG - s4 s4 s4 XCHG3 - 0 PUSHINT - SWAP // s_addr _65 query_id op _66=0 mode - send_message_back INLINECALLDICT - }> // msg_value s_addr op query_id in_msg - s4 POP // in_msg s_addr op query_id - OVER - 1450460016 PUSHINT // in_msg s_addr op query_id op _68=1450460016 - EQUAL // in_msg s_addr op query_id _69 - IFJMP:<{ // in_msg s_addr op query_id - s0 s3 XCHG - 9 PUSHPOW2 // query_id s_addr op in_msg _72=512 - LDSLICEX // query_id s_addr op signature in_msg - DUP // query_id s_addr op signature msg_body in_msg - 32 LDU // query_id s_addr op signature msg_body _79 in_msg - 16 LDU // query_id s_addr op signature msg_body _79 _82 in_msg - 32 LDU // query_id s_addr op signature msg_body _79 _82 _85 in_msg - 256 LDU // query_id s_addr op signature msg_body sign_tag idx elect_id chash in_msg - ENDS - s0 s3 XCHG - 1450459984 PUSHINT // query_id s_addr op signature msg_body chash idx elect_id sign_tag _93=1450459984 - EQUAL // query_id s_addr op signature msg_body chash idx elect_id _94 - 37 THROWIFNOT - OVER // query_id s_addr op signature msg_body chash idx elect_id idx - get_validator_descr INLINECALLDICT // query_id s_addr op signature msg_body chash idx elect_id _138 _139 - DROP // query_id s_addr op signature msg_body chash idx elect_id vdescr - unpack_validator_descr INLINECALLDICT // query_id s_addr op signature msg_body chash idx elect_id val_pubkey weight - s5 s6 s6 XCHG3 // query_id s_addr op weight elect_id chash idx msg_body signature val_pubkey - CHKSIGNS // query_id s_addr op weight elect_id chash idx _103 - 34 THROWIFNOT - 3 ROLL // query_id s_addr op elect_id chash idx weight - proceed_register_vote INLINECALLDICT // query_id s_addr op res - 3597947456 PUSHINT // query_id s_addr op res _107=3597947456 - ADD // query_id s_addr op _108 - s0 s3 s3 XCHG3 - 0 PUSHINT - 64 PUSHINT // s_addr _108 query_id op _109=0 _110=64 - send_message_back INLINECALLDICT - }> // in_msg s_addr op query_id - s3 POP // query_id s_addr op - DUP - 31 PUSHPOW2 // query_id s_addr op op _114 - AND // query_id s_addr op _115 - IFNOTJMP:<{ // query_id s_addr op - 32 PUSHPOW2DEC // query_id s_addr op _116=4294967295 - s0 s3 s3 XCHG3 - 0 PUSHINT - 64 PUSHINT // s_addr _116=4294967295 query_id op _117=0 _118=64 - send_message_back INLINECALLDICT - }> // query_id s_addr op - 3 BLKDROP // - }> - postpone_elections PROC:<{ - // - FALSE // _0 - }> - compute_total_stake PROCREF:<{ - // l n m_stake - 0 PUSHINT // l n m_stake tot_stake=0 - s0 s2 XCHG // l tot_stake=0 m_stake n - REPEAT:<{ // l tot_stake m_stake - s0 s2 XCHG // m_stake tot_stake l - UNCONS // m_stake tot_stake h l - OVER // m_stake tot_stake h l h - 0 INDEX // m_stake tot_stake h l stake - s0 s2 XCHG // m_stake tot_stake stake l h - 1 INDEX // m_stake tot_stake stake l max_f - s4 PUSH // m_stake tot_stake stake l max_f m_stake - MUL // m_stake tot_stake stake l _13 - 16 RSHIFT# // m_stake tot_stake stake l _15 - s1 s2 XCHG // m_stake tot_stake l stake _15 - MIN // m_stake tot_stake l stake - s1 s2 XCHG // m_stake l tot_stake stake - ADD // m_stake l tot_stake - ROT // l tot_stake m_stake - }> - DROP - NIP // tot_stake - }> - try_elect PROC:<{ - // credits members min_stake max_stake min_total_stake max_stake_factor - 16 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor _7=16 - CONFIGOPTPARAM // credits members min_stake max_stake min_total_stake max_stake_factor _8 - CTOS // credits members min_stake max_stake min_total_stake max_stake_factor cs - 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor _13 cs - 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor _13 _256 _255 - NIP // credits members min_stake max_stake min_total_stake max_stake_factor _13 cs - 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators cs - ENDS - 1 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators _23=1 - MAX // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators - 0 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 - NEWDICT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 sdict - -1 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 sdict pubkey=-1 - UNTIL:<{ - s9 PUSH - 8 PUSHPOW2 // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey members _33=256 - DICTUGETNEXT - NULLSWAPIFNOT2 // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f - DUP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f f - IF:<{ // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f - s0 s2 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey cs - LDGRAMS // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 cs - 32 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 cs - 32 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 _45 cs - 256 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 _45 _48 cs - 256 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake time max_factor addr adnl_addr cs - ENDS - s0 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake adnl_addr max_factor addr time - NEGATE // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake adnl_addr max_factor addr _56 - s0 s4 XCHG - NEWC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _56 adnl_addr max_factor addr stake _57 - 128 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _56 adnl_addr max_factor addr _59 - s1 s4 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _56 _59 - 32 STI // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _61 - s4 s(-1) PUXC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor pubkey _61 - 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _63 - ENDC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _64 - CTOS // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor key - s1 s10 XCPU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key max_factor max_stake_factor - MIN // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _67 - NEWC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _67 _68 - 32 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _70 - s1 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key adnl_addr addr _70 - 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key adnl_addr _72 - 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key _74 - s0 s1 s4 XCHG3 - 416 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n pubkey f _74 key sdict _79 - DICTSETB // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n pubkey f sdict - s0 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey f n - INC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey f n - s3 s1 s3 XCHG3 // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey - }>ELSE<{ - s2 POP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey - }> - SWAP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey f - NOT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey _83 - }> // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey - DROP - s4 POP // credits members min_stake max_stake min_total_stake sdict max_validators min_validators n - ROT // credits members min_stake max_stake min_total_stake sdict min_validators n max_validators - MIN // credits members min_stake max_stake min_total_stake sdict min_validators n - s0 s1 PUSH2 // credits members min_stake max_stake min_total_stake sdict min_validators n n min_validators - LESS // credits members min_stake max_stake min_total_stake sdict min_validators n _85 - IFJMP:<{ // credits members min_stake max_stake min_total_stake sdict min_validators n - 7 BLKDROP // credits - NEWDICT // credits _86 - 0 PUSHINT // credits _86 _87=0 - NEWDICT // credits _86 _87=0 _88 - s1 s1 PUSH2 // credits _86 _87=0 _88 _89=0 _90=0 - }> // credits members min_stake max_stake min_total_stake sdict min_validators n - PUSHNULL // credits members min_stake max_stake min_total_stake sdict min_validators n l - UNTIL:<{ - s0 s3 XCHG - 416 PUSHINT // credits members min_stake max_stake min_total_stake l min_validators n sdict _101 - DICTREMMIN - NULLSWAPIFNOT2 // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f - DUP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f f - IF:<{ // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f - SWAP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key - 128 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _106 key - s1 s9 XCPU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _106 max_stake - MIN // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _109 - SWAP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 key - 32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 _282 _281 - NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 key - 256 PLDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f stake pubkey - s0 s3 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake cs - 32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 cs - 256 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 _286 _285 - NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 cs - 256 PLDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake max_f adnl_addr - s1 s3 s0 XCHG3 - s1 s4 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict f stake max_f pubkey adnl_addr - 4 TUPLE // credits members min_stake max_stake min_total_stake l min_validators n sdict f _126 - s0 s5 XCHG2 // credits members min_stake max_stake min_total_stake f min_validators n sdict _126 l - CONS // credits members min_stake max_stake min_total_stake f min_validators n sdict l - s0 s4 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict f - }>ELSE<{ - 2 1 BLKDROP2 // credits members min_stake max_stake min_total_stake l min_validators n sdict f - }> - NOT // credits members min_stake max_stake min_total_stake l min_validators n sdict _128 - s1 s4 XCHG // credits members min_stake max_stake min_total_stake sdict min_validators n l _128 - }> // credits members min_stake max_stake min_total_stake sdict min_validators n l - s3 POP - s4 POP // credits members min_stake n min_total_stake l min_validators - DEC // credits members min_stake n min_total_stake l i - 2DUP // credits members min_stake n min_total_stake l i l1 i - REPEAT:<{ // credits members min_stake n min_total_stake l i l1 - CDR // credits members min_stake n min_total_stake l i l1 - }> - 0 PUSHINT // credits members min_stake n min_total_stake l i l1 _136=0 - DUP // credits members min_stake n min_total_stake l i l1 best_stake=0 m=0 - UNTIL:<{ - s0 s2 XCHG // credits members min_stake n min_total_stake l i m best_stake l1 - UNCONS // credits members min_stake n min_total_stake l i m best_stake _139 l1 - SWAP // credits members min_stake n min_total_stake l i m best_stake l1 _139 - 0 INDEX // credits members min_stake n min_total_stake l i m best_stake l1 stake - s0 s4 XCHG // credits members min_stake n min_total_stake l stake m best_stake l1 i - INC // credits members min_stake n min_total_stake l stake m best_stake l1 i - s4 s8 PUSH2 // credits members min_stake n min_total_stake l stake m best_stake l1 i stake min_stake - GEQ // credits members min_stake n min_total_stake l stake m best_stake l1 i _145 - IF:<{ // credits members min_stake n min_total_stake l stake m best_stake l1 i - s5 s(-1) s4 PU2XC // credits members min_stake n min_total_stake l i m best_stake l1 l i stake - compute_total_stake INLINECALLDICT // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake - s0 s2 PUSH2 // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake tot_stake best_stake - GREATER // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake _148 - IF:<{ // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake - 2 2 BLKDROP2 // credits members min_stake n min_total_stake l i l1 tot_stake - s2 PUSH // credits members min_stake n min_total_stake l i l1 best_stake m - s0 s2 XCHG // credits members min_stake n min_total_stake l i m best_stake l1 - }>ELSE<{ - DROP // credits members min_stake n min_total_stake l i m best_stake l1 - }> - }>ELSE<{ - s4 POP // credits members min_stake n min_total_stake l i m best_stake l1 - }> - s3 s6 PUSH2 // credits members min_stake n min_total_stake l i m best_stake l1 i n - GEQ // credits members min_stake n min_total_stake l i m best_stake l1 _149 - s1 s3 XCHG // credits members min_stake n min_total_stake l i l1 best_stake m _149 - }> // credits members min_stake n min_total_stake l i l1 best_stake m - s6 POP - s6 POP - 2DROP // credits members best_stake m min_total_stake l - s2 PUSH // credits members best_stake m min_total_stake l m - 0 EQINT // credits members best_stake m min_total_stake l _151 - s4 s2 PUXC // credits members best_stake m _151 l best_stake min_total_stake - LESS // credits members best_stake m _151 l _152 - s1 s2 XCHG // credits members best_stake m l _151 _152 - OR // credits members best_stake m l _153 - IFJMP:<{ // credits members best_stake m l - 4 BLKDROP // credits - NEWDICT // credits _154 - 0 PUSHINT // credits _154 _155=0 - NEWDICT // credits _154 _155=0 _156 - s1 s1 PUSH2 // credits _154 _155=0 _156 _157=0 _158=0 - }> // credits members best_stake m l - s0 s1 PUSH2 // credits members best_stake m l l1 m - DEC // credits members best_stake m l l1 _161 - REPEAT:<{ // credits members best_stake m l l1 - CDR // credits members best_stake m l l1 - }> - CAR // credits members best_stake m l _164 - 0 INDEX // credits members best_stake m l m_stake - 0 PUSHINT // credits members best_stake m l m_stake i=0 - s0 s0 PUSH2 // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=0 - NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=0 vset - NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=0 vset frozen - UNTIL:<{ - s0 s6 XCHG // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l - UNCONS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset _181 l - SWAP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l _181 - 4 UNTUPLE // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr - s1 s13 PUSH2 - 8 PUSHPOW2 // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr pubkey members _186=256 - DICTUGET - NULLSWAPIFNOT // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr val f - 61 THROWIFNOT - LDGRAMS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr _298 _297 - NIP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr val - 64 LDU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr _300 _299 - NIP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr val - 256 PLDU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr - s9 s12 PUSH2 // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr i m - LESS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr _200 - IF:<{ // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr - s3 s10 XCPU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr max_f m_stake - MUL // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr _202 - 16 RSHIFT# // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr _204 - s4 s(-1) PUXC // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr stake _204 - MIN // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr true_stake - s4 s4 XCPU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake true_stake - SUB // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake - s4 PUSH // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake true_stake - 60 LSHIFT# // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake _209 - s14 PUSH // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake _209 best_stake - DIV // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake weight - s9 s5 XCPU // credits members best_stake m frozen m_stake i weight tot_weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake true_stake - ADD // credits members best_stake m frozen m_stake i weight tot_weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake - s8 s9 XCPU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight weight - ADD // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight - 2390828938 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 - s3 PUSH // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 adnl_addr - IF:<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 - 115 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 _215=115 - }>ELSE<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 - 83 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 _215=83 - }> - NEWC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 _215 _218 - 8 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _214=2390828938 _220 - 32 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _222 - s4 s(-1) PUXC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight pubkey _222 - 256 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _224 - s10 s(-1) PUXC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight weight _224 - 64 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo - s3 PUSH // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo adnl_addr - IF:<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo - s1 s3 XCHG // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey tot_weight stake adnl_addr vinfo - 256 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey tot_weight stake vinfo - s0 s2 XCHG // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey vinfo stake tot_weight - }>ELSE<{ - s3 POP // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey vinfo stake tot_weight - }> - s2 s10 s7 XCPUXC - 16 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake tot_weight l true_stake src_addr pubkey stake vinfo i vset _231=16 - DICTUSETB // credits members best_stake m frozen m_stake i weight tot_stake tot_weight l true_stake src_addr pubkey stake vset - FALSE // credits members best_stake m frozen m_stake i weight tot_stake tot_weight l true_stake src_addr pubkey stake vset _234 - s4 PUSH - NEWC // credits members best_stake m frozen m_stake i weight tot_stake tot_weight l true_stake src_addr pubkey stake vset _234 src_addr _235 - 256 STU // credits members best_stake m frozen m_stake i weight tot_stake tot_weight l true_stake src_addr pubkey stake vset _234 _237 - s1 s10 XCHG // credits members best_stake m frozen m_stake i _234 tot_stake tot_weight l true_stake src_addr pubkey stake vset weight _237 - 64 STU // credits members best_stake m frozen m_stake i _234 tot_stake tot_weight l true_stake src_addr pubkey stake vset _239 - s0 s5 XCHG2 // credits members best_stake m frozen m_stake i _234 tot_stake tot_weight l vset src_addr pubkey stake _239 true_stake - STGRAMS // credits members best_stake m frozen m_stake i _234 tot_stake tot_weight l vset src_addr pubkey stake _240 - s1 s8 XCHG // credits members best_stake m frozen m_stake i stake tot_stake tot_weight l vset src_addr pubkey _234 _240 - 1 STI // credits members best_stake m frozen m_stake i stake tot_stake tot_weight l vset src_addr pubkey _242 - s0 s1 s10 XCHG3 - 8 PUSHPOW2 // credits members best_stake m src_addr m_stake i stake tot_stake tot_weight l vset _242 pubkey frozen _243=256 - DICTUSETB // credits members best_stake m src_addr m_stake i stake tot_stake tot_weight l vset frozen - s0 s8 XCHG - s4 s5 XCHG - s1 s3 XCHG - s1 s4 XCHG // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr - }>ELSE<{ - 3 1 BLKDROP2 // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr - }> - OVER // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr stake - IF:<{ // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr - s12 s0 s0 XCHG3 // l members best_stake m frozen m_stake i tot_stake tot_weight vset credits src_addr stake - ~credit_to INLINECALLDICT // l members best_stake m frozen m_stake i tot_stake tot_weight vset credits - s0 s10 XCHG // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l - }>ELSE<{ - 2DROP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l - }> - s0 s4 XCHG // credits members best_stake m frozen m_stake l tot_stake tot_weight vset i - INC // credits members best_stake m frozen m_stake l tot_stake tot_weight vset i - s4 PUSH // credits members best_stake m frozen m_stake l tot_stake tot_weight vset i l - ISNULL // credits members best_stake m frozen m_stake l tot_stake tot_weight vset i _249 - s1 s5 XCHG - s1 s7 XCHG // credits members best_stake m l m_stake i tot_stake tot_weight vset frozen _249 - }> // credits members best_stake m l m_stake i tot_stake tot_weight vset frozen - s4 POP - s4 POP - s4 POP - s6 POP // credits tot_stake best_stake m tot_weight vset frozen - s5 s4 PUXC // credits tot_stake frozen m tot_weight vset tot_stake best_stake - EQUAL // credits tot_stake frozen m tot_weight vset _251 - 49 THROWIFNOT - s4 s4 XCHG2 - s3 s1 s3 XCHG3 // credits vset tot_weight frozen tot_stake m - }> - conduct_elections PROC:<{ - // ds elect credits - SWAP // ds credits elect - unpack_elect INLINECALLDICT // ds credits _121 _122 _123 _124 _125 _126 _127 - s4 POP // ds credits elect_at elect_close finished total_stake members failed - NOW // ds credits elect_at elect_close finished total_stake members failed _11 - s5 PUSH // ds credits elect_at elect_close finished total_stake members failed _11 elect_close - LESS // ds credits elect_at elect_close finished total_stake members failed _12 - IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed - 8 BLKDROP // - FALSE // _13 - }> // ds credits elect_at elect_close finished total_stake members failed - 0 PUSHINT // ds credits elect_at elect_close finished total_stake members failed _14=0 - CONFIGOPTPARAM // ds credits elect_at elect_close finished total_stake members failed _15 - ISNULL // ds credits elect_at elect_close finished total_stake members failed _16 - IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed - 8 BLKDROP // - postpone_elections CALLDICT // _17 - }> // ds credits elect_at elect_close finished total_stake members failed - 17 PUSHINT // ds credits elect_at elect_close finished total_stake members failed _19=17 - CONFIGOPTPARAM // ds credits elect_at elect_close finished total_stake members failed _20 - CTOS // ds credits elect_at elect_close finished total_stake members failed cs - LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake cs - LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake cs - LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake cs - 32 LDU // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor cs - ENDS - s6 s1 PUSH2 // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor total_stake min_total_stake - LESS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor _35 - IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor - 12 BLKDROP // - postpone_elections CALLDICT // _36 - }> // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor - s0 s4 XCHG // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake failed - IFJMP:<{ // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake - 11 BLKDROP // - postpone_elections CALLDICT // _37 - }> // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake - s0 s6 XCHG // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake finished - IFJMP:<{ // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake - 10 BLKDROP // - FALSE // _38 - }> // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake - s3 PUSH - s4 s9 XCHG - s3 s2 XCPU - s7 s7 XCHG2 // ds members elect_at elect_close min_stake total_stake credits members min_stake max_stake min_total_stake max_stake_factor - try_elect CALLDICT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt - DUP // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt cnt - 0 EQINT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed - DUP // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed failed - NOT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed finished - s11 PUSH - s0 s6 XCHG - s5 s11 XCHG - s4 s10 XCHG - s3 s9 XCHG - s13 s13 s13 XCHG3 // ds total_weight elect_at frozen total_stakes cnt credits vdict elect_at elect_close min_stake total_stake members failed finished - pack_elect INLINECALLDICT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect - s3 PUSH // ds total_weight elect_at frozen total_stakes cnt credits vdict elect cnt - IFNOTJMP:<{ // ds total_weight elect_at frozen total_stakes cnt credits vdict elect - NIP - 5 2 BLKDROP2 - NEWC // ds credits elect _49 - STDICT // ds credits _50 - STDICT // ds _51 - SWAP // _51 ds - STSLICER // _52 - ENDC // _53 - c4 POP - postpone_elections CALLDICT // _55 - }> // ds total_weight elect_at frozen total_stakes cnt credits vdict elect - get_validator_conf CALLDICT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect _142 _143 _144 _145 - s2 POP // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held elect_end_before - NOW // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held elect_end_before _62 - SWAP // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _62 elect_end_before - ADD // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _63 - -60 ADDCONST // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _65 - s9 PUSH // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _65 elect_at - MAX // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start - 16 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _68=16 - CONFIGOPTPARAM // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _69 - CTOS // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _70 - 16 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _70 _71=16 - SDSKIPFIRST // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _72 - 16 PLDU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start main_validators - s7 s(-1) PUXC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start cnt main_validators - MIN // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 - s1 s3 PUSH2 // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 start elect_for - ADD // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 - 18 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _78=18 - NEWC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _78=18 _79 - 8 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _81 - s3 s(-1) PUXC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 start _81 - 32 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _83 - 32 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _85 - s1 s8 XCHG // ds total_weight elect_at frozen total_stakes _76 credits vdict elect elect_for stake_held start cnt _85 - 16 STU // ds total_weight elect_at frozen total_stakes _76 credits vdict elect elect_for stake_held start _87 - s1 s7 XCHG // ds total_weight elect_at frozen total_stakes start credits vdict elect elect_for stake_held _76 _87 - 16 STU // ds total_weight elect_at frozen total_stakes start credits vdict elect elect_for stake_held _89 - s1 s10 XCHG // ds stake_held elect_at frozen total_stakes start credits vdict elect elect_for total_weight _89 - 64 STU // ds stake_held elect_at frozen total_stakes start credits vdict elect elect_for _91 - s1 s3 XCHG // ds stake_held elect_at frozen total_stakes start credits elect_for elect vdict _91 - STDICT // ds stake_held elect_at frozen total_stakes start credits elect_for elect _92 - ENDC // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset - 0 PUSHINT // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _95=0 - CONFIGOPTPARAM // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _96 - CTOS // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _97 - 256 PLDU // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset config_addr - s1 s8 PUSH2 // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset config_addr vset elect_at - send_validator_set_to_config INLINECALLDICT - s0 s9 XCHG // vset stake_held elect_at frozen total_stakes start credits elect_for elect ds - LDDICT // vset stake_held elect_at frozen total_stakes start credits elect_for elect past_elections ds - s5 s3 XCHG2 // vset stake_held elect_at frozen total_stakes past_elections credits ds elect start elect_for - ADD // vset stake_held elect_at frozen total_stakes past_elections credits ds elect _105 - s8 PUSH // vset stake_held elect_at frozen total_stakes past_elections credits ds elect _105 stake_held - ADD // vset stake_held elect_at frozen total_stakes past_elections credits ds elect _106 - s0 s9 XCHG // _106 stake_held elect_at frozen total_stakes past_elections credits ds elect vset - HASHCU // _106 stake_held elect_at frozen total_stakes past_elections credits ds elect _107 - s4 s9 XCHG - s3 s8 XCHG - s0 s6 s5 XCHG3 - 0 PUSHINT - PUSHNULL // past_elections credits elect_at elect ds _106 stake_held _107 frozen total_stakes _108=0 _109 - pack_past_election INLINECALLDICT // past_elections credits elect_at elect ds _110 - s0 s3 s5 XCHG3 - 32 PUSHINT // elect credits ds _110 elect_at past_elections _111=32 - DICTUSETB // elect credits ds past_elections - s0 s3 XCHG - NEWC // past_elections credits ds elect _113 - STDICT // past_elections credits ds _114 - s1 s2 XCHG // past_elections ds credits _114 - STDICT // past_elections ds _115 - s1 s2 XCHG // ds past_elections _115 - STDICT // ds _116 - SWAP // _116 ds - STSLICER // _117 - ENDC // _118 - c4 POP - TRUE // _120 - }> - update_active_vset_id PROC:<{ - // - load_data INLINECALLDICT // elect credits past_elections grams active_id active_hash - 34 PUSHINT // elect credits past_elections grams active_id active_hash _8=34 - CONFIGOPTPARAM // elect credits past_elections grams active_id active_hash _9 - HASHCU // elect credits past_elections grams active_id active_hash cur_hash - s0 s1 PUSH2 // elect credits past_elections grams active_id active_hash cur_hash cur_hash active_hash - EQUAL // elect credits past_elections grams active_id active_hash cur_hash _11 - IFJMP:<{ // elect credits past_elections grams active_id active_hash cur_hash - 7 BLKDROP // - FALSE // _12 - }> // elect credits past_elections grams active_id active_hash cur_hash - s2 PUSH // elect credits past_elections grams active_id active_hash cur_hash active_id - IF:<{ // elect credits past_elections grams active_id active_hash cur_hash - s2 s4 PUSH2 - 32 PUSHINT // elect credits past_elections grams active_id active_hash cur_hash active_id past_elections _15=32 - DICTUGET - NULLSWAPIFNOT // elect credits past_elections grams active_id active_hash cur_hash fs f - IF:<{ // elect credits past_elections grams active_id active_hash cur_hash fs - 32 LDU // elect credits past_elections grams active_id active_hash cur_hash _99 _98 - NIP // elect credits past_elections grams active_id active_hash cur_hash fs - DUP // elect credits past_elections grams active_id active_hash cur_hash fs0 fs - 32 LDU // elect credits past_elections grams active_id active_hash cur_hash fs0 _24 fs - 256 LDU // elect credits past_elections grams active_id active_hash cur_hash fs0 _24 _103 _102 - DROP // elect credits past_elections grams active_id active_hash cur_hash fs0 stake_held hash - s0 s4 XCHG2 // elect credits past_elections grams active_id stake_held cur_hash fs0 hash active_hash - EQUAL // elect credits past_elections grams active_id stake_held cur_hash fs0 _31 - 57 THROWIFNOT - NOW // elect credits past_elections grams active_id stake_held cur_hash fs0 _33 - s0 s3 XCHG2 // elect credits past_elections grams active_id fs0 cur_hash _33 stake_held - ADD // elect credits past_elections grams active_id fs0 cur_hash unfreeze_time - NEWC // elect credits past_elections grams active_id fs0 cur_hash unfreeze_time _36 - 32 STU // elect credits past_elections grams active_id fs0 cur_hash _38 - ROT // elect credits past_elections grams active_id cur_hash _38 fs0 - STSLICER // elect credits past_elections grams active_id cur_hash _39 - s0 s0 s4 XCHG3 - 32 PUSHINT // elect credits cur_hash grams _39 active_id past_elections _40=32 - DICTUSETB // elect credits cur_hash grams past_elections - s0 s2 XCHG // elect credits past_elections grams cur_hash - }>ELSE<{ - s1 s3 XCHG - 3 BLKDROP // elect credits past_elections grams cur_hash - }> - }>ELSE<{ - 2 1 BLKDROP2 // elect credits past_elections grams cur_hash - }> - -1 PUSHINT // elect credits past_elections grams cur_hash id=-1 - UNTIL:<{ - s3 PUSH - 32 PUSHINT // elect credits past_elections grams cur_hash id past_elections _46=32 - DICTUGETNEXT - NULLSWAPIFNOT2 // elect credits past_elections grams cur_hash fs id f - DUP // elect credits past_elections grams cur_hash fs id f f - IF:<{ // elect credits past_elections grams cur_hash fs id f - s0 s2 XCHG // elect credits past_elections grams cur_hash f id fs - 64 LDU // elect credits past_elections grams cur_hash f id _50 fs - 256 LDU // elect credits past_elections grams cur_hash f id tm hash fs - s1 s5 PUSH2 // elect credits past_elections grams cur_hash f id tm hash fs hash cur_hash - EQUAL // elect credits past_elections grams cur_hash f id tm hash fs _56 - IF:<{ // elect credits past_elections grams cur_hash f id tm hash fs - s4 POP // elect credits past_elections grams cur_hash fs id tm hash - s0 s3 XCHG // elect credits past_elections grams cur_hash hash id tm fs - LDDICT // elect credits past_elections grams cur_hash hash id tm _60 fs - LDGRAMS // elect credits past_elections grams cur_hash hash id tm _60 _62 fs - LDGRAMS // elect credits past_elections grams cur_hash hash id tm dict total_stake bonuses fs - s8 PUSH // elect credits past_elections grams cur_hash hash id tm dict total_stake bonuses fs grams - 3 RSHIFT# // elect credits past_elections grams cur_hash hash id tm dict total_stake bonuses fs amount - s9 s9 XCPU // elect credits past_elections amount cur_hash hash id tm dict total_stake bonuses fs grams amount - SUB // elect credits past_elections amount cur_hash hash id tm dict total_stake bonuses fs grams - s2 s9 XCHG2 // elect credits past_elections grams cur_hash hash id tm dict total_stake fs bonuses amount - ADD // elect credits past_elections grams cur_hash hash id tm dict total_stake fs bonuses - s0 s4 XCHG - NEWC // elect credits past_elections grams cur_hash hash id bonuses dict total_stake fs tm _72 - 64 STU // elect credits past_elections grams cur_hash hash id bonuses dict total_stake fs _74 - s1 s6 XCHG // elect credits past_elections grams cur_hash fs id bonuses dict total_stake hash _74 - 256 STU // elect credits past_elections grams cur_hash fs id bonuses dict total_stake _76 - s1 s2 XCHG // elect credits past_elections grams cur_hash fs id bonuses total_stake dict _76 - STDICT // elect credits past_elections grams cur_hash fs id bonuses total_stake _77 - SWAP // elect credits past_elections grams cur_hash fs id bonuses _77 total_stake - STGRAMS // elect credits past_elections grams cur_hash fs id bonuses _78 - SWAP // elect credits past_elections grams cur_hash fs id _78 bonuses - STGRAMS // elect credits past_elections grams cur_hash fs id _79 - ROT // elect credits past_elections grams cur_hash id _79 fs - STSLICER // elect credits past_elections grams cur_hash id _80 - s0 s0 s4 XCPUXC - 32 PUSHINT // elect credits id grams cur_hash _80 id past_elections _81=32 - DICTUSETB // elect credits id grams cur_hash past_elections - s0 s3 XCHG - FALSE - SWAP // elect credits past_elections grams cur_hash f id - }>ELSE<{ - 3 BLKDROP // elect credits past_elections grams cur_hash f id - }> - }>ELSE<{ - s2 POP // elect credits past_elections grams cur_hash f id - }> - SWAP // elect credits past_elections grams cur_hash id f - NOT // elect credits past_elections grams cur_hash id _84 - }> // elect credits past_elections grams cur_hash id - DUP // elect credits past_elections grams cur_hash id id - ISNULL // elect credits past_elections grams cur_hash id _85 - IF:<{ // elect credits past_elections grams cur_hash id - DROP // elect credits past_elections grams cur_hash - 0 PUSHINT // elect credits past_elections grams cur_hash _86=0 - }>ELSE<{ // elect credits past_elections grams cur_hash _86 - }> // elect credits past_elections grams active_hash active_id - SWAP // elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - TRUE // _89 - }> - cell_hash_eq? PROCREF:<{ - // vset expected_vset_hash - OVER // vset expected_vset_hash vset - ISNULL // vset expected_vset_hash _2 - IF:<{ // vset expected_vset_hash - 2DROP // - FALSE // _3 - }>ELSE<{ // vset expected_vset_hash - SWAP // expected_vset_hash vset - HASHCU // expected_vset_hash _5 - SWAP // _5 expected_vset_hash - EQUAL // _3 - }> - }> - validator_set_installed PROC:<{ - // ds elect credits - SWAP // ds credits elect - unpack_elect INLINECALLDICT // ds credits _44 _45 _46 _47 _48 _49 _50 - 5 1 BLKDROP2 // ds credits elect_at finished - IFNOTJMP:<{ // ds credits elect_at - 3 BLKDROP // - FALSE // _11 - }> // ds credits elect_at - s0 s2 XCHG // elect_at credits ds - LDDICT // elect_at credits past_elections ds - s3 s1 XCPU - 32 PUSHINT // ds credits past_elections elect_at past_elections _17=32 - DICTUGET - NULLSWAPIFNOT // ds credits past_elections fs f - IFNOTJMP:<{ // ds credits past_elections fs - 4 BLKDROP // - FALSE // _19 - }> // ds credits past_elections fs - 64 PUSHINT // ds credits past_elections fs _21=64 - SDSKIPFIRST // ds credits past_elections _22 - 256 PLDU // ds credits past_elections vset_hash - 34 PUSHINT // ds credits past_elections vset_hash _25=34 - CONFIGOPTPARAM // ds credits past_elections vset_hash _26 - OVER // ds credits past_elections vset_hash _26 vset_hash - cell_hash_eq? INLINECALLDICT // ds credits past_elections vset_hash _27 - 36 PUSHINT // ds credits past_elections vset_hash _27 _28=36 - CONFIGOPTPARAM // ds credits past_elections vset_hash _27 _29 - ROT // ds credits past_elections _27 _29 vset_hash - cell_hash_eq? INLINECALLDICT // ds credits past_elections _27 _30 - OR // ds credits past_elections _31 - IFJMP:<{ // ds credits past_elections - FALSE // ds credits past_elections _32 - NEWC // ds credits past_elections _32 _33 - 1 STI // ds credits past_elections _35 - s1 s2 XCHG // ds past_elections credits _35 - STDICT // ds past_elections _36 - STDICT // ds _37 - SWAP // _37 ds - STSLICER // _38 - ENDC // _39 - c4 POP - update_active_vset_id CALLDICT // _41 - DROP // - TRUE // _42 - }> // ds credits past_elections - 3 BLKDROP // - FALSE // _43 - }> - check_unfreeze PROC:<{ - // - load_data INLINECALLDICT // elect credits past_elections grams active_id active_hash - -1 PUSHINT // elect credits past_elections grams active_id active_hash id=-1 - UNTIL:<{ - s4 PUSH - 32 PUSHINT // elect credits past_elections grams active_id active_hash id past_elections _11=32 - DICTUGETNEXT - NULLSWAPIFNOT2 // elect credits past_elections grams active_id active_hash fs id f - DUP // elect credits past_elections grams active_id active_hash fs id f f - IF:<{ // elect credits past_elections grams active_id active_hash fs id f - s0 s2 XCHG // elect credits past_elections grams active_id active_hash f id fs - 32 LDU // elect credits past_elections grams active_id active_hash f id _39 _38 - DROP // elect credits past_elections grams active_id active_hash f id unfreeze_at - NOW // elect credits past_elections grams active_id active_hash f id unfreeze_at _17 - LEQ // elect credits past_elections grams active_id active_hash f id _18 - s1 s4 PUSH2 // elect credits past_elections grams active_id active_hash f id _18 id active_id - NEQ // elect credits past_elections grams active_id active_hash f id _18 _19 - AND // elect credits past_elections grams active_id active_hash f id _20 - IF:<{ // elect credits past_elections grams active_id active_hash f id - NIP // elect credits past_elections grams active_id active_hash id - s5 s4 s4 XC2PU // elect active_hash id grams active_id credits past_elections id - unfreeze_all INLINECALLDICT // elect active_hash id grams active_id credits past_elections unused_prizes - s1 s4 XCHG // elect active_hash id past_elections active_id credits grams unused_prizes - ADD // elect active_hash id past_elections active_id credits grams - s6 s1 s3 PUSH3 - s3 s5 s8 PUSH3 // elect active_hash id past_elections active_id credits grams elect credits past_elections grams active_id active_hash - store_data INLINECALLDICT - s0 s3 XCHG - s5 s4 XCHG2 - FALSE - SWAP // elect credits past_elections grams active_id active_hash f id - }> // elect credits past_elections grams active_id active_hash f id - }>ELSE<{ - s2 POP // elect credits past_elections grams active_id active_hash f id - }> - SWAP // elect credits past_elections grams active_id active_hash id f - NOT // elect credits past_elections grams active_id active_hash id _26 - }> // elect credits past_elections grams active_id active_hash id - 6 1 BLKDROP2 // id - ISNULL // _27 - NOT // _28 - }> - announce_new_elections PROC:<{ - // ds elect credits - NIP // ds credits - 36 PUSHINT // ds credits _4=36 - CONFIGOPTPARAM // ds credits next_vset - ISNULL // ds credits _6 - IFNOTJMP:<{ // ds credits - 2DROP // - FALSE // _7 - }> // ds credits - 1 PUSHINT // ds credits _9=1 - CONFIGOPTPARAM // ds credits _10 - CTOS // ds credits _11 - 256 PLDU // ds credits elector_addr - MYADDR // ds credits elector_addr _16 - REWRITESTDADDR // ds credits elector_addr my_wc my_addr - SWAP // ds credits elector_addr my_addr my_wc - INC // ds credits elector_addr my_addr _19 - s0 s2 XCHG // ds credits _19 my_addr elector_addr - NEQ // ds credits _19 _20 - OR // ds credits _21 - IFJMP:<{ // ds credits - 2DROP // - FALSE // _22 - }> // ds credits - 34 PUSHINT // ds credits _24=34 - CONFIGOPTPARAM // ds credits cur_vset - DUP // ds credits cur_vset cur_vset - ISNULL // ds credits cur_vset _26 - IFJMP:<{ // ds credits cur_vset - 3 BLKDROP // - FALSE // _27 - }> // ds credits cur_vset - get_validator_conf CALLDICT // ds credits cur_vset _74 _75 _76 _77 - DROP - s2 POP // ds credits cur_vset elect_end_before elect_begin_before - s0 s2 XCHG // ds credits elect_begin_before elect_end_before cur_vset - CTOS // ds credits elect_begin_before elect_end_before _34 - 40 PUSHINT // ds credits elect_begin_before elect_end_before _34 _37 - SDSKIPFIRST // ds credits elect_begin_before elect_end_before _38 - 32 PLDU // ds credits elect_begin_before elect_end_before cur_valid_until - NOW // ds credits elect_begin_before elect_end_before cur_valid_until t - s1 s3 XCPU // ds credits elect_begin_before elect_end_before t cur_valid_until elect_begin_before - SUB // ds credits elect_begin_before elect_end_before t t0 - 2DUP // ds credits elect_begin_before elect_end_before t t0 t t0 - LESS // ds credits elect_begin_before elect_end_before t t0 _45 - IFJMP:<{ // ds credits elect_begin_before elect_end_before t t0 - 6 BLKDROP // - FALSE // _46 - }> // ds credits elect_begin_before elect_end_before t t0 - 2DUP // ds credits elect_begin_before elect_end_before t t0 t t0 - SUB // ds credits elect_begin_before elect_end_before t t0 _47 - 60 LESSINT // ds credits elect_begin_before elect_end_before t t0 _49 - IF:<{ // ds credits elect_begin_before elect_end_before t t0 - NIP // ds credits elect_begin_before elect_end_before t - }>ELSE<{ - DROP // ds credits elect_begin_before elect_end_before t - }> - 17 PUSHINT // ds credits elect_begin_before elect_end_before t _52=17 - CONFIGOPTPARAM // ds credits elect_begin_before elect_end_before t _53 - CTOS // ds credits elect_begin_before elect_end_before t _54 - LDGRAMS // ds credits elect_begin_before elect_end_before t _79 _78 - DROP // ds credits elect_begin_before elect_end_before t min_stake - s0 s3 XCHG // ds credits min_stake elect_end_before t elect_begin_before - ADD // ds credits min_stake elect_end_before elect_at - s0 s1 PUXC // ds credits min_stake elect_at elect_at elect_end_before - SUB // ds credits min_stake elect_at elect_close - 0 PUSHINT // ds credits min_stake elect_at elect_close _60=0 - NEWDICT // ds credits min_stake elect_at elect_close _60=0 _61 - s3 s4 XCHG - s2 s3 XCHG - FALSE - FALSE // ds credits elect_at elect_close min_stake _60=0 _61 _62 _63 - pack_elect INLINECALLDICT // ds credits elect - NEWC // ds credits elect _65 - STDICT // ds credits _66 - STDICT // ds _67 - SWAP // _67 ds - STSLICER // _68 - ENDC // _69 - c4 POP - TRUE // _71 - }> - run_ticktock PROC:<{ - // is_tock - DROP // - c4 PUSH // _2 - CTOS // ds - LDDICT // _6 ds - LDDICT // elect credits ds - s2 PUSH // elect credits ds elect - ISNULL // elect credits ds _10 - IF:<{ // elect credits ds - -ROT // ds elect credits - announce_new_elections CALLDICT // _18 - 0 THROWIF - }>ELSE<{ // elect credits ds - s0 s2 s1 PUSH3 // elect credits ds ds elect credits - conduct_elections CALLDICT // elect credits ds _12 - 0 THROWIF - -ROT // ds elect credits - validator_set_installed CALLDICT // _15 - 0 THROWIF - }> - update_active_vset_id CALLDICT // _21 - 0 THROWIF - check_unfreeze CALLDICT // _23 - DROP // - }> - active_election_id PROC:<{ - // - c4 PUSH // _1 - CTOS // _2 - PLDDICT // elect - DUP // elect elect - ISNULL // elect _4 - IF:<{ // elect - DROP // - 0 PUSHINT // _5=0 - }>ELSE<{ // elect - CTOS // _7 - 32 PLDU // _5 - }> - }> - participates_in PROC:<{ - // validator_pubkey - c4 PUSH // validator_pubkey _2 - CTOS // validator_pubkey _3 - PLDDICT // validator_pubkey elect - DUP // validator_pubkey elect elect - ISNULL // validator_pubkey elect _5 - IFJMP:<{ // validator_pubkey elect - 2DROP // - 0 PUSHINT // _6=0 - }> // validator_pubkey elect - unpack_elect INLINECALLDICT // validator_pubkey _23 _24 _25 _26 _27 _28 _29 - s2 s6 XCHG - 6 BLKDROP // validator_pubkey members - 8 PUSHPOW2 // validator_pubkey members _17=256 - DICTUGET - NULLSWAPIFNOT // mem found - IF:<{ // mem - LDGRAMS // _33 _32 - DROP // _19 - }>ELSE<{ // mem - DROP // - 0 PUSHINT // _19=0 - }> - }> - participant_list PROC:<{ - // - c4 PUSH // _1 - CTOS // _2 - PLDDICT // elect - DUP // elect elect - ISNULL // elect _4 - IFJMP:<{ // elect - DROP // - PUSHNULL // _5 - }> // elect - unpack_elect INLINECALLDICT // _35 _36 _37 _38 _39 _40 _41 - s2 s6 XCHG - 6 BLKDROP // members - PUSHNULL // members l - 256 PUSHPOW2DEC // members l id - UNTIL:<{ - s2 PUSH - 8 PUSHPOW2 // members l id members _28=256 - DICTUGETPREV - NULLSWAPIFNOT2 // members l fs id f - DUP // members l fs id f f - IF:<{ // members l fs id f - s0 s2 XCHG // members l f id fs - LDGRAMS // members l f id _46 _45 - DROP // members l f id _31 - s1 s(-1) PUXC // members l f id id _31 - PAIR // members l f id _30 - s0 s3 XCHG2 // members id f _30 l - CONS // members id f l - s0 s2 XCHG // members l f id - }>ELSE<{ - s2 POP // members l f id - }> - SWAP // members l id f - NOT // members l id _34 - }> // members l id - DROP - NIP // l - }> - participant_list_extended PROC:<{ - // - c4 PUSH // _1 - CTOS // _2 - PLDDICT // elect - DUP // elect elect - ISNULL // elect _4 - IFJMP:<{ // elect - DROP // - 0 PUSHINT // _5=0 - s0 s0 s0 PUSH3 // _5=0 _6=0 _7=0 _8=0 - PUSHNULL // _5=0 _6=0 _7=0 _8=0 _9 - s1 s1 PUSH2 // _5=0 _6=0 _7=0 _8=0 _9 _10=0 _11=0 - }> // elect - unpack_elect INLINECALLDICT // elect_at elect_close min_stake total_stake members failed finished - PUSHNULL // elect_at elect_close min_stake total_stake members failed finished l - 256 PUSHPOW2DEC // elect_at elect_close min_stake total_stake members failed finished l id - UNTIL:<{ - s4 PUSH - 8 PUSHPOW2 // elect_at elect_close min_stake total_stake members failed finished l id members _34=256 - DICTUGETPREV - NULLSWAPIFNOT2 // elect_at elect_close min_stake total_stake members failed finished l cs id f - DUP // elect_at elect_close min_stake total_stake members failed finished l cs id f f - IF:<{ // elect_at elect_close min_stake total_stake members failed finished l cs id f - s0 s2 XCHG // elect_at elect_close min_stake total_stake members failed finished l f id cs - LDGRAMS // elect_at elect_close min_stake total_stake members failed finished l f id _41 cs - 32 LDU // elect_at elect_close min_stake total_stake members failed finished l f id _41 _73 _72 - NIP // elect_at elect_close min_stake total_stake members failed finished l f id _41 cs - 32 LDU // elect_at elect_close min_stake total_stake members failed finished l f id _41 _46 cs - 256 LDU // elect_at elect_close min_stake total_stake members failed finished l f id _41 _46 _49 cs - 256 LDU // elect_at elect_close min_stake total_stake members failed finished l f id stake max_factor addr adnl_addr cs - ENDS - 4 TUPLE // elect_at elect_close min_stake total_stake members failed finished l f id _57 - s1 s(-1) PUXC // elect_at elect_close min_stake total_stake members failed finished l f id id _57 - PAIR // elect_at elect_close min_stake total_stake members failed finished l f id _56 - s0 s3 XCHG2 // elect_at elect_close min_stake total_stake members failed finished id f _56 l - CONS // elect_at elect_close min_stake total_stake members failed finished id f l - s0 s2 XCHG // elect_at elect_close min_stake total_stake members failed finished l f id - }>ELSE<{ - s2 POP // elect_at elect_close min_stake total_stake members failed finished l f id - }> - SWAP // elect_at elect_close min_stake total_stake members failed finished l id f - NOT // elect_at elect_close min_stake total_stake members failed finished l id _59 - }> // elect_at elect_close min_stake total_stake members failed finished l id - DROP - s3 POP // elect_at elect_close min_stake total_stake l failed finished - }> - compute_returned_stake PROC:<{ - // wallet_addr - c4 PUSH // wallet_addr _2 - CTOS // wallet_addr cs - LDDICT // wallet_addr _19 _18 - NIP // wallet_addr cs - LDDICT // wallet_addr _21 _20 - DROP // wallet_addr credits - 8 PUSHPOW2 // wallet_addr credits _12=256 - DICTUGET - NULLSWAPIFNOT // val f - IF:<{ // val - LDGRAMS // _25 _24 - DROP // _14 - }>ELSE<{ // val - DROP // - 0 PUSHINT // _14=0 - }> - }> - past_election_ids PROC:<{ - // - load_data INLINECALLDICT // _19 _20 _21 _22 _23 _24 - s3 s5 XCHG - 5 BLKDROP // past_elections - 32 PUSHPOW2 // past_elections id - PUSHNULL // past_elections id list - UNTIL:<{ - s1 s2 XCPU - 32 PUSHINT // past_elections list id past_elections _15=32 - DICTUGETPREV - NULLSWAPIFNOT2 // past_elections list _26 _25 _27 - s2 POP // past_elections list f id - OVER // past_elections list f id f - IF:<{ // past_elections list f id - s0 s2 PUXC // past_elections id f id list - CONS // past_elections id f list - s0 s2 XCHG // past_elections list f id - }> // past_elections list f id - SWAP // past_elections list id f - NOT // past_elections list id _18 - s1 s2 XCHG // past_elections id list _18 - }> // past_elections id list - 2 1 BLKDROP2 // list - }> - past_elections PROC:<{ - // - load_data INLINECALLDICT // _21 _22 _23 _24 _25 _26 - s3 s5 XCHG - 5 BLKDROP // past_elections - 32 PUSHPOW2 // past_elections id - PUSHNULL // past_elections id list - UNTIL:<{ - s1 s2 XCPU - 32 PUSHINT // past_elections list id past_elections _15=32 - DICTUGETPREV - NULLSWAPIFNOT2 // past_elections list fs id found - DUP // past_elections list fs id found found - IF:<{ // past_elections list fs id found - s0 s2 XCHG // past_elections list found id fs - unpack_past_election INLINECALLDICT // past_elections list found id _30 _31 _32 _33 _34 _35 _36 - s7 PUSH - 7 -ROLL // past_elections list found id id _30 _31 _32 _33 _34 _35 _36 - 8 TUPLE // past_elections list found id _17 - s0 s3 XCHG2 // past_elections id found _17 list - CONS // past_elections id found list - s0 s2 XCHG // past_elections list found id - }>ELSE<{ - s2 POP // past_elections list found id - }> - SWAP // past_elections list id found - NOT // past_elections list id _20 - s1 s2 XCHG // past_elections id list _20 - }> // past_elections id list - 2 1 BLKDROP2 // list - }> - past_elections_list PROC:<{ - // - load_data INLINECALLDICT // _28 _29 _30 _31 _32 _33 - s3 s5 XCHG - 5 BLKDROP // past_elections - 32 PUSHPOW2 // past_elections id - PUSHNULL // past_elections id list - UNTIL:<{ - s1 s2 XCPU - 32 PUSHINT // past_elections list id past_elections _15=32 - DICTUGETPREV - NULLSWAPIFNOT2 // past_elections list fs id found - DUP // past_elections list fs id found found - IF:<{ // past_elections list fs id found - s0 s2 XCHG // past_elections list found id fs - unpack_past_election INLINECALLDICT // past_elections list found id _37 _38 _39 _40 _41 _42 _43 - 4 BLKDROP // past_elections list found id unfreeze_at stake_held vset_hash - s3 PUSH - s3 s1 s3 XCHG3 // past_elections list found id id unfreeze_at vset_hash stake_held - 4 TUPLE // past_elections list found id _25 - s0 s3 XCHG2 // past_elections id found _25 list - CONS // past_elections id found list - s0 s2 XCHG // past_elections list found id - }>ELSE<{ - s2 POP // past_elections list found id - }> - SWAP // past_elections list id found - NOT // past_elections list id _27 - s1 s2 XCHG // past_elections id list _27 - }> // past_elections id list - 2 1 BLKDROP2 // list - }> - complete_unpack_complaint PROCREF:<{ - // cs - unpack_complaint_status INLINECALLDICT // complaint voters vset_id weight_remaining - PUSHNULL // complaint voters vset_id weight_remaining voters_list - 32 PUSHPOW2 // complaint voters vset_id weight_remaining voters_list voter_id - UNTIL:<{ - s4 PUSH - 16 PUSHINT // complaint voters vset_id weight_remaining voters_list voter_id voters _14=16 - DICTUGETPREV - NULLSWAPIFNOT2 // complaint voters vset_id weight_remaining voters_list _27 _26 _28 - s2 POP // complaint voters vset_id weight_remaining voters_list f voter_id - OVER // complaint voters vset_id weight_remaining voters_list f voter_id f - IF:<{ // complaint voters vset_id weight_remaining voters_list f voter_id - s0 s2 PUXC // complaint voters vset_id weight_remaining voter_id f voter_id voters_list - CONS // complaint voters vset_id weight_remaining voter_id f voters_list - s0 s2 XCHG // complaint voters vset_id weight_remaining voters_list f voter_id - }> // complaint voters vset_id weight_remaining voters_list f voter_id - SWAP // complaint voters vset_id weight_remaining voters_list voter_id f - NOT // complaint voters vset_id weight_remaining voters_list voter_id _17 - }> // complaint voters vset_id weight_remaining voters_list voter_id - DROP - s3 POP // complaint voters_list vset_id weight_remaining - s0 s3 XCHG // weight_remaining voters_list vset_id complaint - CTOS // weight_remaining voters_list vset_id _20 - unpack_complaint INLINECALLDICT // weight_remaining voters_list vset_id _29 _30 _31 _32 _33 _34 _35 _36 - 8 TUPLE // weight_remaining voters_list vset_id _19 - s0 s3 XCHG // _19 voters_list vset_id weight_remaining - 4 TUPLE // _18 - }> - get_past_complaints PROCREF:<{ - // election_id - load_data INLINECALLDICT // election_id _21 _22 _23 _24 _25 _26 - s3 s5 XCHG - 5 BLKDROP // election_id past_elections - 32 PUSHINT // election_id past_elections _10=32 - DICTUGET - NULLSWAPIFNOT // fs found? - IFNOTJMP:<{ // fs - DROP // - PUSHNULL // _12 - }> // fs - unpack_past_election INLINECALLDICT // _29 _30 _31 _32 _33 _34 _35 - 6 1 BLKDROP2 // complaints - }> - show_complaint PROC:<{ - // election_id chash - SWAP // chash election_id - get_past_complaints INLINECALLDICT // chash complaints - 8 PUSHPOW2 // chash complaints _6=256 - DICTUGET - NULLSWAPIFNOT // cs found - IF:<{ // cs - complete_unpack_complaint INLINECALLDICT // _8 - }>ELSE<{ // cs - DROP // - PUSHNULL // _8 - }> - }> - list_complaints PROC:<{ - // election_id - get_past_complaints INLINECALLDICT // complaints - 256 PUSHPOW2DEC // complaints id - PUSHNULL // complaints id list - UNTIL:<{ - s1 s2 XCPU - 8 PUSHPOW2 // complaints list id complaints _17=256 - DICTUGETPREV - NULLSWAPIFNOT2 // complaints list cs id found? - DUP // complaints list cs id found? found? - IF:<{ // complaints list cs id found? - s0 s2 XCHG // complaints list found? id cs - complete_unpack_complaint INLINECALLDICT // complaints list found? id _19 - s1 s(-1) PUXC // complaints list found? id id _19 - PAIR // complaints list found? id _20 - s0 s3 XCHG2 // complaints id found? _20 list - CONS // complaints id found? list - s0 s2 XCHG // complaints list found? id - }>ELSE<{ - s2 POP // complaints list found? id - }> - SWAP // complaints list id found? - NOT // complaints list id _22 - s1 s2 XCHG // complaints id list _22 - }> // complaints id list - 2 1 BLKDROP2 // list - }> - complaint_storage_price PROC:<{ - // bits refs expire_in - get_complaint_prices INLINECALLDICT // bits refs expire_in deposit bit_price cell_price - s0 s5 XCHG - 10 PUSHPOW2 // cell_price refs expire_in deposit bit_price bits _8=1024 - ADD // cell_price refs expire_in deposit bit_price _9 - SWAP // cell_price refs expire_in deposit _9 bit_price - MUL // cell_price refs expire_in deposit _10 - s0 s3 XCHG // cell_price _10 expire_in deposit refs - 2 ADDCONST // cell_price _10 expire_in deposit _12 - s0 s4 XCHG2 // deposit _10 expire_in _12 cell_price - MUL // deposit _10 expire_in _13 - s1 s2 XCHG // deposit expire_in _10 _13 - ADD // deposit expire_in pps - SWAP // deposit pps expire_in - MUL // deposit _16 - SWAP // _16 deposit - ADD // paid - 30 PUSHPOW2 // paid _20 - ADD // _21 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp deleted file mode 100644 index 1fac6119..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("highload-wallet", "te6ccgEBCAEAlwABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC48oMI1xgg0x/TH9MfAvgju/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhYhgBD0eG+lIJgC0wfUMAH7AJEy4gGz5lsBpMjLH8sfy//J7VQABNAwAgFIBgcAF7s5ztRNDTPzHXC/+AARuMl+1E0NcLH4"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif deleted file mode 100644 index 8c74293e..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif +++ /dev/null @@ -1,87 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - recv_internal PROC:<{ - // in_msg - DROP // - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _9 cs - 32 LDU // signature in_msg _9 _12 cs - 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - s0 s2 XCHG - NOW // signature in_msg subwallet_id cs msg_seqno valid_until _19 - LEQ // signature in_msg subwallet_id cs msg_seqno _20 - 35 THROWIF - c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23 - CTOS // signature in_msg subwallet_id cs msg_seqno ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds - 256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds - ENDS - s3 s2 XCPU // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet msg_seqno stored_seqno - EQUAL // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet _39 - 33 THROWIFNOT - s4 s4 XCPU // signature in_msg stored_subwallet cs public_key stored_seqno subwallet_id stored_subwallet - EQUAL // signature in_msg stored_subwallet cs public_key stored_seqno _42 - 34 THROWIFNOT - s0 s4 XCHG // signature stored_seqno stored_subwallet cs public_key in_msg - HASHSU // signature stored_seqno stored_subwallet cs public_key _45 - s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs _45 signature public_key - CHKSIGNU // public_key stored_seqno stored_subwallet cs _46 - 35 THROWIFNOT - LDDICT // public_key stored_seqno stored_subwallet dict cs - ENDS - ACCEPT - -1 PUSHINT // public_key stored_seqno stored_subwallet dict i=-1 - UNTIL:<{ - OVER - 16 PUSHINT // public_key stored_seqno stored_subwallet dict i dict _57=16 - DICTIGETNEXT - NULLSWAPIFNOT2 // public_key stored_seqno stored_subwallet dict cs i f - DUP // public_key stored_seqno stored_subwallet dict cs i f f - IF:<{ // public_key stored_seqno stored_subwallet dict cs i f - s0 s2 XCHG // public_key stored_seqno stored_subwallet dict f i cs - 8 LDU // public_key stored_seqno stored_subwallet dict f i mode cs - LDREF // public_key stored_seqno stored_subwallet dict f i mode _100 _99 - DROP // public_key stored_seqno stored_subwallet dict f i mode _63 - SWAP // public_key stored_seqno stored_subwallet dict f i _63 mode - SENDRAWMSG - }>ELSE<{ - s2 POP // public_key stored_seqno stored_subwallet dict f i - }> - SWAP // public_key stored_seqno stored_subwallet dict i f - NOT // public_key stored_seqno stored_subwallet dict i _66 - }> // public_key stored_seqno stored_subwallet dict i - 2DROP // public_key stored_seqno stored_subwallet - SWAP // public_key stored_subwallet stored_seqno - INC // public_key stored_subwallet _68 - NEWC // public_key stored_subwallet _68 _69 - 32 STU // public_key stored_subwallet _71 - 32 STU // public_key _73 - 256 STU // _75 - ENDC // _76 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 64 LDU // _9 _8 - NIP // cs - 256 PLDU // _7 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp deleted file mode 100644 index ca5daab5..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("highload-wallet-v2", "te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQHq8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44WIYAQ9HhvpSCYAtMH1DAB+wCRMuIBs+ZbgyWhyEA0gED0Q4rmMQHIyx8Tyz/L//QAye1UCAAE0DACASAGBwAXvZznaiaGmvmOuF/8AEG+X5dqJoaY+Y6Z/p/5j6AmipEEAgegc30JjJLb/JXdHxQANCCAQPSWb6VsEiCUMFMDud4gkzM2AZJsIeKz"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif deleted file mode 100644 index 5b2c64e0..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif +++ /dev/null @@ -1,140 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-v2-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC recv_external - 117746 DECLMETHOD processed? - 78748 DECLMETHOD get_public_key - recv_internal PROC:<{ - // in_msg - DROP // - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _8 cs - 64 LDU // signature in_msg subwallet_id query_id cs - NOW // signature in_msg subwallet_id query_id cs _15 - 32 LSHIFT# // signature in_msg subwallet_id query_id cs bound - s2 s0 PUSH2 // signature in_msg subwallet_id query_id cs bound query_id bound - LESS // signature in_msg subwallet_id query_id cs bound _19 - 35 THROWIF - c4 PUSH // signature in_msg subwallet_id query_id cs bound _22 - CTOS // signature in_msg subwallet_id query_id cs bound ds - 32 LDU // signature in_msg subwallet_id query_id cs bound _28 ds - 64 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 ds - 256 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 _34 ds - LDDICT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries ds - ENDS - s6 s0 PUSH2 - 64 PUSHINT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries query_id old_queries _42=64 - DICTUGET - NULLSWAPIFNOT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries _115 _116 - NIP // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries found? - 32 THROWIF - s7 s3 XCPU // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key subwallet_id stored_subwallet - EQUAL // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key _47 - 34 THROWIFNOT - s0 s7 XCHG // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned in_msg - HASHSU // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned _50 - s0 s8 s7 XC2PU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _50 signature public_key - CHKSIGNU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _51 - 35 THROWIFNOT - s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound cs - LDDICT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs - ENDS - ACCEPT - -1 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i=-1 - UNTIL:<{ - OVER - 16 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i dict _62=16 - DICTIGETNEXT - NULLSWAPIFNOT2 // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f - DUP // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f f - IF:<{ // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f - s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i cs - 8 LDU // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode cs - LDREF // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _125 _124 - DROP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _68 - SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i _68 mode - SENDRAWMSG - }>ELSE<{ - s2 POP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i - }> - SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict i f - NOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i _71 - }> // last_cleaned public_key old_queries query_id stored_subwallet bound dict i - 2DROP // last_cleaned public_key old_queries query_id stored_subwallet bound - 38 PUSHPOW2 // last_cleaned public_key old_queries query_id stored_subwallet bound _74 - SUB // last_cleaned public_key old_queries query_id stored_subwallet bound - NEWC // last_cleaned public_key old_queries query_id stored_subwallet bound _77 - s0 s3 s4 XCHG3 - 64 PUSHINT // last_cleaned public_key stored_subwallet bound _77 query_id old_queries _78=64 - DICTUSETB // last_cleaned public_key stored_subwallet bound old_queries - UNTIL:<{ - DUP - 64 PUSHINT // last_cleaned public_key stored_subwallet bound old_queries old_queries _85=64 - DICTUREMMIN - NULLSWAPIFNOT2 // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129 - 1 2 BLKDROP2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f - DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f - IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f - DROP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i - s0 s3 PUSH2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i i bound - LESS // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f - }> // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f - DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f - IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f - s3 POP - s6 POP // last_cleaned public_key stored_subwallet bound f old_queries - SWAP // last_cleaned public_key stored_subwallet bound old_queries f - }>ELSE<{ - 2 1 BLKDROP2 // last_cleaned public_key stored_subwallet bound old_queries f - }> - NOT // last_cleaned public_key stored_subwallet bound old_queries _90 - }> // last_cleaned public_key stored_subwallet bound old_queries - NIP // last_cleaned public_key stored_subwallet old_queries - SWAP - NEWC // last_cleaned public_key old_queries stored_subwallet _91 - 32 STU // last_cleaned public_key old_queries _93 - s1 s3 XCHG // old_queries public_key last_cleaned _93 - 64 STU // old_queries public_key _95 - 256 STU // old_queries _97 - STDICT // _98 - ENDC // _99 - c4 POP - }> - processed? PROC:<{ - // query_id - c4 PUSH // query_id _2 - CTOS // query_id ds - 32 LDU // query_id _29 _28 - NIP // query_id ds - 64 LDU // query_id _11 ds - 256 LDU // query_id _11 _33 _32 - NIP // query_id _11 ds - LDDICT // query_id last_cleaned old_queries ds - ENDS - s2 s(-1) PUXC - 64 PUSHINT // query_id last_cleaned query_id old_queries _22=64 - DICTUGET - NULLSWAPIFNOT // query_id last_cleaned _36 _37 - NIP // query_id last_cleaned found - IF:<{ // query_id last_cleaned - 2DROP // - TRUE // _24 - }>ELSE<{ // query_id last_cleaned - LEQ // _26 - NEGATE // _24 - }> - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 96 LDU // _11 _10 - NIP // cs - 256 PLDU // _9 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp deleted file mode 100644 index 78319896..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("multisig", "te6ccgECKQEAA/oAART/APSkE/S88sgLAQIBIAIDAgFIBAUE2vIgxwCOgzDbPOCDCNcYIPkBAdMH2zwiwAAToVNxePQOb6Hyn9s8VBq6+RDyoAb0BCD5AQHTH1EYuvKq0z9wUwHwCgHCCAGDCryx8mhTFYBA9A5voSCYDqQgwgryZw7f+COqH1NAufJhVCOjU04eIR8gAgLMBgcCASAMDQIBIAgJAgFmCgsAA9GEAiPymAvHoHN9CYbZ5S7Z4BPHohwfIwAtAKkItdJEqCTItdKlwLUAdAT8ArobBKAATwhbpEx4CBukTDgAdAg10rDAJrUAvALyFjPFszJ4HHXI8gBzxb0AMmACASAODwIBIBQVARW77ZbVA0cFUg2zyCgCAUgQEQIBIBITAXOxHXQgwjXGCD5AQHTB4IB1MTtQ9hTIHj0Dm+h8p/XC/9eMfkQ8qCuAfQEIW6TW3Ey4PkBWNs8AaQBgJQA9rtqA6ADoAPoCAXoCEfyAgPyA3XlP+AXkegAA54tkwAAVrhlXQQDVZnah7EACASAWFwIBSBgZAVG3JVtnhiZGakYQCB6BzfQxwk2EWkAAMxph5i4AWuAmHAtv7hwLd3RuECEBhbVZm2eGq+Bv7bHGiiJwCB6PjfSkEcRgWkAAMcNEEAIa5CS64GT2E5kAOeLKhACQCB6IYFImHFImHFImXEA2YlzNiDAhAgEgGhsCA5k4HB0BEawabZ4vgbYJQCEAFa35QQDMlXah7BhAAQ2pNs8FV8FgIQAVrdws4IBqsztQ9iACINs8AvJl+ABQQ3FDE9s87VQhKAAK0//TBzAEpts8L65TILDyYhKxAqQls1McubAlgiAOEAAAAACgKLyw8mmCAYag+AEFlwIREAI+PjCOjREQH9s8QNd49EMQvQXiVBZbVHPnVhBT3Ns8VHEKVHq8IiMmJAAg7UTQ0x/TB9MH0z/0BPQE0QBIAY4aMNIAAfKj0wfTB1AD1wEg+QEF+QEVuvKkUAPgbCFwVCATAAwByMv/ywcE1ts87VT4D3AlblOJvrGYEG4QLVDHXwePGzBUJANQTds8UFWgRlAQSRA6SwlTuds8UFQWf+L4AAeDJaGOLCaAQPSWb6UglDBTA7neII4WODk5CNIAAZfTBzAW8AcFkTDifwgHBZJsMeKz5jAGKCUmJwBgcI4pA9CDCNcY0wf0BDBTFnj0Dm+h8qXXC/9URUT5EPKmrlIgsVIDvRShI27mbCIyAH5SML6OIF8D+ACTItdKmALTB9QC+wAC6DJwyMoAQBSAQPRDAvAHjhdxyMsAFMsHEssHWM8BWM8WQBOAQPRDAeIBII6KEEUQNEMA2zztVJJfBuIoABzIyx/LB8sHyz/0APQAyQ=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif deleted file mode 100644 index aaf44624..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif +++ /dev/null @@ -1,624 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/multisig-code.fc` -PROGRAM{ - DECLPROC unpack_state - DECLPROC pack_state - DECLPROC pack_owner_info - DECLPROC unpack_owner_info - DECLPROC check_signatures - DECLPROC recv_internal - DECLPROC unpack_query_data - DECLPROC dec_flood - DECLPROC try_init - DECLPROC update_pending_queries - DECLPROC calc_boc_size - DECLPROC recv_external - 104746 DECLMETHOD get_query_state - 117746 DECLMETHOD processed? - 81625 DECLMETHOD create_init_state - DECLPROC merge_list - 120004 DECLMETHOD get_public_keys - 87157 DECLMETHOD check_query_signatures - 109260 DECLMETHOD messages_by_mask - 85042 DECLMETHOD get_messages_unsigned_by_id - 120055 DECLMETHOD get_messages_unsigned - 114740 DECLMETHOD get_n_k - 83381 DECLMETHOD merge_inner_queries - unpack_state PROCREF:<{ - // - c4 PUSH // _1 - CTOS // ds - 32 LDU // _4 ds - 8 LDU // _4 _7 ds - 8 LDU // _4 _7 _10 ds - 64 LDU // _4 _7 _10 _13 ds - LDDICT // _4 _7 _10 _13 _16 ds - LDDICT // res res res res res res ds - ENDS - }> - pack_state PROCREF:<{ - // pending_queries owner_infos last_cleaned k n wallet_id - NEWC // pending_queries owner_infos last_cleaned k n wallet_id _6 - 32 STU // pending_queries owner_infos last_cleaned k n _8 - 8 STU // pending_queries owner_infos last_cleaned k _10 - 8 STU // pending_queries owner_infos last_cleaned _12 - 64 STU // pending_queries owner_infos _14 - STDICT // pending_queries _15 - STDICT // _16 - ENDC // _17 - }> - pack_owner_info PROCREF:<{ - // public_key flood - SWAP - NEWC // flood public_key _2 - 256 STU // flood _4 - 8 STU // _6 - }> - unpack_owner_info PROCREF:<{ - // cs - 256 LDU // _1 cs - 8 LDU // _1 _10 _9 - DROP // _1 _4 - }> - check_signatures PROCREF:<{ - // public_keys signatures hash cnt_bits - 0 PUSHINT // public_keys signatures hash cnt_bits cnt=0 - UNTIL:<{ - s0 s3 XCHG // public_keys cnt hash cnt_bits signatures - CTOS // public_keys cnt hash cnt_bits cs - 9 PUSHPOW2 // public_keys cnt hash cnt_bits cs _10=512 - LDSLICEX // public_keys cnt hash cnt_bits signature cs - 8 LDU // public_keys cnt hash cnt_bits signature i cs - LDDICT // public_keys cnt hash cnt_bits signature i _43 _42 - DROP // public_keys cnt hash cnt_bits signature i signatures - s1 s6 PUSH2 - 8 PUSHINT // public_keys cnt hash cnt_bits signature i signatures i public_keys _20=8 - DICTUGET - NULLSWAPIFNOT // public_keys cnt hash cnt_bits signature i signatures public_key found? - 37 THROWIFNOT - 256 PLDU // public_keys cnt hash cnt_bits signature i signatures _26 - s5 s3 s3 PUXC2 // public_keys cnt hash cnt_bits signatures i hash signature _26 - CHKSIGNU // public_keys cnt hash cnt_bits signatures i _27 - 38 THROWIFNOT - POW2 // public_keys cnt hash cnt_bits signatures mask - s2 s(-1) PUXC // public_keys cnt hash old_cnt_bits signatures cnt_bits mask - OR // public_keys cnt hash old_cnt_bits signatures cnt_bits - s0 s2 PUXC // public_keys cnt hash cnt_bits signatures cnt_bits old_cnt_bits - NEQ // public_keys cnt hash cnt_bits signatures should_check - s1 s4 XCHG // public_keys signatures hash cnt_bits cnt should_check - SUB // public_keys signatures hash cnt_bits cnt - s3 PUSH // public_keys signatures hash cnt_bits cnt signatures - ISNULL // public_keys signatures hash cnt_bits cnt _37 - }> // public_keys signatures hash cnt_bits cnt - 2 2 BLKDROP2 - s2 POP // cnt cnt_bits - }> - recv_internal PROC:<{ - // in_msg - DROP // - }> - unpack_query_data PROCREF:<{ - // in_msg n query found? root_i - SWAP // in_msg n query root_i found? - IFJMP:<{ // in_msg n query root_i - DROP // in_msg n query - 1 LDI // in_msg n _6 query - SWAP // in_msg n query _6 - 35 THROWIFNOT - 8 LDU // in_msg n _14 query - 8 LDU // in_msg n _14 _17 query - s0 s3 XCHG2 // in_msg _17 _14 query n - LDUX // in_msg cnt creator_i cnt_bits msg - DUP // in_msg cnt creator_i cnt_bits msg msg - HASHSU // in_msg cnt creator_i cnt_bits msg _23 - s0 s5 XCHG // _23 cnt creator_i cnt_bits msg in_msg - HASHSU // _23 cnt creator_i cnt_bits msg _24 - s1 s5 XCHG // msg cnt creator_i cnt_bits _23 _24 - EQUAL // msg cnt creator_i cnt_bits _25 - 36 THROWIFNOT - s0 s3 XCHG2 // creator_i cnt cnt_bits msg - }> // in_msg n query root_i - 2 1 BLKDROP2 // in_msg root_i - 0 PUSHINT // in_msg root_i _27=0 - s0 s1 s2 XCPUXC // root_i _27=0 _28=0 in_msg - }> - dec_flood PROC:<{ - // owner_infos creator_i - s0 s1 PUSH2 - 8 PUSHINT // owner_infos creator_i creator_i owner_infos _4=8 - DICTUGET - NULLSWAPIFNOT // owner_infos creator_i _15 _16 - DROP // owner_infos creator_i owner_info - unpack_owner_info INLINECALLDICT // owner_infos creator_i public_key flood - DEC // owner_infos creator_i public_key _11 - pack_owner_info INLINECALLDICT // owner_infos creator_i _12 - s0 s2 XCHG - 8 PUSHINT // _12 creator_i owner_infos _13=8 - DICTUSETB // owner_infos - }> - try_init PROCREF:<{ - // - unpack_state INLINECALLDICT // wallet_id n k last_cleaned owner_infos pending_queries - s0 s2 XCHG // wallet_id n k pending_queries owner_infos last_cleaned - 37 THROWIF - ACCEPT - s4 s3 XCHG2 - 1 PUSHINT - s3 s1 s3 XCHG3 // pending_queries owner_infos _10=1 k n wallet_id - pack_state INLINECALLDICT // _11 - c4 POP - }> - update_pending_queries PROCREF:<{ - // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k - s3 s(-1) PUXC // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n cnt k - GEQ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _9 - IF:<{ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n - 3 BLKDROP // pending_queries owner_infos msg query_id creator_i - ACCEPT - WHILE:<{ - s2 PUSH // pending_queries owner_infos msg query_id creator_i msg - SREFS // pending_queries owner_infos msg query_id creator_i _11 - }>DO<{ // pending_queries owner_infos msg query_id creator_i - s0 s2 XCHG // pending_queries owner_infos creator_i query_id msg - 8 LDU // pending_queries owner_infos creator_i query_id mode msg - LDREF // pending_queries owner_infos creator_i query_id mode _16 msg - s0 s2 XCHG // pending_queries owner_infos creator_i query_id msg _16 mode - SENDRAWMSG - s0 s2 XCHG // pending_queries owner_infos msg query_id creator_i - }> // pending_queries owner_infos msg query_id creator_i - s2 POP // pending_queries owner_infos creator_i query_id - 0 PUSHINT // pending_queries owner_infos creator_i query_id _20=0 - NEWC // pending_queries owner_infos creator_i query_id _20=0 _21 - 1 STI // pending_queries owner_infos creator_i query_id _23 - s0 s1 s4 XCHG3 - 64 PUSHINT // creator_i owner_infos _23 query_id pending_queries _24=64 - DICTUSETB // creator_i owner_infos pending_queries - s0 s2 XCHG // pending_queries owner_infos creator_i - dec_flood CALLDICT // pending_queries owner_infos - }>ELSE<{ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n - 1 PUSHINT // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _29=1 - NEWC // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _29=1 _30 - 1 STU // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _32 - s1 s4 XCHG // pending_queries owner_infos msg query_id n cnt cnt_bits creator_i _32 - 8 STU // pending_queries owner_infos msg query_id n cnt cnt_bits _34 - s1 s2 XCHG // pending_queries owner_infos msg query_id n cnt_bits cnt _34 - 8 STU // pending_queries owner_infos msg query_id n cnt_bits _36 - ROT // pending_queries owner_infos msg query_id cnt_bits _36 n - STUX // pending_queries owner_infos msg query_id _37 - ROT // pending_queries owner_infos query_id _37 msg - STSLICER // pending_queries owner_infos query_id _38 - s0 s1 s3 XCHG3 - 64 PUSHINT // owner_infos _38 query_id pending_queries _39=64 - DICTUSETB // owner_infos pending_queries - SWAP // pending_queries owner_infos - }> - }> - calc_boc_size PROC:<{ - // cells bits root - s0 s2 XCHG // root bits cells - INC // root bits cells - s2 PUSH // root bits cells root - SBITS // root bits cells _5 - s1 s2 XCHG // root cells bits _5 - ADD // root cells bits - WHILE:<{ - s2 PUSH // root cells bits root - SREFS // root cells bits _7 - }>DO<{ // root cells bits - s0 s2 XCHG // bits cells root - LDREF // bits cells _8 root - SWAP // bits cells root _8 - CTOS // bits cells root _10 - s1 s3 XCHG // root cells bits _10 - calc_boc_size CALLDICT // root cells bits - }> // root cells bits - 1 2 BLKDROP2 // cells bits - }> - recv_external PROC:<{ - // in_msg - DUP // in_msg in_msg - SEMPTY // in_msg _1 - IFJMP:<{ // in_msg - DROP // - try_init INLINECALLDICT - }> // in_msg - 9 PUSHPOW2 // in_msg _5=512 - LDSLICEX // root_signature in_msg - DUP // root_signature in_msg in_msg - HASHSU // root_signature in_msg root_hash - SWAP // root_signature root_hash in_msg - 8 LDU // root_signature root_hash root_i in_msg - unpack_state INLINECALLDICT // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries - s2 PUSH // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries last_cleaned - 0 EQINT // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries _21 - s1 s3 XCHG // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned _21 - SUB // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned - s7 s1 PUSH2 - 8 PUSHINT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned root_i owner_infos _25=8 - DICTUGET - NULLSWAPIFNOT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned owner_info found? - 31 THROWIFNOT - unpack_owner_info INLINECALLDICT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned public_key flood - s10 s11 s10 XC2PU // flood public_key root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned root_hash root_signature public_key - CHKSIGNU // flood public_key root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned _33 - 32 THROWIFNOT - s0 s6 XCHG // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos in_msg - LDDICT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg - DUP // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg in_msg - HASHSU // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg hash - SWAP // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg - 32 LDU // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_wallet_id in_msg - s1 s8 XCPU // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg query_wallet_id wallet_id - EQUAL // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg _45 - 42 THROWIFNOT - 64 LDU // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg - 0 PUSHINT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _53=0 - s0 s1 PUSH2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _53=0 _54=0 in_msg - calc_boc_size CALLDICT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg cnt bits - SWAP // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg bits cnt - 8 GTINT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg bits _58 - SWAP - 11 PUSHPOW2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _58 bits _59=2048 - GREATER // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _58 _60 - OR // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _61 - 40 THROWIF - s1 s5 PUSH2 - 64 PUSHINT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query_id pending_queries _65=64 - DICTUGET - NULLSWAPIFNOT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? - DUP // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? found? - IFNOT:<{ // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? - s0 s14 XCHG // found? public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood - INC // found? public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood - DUP // found? public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood flood - 10 GTINT // found? public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood _71 - 39 THROWIF - s0 s14 XCHG // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? - }> // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? - NOW // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? _74 - 32 LSHIFT# // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound - s4 s0 PUSH2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound query_id bound - LESS // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound _78 - 33 THROWIF - s3 s10 s2 XCPUXC - s4 s14 PUSH2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound in_msg n query found? root_i - unpack_query_data INLINECALLDICT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg - s15 PUSH // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg root_i - POW2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask - s2 s0 PUSH2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask cnt_bits mask - AND // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask _89 - 34 THROWIF - s1 s2 XCHG // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt msg cnt_bits mask - OR // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt msg cnt_bits - s0 s2 XCHG // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt - INC // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt - s5 PUSH // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt found? - NOT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _95 - s1 s12 PUSH2 // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _95 cnt k - LESS // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _95 _96 - AND // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _97 - s5 PUSH - 15461882265600 PUSHINT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _97 bound _102 - ADD // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _97 _103 - s8 PUSH // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _97 _103 query_id - GREATER // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _97 _104 - AND // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _105 - 41 THROWIF - 100000 PUSHINT // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _107=100000 - SETGASLIMIT - s0 s5 XCHG // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i cnt_bits msg found? - IFNOT:<{ // flood public_key root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i cnt_bits msg - s0 16 s() XCHG - s1 s15 XCHG // msg cnt_bits root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i public_key flood - pack_owner_info INLINECALLDICT // msg cnt_bits root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i _110 - s0 s13 s7 XCHG3 - 8 PUSHINT // msg cnt_bits creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt _110 root_i owner_infos _111=8 - DICTUSETB // msg cnt_bits creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos - s11 s13 XCHG - s0 s5 XCHG // creator_i cnt_bits msg last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound - }>ELSE<{ - s2 16 s() XCHG - s14 POP - s14 POP - DROP // creator_i cnt_bits msg last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound - }> - s6 s5 s11 XC2PU - s3 s14 s7 PUSH3 - 16 s() PUSH - s13 s12 PUSH2 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k - update_pending_queries INLINECALLDICT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos - s1 s0 s10 PUSH3 - s10 s11 s12 PUSH3 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos pending_queries owner_infos last_cleaned k n wallet_id - pack_state INLINECALLDICT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos _114 - c4 POP - COMMIT - 0 PUSHINT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 - s5 PUSH // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 signatures - ISNULL // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _119 - s8 s9 PUSH2 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _119 cnt k - GEQ // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _119 _120 - OR // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _121 - IFNOT:<{ // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 - DROP // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos - s4 s0 s2 XCPUXC - s4 s13 XCHG2 // creator_i query_id msg last_cleaned wallet_id n k cnt bound pending_queries owner_infos owner_infos signatures hash cnt_bits - check_signatures INLINECALLDICT // creator_i query_id msg last_cleaned wallet_id n k cnt bound pending_queries owner_infos new_cnt cnt_bits - s5 s5 XCHG2 // creator_i query_id msg last_cleaned wallet_id n k cnt_bits bound pending_queries owner_infos cnt new_cnt - ADD // creator_i query_id msg last_cleaned wallet_id n k cnt_bits bound pending_queries owner_infos cnt - s6 s5 s0 XCHG3 - s4 s9 XCHG - s3 s10 XCHG - s11 s0 s9 XCHG3 - s11 s9 PUSH2 // n bound k last_cleaned wallet_id pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k - update_pending_queries INLINECALLDICT // n bound k last_cleaned wallet_id pending_queries owner_infos - s5 s4 XCHG2 - s1 s6 XCHG - -1 PUSHINT // bound pending_queries owner_infos last_cleaned wallet_id n k need_save=-1 - }>ELSE<{ - s6 s14 XCHG - s2 s13 XCHG - s12 s7 XCHG2 - 7 BLKDROP // bound pending_queries owner_infos last_cleaned wallet_id n k need_save - }> - ACCEPT - s0 s7 XCHG - 38 PUSHPOW2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound _130 - SUB // need_save pending_queries owner_infos last_cleaned wallet_id n k bound - UNTIL:<{ - s6 PUSH - 64 PUSHINT // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries _137=64 - DICTUREMMIN - NULLSWAPIFNOT2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f - DUP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f f - IF:<{ // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f - DROP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i - s0 s3 PUSH2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i i bound - LESS // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f - }> // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f - DUP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f f - IF:<{ // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' query i f - s8 POP - s9 POP - s9 POP // query i owner_infos f wallet_id n k bound pending_queries' - s0 s8 XCHG // pending_queries' i owner_infos f wallet_id n k bound query - 1 LDI // pending_queries' i owner_infos f wallet_id n k bound _142 query - SWAP // pending_queries' i owner_infos f wallet_id n k bound query _142 - IF:<{ // pending_queries' i owner_infos f wallet_id n k bound query - 8 LDU // pending_queries' i owner_infos f wallet_id n k bound _195 _194 - DROP // pending_queries' i owner_infos f wallet_id n k bound _146 - s1 s6 XCHG // pending_queries' i bound f wallet_id n k owner_infos _146 - dec_flood CALLDICT // pending_queries' i bound f wallet_id n k owner_infos - s0 s5 XCHG // pending_queries' i owner_infos f wallet_id n k bound - }>ELSE<{ - DROP // pending_queries' i owner_infos f wallet_id n k bound - }> // pending_queries last_cleaned owner_infos f wallet_id n k bound - -1 PUSHINT // pending_queries last_cleaned owner_infos f wallet_id n k bound need_save=-1 - s0 s8 XCHG - s0 s7 XCHG - s0 s5 XCHG // need_save=-1 pending_queries owner_infos last_cleaned wallet_id n k bound f - }>ELSE<{ - 3 1 BLKDROP2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound f - }> - NOT // need_save pending_queries owner_infos last_cleaned wallet_id n k bound _151 - }> // need_save pending_queries owner_infos last_cleaned wallet_id n k bound - DROP // need_save pending_queries owner_infos last_cleaned wallet_id n k - s0 s6 XCHG // k pending_queries owner_infos last_cleaned wallet_id n need_save - IF:<{ // k pending_queries owner_infos last_cleaned wallet_id n - s4 s5 XCHG - s3 s4 XCHG - s3 s0 s0 XCHG3 // pending_queries owner_infos last_cleaned k n wallet_id - pack_state INLINECALLDICT // _152 - c4 POP - }>ELSE<{ - 6 BLKDROP // - }> - }> - get_query_state PROC:<{ - // query_id - unpack_state INLINECALLDICT // query_id _28 _29 _30 _31 _32 _33 - NIP - s2 POP - s3 POP // query_id last_cleaned n pending_queries - s3 s(-1) PUXC - 64 PUSHINT // query_id last_cleaned n query_id pending_queries _10=64 - DICTUGET - NULLSWAPIFNOT // query_id last_cleaned n cs found - IFJMP:<{ // query_id last_cleaned n cs - 2 2 BLKDROP2 // n cs - 1 LDI // n _12 cs - SWAP // n cs _12 - IFJMP:<{ // n cs - 16 LDU // n _39 _38 - NIP // n cs - 0 PUSHINT // n cs _20=0 - s0 s2 XCHG // _20=0 cs n - LDUX // _20=0 _41 _40 - DROP // _20=0 _21 - }> // n cs - 2DROP // - -1 PUSHINT // _23=-1 - 0 PUSHINT // _23=-1 _24=0 - }> // query_id last_cleaned n cs - 2DROP // query_id last_cleaned - LEQ // _25 - NEGATE // _26 - 0 PUSHINT // _26 _27=0 - }> - processed? PROC:<{ - // query_id - get_query_state CALLDICT // _4 _5 - DROP // x - }> - create_init_state PROC:<{ - // wallet_id n k owners_info - NEWDICT // wallet_id n k owners_info _4 - s3 s4 XCHG2 - 0 PUSHINT - 3 -ROLL // _4 owners_info _5=0 k n wallet_id - pack_state INLINECALLDICT // _6 - }> - merge_list PROC:<{ - // a b - OVER // a b a - ISNULL // a b _2 - IFJMP:<{ // a b - NIP // b - }> // a b - DUP // a b b - ISNULL // a b _3 - IFJMP:<{ // a b - DROP // a - }> // a b - SWAP // b a - CTOS // b as - DUP // b as as - SREFS // b as _6 - 0 NEQINT // b as _8 - IFJMP:<{ // b as - LDREF // b _10 as - s0 s2 XCHG // as _10 b - merge_list CALLDICT // as tail - NEWC - ROT // tail _13 as - STSLICER // tail _14 - STREF // _15 - ENDC // _16 - }> // b as - 1 PUSHINT // b as _18=1 - SDSKIPLAST // b as - NEWC // b as _20 - SWAP // b _20 as - STSLICER // b _21 - STDICT // _22 - ENDC // _23 - }> - get_public_keys PROC:<{ - // - unpack_state INLINECALLDICT // _7 _8 _9 _10 _11 _12 - s1 s5 XCHG - 5 BLKDROP // public_keys - }> - check_query_signatures PROC:<{ - // query - CTOS // cs - 9 PUSHPOW2 // cs _5=512 - LDSLICEX // root_signature cs - DUP // root_signature cs cs - HASHSU // root_signature cs root_hash - SWAP // root_signature root_hash cs - 8 LDU // root_signature root_hash root_i cs - get_public_keys CALLDICT // root_signature root_hash root_i cs public_keys - s2 s0 PUSH2 - 8 PUSHINT // root_signature root_hash root_i cs public_keys root_i public_keys _17=8 - DICTUGET - NULLSWAPIFNOT // root_signature root_hash root_i cs public_keys public_key found? - 31 THROWIFNOT - 256 PLDU // root_signature root_hash root_i cs public_keys _23 - 5 1 REVERSE // public_keys cs root_i root_hash root_signature _23 - CHKSIGNU // public_keys cs root_i _24 - 32 THROWIFNOT - POW2 // public_keys cs mask - SWAP // public_keys mask cs - LDDICT // public_keys mask signatures cs - OVER // public_keys mask signatures cs signatures - ISNULL // public_keys mask signatures cs _32 - IFJMP:<{ // public_keys mask signatures cs - 2DROP - 1 PUSHINT - s2 POP // _33=1 mask - }> // public_keys mask signatures cs - HASHSU // public_keys mask signatures _35 - ROT // public_keys signatures _35 mask - check_signatures INLINECALLDICT // cnt mask - SWAP // mask cnt - INC // mask _38 - SWAP // _38 mask - }> - messages_by_mask PROC:<{ - // mask - unpack_state INLINECALLDICT // mask _32 _33 _34 _35 _36 _37 - s5 POP - 3 BLKDROP // mask pending_queries n - -1 PUSHINT // mask pending_queries n i=-1 - NEWDICT // mask pending_queries n i=-1 a - UNTIL:<{ - s1 s3 XCPU - 64 PUSHINT // mask pending_queries n a i pending_queries _14=64 - DICTUGETNEXT - NULLSWAPIFNOT2 // mask pending_queries n a cs i f - DUP // mask pending_queries n a cs i f f - IF:<{ // mask pending_queries n a cs i f - s0 s2 XCHG // mask pending_queries n a f i cs - 1 LDI // mask pending_queries n a f i _16 cs - SWAP // mask pending_queries n a f i cs _16 - IF:<{ // mask pending_queries n a f i cs - DUP - 16 PUSHINT // mask pending_queries n a f i cs cs _22 - SDSKIPFIRST // mask pending_queries n a f i cs _23 - s5 PUSH // mask pending_queries n a f i cs _23 n - PLDUX // mask pending_queries n a f i cs cnt_bits - s7 PUSH // mask pending_queries n a f i cs cnt_bits mask - AND // mask pending_queries n a f i cs _25 - IF:<{ // mask pending_queries n a f i cs - NEWC // mask pending_queries n a f i cs _27 - SWAP // mask pending_queries n a f i _27 cs - STSLICER // mask pending_queries n a f i _28 - s0 s0 s3 XCPUXC - 64 PUSHINT // mask pending_queries n i f _28 i a _29=64 - DICTUSETB // mask pending_queries n i f a - s0 s2 XCHG // mask pending_queries n a f i - }>ELSE<{ - DROP // mask pending_queries n a f i - }> - }>ELSE<{ - DROP // mask pending_queries n a f i - }> - }>ELSE<{ - s2 POP // mask pending_queries n a f i - }> - SWAP // mask pending_queries n a i f - NOT // mask pending_queries n a i _31 - s1 s2 XCHG // mask pending_queries n i a _31 - }> // mask pending_queries n i a - 4 1 BLKDROP2 // a - }> - get_messages_unsigned_by_id PROC:<{ - // id - POW2 // _2 - messages_by_mask CALLDICT // _3 - }> - get_messages_unsigned PROC:<{ - // - 0 PUSHINT // _0=0 - NOT // _1 - messages_by_mask CALLDICT // _2 - }> - get_n_k PROC:<{ - // - unpack_state INLINECALLDICT // _7 _8 _9 _10 _11 _12 - 3 BLKDROP - 1 2 BLKDROP2 // n k - }> - merge_inner_queries PROC:<{ - // a b - SWAP // b a - CTOS // b ca - SWAP // ca b - CTOS // ca cb - SWAP // cb ca - LDDICT // cb list_a ca - s0 s2 XCHG // ca list_a cb - LDDICT // ca list_a list_b cb - s3 PUSH // ca list_a list_b cb ca - HASHSU // ca list_a list_b cb _13 - SWAP // ca list_a list_b _13 cb - HASHSU // ca list_a list_b _13 _14 - EQUAL // ca list_a list_b _15 - 31 THROWIFNOT - merge_list CALLDICT // ca _17 - NEWC // ca _17 _18 - STDICT // ca _19 - SWAP // _19 ca - STSLICER // _20 - ENDC // _21 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.cpp deleted file mode 100644 index 83fa2b0c..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("payment-channel", "te6ccgECIwEAA/0AART/APSkE/S88sgLAQIBIAIDAgLOBAUACvJwAfAOAgEgBgcCASAPEAIBIAgJAgEgCgsAB0MfAOgALV0NMf0x/T/9P/1AHQAdQB0AHTP/oA0YAgEgDA4CASANDgCLALSAFMBmDDUAdCDCNcZ3gHSAFMBmDDUAdCDCNcZ3iH5ASWcgB9UQWj5EBTy9BAkkjQ14iGagCBDVvkQFPL0EpM1MzDiAYAA1HDIygIXygAVygBQA/oCAfoCyx8B+gIB+gLJgAB80gDSAPoA+gDTH/oA+gAwgAgEgERICASAYGQIBIBMUAgEgFRYANRxyMoCF8oAFcoAUAP6AgH6AssfAfoCAfoCyYABBIIQN/54EHCAEMjLBVAGzxZQBPoCFMtqEssfyz/JAfsAgAGs+ABQVqEjo1IQuZMwIqPeUwK8kjAh3lEzoFAjoVQzNHPwCVQgBIEAg/AJcsjKAlj6AgH6AsmAB9wJ8AUiwACYMvgjUAigUAeROOIM0x+CEEMniihSILqOGBAmXwY1NTY2gCMC+CO5EvL0cFIFUGPwCuCAJIIQJzF4IhO6EvL0+gD6APoA+gDTPzCAJ1EbuvL0gCFTQ6ABERIBuQEREQHy8oAiU+i5U+i5sfL0UOKgUI2gUFuAXAJCxUya5kjIVkTbiUCixU3q5kzcQaZE64lM5sI4jMTI3UFehUWa8USO8ErGXcFIFFhTwCuATXwNwVHAAIFUU8AjgMjMzN0BD8AYCASAaGwTxQgxwCRW+DTHyHBApJfA+CAKIIQkSg40RO6EvL02zwh8ANUOlTwBCrQ0wJwUiC6jho8K08TJFEhVhFUSjAqAgEREAFSoBEU8AsJCJUQLzs9MOJxUsC6jhU5J1RBZVMEEGwQXxBJVBCv8AxHFFmVMBA7bEPiche64w+B4fICEC9wJ8AciwACYMvgjUAegUAaRN+IN0x+CEEMniihSILqOGFszMzY2NjaAIwT4I7kU8vQWEDUQNFnwCuCAJYIQ8orhgxO6EvL0gCJT1rlT1rmx8vRRXLFRS7EF+gD6ANIAAY4TO1s5gCZQurAZ8vRwIBCKB1CZCOMNCdM/+gCAcHQBvAPTHzCAJYIQN/54EBK68vQD+gD6ADCAKVMhoIIQO5rKAKD4J28QufL0+ABUFANz8AlZgQCD8AmAAZtQB0IMI1xkh+QEREJE9njOAH1RvT/kQHfL0G3AC4g2VEC06OjCcMIAgTbr5EBjy9HAH4gB6+gAwgCdRP7oT8vT4AFAJoFy5kTGRMOJQdqBTcLmRN5Ew4lNQsJwwNDUWEDUQNEAz8ArgbCI3ECZFQBLwCAAM7UTQ1NTRAAwQJF4y8A0ACF8DbCIBBNs8IgAOAcjMzMntVA=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.fif deleted file mode 100644 index e0492077..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/payment-channel-code.fif +++ /dev/null @@ -1,648 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/payment-channel-code.fc` -PROGRAM{ - DECLPROC unpack_data - DECLPROC pack_data - DECLPROC unpack_config - DECLPROC unwrap_signatures - DECLPROC unpack_state_init - DECLPROC pack_state_init - DECLPROC unpack_state_close - DECLPROC pack_state_close - DECLPROC send_payout - DECLPROC do_payout - DECLPROC with_init - DECLPROC with_close - DECLPROC with_payout - DECLPROC recv_any - DECLPROC recv_internal - DECLPROC recv_external - unpack_data PROCREF:<{ - // - c4 PUSH // _1 - CTOS // cs - LDREF // _4 cs - LDREF // res res cs - ENDS - }> - pack_data PROCREF:<{ - // config state - SWAP - NEWC // state config _2 - STREF // state _3 - STREF // _4 - ENDC // _5 - c4 POP - }> - unpack_config PROC:<{ - // config - CTOS // cs - 32 LDU // _4 cs - 32 LDU // _4 _7 cs - 256 LDU // _4 _7 _10 cs - 256 LDU // _4 _7 _10 _13 cs - LDREF // _4 _7 _10 _13 _16 cs - SWAP // _4 _7 _10 _13 cs _16 - CTOS // _4 _7 _10 _13 cs _18 - SWAP // _4 _7 _10 _13 _18 cs - LDREF // _4 _7 _10 _13 _18 _19 cs - SWAP // _4 _7 _10 _13 _18 cs _19 - CTOS // _4 _7 _10 _13 _18 cs _21 - SWAP // _4 _7 _10 _13 _18 _21 cs - 64 LDU // _4 _7 _10 _13 _18 _21 _22 cs - LDGRAMS // res res res res res res res res cs - ENDS - }> - unwrap_signatures PROC:<{ - // cs a_key b_key - s0 s2 XCHG // b_key a_key cs - 1 LDI // b_key a_key a? cs - s0 s1 PUSH2 // b_key a_key a? cs a_sig a? - IF:<{ // b_key a_key a? cs a_sig - DROP // b_key a_key a? cs - LDREF // b_key a_key a? _8 cs - SWAP // b_key a_key a? cs _8 - CTOS // b_key a_key a? cs _10 - 9 PUSHPOW2 // b_key a_key a? cs _10 _11=512 - PLDSLICEX // b_key a_key a? cs a_sig - }> // b_key a_key a? cs a_sig - SWAP // b_key a_key a? a_sig cs - 1 LDI // b_key a_key a? a_sig b? cs - s0 s1 PUSH2 // b_key a_key a? a_sig b? cs b_sig b? - IF:<{ // b_key a_key a? a_sig b? cs b_sig - DROP // b_key a_key a? a_sig b? cs - LDREF // b_key a_key a? a_sig b? _18 cs - SWAP // b_key a_key a? a_sig b? cs _18 - CTOS // b_key a_key a? a_sig b? cs _20 - 9 PUSHPOW2 // b_key a_key a? a_sig b? cs _20 _21=512 - PLDSLICEX // b_key a_key a? a_sig b? cs b_sig - }> // b_key a_key a? a_sig b? cs b_sig - OVER // b_key a_key a? a_sig b? cs b_sig cs - HASHSU // b_key a_key a? a_sig b? cs b_sig hash - s5 PUSH // b_key a_key a? a_sig b? cs b_sig hash a? - IF:<{ // b_key a_key a? a_sig b? cs b_sig hash - 31 PUSHINT // b_key a_key a? a_sig b? cs b_sig hash _25 - s1 s5 s7 PUXC2 // b_key hash a? _25 b? cs b_sig hash a_sig a_key - CHKSIGNU // b_key hash a? _25 b? cs b_sig _26 - s1 s4 XCHG // b_key hash a? b_sig b? cs _25 _26 - THROWANYIFNOT - s2 s4 XCHG // b_key b_sig a? hash b? cs - }>ELSE<{ - s4 POP - s5 POP // b_key b_sig a? hash b? cs - }> - OVER // b_key b_sig a? hash b? cs b? - IF:<{ // b_key b_sig a? hash b? cs - 32 PUSHINT // b_key b_sig a? hash b? cs _28 - s3 s5 s6 XCHG3 // _28 cs a? b? hash b_sig b_key - CHKSIGNU // _28 cs a? b? _29 - s1 s4 XCHG // b? cs a? _28 _29 - THROWANYIFNOT - s1 s2 XCHG // cs b? a? - }>ELSE<{ - s5 POP - s3 POP - DROP // cs b? a? - }> - SWAP // cs a? b? - }> - unpack_state_init PROC:<{ - // state - 1 LDI // _1 state - 1 LDI // _1 _4 state - LDGRAMS // _1 _4 _7 state - LDGRAMS // _1 _4 _7 _9 state - 32 LDU // _1 _4 _7 _9 _11 state - LDGRAMS // _1 _4 _7 _9 _11 _14 state - LDGRAMS // _1 _4 _7 _9 _11 _14 _31 _30 - DROP // _1 _4 _7 _9 _11 _14 _16 - }> - pack_state_init PROC:<{ - // signed_A? signed_B? min_A min_B expire_at A B - 0 PUSHINT // signed_A? signed_B? min_A min_B expire_at A B _7 - NEWC // signed_A? signed_B? min_A min_B expire_at A B _7 _8 - 3 STI // signed_A? signed_B? min_A min_B expire_at A B _10 - s1 s7 XCHG // B signed_B? min_A min_B expire_at A signed_A? _10 - 1 STI // B signed_B? min_A min_B expire_at A _12 - s1 s5 XCHG // B A min_A min_B expire_at signed_B? _12 - 1 STI // B A min_A min_B expire_at _14 - s0 s3 XCHG2 // B A expire_at min_B _14 min_A - STGRAMS // B A expire_at min_B _15 - SWAP // B A expire_at _15 min_B - STGRAMS // B A expire_at _16 - 32 STU // B A _18 - SWAP // B _18 A - STGRAMS // B _19 - SWAP // _19 B - STGRAMS // _20 - ENDC // _21 - }> - unpack_state_close PROC:<{ - // state - 1 LDI // _1 state - 1 LDI // _1 _4 state - LDGRAMS // _1 _4 _7 state - LDGRAMS // _1 _4 _7 _9 state - 32 LDU // _1 _4 _7 _9 _11 state - LDGRAMS // _1 _4 _7 _9 _11 _14 state - LDGRAMS // _1 _4 _7 _9 _11 _14 _31 _30 - DROP // _1 _4 _7 _9 _11 _14 _16 - }> - pack_state_close PROC:<{ - // signed_A? signed_B? promise_A promise_B expire_at A B - 1 PUSHINT // signed_A? signed_B? promise_A promise_B expire_at A B _7 - NEWC // signed_A? signed_B? promise_A promise_B expire_at A B _7 _8 - 3 STI // signed_A? signed_B? promise_A promise_B expire_at A B _10 - s1 s7 XCHG // B signed_B? promise_A promise_B expire_at A signed_A? _10 - 1 STI // B signed_B? promise_A promise_B expire_at A _12 - s1 s5 XCHG // B A promise_A promise_B expire_at signed_B? _12 - 1 STI // B A promise_A promise_B expire_at _14 - s0 s3 XCHG2 // B A expire_at promise_B _14 promise_A - STGRAMS // B A expire_at promise_B _15 - SWAP // B A expire_at _15 promise_B - STGRAMS // B A expire_at _16 - 32 STU // B A _18 - SWAP // B _18 A - STGRAMS // B _19 - SWAP // _19 B - STGRAMS // _20 - ENDC // _21 - }> - send_payout PROC:<{ - // s_addr amount channel_id flags - 0x37fe7810 PUSHINT // s_addr amount channel_id flags _4 - 0 PUSHINT // s_addr amount channel_id flags _4 _5=0 - 16 PUSHINT // s_addr amount channel_id flags _4 _5=0 _6=16 - NEWC // s_addr amount channel_id flags _4 _5=0 _6=16 _7 - 6 STU // s_addr amount channel_id flags _4 _5=0 _9 - s0 s6 XCHG2 // _5=0 amount channel_id flags _4 _9 s_addr - STSLICER // _5=0 amount channel_id flags _4 _10 - s0 s4 XCHG2 // _5=0 _4 channel_id flags _10 amount - STGRAMS // _5=0 _4 channel_id flags _11 - s1 s4 XCHG // flags _4 channel_id _5=0 _11 - 107 STU // flags _4 channel_id _25 - s1 s2 XCHG // flags channel_id _4 _25 - 32 STU // flags channel_id _27 - 64 STU // flags _29 - ENDC // flags _30 - SWAP // _30 flags - SENDRAWMSG - }> - do_payout PROC:<{ - // promise_A promise_B A B a_addr b_addr channel_id - ACCEPT - s5 s6 XCHG2 // channel_id b_addr A B a_addr promise_B promise_A - SUB // channel_id b_addr A B a_addr diff - s3 PUSH // channel_id b_addr A B a_addr diff A - NEGATE // channel_id b_addr A B a_addr diff _10 - s1 s(-1) PUXC // channel_id b_addr A B a_addr diff diff _10 - LESS // channel_id b_addr A B a_addr diff _11 - IF:<{ // channel_id b_addr A B a_addr diff - DROP // channel_id b_addr A B a_addr - s2 PUSH // channel_id b_addr A B a_addr A - NEGATE // channel_id b_addr A B a_addr diff - }> // channel_id b_addr A B a_addr diff - s0 s2 PUSH2 // channel_id b_addr A B a_addr diff diff B - GREATER // channel_id b_addr A B a_addr diff _13 - IF:<{ // channel_id b_addr A B a_addr diff - DROP // channel_id b_addr A B a_addr - OVER // channel_id b_addr A B a_addr diff - }> // channel_id b_addr A B a_addr diff - s3 s3 XCPU // channel_id b_addr diff B a_addr A diff - ADD // channel_id b_addr diff B a_addr A - s2 s3 XCHG2 // channel_id b_addr A a_addr B diff - SUB // channel_id b_addr A a_addr B - s3 s3 s4 XCPU2 - 3 PUSHINT // channel_id B A a_addr b_addr B channel_id _16=3 - send_payout CALLDICT - s0 s0 s3 XCPUXC - 131 PUSHINT // A B a_addr A channel_id _20 - send_payout CALLDICT - 2 PUSHINT // A B _22 - NEWC // A B _22 _23 - 3 STI // A B _25 - ROT // B _25 A - STGRAMS // B _26 - SWAP // _26 B - STGRAMS // _27 - ENDC // _28 - }> - with_init PROC:<{ - // state msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id min_A_extra - s0 s9 XCHG // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id state - unpack_state_init CALLDICT // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B expire_at A B - s2 PUSH // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B expire_at A B expire_at - 0 EQINT // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B expire_at A B _19 - IF:<{ // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B expire_at A B - s2 POP // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B B A - NOW // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id signed_A? signed_B? min_A min_B B A _20 - s0 s8 XCHG2 // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr A channel_id signed_A? signed_B? min_A min_B B _20 init_timeout - ADD // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr A channel_id signed_A? signed_B? min_A min_B B expire_at - s0 s7 XCHG2 // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at A - }>ELSE<{ - s8 POP // min_A_extra msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at A - }> - s0 s12 XCHG // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at msg - 32 LDU // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg - 0x43278a28 PUSHINT // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg _26 - s2 s(-1) PUXC // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg op _26 - EQUAL // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg _27 - IFJMP:<{ // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg - s2 s6 XCHG - 6 BLKDROP - s5 POP - s5 POP - s6 POP - s6 POP // b_addr B A channel_id expire_at a_addr - 35 PUSHINT // b_addr B A channel_id expire_at a_addr _28 - s0 s2 XCHG - NOW // b_addr B A channel_id _28 a_addr expire_at _29 - LESS // b_addr B A channel_id _28 a_addr _30 - s1 s2 XCHG // b_addr B A channel_id a_addr _28 _30 - THROWANYIFNOT - 0 PUSHINT // b_addr B A channel_id a_addr _32=0 - s0 s4 PUXC - s6 s3 XCHG2 // _32=0 _33=0 A B a_addr b_addr channel_id - do_payout CALLDICT // _34 - }> // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg - 36 PUSHINT // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg _35 - 0x27317822 PUSHINT // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at op msg _35 _36 - s1 s3 XCHG // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _35 msg op _36 - EQUAL // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _35 msg _37 - s1 s2 XCHG // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at msg _35 _37 - THROWANYIFNOT - LDGRAMS // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _44 msg - LDGRAMS // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _44 _46 msg - LDGRAMS // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _44 _46 _48 msg - LDGRAMS // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _44 _46 _48 _50 msg - 64 LDU // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at _44 _46 _48 _50 _106 _105 - DROP // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B got_channel_id - 39 PUSHINT // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B got_channel_id _55 - s1 s11 XCPU // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _55 got_channel_id channel_id - EQUAL // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _55 _56 - THROWANYIFNOT - 33 PUSHINT // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _58 - s4 s3 PUSH2 // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _58 inc_A inc_B - ADD // min_A_extra msg_value A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _58 _59 - s1 18 s() XCHG // min_A_extra _58 A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B msg_value _59 - LESS // min_A_extra _58 A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A upd_min_B _60 - s1 17 s() XCHG // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _58 _60 - THROWANYIF - 34 PUSHINT // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 - s14 s8 PUSH2 // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 msg_signed_A? signed_A? - LESS // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 _63 - s14 s8 PUSH2 // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 _63 msg_signed_B? signed_B? - LESS // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 _63 _64 - OR // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at inc_A inc_B upd_min_A _62 _65 - THROWANYIFNOT - s14 s2 XCHG2 // min_A_extra upd_min_B inc_B msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at upd_min_A A inc_A - ADD // min_A_extra upd_min_B inc_B msg_signed_A? msg_signed_B? a_addr b_addr B channel_id signed_A? signed_B? min_A min_B expire_at upd_min_A A - s8 s13 XCHG2 // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr upd_min_A channel_id signed_A? signed_B? min_A min_B expire_at B inc_B - ADD // min_A_extra upd_min_B A msg_signed_A? msg_signed_B? a_addr b_addr upd_min_A channel_id signed_A? signed_B? min_A min_B expire_at B - s5 s11 XCHG2 // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr upd_min_A channel_id expire_at signed_B? min_A min_B signed_A? msg_signed_A? - OR // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr upd_min_A channel_id expire_at signed_B? min_A min_B signed_A? - s2 s6 PUSH2 // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr upd_min_A channel_id expire_at signed_B? min_A min_B signed_A? min_A upd_min_A - LESS // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr upd_min_A channel_id expire_at signed_B? min_A min_B signed_A? _70 - IF:<{ // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr upd_min_A channel_id expire_at signed_B? min_A min_B signed_A? - s2 POP // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr min_A channel_id expire_at signed_B? signed_A? min_B - s1 s5 XCHG // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr signed_A? channel_id expire_at signed_B? min_A min_B - }>ELSE<{ - s6 POP // min_A_extra upd_min_B A B msg_signed_B? a_addr b_addr signed_A? channel_id expire_at signed_B? min_A min_B - }> - s2 s8 XCHG2 // min_A_extra upd_min_B A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_B? msg_signed_B? - OR // min_A_extra upd_min_B A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_B? - s7 s10 PUSH2 // min_A_extra upd_min_B A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_B? min_B upd_min_B - LESS // min_A_extra upd_min_B A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_B? _72 - IF:<{ // min_A_extra upd_min_B A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_B? - s7 POP // min_A_extra min_B A B signed_B? a_addr b_addr signed_A? channel_id expire_at min_A - s6 s9 XCHG // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A - }>ELSE<{ - s10 POP // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A - }> - s3 s9 PUSH2 // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A signed_A? signed_B? - AND // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A _73 - IFJMP:<{ // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A - NIP - s2 POP - s7 POP // min_A_extra channel_id A B min_B a_addr b_addr min_A - s5 s7 XCHG2 // min_A channel_id b_addr B min_B a_addr A min_A_extra - SUB // min_A channel_id b_addr B min_B a_addr A - s6 s6 XCPU // A channel_id b_addr B min_B a_addr min_A A - GREATER // A channel_id b_addr B min_B a_addr _75 - s2 s3 XCPU // A channel_id b_addr B _75 a_addr min_B B - GREATER // A channel_id b_addr B _75 a_addr _76 - s1 s2 XCHG // A channel_id b_addr B a_addr _75 _76 - OR // A channel_id b_addr B a_addr _77 - IFJMP:<{ // A channel_id b_addr B a_addr - 0 PUSHINT // A channel_id b_addr B a_addr _78=0 - s0 s4 PUXC - s1 s6 XCHG - s1 s4 XCHG // _78=0 _79=0 A B a_addr b_addr channel_id - do_payout CALLDICT // _80 - }> // A channel_id b_addr B a_addr - s1 s3 XCHG - 3 BLKDROP // A B - 0 PUSHINT // A B _81=0 - s0 s0 s0 PUSH3 // A B _81=0 _82=0 _83=0 _84=0 - DUP // A B _81=0 _82=0 _83=0 _84=0 _85=0 - 2 5 BLKSWAP // _81=0 _82=0 _83=0 _84=0 _85=0 A B - pack_state_close CALLDICT // _86 - }> // min_A_extra signed_B? A B min_B a_addr b_addr signed_A? channel_id expire_at min_A - s2 POP - s3 POP - s3 POP - s7 POP // signed_A? signed_B? A B min_B min_A expire_at - s0 s4 s3 XCHG3 // signed_A? signed_B? min_A min_B expire_at A B - pack_state_init CALLDICT // _87 - }> - with_close PROC:<{ - // cs msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout channel_id - s0 s9 XCHG // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout cs - unpack_state_close CALLDICT // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B expire_at A B - s2 PUSH // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B expire_at A B expire_at - 0 EQINT // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B expire_at A B _19 - IF:<{ // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B expire_at A B - s2 POP // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B B A - NOW // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr expire_timeout signed_A? signed_B? promise_A promise_B B A _20 - s0 s7 XCHG2 // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr A signed_A? signed_B? promise_A promise_B B _20 expire_timeout - ADD // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr A signed_A? signed_B? promise_A promise_B B expire_at - s0 s6 XCHG2 // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at A - }>ELSE<{ - s7 POP // channel_id msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at A - }> - s0 s13 XCHG // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg - 32 LDU // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg - 0x43278a28 PUSHINT // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg _26 - s2 s(-1) PUXC // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg op _26 - EQUAL // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg _27 - IFJMP:<{ // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg - 2DROP - s3 POP - s3 POP - s6 POP - s6 POP - s6 POP - s6 POP // channel_id A B promise_B expire_at promise_A a_addr b_addr - 35 PUSHINT // channel_id A B promise_B expire_at promise_A a_addr b_addr _28 - s0 s4 XCHG - NOW // channel_id A B promise_B _28 promise_A a_addr b_addr expire_at _29 - LESS // channel_id A B promise_B _28 promise_A a_addr b_addr _30 - s1 s4 XCHG // channel_id A B promise_B b_addr promise_A a_addr _28 _30 - THROWANYIFNOT - s1 s6 XCHG - s3 s5 XCHG - s3 s4 XCHG - -ROT // promise_A promise_B A B a_addr b_addr channel_id - do_payout CALLDICT // _32 - }> // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg - 37 PUSHINT // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg _33 - 0xf28ae183 PUSHINT // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at op msg _33 _34 - s1 s3 XCHG // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at _33 msg op _34 - EQUAL // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at _33 msg _35 - s1 s2 XCHG // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _33 _35 - THROWANYIFNOT - 34 PUSHINT // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 - s13 s6 PUSH2 // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 msg_signed_A? signed_A? - LESS // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 _38 - s13 s6 PUSH2 // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 _38 msg_signed_B? signed_B? - LESS // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 _38 _39 - OR // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_A? signed_B? promise_A promise_B expire_at msg _37 _40 - THROWANYIFNOT - s5 s12 XCPU // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B msg signed_B? promise_A promise_B expire_at signed_A? msg_signed_A? - OR // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B msg signed_B? promise_A promise_B expire_at signed_A? - s4 s11 XCPU // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B msg signed_A? promise_A promise_B expire_at signed_B? msg_signed_B? - OR // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B msg signed_A? promise_A promise_B expire_at signed_B? - s0 s5 XCHG // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at msg - LDGRAMS // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at _46 msg - LDGRAMS // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg - 1 LDI // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B has_sig msg - SWAP // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg has_sig - IF:<{ // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg - LDREF // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B _55 msg - SWAP // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg _55 - CTOS // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg _57 - 9 PUSHPOW2 // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg _57 _58=512 - PLDSLICEX // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg sig - OVER // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg sig msg - HASHSU // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg sig hash - s0 16 s() XCHG // channel_id A hash msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg sig msg_signed_A? - IFNOT:<{ // channel_id A hash msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg sig - s3 POP // channel_id A hash msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at sig extra_B msg - 31 PUSHINT // channel_id A hash msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at sig extra_B msg _62 - s15 s3 s13 PU2XC // channel_id A hash msg_signed_B? _62 b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at sig extra_B msg hash sig a_key - CHKSIGNU // channel_id A hash msg_signed_B? _62 b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at sig extra_B msg _63 - s1 s13 XCHG // channel_id A hash msg_signed_B? msg b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at sig extra_B _62 _63 - THROWANYIFNOT - s1 s11 XCHG - 0 PUSHINT - s0 s2 XCHG // channel_id A hash msg_signed_B? sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A=0 extra_B msg - }>ELSE<{ - s13 POP // channel_id A hash msg_signed_B? sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg - }> - s0 s13 XCHG // channel_id A hash msg sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg_signed_B? - IFNOT:<{ // channel_id A hash msg sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B - DROP // channel_id A hash msg sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A - 32 PUSHINT // channel_id A hash msg sig b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A _66 - s13 s11 s10 XCHG3 // channel_id A expire_at msg extra_A _66 a_addr b_addr B signed_B? signed_A? promise_A promise_B hash sig b_key - CHKSIGNU // channel_id A expire_at msg extra_A _66 a_addr b_addr B signed_B? signed_A? promise_A promise_B _67 - s1 s8 XCHG // channel_id A expire_at msg extra_A promise_B a_addr b_addr B signed_B? signed_A? promise_A _66 _67 - THROWANYIFNOT - 0 PUSHINT // channel_id A expire_at msg extra_A promise_B a_addr b_addr B signed_B? signed_A? promise_A extra_B=0 - s0 s7 XCHG // channel_id A expire_at msg extra_A extra_B=0 a_addr b_addr B signed_B? signed_A? promise_A promise_B - }>ELSE<{ - s2 s13 XCHG - s10 POP - s10 POP - DROP // channel_id A expire_at msg extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A promise_B - }> - }>ELSE<{ // channel_id A msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr B signed_B? signed_A? promise_A promise_B expire_at extra_A extra_B msg - s11 POP - 2DROP - s9 POP // channel_id A msg_signed_A? msg_signed_B? expire_at msg a_addr b_addr B signed_B? signed_A? promise_A promise_B - 38 PUSHINT // channel_id A msg_signed_A? msg_signed_B? expire_at msg a_addr b_addr B signed_B? signed_A? promise_A promise_B _70 - s11 s10 XCHG2 // channel_id A promise_B _70 expire_at msg a_addr b_addr B signed_B? signed_A? promise_A msg_signed_A? msg_signed_B? - AND // channel_id A promise_B _70 expire_at msg a_addr b_addr B signed_B? signed_A? promise_A _71 - s1 s9 XCHG // channel_id A promise_B promise_A expire_at msg a_addr b_addr B signed_B? signed_A? _70 _71 - THROWANYIFNOT - 0 PUSHINT // channel_id A promise_B promise_A expire_at msg a_addr b_addr B signed_B? signed_A? extra_A=0 - DUP // channel_id A promise_B promise_A expire_at msg a_addr b_addr B signed_B? signed_A? extra_A=0 extra_B=0 - s8 s10 XCHG - s0 s7 XCHG - s9 s9 XCHG2 - s0 s8 XCHG // channel_id A expire_at msg extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A promise_B - }> - s0 s9 XCHG // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A msg - 64 LDU // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A _78 msg - LDGRAMS // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A _78 _81 msg - LDGRAMS // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A _78 _81 _118 _117 - DROP // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A got_channel_id update_promise_A update_promise_B - 39 PUSHINT // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A got_channel_id update_promise_A update_promise_B _85 - s3 s15 XCPU // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A _85 update_promise_A update_promise_B got_channel_id channel_id - EQUAL // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A _85 update_promise_A update_promise_B _86 - s1 s3 XCHG // channel_id A expire_at promise_B extra_A extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_B update_promise_A _85 _86 - THROWANYIFNOT - ACCEPT - s0 s9 XCHG2 // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_A extra_A - ADD // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_A - 2DUP // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_A promise_A update_promise_A - LESS // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_A _90 - IF:<{ // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A update_promise_A - NIP // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A - }>ELSE<{ - DROP // channel_id A expire_at promise_B update_promise_B extra_B a_addr b_addr B signed_B? signed_A? promise_A - }> - s7 s6 XCHG2 // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? update_promise_B extra_B - ADD // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? update_promise_B - s7 s0 PUSH2 // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? update_promise_B promise_B update_promise_B - LESS // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? update_promise_B _92 - IF:<{ // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? update_promise_B - s7 POP // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? - }>ELSE<{ - DROP // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? - }> - s5 s0 PUSH2 // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? signed_A? signed_B? - AND // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? _93 - IFJMP:<{ // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? - DROP - s4 POP - s5 POP // channel_id A b_addr promise_B B promise_A a_addr - s1 s6 XCHG - s3 s5 XCHG - s3 s4 XCHG - s0 s3 s3 XCHG3 // promise_A promise_B A B a_addr b_addr channel_id - do_payout CALLDICT // _94 - }> // channel_id A expire_at promise_B signed_A? promise_A a_addr b_addr B signed_B? - 2 2 BLKDROP2 - s7 POP // signed_B? A expire_at promise_B signed_A? promise_A B - s2 s6 XCHG - s5 s4 s0 XCHG3 - s1 s2 XCHG // signed_A? signed_B? promise_A promise_B expire_at A B - pack_state_close CALLDICT // _95 - }> - with_payout PROC:<{ - // cs msg a_addr b_addr channel_id - s0 s3 XCHG // cs channel_id a_addr b_addr msg - 32 LDU // cs channel_id a_addr b_addr _35 _34 - DROP // cs channel_id a_addr b_addr op - 37 PUSHINT // cs channel_id a_addr b_addr op _9 - 0x37fe7810 PUSHINT // cs channel_id a_addr b_addr op _9 _10 - s1 s2 XCHG // cs channel_id a_addr b_addr _9 op _10 - EQUAL // cs channel_id a_addr b_addr _9 _11 - THROWANYIFNOT - s0 s3 XCHG // b_addr channel_id a_addr cs - LDGRAMS // b_addr channel_id a_addr _15 cs - LDGRAMS // b_addr channel_id a_addr _15 _39 _38 - DROP // b_addr channel_id a_addr A B - 41 PUSHINT // b_addr channel_id a_addr A B _19 - s2 s1 PUSH2 // b_addr channel_id a_addr A B _19 A B - ADD // b_addr channel_id a_addr A B _19 _20 - 1000000000 PUSHINT // b_addr channel_id a_addr A B _19 _20 _21=1000000000 - ADD // b_addr channel_id a_addr A B _19 _22 - BALANCE // b_addr channel_id a_addr A B _19 _22 _23 - FIRST // b_addr channel_id a_addr A B _19 _22 _24 - LESS // b_addr channel_id a_addr A B _19 _25 - THROWANYIFNOT - ACCEPT - s4 s0 s3 XC2PU - 3 PUSHINT // A channel_id a_addr b_addr B channel_id _28=3 - send_payout CALLDICT - -ROT - 131 PUSHINT // a_addr A channel_id _32 - send_payout CALLDICT - }> - recv_any PROC:<{ - // msg_value msg - DUP // msg_value msg msg - SEMPTY // msg_value msg _2 - IFJMP:<{ // msg_value msg - 2DROP // - }> // msg_value msg - 32 LDU // msg_value op msg - OVER // msg_value op msg op - 2 LESSINT // msg_value op msg _8 - IFJMP:<{ // msg_value op msg - 3 BLKDROP // - }> // msg_value op msg - 40 PUSHINT // msg_value op msg _9 - 0x912838d1 PUSHINT // msg_value op msg _9 _10 - s1 s3 XCHG // msg_value _9 msg op _10 - EQUAL // msg_value _9 msg _11 - s1 s2 XCHG // msg_value msg _9 _11 - THROWANYIFNOT - unpack_data INLINECALLDICT // msg_value msg config state - OVER // msg_value msg config state config - unpack_config CALLDICT // msg_value msg config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id min_A_extra - s10 s5 s4 XCPU2 // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg a_key b_key - unwrap_signatures CALLDICT // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? - s10 PUSH // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state - CTOS // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? cs - 3 LDU // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type cs - 0 PUSHINT // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type cs _35 - s2 s(-1) PUXC // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type cs state_type _35 - EQUAL // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type cs _36 - IF:<{ // msg_value min_A_extra config state init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type cs - s12 POP // msg_value min_A_extra config cs init_timeout close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? msg_signed_B? state_type - s11 PUSH - s15 s1 s3 XCHG3 - s4 PUSH - s2 s1 XCPU - 17 s() PUSH - s10 s2 s(-1) PUXC2 - s10 PUSH - s0 s2 XCHG - s1 16 s() XCHG - s10 s(-1) PUXC - s0 20 s() XCHG // msg_signed_B? state_type config cs msg_signed_A? close_timeout a_key b_key a_addr b_addr channel_id msg cs msg_value msg msg_signed_A? msg_signed_B? a_addr b_addr init_timeout channel_id min_A_extra - with_init CALLDICT // msg_signed_B? state_type config cs msg_signed_A? close_timeout a_key b_key a_addr b_addr channel_id msg state - s0 s9 XCHG - s0 s8 XCHG // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? - }>ELSE<{ - s2 s15 XCHG - s11 POP - s13 POP - DROP // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? - }> - 1 PUSHINT // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? _38 - s12 s(-1) PUXC // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? state_type _38 - EQUAL // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? _39 - IF:<{ // msg_signed_B? state_type config state cs close_timeout a_key b_key a_addr b_addr channel_id msg msg_signed_A? - s9 POP // msg_signed_B? state_type config msg_signed_A? cs close_timeout a_key b_key a_addr b_addr channel_id msg - s7 PUSH - s1 s5 s4 PUXC2 - s0 s4 PUSH2 - s6 s12 XCHG - s5 s15 XCHG - s4 s9 XCHG - s0 s10 s15 XC2PU // channel_id state_type config b_addr cs a_addr msg cs msg msg_signed_A? msg_signed_B? a_key b_key a_addr b_addr close_timeout channel_id - with_close CALLDICT // channel_id state_type config b_addr cs a_addr msg state - s7 s1 s4 XCHG3 - -ROT // a_addr state_type config state cs b_addr channel_id msg - }>ELSE<{ - DROP - s3 s11 XCHG - 4 3 BLKDROP2 // a_addr state_type config state cs b_addr channel_id msg - }> - 2 PUSHINT // a_addr state_type config state cs b_addr channel_id msg _41 - s1 s7 XCHG // a_addr msg config state cs b_addr channel_id state_type _41 - EQUAL // a_addr msg config state cs b_addr channel_id _42 - IF:<{ // a_addr msg config state cs b_addr channel_id - s2 s4 XCHG - 5 2 REVERSE // config state cs msg a_addr b_addr channel_id - with_payout CALLDICT - }>ELSE<{ - 3 BLKDROP - 2 2 BLKDROP2 // config state - }> - pack_data INLINECALLDICT - }> - recv_internal PROC:<{ - // msg_value in_msg_cell in_msg - NIP // msg_value in_msg - recv_any CALLDICT - }> - recv_external PROC:<{ - // in_msg - 0 PUSHINT // in_msg _1=0 - SWAP // _1=0 in_msg - recv_any CALLDICT - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp deleted file mode 100644 index e27ef8fe..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("restricted-wallet", "te6ccgEBDAEA+wABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQL28oMI1xgg0x/THwH4I7vyY+1E0NMf0//RUzG68qEDnjFsIvgApMjLH8v/ye1U4QP5AVQQQvkQ8qL4AIDz+DMgbpIwf5fQ1wsf+CO84nH4M9DXC/8EkyDXSo6V0wfUfySOhTBTFts83pMC+wCSbCHi6DEzAtGkyMsfy//JCgsABNAwAgEgBgcCASAICQA5vLYEB5/BmQN0kYP8voa4WP/BHecUi4SnwTt4hxQAF7s5ztRNDTHzHXC/+AARuMl+1E0NcLH4ADIB0NMDAXiwklt/4PpAMfpAMPpEAcD/ArqwAATtVA=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif deleted file mode 100644 index f536a439..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif +++ /dev/null @@ -1,151 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC restricted? - DECLPROC check_destination - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - 104128 DECLMETHOD balance - recv_internal PROC:<{ - // in_msg - DROP // - }> - restricted? PROC:<{ - // - -13 PUSHINT // _1=-13 - CONFIGOPTPARAM // p - DUP // p p - ISNULL // p _3 - IF:<{ // p - DROP // - TRUE // _4 - }>ELSE<{ // p - CTOS // _6 - 32 PLDU // _8 - NOW // _8 _9 - GREATER // _4 - }> - }> - check_destination PROCREF:<{ - // msg dest - SWAP // dest msg - CTOS // dest cs - 4 LDU // dest flags cs - SWAP - 8 PUSHINT // dest cs flags _8=8 - AND // dest cs _9 - IFJMP:<{ // dest cs - 2DROP // - TRUE // _10 - }> // dest cs - LDMSGADDR // dest _27 _26 - NIP // dest cs - LDMSGADDR // dest _29 _28 - DROP // dest d_addr - REWRITESTDADDR // dest dest_wc dest_addr - SWAP // dest dest_addr dest_wc - -1 EQINT // dest dest_addr _21 - s0 s2 XCHG // _21 dest_addr dest - EQUAL // _21 _22 - AND // _23 - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _8 cs - 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP - NOW // signature in_msg msg_seqno cs valid_until _15 - LEQ // signature in_msg msg_seqno cs _16 - 35 THROWIF - c4 PUSH // signature in_msg msg_seqno cs _19 - CTOS // signature in_msg msg_seqno cs ds - 32 LDU // signature in_msg msg_seqno cs _23 ds - 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds - ENDS - s3 s1 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key msg_seqno stored_seqno - EQUAL // signature in_msg msg_seqno cs stored_seqno public_key _31 - 33 THROWIFNOT - s0 s3 XCHG // signature in_msg public_key cs stored_seqno msg_seqno - IFNOTJMP:<{ // signature in_msg public_key cs stored_seqno - NIP - 2 2 BLKDROP2 // public_key stored_seqno - ACCEPT - INC // public_key _35 - NEWC // public_key _35 _36 - 32 STU // public_key _38 - 256 STU // _40 - ENDC // _41 - c4 POP - }> // signature in_msg public_key cs stored_seqno - s0 s3 XCHG // signature stored_seqno public_key cs in_msg - HASHSU // signature stored_seqno public_key cs _44 - s0 s4 s2 XC2PU // cs stored_seqno public_key _44 signature public_key - CHKSIGNU // cs stored_seqno public_key _45 - 34 THROWIFNOT - ACCEPT - restricted? INLINECALLDICT // cs stored_seqno public_key restrict - 1 PUSHINT // cs stored_seqno public_key restrict _51=1 - CONFIGOPTPARAM // cs stored_seqno public_key restrict _52 - CTOS // cs stored_seqno public_key restrict _53 - 256 PLDU // cs stored_seqno public_key restrict elector - s0 s4 XCHG // elector stored_seqno public_key restrict cs - WHILE:<{ - DUP // elector stored_seqno public_key restrict cs cs - SREFS // elector stored_seqno public_key restrict cs _58 - }>DO<{ // elector stored_seqno public_key restrict cs - 8 LDU // elector stored_seqno public_key restrict mode cs - LDREF // elector stored_seqno public_key restrict mode msg cs - TRUE // elector stored_seqno public_key restrict mode msg cs ok - s4 PUSH // elector stored_seqno public_key restrict mode msg cs ok restrict - IF:<{ // elector stored_seqno public_key restrict mode msg cs ok - DROP // elector stored_seqno public_key restrict mode msg cs - s1 s6 PUSH2 // elector stored_seqno public_key restrict mode msg cs msg elector - check_destination INLINECALLDICT // elector stored_seqno public_key restrict mode msg cs ok - }> // elector stored_seqno public_key restrict mode msg cs ok - IF:<{ // elector stored_seqno public_key restrict mode msg cs - s0 s2 XCHG // elector stored_seqno public_key restrict cs msg mode - SENDRAWMSG - }>ELSE<{ - 2 1 BLKDROP2 // elector stored_seqno public_key restrict cs - }> - }> // elector stored_seqno public_key restrict cs - NIP - s3 POP // cs stored_seqno public_key - s0 s2 XCHG // public_key stored_seqno cs - ENDS - INC // public_key _72 - NEWC // public_key _72 _73 - 32 STU // public_key _75 - 256 STU // _77 - ENDC // _78 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 32 LDU // _9 _8 - NIP // cs - 256 PLDU // _7 - }> - balance PROC:<{ - // - restricted? INLINECALLDICT // _0 - IF:<{ // - 0 PUSHINT // _1=0 - }>ELSE<{ // - BALANCE // _3 - FIRST // _1 - }> - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp deleted file mode 100644 index 83fb4002..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("restricted-wallet2", "te6ccgECDgEAARoAART/APSkE/S88sgLAQIBIAIDAgFIBAUB8vKDCNcYINMf0x8B+CO78mPtRNDTH9P/0x/0BNFTU7ryoQWOFTM0NPgAA6TIyx8Sy/8Syx/0AMntVOEF+QFUEGb5EPKi+AAj+CPbPCOAIPR7b6UxlvoAMHL7ApEw4gGTINdKltMH1AL7AOjRpMjLHxPL/8sf9ADJ7VQNAATQMAIBIAYHAgEgCAkCAUgKCwAXuznO1E0NMfMdcL/4ABG4yX7UTQ1wsfgBDbbYHwR7Z5AMAQm1B1tnkAwBTu1E0IEBINch0x/0BNEC2zz4J28QAoAg9HtvpTGX+gAwoXC2CZEw4g0AOiGOETGA8/gzIG6SMHCU0NcLH+IB3yGSAaGSW3/i"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif deleted file mode 100644 index 0b69a9c3..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif +++ /dev/null @@ -1,175 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet2-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC seconds_passed - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - DECLPROC compute_balance_at - 108602 DECLMETHOD balance_at - 104128 DECLMETHOD balance - recv_internal PROC:<{ - // in_msg - DROP // - }> - seconds_passed PROCREF:<{ - // start_at utime - OVER // start_at utime start_at - IFNOT:<{ // start_at utime - NIP // utime - -13 PUSHINT // utime _3=-13 - CONFIGOPTPARAM // utime p - DUP // utime p p - ISNULL // utime p _5 - IF:<{ // utime p - DROP // utime - 0 PUSHINT // utime _6=0 - }>ELSE<{ // utime p - CTOS // utime _8 - 32 PLDU // utime _6 - }> // utime start_at - SWAP // start_at utime - }> // start_at utime - OVER // start_at utime start_at - IF:<{ // start_at utime - SWAP // utime start_at - SUB // _11 - }>ELSE<{ // start_at utime - 2DROP // - -1 PUSHINT // _11=-1 - }> - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _8 cs - 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP - NOW // signature in_msg msg_seqno cs valid_until _15 - LEQ // signature in_msg msg_seqno cs _16 - 35 THROWIF - c4 PUSH // signature in_msg msg_seqno cs _19 - CTOS // signature in_msg msg_seqno cs ds - 32 LDU // signature in_msg msg_seqno cs _25 ds - 256 LDU // signature in_msg msg_seqno cs _25 _28 ds - 32 LDU // signature in_msg msg_seqno cs _25 _28 _31 ds - LDDICT // signature in_msg msg_seqno cs stored_seqno public_key start_at rdict ds - ENDS - s5 s3 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key start_at rdict msg_seqno stored_seqno - EQUAL // signature in_msg msg_seqno cs stored_seqno public_key start_at rdict _38 - 33 THROWIFNOT - s0 s5 XCHG // signature in_msg rdict cs stored_seqno public_key start_at msg_seqno - IFNOTJMP:<{ // signature in_msg rdict cs stored_seqno public_key start_at - s3 POP - s4 POP - s4 POP // stored_seqno public_key rdict start_at - ACCEPT - s0 s3 XCHG // start_at public_key rdict stored_seqno - INC // start_at public_key rdict _42 - NEWC // start_at public_key rdict _42 _43 - 32 STU // start_at public_key rdict _45 - s1 s2 XCHG // start_at rdict public_key _45 - 256 STU // start_at rdict _47 - s1 s2 XCHG // rdict start_at _47 - 32 STU // rdict _49 - STDICT // _50 - ENDC // _51 - c4 POP - }> // signature in_msg rdict cs stored_seqno public_key start_at - s0 s5 XCHG // signature start_at rdict cs stored_seqno public_key in_msg - HASHSU // signature start_at rdict cs stored_seqno public_key _54 - s0 s6 s6 XC2PU // public_key start_at rdict cs stored_seqno _54 signature public_key - CHKSIGNU // public_key start_at rdict cs stored_seqno _55 - 34 THROWIFNOT - ACCEPT - s3 PUSH - NOW // public_key start_at rdict cs stored_seqno start_at _59 - seconds_passed INLINECALLDICT // public_key start_at rdict cs stored_seqno ts - s3 PUSH - 32 PUSHINT // public_key start_at rdict cs stored_seqno ts rdict _64=32 - DICTIGETPREVEQ - NULLSWAPIFNOT2 // public_key start_at rdict cs stored_seqno _109 _108 _110 - NIP // public_key start_at rdict cs stored_seqno value found - IF:<{ // public_key start_at rdict cs stored_seqno value - LDGRAMS // public_key start_at rdict cs stored_seqno _112 _111 - DROP // public_key start_at rdict cs stored_seqno _66 - 2 PUSHINT // public_key start_at rdict cs stored_seqno _66 _68=2 - RAWRESERVE - }>ELSE<{ - DROP // public_key start_at rdict cs stored_seqno - }> - SWAP // public_key start_at rdict stored_seqno cs - WHILE:<{ - DUP // public_key start_at rdict stored_seqno cs cs - SREFS // public_key start_at rdict stored_seqno cs _72 - }>DO<{ // public_key start_at rdict stored_seqno cs - 8 LDU // public_key start_at rdict stored_seqno mode cs - LDREF // public_key start_at rdict stored_seqno mode msg cs - s0 s2 XCHG // public_key start_at rdict stored_seqno cs msg mode - SENDRAWMSG - }> // public_key start_at rdict stored_seqno cs - ENDS - INC // public_key start_at rdict _83 - NEWC // public_key start_at rdict _83 _84 - 32 STU // public_key start_at rdict _86 - s1 s3 XCHG // rdict start_at public_key _86 - 256 STU // rdict start_at _88 - 32 STU // rdict _90 - STDICT // _91 - ENDC // _92 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 32 LDU // _9 _8 - NIP // cs - 256 PLDU // _7 - }> - compute_balance_at PROCREF:<{ - // utime - c4 PUSH // utime _2 - CTOS // utime _3 - 288 PUSHINT // utime _3 _6 - SDSKIPFIRST // utime ds - 32 LDU // utime _10 ds - LDDICT // utime start_at rdict ds - ENDS - s0 s2 XCHG // rdict start_at utime - seconds_passed INLINECALLDICT // rdict ts - BALANCE // rdict ts _19 - FIRST // rdict ts balance - s0 s2 XCHG - 32 PUSHINT // balance ts rdict _24=32 - DICTIGETPREVEQ - NULLSWAPIFNOT2 // balance _36 _35 _37 - NIP // balance value found - IF:<{ // balance value - LDGRAMS // balance _39 _38 - DROP // balance _26 - SUB // _28 - 0 PUSHINT // _28 _29=0 - MAX // balance - }>ELSE<{ - DROP // balance - }> - }> - balance_at PROC:<{ - // utime - compute_balance_at INLINECALLDICT // _1 - }> - balance PROC:<{ - // - NOW // _0 - compute_balance_at INLINECALLDICT // _1 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.cpp deleted file mode 100644 index 7b95f0b6..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("restricted-wallet3", "te6ccgECEgEAAUsAART/APSkE/S88sgLAQIBIAIDAgFIBAUD+PKDCNcYINMf0x/THwL4I7vyY+1E0NMf0x/T/1NDuvKhUWK68qIG+QFUEHb5EPKkAY4fMwHT/9EB0x/0BNH4AAOkyMsfFMsfy/8Syx/0AMntVOEC0x/0BNH4ACH4I9s8IYAg9HtvpTGW+gAwcvsCkTDiApMg10qK6NECpMgPEBEABNAwAgEgBgcCASAICQIBSAwNAgFuCgsAEbjJftRNDXCx+AAXrc52omhpn5jrhf/AABesePaiaGmPmOuFj8ABDbbYHwR7Z5AOAQm1B1tnkA4BTu1E0IEBQNch0x/0BNEC2zz4J28QAoAg9HtvpTGX+gAwoXC2CZEw4g8AOiGOETGA8/gzIG6SMHCU0NcLH+IB3yGSAaGSW3/iAAzTB9QC+wAAHssfFMsfEsv/yx/0AMntVA=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.fif deleted file mode 100644 index f84d3dcb..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet3-code.fif +++ /dev/null @@ -1,199 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet3-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC seconds_passed - DECLPROC recv_external - 85143 DECLMETHOD seqno - 80113 DECLMETHOD wallet_id - 78748 DECLMETHOD get_public_key - DECLPROC compute_balance_at - 108602 DECLMETHOD balance_at - 104128 DECLMETHOD balance - recv_internal PROC:<{ - // in_msg - DROP // - }> - seconds_passed PROCREF:<{ - // start_at utime - OVER // start_at utime start_at - IFNOT:<{ // start_at utime - NIP // utime - -13 PUSHINT // utime _3=-13 - CONFIGOPTPARAM // utime p - DUP // utime p p - ISNULL // utime p _5 - IF:<{ // utime p - DROP // utime - 0 PUSHINT // utime _6=0 - }>ELSE<{ // utime p - CTOS // utime _8 - 32 PLDU // utime _6 - }> // utime start_at - SWAP // start_at utime - }> // start_at utime - OVER // start_at utime start_at - IF:<{ // start_at utime - SWAP // utime start_at - SUB // _11 - }>ELSE<{ // start_at utime - 2DROP // - -1 PUSHINT // _11=-1 - }> - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _9 cs - 32 LDU // signature in_msg _9 _12 cs - 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - s0 s2 XCHG - NOW // signature in_msg subwallet_id cs msg_seqno valid_until _19 - LEQ // signature in_msg subwallet_id cs msg_seqno _20 - 35 THROWIF - c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23 - CTOS // signature in_msg subwallet_id cs msg_seqno ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds - 256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds - s4 s3 PUSH2 // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds msg_seqno stored_seqno - EQUAL // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds _38 - 33 THROWIFNOT - s6 s2 XCPU // signature in_msg ds cs msg_seqno stored_seqno stored_subwallet public_key subwallet_id stored_subwallet - EQUAL // signature in_msg ds cs msg_seqno stored_seqno stored_subwallet public_key _41 - 34 THROWIFNOT - s0 s6 XCHG // signature public_key ds cs msg_seqno stored_seqno stored_subwallet in_msg - HASHSU // signature public_key ds cs msg_seqno stored_seqno stored_subwallet _44 - s0 s7 s6 XC2PU // stored_subwallet public_key ds cs msg_seqno stored_seqno _44 signature public_key - CHKSIGNU // stored_subwallet public_key ds cs msg_seqno stored_seqno _45 - 36 THROWIFNOT - SWAP // stored_subwallet public_key ds cs stored_seqno msg_seqno - IFNOTJMP:<{ // stored_subwallet public_key ds cs stored_seqno - s3 POP // stored_subwallet stored_seqno ds cs - SWAP // stored_subwallet stored_seqno cs ds - 256 LDU // stored_subwallet stored_seqno cs public_key ds - ENDS - SWAP // stored_subwallet stored_seqno public_key cs - 32 LDU // stored_subwallet stored_seqno public_key _55 cs - LDDICT // stored_subwallet stored_seqno public_key start_at rdict cs - ENDS - ACCEPT - s0 s3 XCHG // stored_subwallet rdict public_key start_at stored_seqno - INC // stored_subwallet rdict public_key start_at _63 - NEWC // stored_subwallet rdict public_key start_at _63 _64 - 32 STU // stored_subwallet rdict public_key start_at _66 - s1 s4 XCHG // start_at rdict public_key stored_subwallet _66 - 32 STU // start_at rdict public_key _68 - 256 STU // start_at rdict _70 - s1 s2 XCHG // rdict start_at _70 - 32 STU // rdict _72 - STDICT // _73 - ENDC // _74 - c4 POP - }> // stored_subwallet public_key ds cs stored_seqno - s0 s2 XCHG // stored_subwallet public_key stored_seqno cs ds - 32 LDU // stored_subwallet public_key stored_seqno cs _78 ds - LDDICT // stored_subwallet public_key stored_seqno cs start_at rdict ds - ENDS - ACCEPT - OVER - NOW // stored_subwallet public_key stored_seqno cs start_at rdict start_at _86 - seconds_passed INLINECALLDICT // stored_subwallet public_key stored_seqno cs start_at rdict ts - OVER - 32 PUSHINT // stored_subwallet public_key stored_seqno cs start_at rdict ts rdict _91=32 - DICTIGETPREVEQ - NULLSWAPIFNOT2 // stored_subwallet public_key stored_seqno cs start_at rdict _148 _147 _149 - NIP // stored_subwallet public_key stored_seqno cs start_at rdict value found - IF:<{ // stored_subwallet public_key stored_seqno cs start_at rdict value - LDGRAMS // stored_subwallet public_key stored_seqno cs start_at rdict _151 _150 - DROP // stored_subwallet public_key stored_seqno cs start_at rdict _93 - 2 PUSHINT // stored_subwallet public_key stored_seqno cs start_at rdict _93 _95=2 - RAWRESERVE - }>ELSE<{ - DROP // stored_subwallet public_key stored_seqno cs start_at rdict - }> - s0 s2 XCHG // stored_subwallet public_key stored_seqno rdict start_at cs - WHILE:<{ - DUP // stored_subwallet public_key stored_seqno rdict start_at cs cs - SREFS // stored_subwallet public_key stored_seqno rdict start_at cs _99 - }>DO<{ // stored_subwallet public_key stored_seqno rdict start_at cs - 8 LDU // stored_subwallet public_key stored_seqno rdict start_at mode cs - LDREF // stored_subwallet public_key stored_seqno rdict start_at mode msg cs - s0 s2 XCHG // stored_subwallet public_key stored_seqno rdict start_at cs msg mode - SENDRAWMSG - }> // stored_subwallet public_key stored_seqno rdict start_at cs - ENDS - s0 s2 XCHG // stored_subwallet public_key start_at rdict stored_seqno - INC // stored_subwallet public_key start_at rdict _110 - NEWC // stored_subwallet public_key start_at rdict _110 _111 - 32 STU // stored_subwallet public_key start_at rdict _113 - s1 s4 XCHG // rdict public_key start_at stored_subwallet _113 - 32 STU // rdict public_key start_at _115 - s1 s2 XCHG // rdict start_at public_key _115 - 256 STU // rdict start_at _117 - 32 STU // rdict _119 - STDICT // _120 - ENDC // _121 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - wallet_id PROC:<{ - // - c4 PUSH // _1 - CTOS // ds - 32 LDU // _9 _8 - NIP // ds - 32 PLDU // _7 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // ds - 64 LDU // _11 _10 - NIP // ds - 256 PLDU // _9 - }> - compute_balance_at PROCREF:<{ - // utime - c4 PUSH // utime _2 - CTOS // utime _3 - 320 PUSHINT // utime _3 _8 - SDSKIPFIRST // utime ds - 32 LDU // utime _12 ds - LDDICT // utime start_at rdict ds - ENDS - s0 s2 XCHG // rdict start_at utime - seconds_passed INLINECALLDICT // rdict ts - BALANCE // rdict ts _21 - FIRST // rdict ts balance - s0 s2 XCHG - 32 PUSHINT // balance ts rdict _26=32 - DICTIGETPREVEQ - NULLSWAPIFNOT2 // balance _38 _37 _39 - NIP // balance value found - IF:<{ // balance value - LDGRAMS // balance _41 _40 - DROP // balance _28 - SUB // _30 - 0 PUSHINT // _30 _31=0 - MAX // balance - }>ELSE<{ - DROP // balance - }> - }> - balance_at PROC:<{ - // utime - compute_balance_at INLINECALLDICT // _1 - }> - balance PROC:<{ - // - NOW // _0 - compute_balance_at INLINECALLDICT // _1 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp deleted file mode 100644 index 1bffadf5..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9LzyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif deleted file mode 100644 index c052d4b6..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif +++ /dev/null @@ -1,45 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC recv_external - recv_internal PROC:<{ - // in_msg - DROP // - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg msg_seqno cs - c4 PUSH // signature in_msg msg_seqno cs _11 - CTOS // signature in_msg msg_seqno cs cs2 - 32 LDU // signature in_msg msg_seqno cs stored_seqno cs2 - 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key cs2 - ENDS - s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno - EQUAL // signature in_msg public_key cs stored_seqno _23 - 33 THROWIFNOT - s0 s3 XCHG // signature stored_seqno public_key cs in_msg - HASHSU // signature stored_seqno public_key cs _26 - s0 s4 s2 XC2PU // cs stored_seqno public_key _26 signature public_key - CHKSIGNU // cs stored_seqno public_key _27 - 34 THROWIFNOT - ACCEPT - s2 s0 XCPU // public_key stored_seqno cs cs - SREFS // public_key stored_seqno cs _32 - IF:<{ // public_key stored_seqno cs - 8 LDU // public_key stored_seqno mode cs - LDREF // public_key stored_seqno mode _37 cs - s0 s2 XCHG // public_key stored_seqno cs _37 mode - SENDRAWMSG - }> // public_key stored_seqno cs - ENDS - INC // public_key _42 - NEWC // public_key _42 _43 - 32 STU // public_key _45 - 256 STU // _47 - ENDC // _48 - c4 POP - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp deleted file mode 100644 index 3370e53e..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("simple-wallet-ext", "te6ccgEBGAEA3AABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQA08vACVDIS8AT4ACDXSpbTB9QC+wDe0aQB8AMCAs0GBwIBIA4PAgEgCAkAKdAUGEa4wQaY+CXXlQ/ICgCfyIeVFAIBIAoLAgEgDA0AAwwgAA8AcjLH8v/yYAARO1E0NMf0/8wgAAk8AHtVIAIBIBARAgEgFhcCAW4SEwIBIBQVAAutzngBGMAADa9suAD4AMAAEbWS/aiaGuFj8AANtpeeAF4AkAAhuNAYIBTJftQ9iCAcjg7UPYgAFbiODIyx8SywfMyY"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif deleted file mode 100644 index b7975e94..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif +++ /dev/null @@ -1,110 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-ext-code.fc` -PROGRAM{ - DECLPROC create_state - DECLPROC load_state - DECLPROC save_state - DECLPROC recv_internal - DECLPROC do_verify_message - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - 81625 DECLMETHOD create_init_state - 116960 DECLMETHOD prepare_send_message_with_seqno - 101633 DECLMETHOD prepare_send_message - 95420 DECLMETHOD verify_message - create_state PROC:<{ - // seqno public_key - SWAP - NEWC // public_key seqno _2 - 32 STU // public_key _4 - 256 STU // _6 - ENDC // _7 - }> - load_state PROC:<{ - // - c4 PUSH // _1 - CTOS // cs2 - 32 LDU // _3 cs2 - 256 LDU // _3 _12 _11 - DROP // _3 _6 - }> - save_state PROC:<{ - // seqno public_key - create_state CALLDICT // _2 - c4 POP - }> - recv_internal PROC:<{ - // in_msg - DROP // - }> - do_verify_message PROC:<{ - // in_msg seqno public_key - s0 s2 XCHG - 9 PUSHPOW2 // public_key seqno in_msg _5=512 - LDSLICEX // public_key seqno signature in_msg - DUP // public_key seqno signature in_msg cs - 32 LDU // public_key seqno signature in_msg msg_seqno cs - s0 s4 XCHG // public_key cs signature in_msg msg_seqno seqno - EQUAL // public_key cs signature in_msg _13 - 33 THROWIFNOT - HASHSU // public_key cs signature _16 - s0 s1 s3 XCHG3 // cs _16 signature public_key - CHKSIGNU // cs _17 - 34 THROWIFNOT - }> - recv_external PROC:<{ - // in_msg - load_state CALLDICT // in_msg stored_seqno public_key - s2 s1 s2 XCPU2 // public_key stored_seqno in_msg stored_seqno public_key - do_verify_message CALLDICT // public_key stored_seqno cs - ACCEPT // public_key stored_seqno cs - DUP // public_key stored_seqno cs cs - SREFS // public_key stored_seqno cs _9 - IF:<{ // public_key stored_seqno cs - 8 LDU // public_key stored_seqno mode cs - LDREF // public_key stored_seqno mode _14 cs - s0 s2 XCHG // public_key stored_seqno cs _14 mode - SENDRAWMSG - }> // public_key stored_seqno cs - ENDS - INC // public_key _19 - SWAP // _19 public_key - save_state CALLDICT - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - load_state CALLDICT // _3 _4 - NIP // public_key - }> - create_init_state PROC:<{ - // public_key - 0 PUSHINT // public_key _1=0 - SWAP // _1=0 public_key - create_state CALLDICT // _2 - }> - prepare_send_message_with_seqno PROC:<{ - // mode msg seqno - NEWC // mode msg seqno _3 - 32 STU // mode msg _5 - s1 s2 XCHG // msg mode _5 - 8 STU // msg _7 - STREF // _8 - ENDC // _9 - }> - prepare_send_message PROC:<{ - // mode msg - seqno CALLDICT // mode msg _2 - prepare_send_message_with_seqno CALLDICT // _3 - }> - verify_message PROC:<{ - // msg - load_state CALLDICT // msg stored_seqno public_key - do_verify_message CALLDICT // _4 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp deleted file mode 100644 index 690c18da..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("wallet", "te6ccgEBCAEAewABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/THwH4I7vyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DACAUgGBwAXuznO1E0NMfMdcL/4ABG4yX7UTQ1wsfg="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif deleted file mode 100644 index 5038c7d6..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif +++ /dev/null @@ -1,68 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - recv_internal PROC:<{ - // in_msg - DROP // - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _8 cs - 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP - NOW // signature in_msg msg_seqno cs valid_until _15 - LEQ // signature in_msg msg_seqno cs _16 - 35 THROWIF - c4 PUSH // signature in_msg msg_seqno cs _19 - CTOS // signature in_msg msg_seqno cs ds - 32 LDU // signature in_msg msg_seqno cs _23 ds - 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds - ENDS - s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno - EQUAL // signature in_msg public_key cs stored_seqno _31 - 33 THROWIFNOT - s0 s3 XCHG // signature stored_seqno public_key cs in_msg - HASHSU // signature stored_seqno public_key cs _34 - s0 s4 s2 XC2PU // cs stored_seqno public_key _34 signature public_key - CHKSIGNU // cs stored_seqno public_key _35 - 34 THROWIFNOT - ACCEPT - s0 s2 XCHG // public_key stored_seqno cs - WHILE:<{ - DUP // public_key stored_seqno cs cs - SREFS // public_key stored_seqno cs _40 - }>DO<{ // public_key stored_seqno cs - 8 LDU // public_key stored_seqno mode cs - LDREF // public_key stored_seqno mode _45 cs - s0 s2 XCHG // public_key stored_seqno cs _45 mode - SENDRAWMSG - }> // public_key stored_seqno cs - ENDS - INC // public_key _50 - NEWC // public_key _50 _51 - 32 STU // public_key _53 - 256 STU // _55 - ENDC // _56 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 32 LDU // _9 _8 - NIP // cs - 256 PLDU // _7 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.cpp deleted file mode 100644 index e0bfae8f..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.cpp +++ /dev/null @@ -1 +0,0 @@ -with_tvm_code("wallet3", "te6ccgEBCAEAhgABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQCW8oMI1xgg0x/TH9MfAvgju/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj+ACTINdKltMH1AL7AOgwAaTIyx/LH8v/ye1UAATQMAIBSAYHABe7Oc7UTQ0z8x1wv/gAEbjJftRNDXCx+A=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.fif deleted file mode 100644 index 3af74c3c..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet3-code.fif +++ /dev/null @@ -1,74 +0,0 @@ -// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet3-code.fc` -PROGRAM{ - DECLPROC recv_internal - DECLPROC recv_external - 85143 DECLMETHOD seqno - 78748 DECLMETHOD get_public_key - recv_internal PROC:<{ - // in_msg - DROP // - }> - recv_external PROC:<{ - // in_msg - 9 PUSHPOW2 // in_msg _3=512 - LDSLICEX // signature in_msg - DUP // signature in_msg cs - 32 LDU // signature in_msg _9 cs - 32 LDU // signature in_msg _9 _12 cs - 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - s0 s2 XCHG - NOW // signature in_msg subwallet_id cs msg_seqno valid_until _19 - LEQ // signature in_msg subwallet_id cs msg_seqno _20 - 35 THROWIF - c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23 - CTOS // signature in_msg subwallet_id cs msg_seqno ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds - 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds - 256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds - ENDS - s3 s2 XCPU // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet msg_seqno stored_seqno - EQUAL // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet _39 - 33 THROWIFNOT - s4 s4 XCPU // signature in_msg stored_subwallet cs public_key stored_seqno subwallet_id stored_subwallet - EQUAL // signature in_msg stored_subwallet cs public_key stored_seqno _42 - 34 THROWIFNOT - s0 s4 XCHG // signature stored_seqno stored_subwallet cs public_key in_msg - HASHSU // signature stored_seqno stored_subwallet cs public_key _45 - s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs _45 signature public_key - CHKSIGNU // public_key stored_seqno stored_subwallet cs _46 - 35 THROWIFNOT - ACCEPT // public_key stored_seqno stored_subwallet cs - WHILE:<{ - DUP // public_key stored_seqno stored_subwallet cs cs - SREFS // public_key stored_seqno stored_subwallet cs _51 - }>DO<{ // public_key stored_seqno stored_subwallet cs - 8 LDU // public_key stored_seqno stored_subwallet mode cs - LDREF // public_key stored_seqno stored_subwallet mode _56 cs - s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode - SENDRAWMSG - }> // public_key stored_seqno stored_subwallet cs - DROP // public_key stored_seqno stored_subwallet - SWAP // public_key stored_subwallet stored_seqno - INC // public_key stored_subwallet _60 - NEWC // public_key stored_subwallet _60 _61 - 32 STU // public_key stored_subwallet _63 - 32 STU // public_key _65 - 256 STU // _67 - ENDC // _68 - c4 POP - }> - seqno PROC:<{ - // - c4 PUSH // _0 - CTOS // _1 - 32 PLDU // _3 - }> - get_public_key PROC:<{ - // - c4 PUSH // _1 - CTOS // cs - 64 LDU // _9 _8 - NIP // cs - 256 PLDU // _7 - }> -}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-req.fif b/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-req.fif deleted file mode 100644 index f771f6fd..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-req.fif +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -"validator-to-sign.req" =: savefile - -{ ."usage: " @' $0 type ." []" cr - ."Creates an unsigned request to vote for complaint (decimal; prefix with '0x' if needed) of past validator set on behalf of validator with zero-based index in current validator set (as stored in configuration parameter 34)." cr - ."The result is saved into (" savefile type ." by default) and output in hexadecimal form, to be signed later by the validator public key" cr 1 halt -} : usage - -$# dup 3 < swap 4 > or ' usage if -4 :$1..n - -$1 parse-int dup =: val-idx - 16 ufits not abort"validator index out of range" -$2 parse-int dup =: elect-id - 32 ufits not abort"invalid election id" -$3 parse-int dup =: compl-hash - 256 ufits not abort"invalid complaint hash" -$4 savefile replace-if-null =: savefile - -."Creating a request to vote for complaint 0x" compl-hash 64x. ."of past validator set " elect-id . -."on behalf of current validator with index " val-idx . cr - -B{56744350} val-idx 16 u>B B+ elect-id 32 u>B B+ compl-hash 256 u>B B+ -dup Bx. cr -dup B>base64url type cr -savefile tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-signed.fif b/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-signed.fif deleted file mode 100644 index 90a36a54..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/complaint-vote-signed.fif +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -"vote-query.boc" =: savefile - -{ ."usage: " @' $0 type ." []" cr - ."Creates an internal message body to be sent from any smart contract residing in the masterchain to the elections smart contract containing a signed request to vote for complaint (decimal; prefix with '0x' if needed) of past validator set on behalf of current validator with zero-based index and (Base64) public key in current validator set (as stored in configuration parameter 34)" cr - ." must be the base64 representation of Ed25519 signature of the previously generated unsigned request by means of " cr - ."The result is saved into (" savefile type ." by default), to be embedded later into an internal message" cr 1 halt -} : usage - -$# dup 5 < swap 6 > or ' usage if -6 :$1..n - -$1 parse-int dup =: val-idx - 16 ufits not abort"validator index out of range" -$2 parse-int dup =: elect-id - 32 ufits not abort"invalid election id" -$3 parse-int dup =: compl-hash - 256 ufits not abort"invalid complaint hash" -$4 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long" - 32 B>u@+ 0xC6B41348 <> abort"invalid Ed25519 public key: unknown magic number" - =: pubkey -$5 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long" - =: signature -$6 savefile replace-if-null =: savefile - -."Creating the body of an internal message to be sent to the elections smart contract" cr } -."containing a signed request to vote for complaint 0x" compl-hash 64x. ."of past validator set " elect-id . -."on behalf of current validator with index " val-idx . "and public key" pubkey Bx. cr - -B{56744350} val-idx 16 u>B B+ elect-id 32 u>B B+ compl-hash 256 u>B B+ dup =: to_sign -."String to sign is " Bx. cr - -to_sign signature pubkey ed25519_chksign not abort"Ed25519 signature is invalid" -."Provided a valid Ed25519 signature " signature Bx. ." with validator public key " pubkey Bx. cr - -now 32 << compl-hash 32 1<< mod + =: query-id - - -."Internal message body is " dup B savefile tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc deleted file mode 100644 index eedb0dc5..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc +++ /dev/null @@ -1,641 +0,0 @@ -;; Simple configuration smart contract - -() set_conf_param(int index, cell value) impure { - var cs = get_data().begin_parse(); - var cfg_dict = cs~load_ref(); - cfg_dict~idict_set_ref(32, index, value); - set_data(begin_cell().store_ref(cfg_dict).store_slice(cs).end_cell()); -} - -(cell, int, int, cell) load_data() inline { - var cs = get_data().begin_parse(); - var res = (cs~load_ref(), cs~load_uint(32), cs~load_uint(256), cs~load_dict()); - cs.end_parse(); - return res; -} - -() store_data(cfg_dict, stored_seqno, public_key, vote_dict) impure inline { - set_data(begin_cell() - .store_ref(cfg_dict) - .store_uint(stored_seqno, 32) - .store_uint(public_key, 256) - .store_dict(vote_dict) - .end_cell()); -} - -;; (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price) -_ parse_vote_config(cell c) inline { - var cs = c.begin_parse(); - throw_unless(44, cs~load_uint(8) == 0x36); - var res = (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); - cs.end_parse(); - return res; -} - -;; cfg_vote_setup#91 normal_params:^ConfigProposalSetup critical_params:^ConfigProposalSetup = ConfigVotingSetup; -_ get_vote_config_internal(int critical?, cell cparam11) inline_ref { - var cs = cparam11.begin_parse(); - throw_unless(44, cs~load_uint(8) == 0x91); - if (critical?) { - cs~load_ref(); - } - return parse_vote_config(cs.preload_ref()); -} - -_ get_vote_config(int critical?) inline { - return get_vote_config_internal(critical?, config_param(11)); -} - -(int, int) check_validator_set(cell vset) { - var cs = vset.begin_parse(); - throw_unless(9, cs~load_uint(8) == 0x12); ;; validators_ext#12 only - int utime_since = cs~load_uint(32); - int utime_until = cs~load_uint(32); - int total = cs~load_uint(16); - int main = cs~load_uint(16); - throw_unless(9, main > 0); - throw_unless(9, total >= main); - return (utime_since, utime_until); -} - -() send_answer(addr, query_id, ans_tag, mode) impure { - ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 011000 - send_raw_message(begin_cell() - .store_uint(0x18, 6) - .store_slice(addr) - .store_uint(0, 5 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(ans_tag, 32) - .store_uint(query_id, 64) - .end_cell(), mode); -} - -() send_confirmation(addr, query_id, ans_tag) impure inline { - return send_answer(addr, query_id, ans_tag, 64); -} - -() send_error(addr, query_id, ans_tag) impure inline { - return send_answer(addr, query_id, ans_tag, 64); -} - -;; forward a message to elector smart contract to make it upgrade its code -() change_elector_code(slice cs) impure { - var dest_addr = config_param(1).begin_parse().preload_uint(256); - var query_id = now(); - send_raw_message(begin_cell() - .store_uint(0xc4ff, 17) - .store_uint(dest_addr, 256) - .store_grams(1 << 30) ;; ~ 1 Gram (will be returned back) - .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(0x4e436f64, 32) ;; action - .store_uint(query_id, 64) - .store_slice(cs) - .end_cell(), 0); -} - -() after_code_upgrade(slice param, cont old_code) impure method_id(1666) { -} - -_ perform_action(cfg_dict, public_key, action, cs) inline_ref { - if (action == 0x43665021) { - ;; change one configuration parameter - var param_index = cs~load_int(32); - var param_value = cs~load_ref(); - cs.end_parse(); - cfg_dict~idict_set_ref(32, param_index, param_value); - return (cfg_dict, public_key); - } elseif (action == 0x4e436f64) { - ;; change configuration smart contract code - var new_code = cs~load_ref(); - set_code(new_code); - var old_code = get_c3(); - set_c3(new_code.begin_parse().bless()); - after_code_upgrade(cs, old_code); - throw(0); - return (cfg_dict, public_key); - } elseif (action == 0x50624b21) { - ;; change configuration master public key - public_key = cs~load_uint(256); - cs.end_parse(); - return (cfg_dict, public_key); - } elseif (action == 0x4e43ef05) { - ;; change election smart contract code - change_elector_code(cs); - return (cfg_dict, public_key); - } else { - throw_if(32, action); - return (cfg_dict, public_key); - } -} - -(cell, int, cell) get_current_vset() inline_ref { - var vset = config_param(34); - var cs = begin_parse(vset); - ;; validators_ext#12 utime_since:uint32 utime_until:uint32 - ;; total:(## 16) main:(## 16) { main <= total } { main >= 1 } - ;; total_weight:uint64 - throw_unless(40, cs~load_uint(8) == 0x12); - cs~skip_bits(32 + 32 + 16 + 16); - var (total_weight, dict) = (cs~load_uint(64), cs~load_dict()); - cs.end_parse(); - return (vset, total_weight, dict); -} - -(slice, int) get_validator_descr(int idx) inline_ref { - var (vset, total_weight, dict) = get_current_vset(); - var (value, _) = dict.udict_get?(16, idx); - return (value, total_weight); -} - -(int, int) unpack_validator_descr(slice cs) inline { - ;; ed25519_pubkey#8e81278a pubkey:bits256 = SigPubKey; - ;; validator#53 public_key:SigPubKey weight:uint64 = ValidatorDescr; - ;; validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr; - throw_unless(41, (cs~load_uint(8) & ~ 0x20) == 0x53); - throw_unless(41, cs~load_uint(32) == 0x8e81278a); - return (cs~load_uint(256), cs~load_uint(64)); -} - -;; cfg_proposal#f3 param_id:int32 param_value:(Maybe ^Cell) if_hash_equal:(Maybe uint256) -;; c -> (param-id param-cell maybe-hash) -(int, cell, int) parse_config_proposal(cell c) inline_ref { - var cs = c.begin_parse(); - throw_unless(44, cs~load_int(8) == 0xf3 - 0x100); - var (id, val, hash) = (cs~load_int(32), cs~load_maybe_ref(), cs~load_int(1)); - if (hash) { - hash = cs~load_uint(256); - } else { - hash = -1; - } - cs.end_parse(); - return (id, val, hash); -} - -(cell, int, cell) accept_proposal(cell cfg_dict, cell proposal, int critical?) inline_ref { - var (param_id, param_val, req_hash) = parse_config_proposal(proposal); - cell cur_val = cfg_dict.idict_get_ref(32, param_id); - int cur_hash = null?(cur_val) ? 0 : cell_hash(cur_val); - if ((cur_hash != req_hash) & (req_hash >= 0)) { - ;; current value has incorrect hash, do not apply changes - return (cfg_dict, 0, null()); - } - cell mparams = cfg_dict.idict_get_ref(32, 9); ;; mandatory parameters - var (_, found?) = mparams.idict_get?(32, param_id); - if (found? & param_val.null?()) { - ;; cannot set a mandatory parameter to (null) - return (cfg_dict, 0, null()); - } - cell cparams = cfg_dict.idict_get_ref(32, 10); ;; critical parameters - (_, found?) = cparams.idict_get?(32, param_id); - if (found? < critical?) { - ;; trying to set a critical parameter after a non-critical voting - return (cfg_dict, 0, null()); - } - ;; CHANGE ONE CONFIGURATION PARAMETER (!) - cfg_dict~idict_set_ref(32, param_id, param_val); - return (cfg_dict, param_id, param_val); -} - -(cell, int) perform_proposed_action(cell cfg_dict, int public_key, int param_id, cell param_val) inline_ref { - if (param_id == -999) { - ;; appoint or depose dictator - return (cfg_dict, param_val.null?() ? 0 : param_val.begin_parse().preload_uint(256)); - } - if (param_val.null?()) { - return (cfg_dict, public_key); - } - if (param_id == -1000) { - ;; upgrade code - var cs = param_val.begin_parse(); - var new_code = cs~load_ref(); - set_code(new_code); - var old_code = get_c3(); - set_c3(new_code.begin_parse().bless()); - after_code_upgrade(cs, old_code); - throw(0); - return (cfg_dict, public_key); - } - if (param_id == -1001) { - ;; update elector code - var cs = param_val.begin_parse(); - change_elector_code(cs); - } - return (cfg_dict, public_key); -} - -;; cfg_proposal_status#ce expires:uint32 proposal:^ConfigProposal is_critical:Bool -;; voters:(HashmapE 16 True) remaining_weight:int64 validator_set_id:uint256 -;; rounds_remaining:uint8 wins:uint8 losses:uint8 = ConfigProposalStatus; -(int, cell, int, cell, int, int, slice) unpack_proposal_status(slice cs) inline_ref { - throw_unless(44, cs~load_int(8) == 0xce - 0x100); - return (cs~load_uint(32), cs~load_ref(), cs~load_int(1), cs~load_dict(), cs~load_int(64), cs~load_uint(256), cs); -} - -slice update_proposal_status(slice rest, int weight_remaining, int critical?) inline_ref { - var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _) = get_vote_config(critical?); - var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8)); - losses -= (weight_remaining >= 0); - if (losses > max_losses) { - ;; lost too many times - return null(); - } - rounds_remaining -= 1; - if (rounds_remaining < 0) { - ;; existed for too many rounds - return null(); - } - return begin_cell() - .store_uint(rounds_remaining, 8) - .store_uint(wins, 8) - .store_uint(losses, 8) - .end_cell().begin_parse(); -} - -builder begin_pack_proposal_status(int expires, cell proposal, int critical?, cell voters, int weight_remaining, int vset_id) inline { - return begin_cell() - .store_int(0xce - 0x100, 8) - .store_uint(expires, 32) - .store_ref(proposal) - .store_int(critical?, 1) - .store_dict(voters) - .store_int(weight_remaining, 64) - .store_uint(vset_id, 256); -} - -(cell, cell, int) register_vote(vote_dict, phash, idx, weight) inline_ref { - var (pstatus, found?) = vote_dict.udict_get?(256, phash); - ifnot (found?) { - ;; config proposal not found - return (vote_dict, null(), -1); - } - var (cur_vset, total_weight, _) = get_current_vset(); - int cur_vset_id = cur_vset.cell_hash(); - var (expires, proposal, critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus); - if (expires <= now()) { - ;; config proposal expired, delete and report not found - vote_dict~udict_delete?(256, phash); - return (vote_dict, null(), -1); - } - if (vset_id != cur_vset_id) { - ;; config proposal belongs to a previous validator set - vset_id = cur_vset_id; - rest = update_proposal_status(rest, weight_remaining, critical?); - voters = null(); - weight_remaining = muldiv(total_weight, 3, 4); - } - if (rest.null?()) { - ;; discard proposal (existed for too many rounds, or too many losses) - vote_dict~udict_delete?(256, phash); - return (vote_dict, null(), -1); - } - var (_, found?) = voters.udict_get?(16, idx); - if (found?) { - ;; already voted for this proposal, ignore vote - return (vote_dict, null(), -2); - } - ;; register vote - voters~udict_set_builder(16, idx, begin_cell().store_uint(now(), 32)); - int old_wr = weight_remaining; - weight_remaining -= weight; - if ((weight_remaining ^ old_wr) >= 0) { - ;; not enough votes, or proposal already accepted in this round - ;; simply update weight_remaining - vote_dict~udict_set_builder(256, phash, begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id).store_slice(rest)); - return (vote_dict, null(), 2); - } - ;; proposal wins in this round - var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _) = get_vote_config(critical?); - var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8)); - wins += 1; - if (wins >= min_wins) { - ;; proposal is accepted, remove and process - vote_dict~udict_delete?(256, phash); - return (vote_dict, proposal, 6 - critical?); - } - ;; update proposal info - vote_dict~udict_set_builder(256, phash, - begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id) - .store_uint(rounds_remaining, 8) - .store_uint(wins, 8) - .store_uint(losses, 8)); - return (vote_dict, null(), 2); -} - -int proceed_register_vote(phash, idx, weight) impure inline_ref { - var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data(); - (vote_dict, var accepted_proposal, var status) = register_vote(vote_dict, phash, idx, weight); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - ifnot (accepted_proposal.null?()) { - var critical? = 6 - status; - (cfg_dict, var param_id, var param_val) = accept_proposal(cfg_dict, accepted_proposal, critical?); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - if (param_id) { - commit(); - (cfg_dict, public_key) = perform_proposed_action(cfg_dict, public_key, param_id, param_val); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - } - } - return status; -} - -(slice, int) scan_proposal(int phash, slice pstatus) inline_ref { - var (cur_vset, total_weight, _) = get_current_vset(); - int cur_vset_id = cur_vset.cell_hash(); - var (expires, proposal, critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus); - if (expires <= now()) { - ;; config proposal expired, delete - return (null(), true); - } - if (vset_id == cur_vset_id) { - ;; config proposal already processed or voted for in this round, change nothing - return (pstatus, false); - } - ;; config proposal belongs to a previous validator set - vset_id = cur_vset_id; - rest = update_proposal_status(rest, weight_remaining, critical?); - voters = null(); - weight_remaining = muldiv(total_weight, 3, 4); - if (rest.null?()) { - ;; discard proposal (existed for too many rounds, or too many losses) - return (null(), true); - } - ;; return updated proposal - return (begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id).store_slice(rest).end_cell().begin_parse(), true); -} - -cell scan_random_proposal(cell vote_dict) inline_ref { - var (phash, pstatus, found?) = vote_dict.udict_get_nexteq?(256, random()); - ifnot (found?) { - return vote_dict; - } - (pstatus, var changed?) = scan_proposal(phash, pstatus); - if (changed?) { - if (pstatus.null?()) { - vote_dict~udict_delete?(256, phash); - } else { - vote_dict~udict_set(256, phash, pstatus); - } - } - return vote_dict; -} - -int register_voting_proposal(slice cs, int msg_value) impure inline_ref { - var (expire_at, proposal, critical?) = (cs~load_uint(32), cs~load_ref(), cs~load_int(1)); - if (expire_at >> 30) { - expire_at -= now(); - } - var (param_id, param_val, hash) = parse_config_proposal(proposal); - if (hash >= 0) { - cell cur_val = config_param(param_id); - int cur_hash = null?(cur_val) ? 0 : cell_hash(cur_val); - if (cur_hash != hash) { - hash = -0xe2646356; ;; bad current value - } - } else { - var m_params = config_param(9); - var (_, found?) = m_params.idict_get?(32, param_id); - if (found?) { - hash = -0xcd506e6c; ;; cannot set mandatory parameter to null - } - } - if (param_val.cell_depth() >= 128) { - hash = -0xc2616456; ;; bad value - } - if (hash < -1) { - return hash; ;; return error if any - } - ifnot (critical?) { - var crit_params = config_param(10); - var (_, found?) = crit_params.idict_get?(32, param_id); - if (found?) { - hash = -0xc3726954; ;; trying to set a critical parameter without critical flag - } - } - if (hash < -1) { - return hash; - } - ;; obtain vote proposal configuration - var vote_cfg = get_vote_config(critical?); - var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price) = vote_cfg; - if (expire_at < min_store_sec) { - return -0xc5787069; ;; expired - } - expire_at = min(expire_at, max_store_sec); - ;; compute price - var (_, bits, refs) = compute_data_size(param_val, 1024); - var pps = bit_price * (bits + 1024) + cell_price * (refs + 2); - var price = pps * expire_at; - expire_at += now(); - var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data(); - int phash = proposal.cell_hash(); - var (pstatus, found?) = vote_dict.udict_get?(256, phash); - if (found?) { - ;; proposal already exists; we can only extend it - var (expires, r_proposal, r_critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus); - if (r_critical? != critical?) { - return -0xc3726955; ;; cannot upgrade critical parameter to non-critical... - } - if (expires >= expire_at) { - return -0xc16c7245; ;; proposal already exists - } - ;; recompute price - price = pps * (expire_at - expires + 16384); - if (msg_value - price < (1 << 30)) { - return -0xf0617924; ;; need more money - } - ;; update expiration time - vote_dict~udict_set_builder(256, phash, begin_pack_proposal_status(expire_at, r_proposal, r_critical?, voters, weight_remaining, vset_id).store_slice(rest)); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - return price; - } - if (msg_value - price < (1 << 30)) { - return -0xf0617924; ;; need more money - } - ;; obtain current validator set data - var (vset, total_weight, _) = get_current_vset(); - int weight_remaining = muldiv(total_weight, 3, 4); - ;; create new proposal - vote_dict~udict_set_builder(256, phash, - begin_pack_proposal_status(expire_at, proposal, critical?, null(), weight_remaining, vset.cell_hash()) - .store_uint(max_tot_rounds, 8).store_uint(0, 16)); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - return price; -} - -() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { - var cs = in_msg_cell.begin_parse(); - var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - var s_addr = cs~load_msg_addr(); - (int src_wc, int src_addr) = s_addr.parse_std_addr(); - if ((src_wc + 1) | (flags & 1) | in_msg.slice_empty?()) { - ;; source not in masterchain, or a bounced message, or a simple transfer - return (); - } - int tag = in_msg~load_uint(32); - int query_id = in_msg~load_uint(64); - if (tag == 0x4e565354) { - ;; set next validator set - var vset = in_msg~load_ref(); - in_msg.end_parse(); - var elector_param = config_param(1); - var elector_addr = cell_null?(elector_param) ? -1 : elector_param.begin_parse().preload_uint(256); - var ok = false; - if (src_addr == elector_addr) { - ;; message from elector smart contract - ;; set next validator set - (var t_since, var t_until) = check_validator_set(vset); - var t = now(); - ok = (t_since > t) & (t_until > t_since); - } - if (ok) { - set_conf_param(36, vset); - ;; send confirmation - return send_confirmation(s_addr, query_id, 0xee764f4b); - } else { - return send_error(s_addr, query_id, 0xee764f6f); - } - } - if (tag == 0x6e565052) { - ;; new voting proposal - var price = register_voting_proposal(in_msg, msg_value); - int mode = 64; - int ans_tag = - price; - if (price >= 0) { - ;; ok, debit price - raw_reserve(price, 4); - ans_tag = 0xee565052; - mode = 128; - } - return send_answer(s_addr, query_id, ans_tag, mode); - } - if (tag == 0x566f7465) { - ;; vote for a configuration proposal - var signature = in_msg~load_bits(512); - var msg_body = in_msg; - var (sign_tag, idx, phash) = (in_msg~load_uint(32), in_msg~load_uint(16), in_msg~load_uint(256)); - in_msg.end_parse(); - throw_unless(37, sign_tag == 0x566f7445); - var (vdescr, total_weight) = get_validator_descr(idx); - var (val_pubkey, weight) = unpack_validator_descr(vdescr); - throw_unless(34, check_data_signature(msg_body, signature, val_pubkey)); - int res = proceed_register_vote(phash, idx, weight); - return send_confirmation(s_addr, query_id, res + 0xd6745240); - } - ;; if tag is non-zero and its higher bit is zero, throw an exception (the message is an unsupported query) - ;; to bounce message back to sender - throw_unless(37, (tag == 0) | (tag & (1 << 31))); - ;; do nothing for other internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - int action = cs~load_uint(32); - int msg_seqno = cs~load_uint(32); - var valid_until = cs~load_uint(32); - throw_if(35, valid_until < now()); - throw_if(39, slice_depth(cs) > 128); - var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data(); - throw_unless(33, msg_seqno == stored_seqno); - if (action == 0x566f7465) { - ;; vote for a configuration proposal - var (idx, phash) = (cs~load_uint(16), cs~load_uint(256)); - cs.end_parse(); - var (vdescr, total_weight) = get_validator_descr(idx); - var (val_pubkey, weight) = unpack_validator_descr(vdescr); - throw_unless(34, check_data_signature(in_msg, signature, val_pubkey)); - accept_message(); - stored_seqno = (stored_seqno + 1) % (1 << 32); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - commit(); - proceed_register_vote(phash, idx, weight); - return (); - } - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - stored_seqno = (stored_seqno + 1) % (1 << 32); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); - commit(); - (cfg_dict, public_key) = perform_action(cfg_dict, public_key, action, cs); - store_data(cfg_dict, stored_seqno, public_key, vote_dict); -} - -() run_ticktock(int is_tock) impure { - var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data(); - int kl = 32; - var next_vset = cfg_dict.idict_get_ref(kl, 36); - var updated? = false; - ifnot (next_vset.null?()) { - ;; check whether we have to set next_vset as the current validator set - var ds = next_vset.begin_parse(); - if (ds.slice_bits() >= 40) { - var tag = ds~load_uint(8); - var since = ds.preload_uint(32); - if ((since <= now()) & (tag == 0x12)) { - ;; next validator set becomes active! - var cur_vset = cfg_dict~idict_set_get_ref(kl, 34, next_vset); ;; next_vset -> cur_vset - cfg_dict~idict_set_get_ref(kl, 32, cur_vset); ;; cur_vset -> prev_vset - cfg_dict~idict_delete?(kl, 36); ;; (null) -> next_vset - updated? = true; - } - } - } - ifnot (updated?) { - ;; if nothing has been done so far, scan a random voting proposal instead - vote_dict = scan_random_proposal(vote_dict); - } - ;; save data and return - return store_data(cfg_dict, stored_seqno, public_key, vote_dict); -} - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -_ unpack_proposal(slice pstatus) inline_ref { - (int expires, cell proposal, int critical?, cell voters, int weight_remaining, int vset_id, slice rest) = unpack_proposal_status(pstatus); - var voters_list = null(); - var voter_id = (1 << 32); - do { - (voter_id, _, var f) = voters.udict_get_prev?(16, voter_id); - if (f) { - voters_list = cons(voter_id, voters_list); - } - } until (~ f); - var (rounds_remaining, losses, wins) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8)); - rest.end_parse(); - var (param_id, param_val, param_hash) = parse_config_proposal(proposal); - return [expires, critical?, [param_id, param_val, param_hash], vset_id, voters_list, weight_remaining, rounds_remaining, losses, wins]; -} - -_ get_proposal(int phash) method_id { - (_, _, _, var vote_dict) = load_data(); - var (pstatus, found?) = vote_dict.udict_get?(256, phash); - ifnot (found?) { - return null(); - } - return unpack_proposal(pstatus); -} - -_ list_proposals() method_id { - (_, _, _, var vote_dict) = load_data(); - var phash = (1 << 255) + ((1 << 255) - 1); - var list = null(); - do { - (phash, var pstatus, var f) = vote_dict.udict_get_prev?(256, phash); - if (f) { - list = cons([phash, unpack_proposal(pstatus)], list); - } - } until (~ f); - return list; -} - -_ proposal_storage_price(int critical?, int seconds, int bits, int refs) method_id { - var cfg_dict = get_data().begin_parse().preload_ref(); - var cparam11 = cfg_dict.idict_get_ref(32, 11); - var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price) = get_vote_config_internal(critical?, cparam11); - if (seconds < min_store_sec) { - return -1; - } - seconds = min(seconds, max_store_sec); - return (bit_price * (bits + 1024) + cell_price * (refs + 2)) * seconds; -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-req.fif b/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-req.fif deleted file mode 100644 index d1eaff9d..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-req.fif +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -"validator-to-sign.req" =: savefile -false =: internal? --1 =: seqno --1 =: expire-at - -{ ."usage: " @' $0 type ." (-i | ) []" cr - ."Creates an unsigned request expiring at unixtime to vote for configuration proposal (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index in current validator set (as stored in configuration parameter 34)." cr - ."If -i is selected, prepares unsigned request to be incorporated into an internal message instead." cr - ."The result is saved into (" savefile type ." by default) and output in hexadecimal form, to be signed later by the validator public key" cr 1 halt -} : usage - -$# dup 3 < swap 5 > or ' usage if -5 :$1..n -{ $* @ dup null? ' dup ' uncons cond $* ! } : $next - -$1 "-i" $= { $next drop true =: internal? } if - -internal? { - $next parse-int =: seqno - $next parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if - dup =: expire-at - dup now <= abort"expiration time must be in the future" - 32 ufits not abort"invalid expiration time" -} ifnot -$# dup 2 < swap 3 > or ' usage if -$1 parse-int dup =: val-idx - 16 ufits not abort"validator index out of range" -$2 parse-int dup =: prop-hash - 256 ufits not abort"invalid proposal hash" -$3 savefile replace-if-null =: savefile - -."Creating a request " internal? { ."with seqno " seqno . ."expiring at " expire-at . } ifnot -."to vote for configuration proposal 0x" prop-hash 64x. -."on behalf of validator with index " val-idx . cr - -internal? { B{566f7445} } { - B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ -} cond -val-idx 16 u>B B+ prop-hash 256 u>B B+ -dup Bx. cr -dup B>base64url type cr -savefile tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-signed.fif b/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-signed.fif deleted file mode 100644 index 5aaf1270..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/config-proposal-vote-signed.fif +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -"vote-query.boc" =: savefile -false =: internal? --1 =: seqno -0 0 2=: config-addr --1 =: expire-at - -{ ."usage: " @' $0 type ." (-i | ) []" cr - ."Creates an external message addressed to the configuration smart contract and current sequence number containing a signed request expiring at unixtime to vote for configuration proposal (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index and (Base64) public key in current validator set (as stored in configuration parameter 34)" cr - ." must be the base64 representation of Ed25519 signature of the previously generated unsigned request by means of " cr - ."If -i is selected, instead generates the body of an internal message to be sent to the configuration smart contract from any smartcontract residing in the masterchain" cr - ."The result is saved into (" savefile type ." by default), to be sent later by the lite-client" cr 1 halt -} : usage - -$# dup 5 < swap 8 > or ' usage if -8 :$1..n - -{ $* @ dup null? ' dup ' uncons cond $* ! } : $next -$1 "-i" $= { $next drop true =: internal? "vote-msg-body.boc" =: savefile } if - -internal? { - $next true parse-load-address drop over 1+ abort"configuration smart contract must be in masterchain" - 2=: config-addr - $next parse-int =: seqno - $next parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if - dup =: expire-at - dup now <= abort"expiration time must be in the future" - 32 ufits not abort"invalid expiration time" -} ifnot -$# dup 4 < swap 5 > or ' usage if -$1 parse-int dup =: val-idx - 16 ufits not abort"validator index out of range" -$2 parse-int dup =: prop-hash - 256 ufits not abort"invalid proposal hash" -$3 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long" - 32 B>u@+ 0xC6B41348 <> abort"invalid Ed25519 public key: unknown magic number" - =: pubkey -$4 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long" - =: signature -$5 savefile replace-if-null =: savefile - -internal? { - ."Creating the body of an internal message to be sent to the configuration smart contract" cr } -{ ."Creating an external message to configuration smart contract " - config-addr 2dup 6 .Addr ." = " .addr cr -} cond -."containing a signed request " internal? { ."expiring at " expire-at . } ifnot -."to vote for configuration proposal 0x" prop-hash 64x. -."on behalf of validator with index " val-idx . "and public key" pubkey Bx. cr - -internal? { B{566f7445} } { - B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ -} cond -val-idx 16 u>B B+ prop-hash 256 u>B B+ dup =: to_sign -."String to sign is " Bx. cr - -to_sign signature pubkey ed25519_chksign not abort"Ed25519 signature is invalid" -."Provided a valid Ed25519 signature " signature Bx. ." with validator public key " pubkey Bx. cr - -now 32 << prop-hash 32 1<< mod + =: query-id - - -cr -internal? { ."Internal message body is " } { ."External message is " } cond -dup B savefile tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/create-config-proposal.fif b/submodules/ton/tonlib-src/crypto/smartcont/create-config-proposal.fif deleted file mode 100644 index 18036d0d..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/create-config-proposal.fif +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage -86400 30 * =: expire-in -false =: critical --1 =: old-hash - -begin-options - " [-x ] [-c] [-H ] []" +cr +tab - +"Creates a new configuration proposal for setting configuration parameter to (`null` means no new value), " - +"and saves it as an internal message body into .boc ('config-msg-body.boc' by default)" - disable-digit-options generic-help-setopt - "c" "--critical" { true =: critical } short-long-option - "Creates a critical parameter change proposal" option-help - "x" "--expires-in" { parse-int =: expire-in } short-long-option-arg - "Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help - "H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash } - short-long-option-arg - "Sets the required cell hash of existing parameter value (0 means no value)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 2 < swap 3 > or ' usage if -3 :$1..n - -$1 parse-int dup =: param-idx - 32 fits not abort"parameter index out of range" -$2 =: boc-filename -$3 "config-msg-body.boc" replace-if-null =: savefile -expire-in now + =: expire-at - -boc-filename dup "null" $= { - ."New value of configuration parameter" param-idx . ."is null" cr drop null -} { - ."Loading new value of configuration parameter " param-idx . ."from file " dup type cr - boc-filename file>B B>boc - dup = tuck 1 i, -rot { 256 u, } { drop } cond b> ref, - critical 1 i, b> - -dup ."resulting internal message body: " B dup Bx. cr - -param-value dup null? { drop } { - totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> " - drop dup Blen . ."BoC data bytes)" cr -} cond - -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/create-config-upgrade-proposal.fif b/submodules/ton/tonlib-src/crypto/smartcont/create-config-upgrade-proposal.fif deleted file mode 100644 index 35caa64b..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/create-config-upgrade-proposal.fif +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/fift -s -"Asm.fif" include -"TonUtil.fif" include -"GetOpt.fif" include - -// only the next three lines differ in elector/configuration smart contract upgrades -"configuration" =: name -"auto/config-code.fif" =: src-file --1000 =: param-idx - -86400 30 * =: expire-in -true =: critical --1 =: old-hash - -{ show-options-help 1 halt } : usage -{ name $+ } : +name - -begin-options - " [-s ] [-x ] [-H ] []" +cr +tab - +"Creates a new configuration proposal for upgrading the " +name +" smart contract code to ('" src-file $+ +"' by default), " - +"and saves it as an internal message body into .boc ('config-msg-body.boc' by default)" - disable-digit-options generic-help-setopt - "x" "--expires-in" { parse-int =: expire-in } short-long-option-arg - "Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help - "s" "--source" { =: src-file } short-long-option-arg - "Fift assembler source file for the new " +name +" smart contract code ('" - src-file $+ +"' by default)" option-help - "H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash } - short-long-option-arg - "Sets the required cell hash of existing parameter value (0 means no value)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 1 > ' usage if -1 :$1..n - -$1 "config-msg-body.boc" replace-if-null =: savefile -expire-in now + =: expire-at - -."Assembling new " name type ." smart contract code from " src-file type cr -src-file include -dup abort"not valid smart contract code" - =: param-value - -critical { ."Critical" } { ."Non-critical" } cond -." configuration proposal for configuration parameter " param-idx . -."will expire at " expire-at . ."(in " expire-in . ."seconds)" cr - -now 32 << param-idx + =: query-id -."Query id is " query-id . cr - -// create message body -= tuck 1 i, -rot { 256 u, } { drop } cond b> ref, - critical 1 i, b> - -dup ."resulting internal message body: " B dup Bx. cr -param-value totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> " -drop dup Blen . ."BoC data bytes)" cr - -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/create-elector-upgrade-proposal.fif b/submodules/ton/tonlib-src/crypto/smartcont/create-elector-upgrade-proposal.fif deleted file mode 100644 index 7eba0b60..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/create-elector-upgrade-proposal.fif +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/fift -s -"Asm.fif" include -"TonUtil.fif" include -"GetOpt.fif" include - -// only the next three lines differ in elector/configuration smart contract upgrades -"elector" =: name -"auto/elector-code.fif" =: src-file --1001 =: param-idx - -86400 30 * =: expire-in -true =: critical --1 =: old-hash - -{ show-options-help 1 halt } : usage -{ name $+ } : +name - -begin-options - " [-s ] [-x ] [-H ] []" +cr +tab - +"Creates a new configuration proposal for upgrading the " +name +" smart contract code to ('" src-file $+ +"' by default), " - +"and saves it as an internal message body into .boc ('config-msg-body.boc' by default)" - disable-digit-options generic-help-setopt - "x" "--expires-in" { parse-int =: expire-in } short-long-option-arg - "Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help - "s" "--source" { =: src-file } short-long-option-arg - "Fift assembler source file for the new " +name +" smart contract code ('" - src-file $+ +"' by default)" option-help - "H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash } - short-long-option-arg - "Sets the required cell hash of existing parameter value (0 means no value)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 1 > ' usage if -1 :$1..n - -$1 "config-msg-body.boc" replace-if-null =: savefile -expire-in now + =: expire-at - -."Assembling new " name type ." smart contract code from " src-file type cr -src-file include -dup abort"not valid smart contract code" - =: param-value - -critical { ."Critical" } { ."Non-critical" } cond -." configuration proposal for configuration parameter " param-idx . -."will expire at " expire-at . ."(in " expire-in . ."seconds)" cr - -now 32 << param-idx + =: query-id -."Query id is " query-id . cr - -// create message body -= tuck 1 i, -rot { 256 u, } { drop } cond b> ref, - critical 1 i, b> - -dup ."resulting internal message body: " B dup Bx. cr -param-value totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> " -drop dup Blen . ."BoC data bytes)" cr - -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/dns-auto-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/dns-auto-code.fc deleted file mode 100644 index e548a70a..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/dns-auto-code.fc +++ /dev/null @@ -1,514 +0,0 @@ -{- - Adapted from original version written by: - /------------------------------------------------------------------------\ - | Created for: Telegram (Open Network) Blockchain Contest | - | Task 2: DNS Resolver (Automatically registering) | - >------------------------------------------------------------------------< - | Author: Oleksandr Murzin (tg: @skydev / em: alexhacker64@gmail.com) | - | October 2019 | - \------------------------------------------------------------------------/ --} - -;;===========================================================================;; -;; Utility functions ;; -;;===========================================================================;; - -{- - Data structure: - Root cell: [OptRef<1b+1r?>:HashmapUInt<32b>,CatTable>:domains] - [OptRef<1b+1r?>:Hashmap(Time|Hash128)->Slice(DomName)>:gc] - [UInt<32b>:stdperiod] [Gram:PPReg] [Gram:PPCell] [Gram:PPBit] - [UInt<32b>:lasthousekeeping] - := HashmapE 16 ^DNSRecord - - STORED DOMAIN NAME SLICE FORMAT: (#ZeroChars<7b>) (Domain name value) - #Zeros allows to simultaneously store, for example, com\0 and com\0google\0 - That will be stored as \1com\0 and \2com\0google\0 (pfx tree has restricitons) - This will allow to resolve more specific requests to subdomains, and resort - to parent domain next resolver lookup if subdomain is not found - com\0goo\0 lookup will, for example look up \2com\0goo\0 and then - \1com\0goo\0 which will return \1com\0 (as per pfx tree) with -1 cat --} - -(cell, cell, cell, [int, int, int, int], int, int) load_data() inline_ref { - slice cs = get_data().begin_parse(); - return ( - cs~load_ref(), ;; control data - cs~load_dict(), ;; pfx tree: domains data and exp - cs~load_dict(), ;; gc auxillary with expiration and 128-bit hash slice - [ cs~load_uint(30), ;; length of this period of time in seconds - cs~load_grams(), ;; standard payment for registering a new subdomain - cs~load_grams(), ;; price paid for each cell (PPC) - cs~load_grams() ], ;; and bit (PPB) - cs~load_uint(32), ;; next housekeeping to be done at - cs~load_uint(32) ;; last housekeeping done at - ); -} - -(int, int, int, int) load_prices() inline_ref { - slice cs = get_data().begin_parse(); - (cs~load_ref(), cs~load_dict(), cs~load_dict()); - return (cs~load_uint(30), cs~load_grams(), cs~load_grams(), cs~load_grams()); -} - -() store_data(cell ctl, cell dd, cell gc, prices, int nhk, int lhk) impure { - var [sp, ppr, ppc, ppb] = prices; - set_data(begin_cell() - .store_ref(ctl) ;; control data - .store_dict(dd) ;; domains data and exp - .store_dict(gc) ;; keyed expiration time and 128-bit hash slice - .store_uint(sp, 30) ;; standard period - .store_grams(ppr) ;; price per registration - .store_grams(ppc) ;; price per cell - .store_grams(ppb) ;; price per bit - .store_uint(nhk, 32) ;; next housekeeping - .store_uint(lhk, 32) ;; last housekeeping - .end_cell()); -} - -global var query_info; - -() send_message(slice addr, int tag, int query_id, - int body, int grams, int mode) impure { - ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - ;; src:MsgAddress -> 011000 0x18 - var msg = begin_cell() - .store_uint (0x18, 6) - .store_slice(addr) - .store_grams(grams) - .store_uint (0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint (tag, 32) - .store_uint (query_id, 64); - if (body >= 0) { - msg~store_uint(body, 32); - } - send_raw_message(msg.end_cell(), mode); -} - -() send_error(int error_code) impure { - var (addr, query_id, op) = query_info; - return send_message(addr, error_code, query_id, op, 0, 64); -} - -() send_ok(int price) impure { - raw_reserve(price, 4); - var (addr, query_id, op) = query_info; - return send_message(addr, 0xef6b6179, query_id, op, 0, 128); -} - -() housekeeping(cell ctl, cell dd, cell gc, prices, int nhk, int lhk, int max_steps) impure { - int n = now(); - if (n < max(nhk, lhk + 60)) { ;; housekeeping cooldown: 1 minute - ;; if housekeeping was done recently, or if next housekeeping is in the future, just save - return store_data(ctl, dd, gc, prices, nhk, lhk); - } - ;; need to do some housekeeping - maybe remove entry with - ;; least expiration but only if it is already expired - ;; no iterating and deleting all to not put too much gas gc - ;; burden on any random specific user request - ;; over time it will do the garbage collection required - (int mkey, _, int found?) = gc.udict_get_min?(256); - while (found? & max_steps) { ;; no short circuit optimization, two nested ifs - nhk = (mkey >> (256 - 32)); - if (nhk < n) { - int key = mkey % (1 << (256 - 32)); - (slice val, found?) = dd.udict_get?(256 - 32, key); - if (found?) { - int exp = val.preload_uint(32); - if (exp <= n) { - dd~udict_delete?(256 - 32, key); - } - } - gc~udict_delete?(256, mkey); - (mkey, _, found?) = gc.udict_get_min?(256); - nhk = (found? ? mkey >> (256 - 32) : 0xffffffff); - max_steps -= 1; - } else { - found? = false; - } - } - store_data(ctl, dd, gc, prices, nhk, n); -} - -int calcprice_internal(slice domain, cell data, ppc, ppb) inline_ref { ;; only for internal calcs - var (_, bits, refs) = compute_data_size(data, 100); ;; 100 cells max - bits += slice_bits(domain) * 2 + (128 + 32 + 32); - return ppc * (refs + 2) + ppb * bits; -} - -int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int strict) inline_ref { - if (strict & cat_table.null?()) { ;; domain not found: return notf | 2^31 - return 0xee6f7466; - } - if (owner_info.null?()) { ;; no owner on this domain: no-2 (in strict mode), ok else - return strict & 0xee6f2d32; - } - var ERR_BAD2 = 0xe2616432; - slice sown = owner_info.begin_parse(); - if (sown.slice_bits() < 16 + 3 + 8 + 256) { ;; bad owner record: bad2 - return ERR_BAD2; - } - if (sown~load_uint(16 + 3) != 0x9fd3 * 8 + 4) { - return ERR_BAD2; - } - (int owner_wc, int owner_addr) = (sown~load_int(8), sown.preload_uint(256)); - if ((owner_wc != src_wc) | (owner_addr != src_addr)) { ;; not owner: nown - return 0xee6f776e; - } - return 0; ;; ok -} - -;;===========================================================================;; -;; Internal message handler (Code 0) ;; -;;===========================================================================;; - -{- - Internal message cell structure: - 8 4 2 1 - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - src:MsgAddressInt dest:MsgAddressInt - value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - created_lt:uint64 created_at:uint32 - Internal message data structure: - [UInt<32b>:op] [UInt<64b>:query_id] [Ref<1r>:domain] - (if not prolong: [Ref<1r>:value->CatTable]) - --} - -;; Control operations: permitted only to the owner of this smartcontract -() perform_ctl_op(int op, int src_wc, int src_addr, slice in_msg) impure inline_ref { - var (ctl, domdata, gc, prices, nhk, lhk) = load_data(); - var cs = ctl.begin_parse(); - if ((cs~load_int(8) != src_wc) | (cs~load_uint(256) != src_addr)) { - return send_error(0xee6f776e); - } - if (op == 0x43685072) { ;; ChPr = Change Prices - var (stdper, ppr, ppc, ppb) = (in_msg~load_uint(32), in_msg~load_grams(), in_msg~load_grams(), in_msg~load_grams()); - in_msg.end_parse(); - ;; NB: stdper == 0 -> disable new actions - store_data(ctl, domdata, gc, [stdper, ppr, ppc, ppb], nhk, lhk); - return send_ok(0); - } - if (op == 0x4344656c) { ;; CDel = destroy smart contract - ifnot (domdata.null?()) { - ;; domain dictionary not empty, force gc - housekeeping(ctl, domdata, gc, prices, nhk, 1, -1); - } - (ctl, domdata, gc, prices, nhk, lhk) = load_data(); - ifnot (domdata.null?()) { - ;; domain dictionary still not empty, error - return send_error(0xee74656d); - } - var (addr, query_id, op) = query_info; - return send_message(addr, 0xef6b6179, query_id, op, 0, 128 + 32); - } - return send_error(0xffffffff); -} - -;; Must send at least GR$1 more for possible gas fees! -() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { - ;; this time very interested in internal messages - if (in_msg.slice_bits() < 32) { - return (); ;; simple transfer or short - } - slice cs = in_msg_cell.begin_parse(); - int flags = cs~load_uint(4); - if (flags & 1) { - return (); ;; bounced messages - } - slice s_addr = cs~load_msg_addr(); - (int src_wc, int src_addr) = s_addr.parse_std_addr(); - int op = in_msg~load_uint(32); - ifnot (op) { - return (); ;; simple transfer with comment - } - int query_id = 0; - if (in_msg.slice_bits() >= 64) { - query_id = in_msg~load_uint(64); - } - - query_info = (s_addr, query_id, op); - - if (op & (1 << 31)) { - return (); ;; an answer to our query - } - if ((op >> 24) == 0x43) { - ;; Control operations - return perform_ctl_op(op, src_wc, src_addr, in_msg); - } - - int qt = (op == 0x72656764) * 1 + (op == 0x70726f6c) * 2 + (op == 0x75706464) * 4 + (op == 0x676f6763) * 8; - ifnot (qt) { ;; unknown query, return error - return send_error(0xffffffff); - } - qt = - qt; - - (cell ctl, cell domdata, cell gc, [int, int, int, int] prices, int nhk, int lhk) = load_data(); - - if (qt == 8) { ;; 0x676f6763 -> GO, GC! go!!! - ;; Manual garbage collection iteration - int max_steps = in_msg~load_int(32); ;; -1 = infty - housekeeping(ctl, domdata, gc, prices, nhk, 1, max_steps); ;; forced - return send_error(0xef6b6179); - } - - slice domain = null(); - cell domain_cell = in_msg~load_maybe_ref(); - int fail = 0; - if (domain_cell.null?()) { - int bytes = in_msg~load_uint(6); - fail = (bytes == 0); - domain = in_msg~load_bits(bytes * 8); - } else { - domain = domain_cell.begin_parse(); - var (bits, refs) = slice_bits_refs(domain); - fail = (refs | ((bits - 8) & (7 - 128))); - } - - ifnot (fail) { - ;; domain must end with \0! no\0 error - fail = domain.slice_last(8).preload_uint(8); - } - if (fail) { - return send_error(0xee6f5c30); - } - - int n = now(); - cell cat_table = cell owner_info = null(); - int key = int exp = int zeros = 0; - slice tail = domain; - repeat (tail.slice_bits() ^>> 3) { - cat_table = null(); - int z = (tail~load_uint(8) == 0); - zeros -= z; - if (z) { - key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32); - var (val, found?) = domdata.udict_get?(256 - 32, key); - if (found?) { - exp = val~load_uint(32); - if (exp >= n) { ;; entry not expired - cell cat_table = val~load_ref(); - val.end_parse(); - var (cown, ok) = cat_table.idict_get_ref?(16, -2); - if (ok) { - owner_info = cown; - } - } - } - } - } - - if (zeros > 4) { ;; too much zero chars (overflow): ov\0 - return send_error(0xef765c30); - } - - ;; ########################################################################## - - int err = check_owner(cat_table, owner_info, src_wc, src_addr, qt != 1); - if (err) { - return send_error(err); - } - - ;; ########################################################################## - - ;; load desired data (reuse old for a "prolong" operation) - cell data = null(); - - if (qt != 2) { ;; not a "prolong", load data dictionary - data = in_msg~load_ref(); - ;; basic integrity check of (client-provided) dictionary - ifnot (data.dict_empty?()) { ;; 1000 gas! - var (oinfo, ok) = data.idict_get_ref?(16, -2); - if (ok) { - var cs = oinfo.begin_parse(); - throw_unless(31, cs.slice_bits() >= 16 + 3 + 8 + 256); - throw_unless(31, cs.preload_uint(19) == 0x9fd3 * 8 + 4); - } - (_, _, int minok) = data.idict_get_min?(16); - (_, _, int maxok) = data.idict_get_max?(16); - throw_unless(31, minok & maxok); - } - } else { - data = cat_table; - } - - ;; load prices - var [stdper, ppr, ppc, ppb] = prices; - ifnot (stdper) { ;; smart contract disabled by owner, no new actions - return send_error(0xd34f4646); - } - - ;; compute action price - int price = calcprice_internal(domain, data, ppc, ppb) + (ppr & (qt != 4)); - if (msg_value - (1 << 30) < price) { ;; gr prol | prolong domain - if (exp > n + stdper) { ;; does not expire soon, cannot prolong - return send_error(0xf365726f); - } - domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp + stdper, 32).store_ref(data)); - - int gckeyO = (exp << (256 - 32)) + key; - int gckeyN = gckeyO + (stdper << (256 - 32)); - gc~udict_delete?(256, gckeyO); ;; delete old gc entry, add new - gc~udict_set_builder(256, gckeyN, begin_cell()); - - housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1); - return send_ok(price); - } - - ;; ########################################################################## - if (qt == 1) { ;; 0x72656764 -> regd | register domain - ifnot (cat_table.null?()) { ;; domain already exists: return alre | 2^31 - return send_error(0xe16c7265); - } - int expires_at = n + stdper; - domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(expires_at, 32).store_ref(data)); - - int gckey = (expires_at << (256 - 32)) | key; - gc~udict_set_builder(256, gckey, begin_cell()); - - housekeeping(ctl, domdata, gc, prices, min(nhk, expires_at), lhk, 1); - return send_ok(price); - } - - ;; ########################################################################## - if (qt == 4) { ;; 0x75706464 -> updd | update domain (data) - domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp, 32).store_ref(data)); - housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1); - return send_ok(price); - } - ;; ########################################################################## - - return (); ;; should NEVER reach this part of code! -} - -;;===========================================================================;; -;; External message handler (Code -1) ;; -;;===========================================================================;; - -() recv_external(slice in_msg) impure { - ;; only for initialization - (cell ctl, cell dd, cell gc, var prices, int nhk, int lhk) = load_data(); - ifnot (lhk) { - accept_message(); - return store_data(ctl, dd, gc, prices, 0xffffffff, now()); - } -} - -;;===========================================================================;; -;; Getter methods ;; -;;===========================================================================;; - -(int, cell, int, slice) dnsdictlookup(slice domain, int nowtime) inline_ref { - (int bits, int refs) = domain.slice_bits_refs(); - throw_if(30, refs | (bits & 7)); ;; malformed input (~ 8n-bit) - ifnot (bits) { - return (0, null(), 0, null()); ;; zero-length input - } - - int domain_last_byte = domain.slice_last(8).preload_uint(8); - if (domain_last_byte) { - domain = begin_cell().store_slice(domain) ;; append zero byte - .store_uint(0, 8).end_cell().begin_parse(); - bits += 8; - } - if (bits == 8) { - return (0, null(), 0, null()); ;; zero-length input, but with zero byte - } - var ds = get_data().begin_parse(); - (_, cell root) = (ds~load_ref(), ds~load_dict()); - - slice val = null(); - int tail_bits = -1; - slice tail = domain; - - repeat (bits >> 3) { - if (tail~load_uint(8) == 0) { - var key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32); - var (v, found?) = root.udict_get?(256 - 32, key); - if (found?) { - if (v.preload_uint(32) >= nowtime) { ;; entry not expired - val = v; - tail_bits = tail.slice_bits(); - } - } - } - } - - if (val.null?()) { - return (0, null(), 0, null()); ;; failed to find entry in subdomain dictionary - } - - return (val~load_uint(32), val~load_ref(), tail_bits == 0, domain.skip_last_bits(tail_bits)); -} - -;;8m dns-record-value -(int, cell) dnsresolve(slice domain, int category) method_id { - (int exp, cell cat_table, int exact?, slice pfx) = dnsdictlookup(domain, now()); - ifnot (exp) { - return (0, null()); - } - ifnot (exact?) { ;; incomplete subdomain found, must return next resolver (-1) - category = -1; - } - - int pfx_bits = pfx.slice_bits(); - - ;; pfx.slice_bits() will contain 8m, where m is number of bytes in subdomain - ;; COUNTING the zero byte (if structurally correct: no multiple-ZB keys) - ;; which corresponds to 8m, m=one plus the number of bytes in the subdomain found) - ifnot (category) { - return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0 - } else { - cell cat_found = cat_table.idict_get_ref(16, category); - return (pfx_bits, cat_found); - } -} - -;; getexpiration needs to know the current time to skip any possible expired -;; subdomains in the chain. it will return 0 if not found or expired. -int getexpirationx(slice domain, int nowtime) inline method_id { - (int exp, _, _, _) = dnsdictlookup(domain, nowtime); - return exp; -} - -int getexpiration(slice domain) method_id { - return getexpirationx(domain, now()); -} - -int getstdperiod() method_id { - (int stdper, _, _, _) = load_prices(); - return stdper; -} - -int getppr() method_id { - (_, int ppr, _, _) = load_prices(); - return ppr; -} - -int getppc() method_id { - (_, _, int ppc, _) = load_prices(); - return ppc; -} - -int getppb() method_id { - ( _, _, _, int ppb) = load_prices(); - return ppb; -} - -int calcprice(slice domain, cell val) method_id { ;; only for external gets (not efficient) - (_, _, int ppc, int ppb) = load_prices(); - return calcprice_internal(domain, val, ppc, ppb); -} - -int calcregprice(slice domain, cell val) method_id { ;; only for external gets (not efficient) - (_, int ppr, int ppc, int ppb) = load_prices(); - return ppr + calcprice_internal(domain, val, ppc, ppb); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/dns-manual-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/dns-manual-code.fc deleted file mode 100644 index 890d5d86..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/dns-manual-code.fc +++ /dev/null @@ -1,348 +0,0 @@ -{- - Originally created by: - /------------------------------------------------------------------------\ - | Created for: Telegram (Open Network) Blockchain Contest | - | Task 3: DNS Resolver (Manually controlled) | - >------------------------------------------------------------------------< - | Author: Oleksandr Murzin (tg: @skydev / em: alexhacker64@gmail.com) | - | October 2019 | - \------------------------------------------------------------------------/ --} - -;;===========================================================================;; -;; Custom ASM instructions ;; -;;===========================================================================;; - -(cell, ()) pfxdict_set_ref(cell dict, int key_len, slice key, cell value) { - throw_unless(33, dict~pfxdict_set?(key_len, key, begin_cell().store_maybe_ref(value).end_cell().begin_parse())); - return (dict, ()); -} - -(slice, cell, slice, int) pfxdict_get_ref(cell dict, int key_len, slice key) inline_ref { - (slice pfx, slice val, slice tail, int succ) = dict.pfxdict_get?(key_len, key); - cell res = succ ? val~load_maybe_ref() : null(); - return (pfx, res, tail, succ); -} - -;;===========================================================================;; -;; Utility functions ;; -;;===========================================================================;; - -(int, int, int, cell, cell) load_data() inline_ref { - slice cs = get_data().begin_parse(); - var res = (cs~load_uint(32), cs~load_uint(64), cs~load_uint(256), cs~load_dict(), cs~load_dict()); - cs.end_parse(); - return res; -} - -() store_data(int contract_id, int last_cleaned, int public_key, cell root, old_queries) impure { - set_data(begin_cell() - .store_uint(contract_id, 32) - .store_uint(last_cleaned, 64) - .store_uint(public_key, 256) - .store_dict(root) - .store_dict(old_queries) - .end_cell()); -} - -;;===========================================================================;; -;; Internal message handler (Code 0) ;; -;;===========================================================================;; - -() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { - ;; not interested at all -} - -;;===========================================================================;; -;; External message handler (Code -1) ;; -;;===========================================================================;; - -{- - External message structure: - [Bytes<512b>:signature] [UInt<32b>:seqno] [UInt<6b>:operation] - [Either b0: inline name (<= 58-x Bytes) or b1: reference-stored name) - x depends on operation - Use of 6-bit op instead of 32-bit allows to save 4 bytes for inline name - Inline [Name] structure: [UInt<6b>:length] [Bytes:data] - Operations (continuation of message): - 00 Contract initialization message (only if seqno = 0) (x=-) - 11 VSet: set specified value to specified subdomain->category (x=2) - [Int<16b>:category] [Name:subdomain] [Cell<1r>:value] - 12 VDel: delete specified subdomain->category (x=2) - [Int<16b>:category] [Name:subdomain] - 21 DSet: replace entire category dictionary of domain with provided (x=0) - [Name:subdomain] [Cell<1r>:new_cat_table] - 22 DDel: delete entire category dictionary of specified domain (x=0) - [Name:subdomain] - 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-) - [Cell<1r>:new_domains_table] - 32 TDel: nullify ENTIRE DOMAIN TABLE (x=-) - 51 OSet: replace owner public key with a new one (x=-) - [UInt<256b>:new_public_key] --} - -() after_code_upgrade(cell root, slice ops, cont old_code) impure method_id(1666); - -(cell, slice) process_op(cell root, slice ops) inline_ref { - int op = ops~load_uint(6); - if (op < 10) { - ifnot (op) { - ;; 00 Noop: No operation - return (root, ops); - } - if (op == 1) { - ;; 01 SMsg: Send Message - var mode = ops~load_uint(8); - send_raw_message(ops~load_ref(), mode); - return (root, ops); - } - if (op == 9) { - ;; 09 CodeUpgrade - var new_code = ops~load_ref(); - set_code(new_code); - var old_code = get_c3(); - set_c3(new_code.begin_parse().bless()); - after_code_upgrade(root, ops, old_code); - throw(0); - return (root, ops); - } - throw(45); - return (root, ops); - } - int cat = 0; - if (op < 20) { - ;; for operations with codes 10..19 category is required - cat = ops~load_int(16); - } - slice name = null(); ;; any slice value - cell cat_table = null(); - if (op < 30) { - ;; for operations with codes 10..29 name is required - int is_name_ref = (ops~load_uint(1) == 1); - if (is_name_ref) { - ;; name is stored in separate referenced cell - name = ops~load_ref().begin_parse(); - } else { - ;; name is stored inline - int name_len = ops~load_uint(6) * 8; - name = ops~load_bits(name_len); - } - ;; at least one character not counting \0 - throw_unless(38, name.slice_bits() >= 16); - ;; name shall end with \0 - int name_last_byte = name.slice_last(8).preload_uint(8); - throw_if(40, name_last_byte); - ;; count zero separators - int zeros = 0; - slice cname = name; - repeat (cname.slice_bits() ^>> 3) { - int c = cname~load_uint(8); - zeros -= (c == 0); - } - ;; throw_unless(39, zeros == 1); - name = begin_cell().store_uint(zeros, 7).store_slice(name).end_cell().begin_parse(); - } - ;; operation with codes 10..19 manipulate category dict - ;; lets try to find it and store into a variable - ;; operations with codes 20..29 replace / delete dict, no need - if (op < 20) { - ;; lets resolve the name here so as not to duplicate the code - (slice pfx, cell val, slice tail, int succ) = - root.pfxdict_get_ref(1023, name); - if (succ) { - ;; must match EXACTLY to prevent accident changes - throw_unless(35, tail.slice_empty?()); - cat_table = val; - } - ;; otherwise cat_table is null which is reasonable for actions - } - ;; 11 VSet: set specified value to specified subdomain->category - if (op == 11) { - cell new_value = ops~load_maybe_ref(); - cat_table~idict_set_get_ref(16, cat, new_value); - root~pfxdict_set_ref(1023, name, cat_table); - return (root, ops); - } - ;; 12 VDel: delete specified subdomain->category value - if (op == 12) { - if (cat_table~idict_delete?(16, cat)) { - root~pfxdict_set_ref(1023, name, cat_table); - } - return (root, ops); - } - ;; 21 DSet: replace entire category dictionary of domain with provided - if (op == 21) { - cell new_cat_table = ops~load_maybe_ref(); - root~pfxdict_set_ref(1023, name, new_cat_table); - return (root, ops); - } - ;; 22 DDel: delete entire category dictionary of specified domain - if (op == 22) { - root~pfxdict_delete?(1023, name); - return (root, ops); - } - ;; 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell - if (op == 31) { - cell new_tree_root = ops~load_maybe_ref(); - ;; no sanity checks cause they would cost immense gas - return (new_tree_root, ops); - } - ;; 32 TDel: nullify ENTIRE DOMAIN TABLE - if (op == 32) { - return (null(), ops); - } - throw(44); ;; invalid operation - return (null(), ops); -} - -cell process_ops(cell root, slice ops) inline_ref { - var stop = false; - root~touch(); - ops~touch(); - do { - (root, ops) = process_op(root, ops); - if (ops.slice_data_empty?()) { - if (ops.slice_refs()) { - ops = ops~load_ref().begin_parse(); - } else { - stop = true; - } - } - } until (stop); - return root; -} - -() recv_external(slice in_msg) impure { - ;; Load data - (int contract_id, int last_cleaned, int public_key, cell root, cell old_queries) = load_data(); - - ;; validate signature and seqno - slice signature = in_msg~load_bits(512); - int shash = slice_hash(in_msg); - var (query_contract, query_id) = (in_msg~load_uint(32), in_msg~load_uint(64)); - var bound = (now() << 32); - throw_if(35, query_id < bound); - (_, var found?) = old_queries.udict_get?(64, query_id); - throw_if(32, found?); - throw_unless(34, contract_id == query_contract); - throw_unless(35, check_signature(shash, signature, public_key)); - accept_message(); ;; message is signed by owner, sanity not guaranteed yet - - int op = in_msg.preload_uint(6); - if (op == 51) { - in_msg~skip_bits(6); - public_key = in_msg~load_uint(256); - } else { - root = process_ops(root, in_msg); - } - - bound -= (64 << 32); ;; clean up records expired more than 64 seconds ago - old_queries~udict_set_builder(64, query_id, begin_cell()); - var queries = old_queries; - do { - var (old_queries', i, _, f) = old_queries.udict_delete_get_min(64); - f~touch(); - if (f) { - f = (i < bound); - } - if (f) { - old_queries = old_queries'; - last_cleaned = i; - } - } until (~ f); - - store_data(contract_id, last_cleaned, public_key, root, old_queries); -} - -() after_code_upgrade(cell root, slice ops, cont old_code) impure method_id(1666) { -} - -{- - Data structure: - Root cell: [UInt<32b>:seqno] [UInt<256b>:owner_public_key] - [OptRef<1b+1r?>:HashmapCatTable>:domains] - := HashmapE 16 ^DNSRecord - - STORED DOMAIN NAME SLICE FORMAT: (#ZeroChars<7b>) (Domain name value) - #Zeros allows to simultaneously store, for example, com\0 and com\0google\0 - That will be stored as \1com\0 and \2com\0google\0 (pfx tree has restricitons) - This will allow to resolve more specific requests to subdomains, and resort - to parent domain next resolver lookup if subdomain is not found - com\0goo\0 lookup will, for example look up \2com\0goo\0 and then - \1com\0goo\0 which will return \1com\0 (as per pfx tree) with -1 cat --} - -;;===========================================================================;; -;; Getter methods ;; -;;===========================================================================;; - -;; Retrieve contract id (in case several contracts are managed with the same private key) -int get_contract_id() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(32 + 64); - return cs.preload_uint(256); -} - -;;8m dns-record-value -(int, cell) dnsresolve(slice subdomain, int category) method_id { - int bits = subdomain.slice_bits(); - ifnot (bits) { - return (0, null()); ;; zero-length input - } - throw_if(30, bits & 7); ;; malformed input (~ 8n-bit) - - int name_last_byte = subdomain.slice_last(8).preload_uint(8); - if (name_last_byte) { - subdomain = begin_cell().store_slice(subdomain) ;; append zero byte - .store_uint(0, 8).end_cell().begin_parse(); - bits += 8; - } - if (bits == 8) { - return (0, null()); ;; zero-length input, but with zero byte - } - (_, _, _, cell root, _) = load_data(); - - slice cname = subdomain; - int zeros = 0; - repeat (bits >> 3) { - int c = cname~load_uint(8); - zeros -= (c == 0); - } - - ;; can't move these declarations lower, will cause errors! - slice pfx = cname; - cell val = null(); - slice tail = cname; - - do { - slice pfxname = begin_cell().store_uint(zeros, 7) - .store_slice(subdomain).end_cell().begin_parse(); - (pfx, val, tail, int succ) = root.pfxdict_get_ref(1023, pfxname); - zeros = succ ^ (zeros - 1); ;; break on success - } until (zeros <= 0); - - ifnot (zeros) { - return (0, null()); ;; failed to find entry in prefix dictionary - } - - zeros = - zeros; - - ifnot (tail.slice_empty?()) { ;; if we have tail then len(pfx) < len(subdomain) - category = -1; ;; incomplete subdomain found, must return next resolver (-1) - } - int pfx_bits = pfx.slice_bits() - 7; - cell cat_table = val; - ;; pfx.slice_bits() will contain 8m, where m is number of bytes in subdomain - ;; COUNTING the zero byte (if structurally correct: no multiple-ZB keys) - ;; which corresponds to 8m, m=one plus the number of bytes in the subdomain found) - if (category == 0) { - return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0 - } else { - cell cat_found = cat_table.idict_get_ref(16, category); - return (pfx_bits, cat_found); - } -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fc deleted file mode 100644 index 844ac90a..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fc +++ /dev/null @@ -1,1168 +0,0 @@ -;; Elector smartcontract - -;; cur_elect credits past_elections grams active_id active_hash -(cell, cell, cell, int, int, int) load_data() inline_ref { - var cs = get_data().begin_parse(); - var res = (cs~load_dict(), cs~load_dict(), cs~load_dict(), cs~load_grams(), cs~load_uint(32), cs~load_uint(256)); - cs.end_parse(); - return res; -} - -;; cur_elect credits past_elections grams active_id active_hash -() store_data(elect, credits, past_elections, grams, active_id, active_hash) impure inline_ref { - set_data(begin_cell() - .store_dict(elect) - .store_dict(credits) - .store_dict(past_elections) - .store_grams(grams) - .store_uint(active_id, 32) - .store_uint(active_hash, 256) - .end_cell()); -} - -;; elect -> elect_at elect_close min_stake total_stake members failed finished -_ unpack_elect(elect) inline_ref { - var es = elect.begin_parse(); - var res = (es~load_uint(32), es~load_uint(32), es~load_grams(), es~load_grams(), es~load_dict(), es~load_int(1), es~load_int(1)); - es.end_parse(); - return res; -} - -cell pack_elect(elect_at, elect_close, min_stake, total_stake, members, failed, finished) inline_ref { - return begin_cell() - .store_uint(elect_at, 32) - .store_uint(elect_close, 32) - .store_grams(min_stake) - .store_grams(total_stake) - .store_dict(members) - .store_int(failed, 1) - .store_int(finished, 1) - .end_cell(); -} - -;; slice -> unfreeze_at stake_held vset_hash frozen_dict total_stake bonuses complaints -_ unpack_past_election(slice fs) inline_ref { - var res = (fs~load_uint(32), fs~load_uint(32), fs~load_uint(256), fs~load_dict(), fs~load_grams(), fs~load_grams(), fs~load_dict()); - fs.end_parse(); - return res; -} - -builder pack_past_election(int unfreeze_at, int stake_held, int vset_hash, cell frozen_dict, int total_stake, int bonuses, cell complaints) inline_ref { - return begin_cell() - .store_uint(unfreeze_at, 32) - .store_uint(stake_held, 32) - .store_uint(vset_hash, 256) - .store_dict(frozen_dict) - .store_grams(total_stake) - .store_grams(bonuses) - .store_dict(complaints); -} - -;; complaint_status#2d complaint:^ValidatorComplaint voters:(HashmapE 16 True) -;; vset_id:uint256 weight_remaining:int64 = ValidatorComplaintStatus; -_ unpack_complaint_status(slice cs) inline_ref { - throw_unless(9, cs~load_uint(8) == 0x2d); - var res = (cs~load_ref(), cs~load_dict(), cs~load_uint(256), cs~load_int(64)); - cs.end_parse(); - return res; -} - -builder pack_complaint_status(cell complaint, cell voters, int vset_id, int weight_remaining) inline_ref { - return begin_cell() - .store_uint(0x2d, 8) - .store_ref(complaint) - .store_dict(voters) - .store_uint(vset_id, 256) - .store_int(weight_remaining, 64); -} - -;; validator_complaint#bc validator_pubkey:uint256 description:^ComplaintDescr -;; created_at:uint32 severity:uint8 reward_addr:uint256 paid:Grams suggested_fine:Grams -;; suggested_fine_part:uint32 = ValidatorComplaint; -_ unpack_complaint(slice cs) inline_ref { - throw_unless(9, cs~load_int(8) == 0xbc - 0x100); - var res = (cs~load_uint(256), cs~load_ref(), cs~load_uint(32), cs~load_uint(8), cs~load_uint(256), cs~load_grams(), cs~load_grams(), cs~load_uint(32)); - cs.end_parse(); - return res; -} - -builder pack_complaint(int validator_pubkey, cell description, int created_at, int severity, int reward_addr, int paid, int suggested_fine, int suggested_fine_part) inline_ref { - return begin_cell() - .store_int(0xbc - 0x100, 8) - .store_uint(validator_pubkey, 256) - .store_ref(description) - .store_uint(created_at, 32) - .store_uint(severity, 8) - .store_uint(reward_addr, 256) - .store_grams(paid) - .store_grams(suggested_fine) - .store_uint(suggested_fine_part, 32); -} - -;; complaint_prices#1a deposit:Grams bit_price:Grams cell_price:Grams = ComplaintPricing; -(int, int, int) parse_complaint_prices(cell info) inline { - var cs = info.begin_parse(); - throw_unless(9, cs~load_uint(8) == 0x1a); - var res = (cs~load_grams(), cs~load_grams(), cs~load_grams()); - cs.end_parse(); - return res; -} - -;; deposit bit_price cell_price -(int, int, int) get_complaint_prices() inline_ref { - var info = config_param(13); - return info.null?() ? (1 << 36, 1, 512) : info.parse_complaint_prices(); -} - -;; elected_for elections_begin_before elections_end_before stake_held_for -(int, int, int, int) get_validator_conf() { - var cs = config_param(15).begin_parse(); - return (cs~load_int(32), cs~load_int(32), cs~load_int(32), cs.preload_int(32)); -} - -;; next three functions return information about current validator set (config param #34) -;; they are borrowed from config-code.fc -(cell, int, cell) get_current_vset() inline_ref { - var vset = config_param(34); - var cs = begin_parse(vset); - ;; validators_ext#12 utime_since:uint32 utime_until:uint32 - ;; total:(## 16) main:(## 16) { main <= total } { main >= 1 } - ;; total_weight:uint64 - throw_unless(40, cs~load_uint(8) == 0x12); - cs~skip_bits(32 + 32 + 16 + 16); - var (total_weight, dict) = (cs~load_uint(64), cs~load_dict()); - cs.end_parse(); - return (vset, total_weight, dict); -} - -(slice, int) get_validator_descr(int idx) inline_ref { - var (vset, total_weight, dict) = get_current_vset(); - var (value, _) = dict.udict_get?(16, idx); - return (value, total_weight); -} - -(int, int) unpack_validator_descr(slice cs) inline { - ;; ed25519_pubkey#8e81278a pubkey:bits256 = SigPubKey; - ;; validator#53 public_key:SigPubKey weight:uint64 = ValidatorDescr; - ;; validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr; - throw_unless(41, (cs~load_uint(8) & ~ 0x20) == 0x53); - throw_unless(41, cs~load_uint(32) == 0x8e81278a); - return (cs~load_uint(256), cs~load_uint(64)); -} - -() send_message_back(addr, ans_tag, query_id, body, grams, mode) impure inline_ref { - ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 011000 - var msg = begin_cell() - .store_uint(0x18, 6) - .store_slice(addr) - .store_grams(grams) - .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(ans_tag, 32) - .store_uint(query_id, 64); - if (body >= 0) { - msg~store_uint(body, 32); - } - send_raw_message(msg.end_cell(), mode); -} - -() return_stake(addr, query_id, reason) impure inline_ref { - return send_message_back(addr, 0xee6f454c, query_id, reason, 0, 64); -} - -() send_confirmation(addr, query_id, comment) impure inline_ref { - return send_message_back(addr, 0xf374484c, query_id, comment, 1000000000, 2); -} - -() send_validator_set_to_config(config_addr, vset, query_id) impure inline_ref { - var msg = begin_cell() - .store_uint(0xc4ff, 17) ;; 0 11000100 0xff - .store_uint(config_addr, 256) - .store_grams(1 << 30) ;; ~1 gram of value to process and obtain answer - .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(0x4e565354, 32) - .store_uint(query_id, 64) - .store_ref(vset); - send_raw_message(msg.end_cell(), 1); -} - -;; credits 'amount' to 'addr' inside credit dictionary 'credits' -_ ~credit_to(credits, addr, amount) inline_ref { - var (val, f) = credits.udict_get?(256, addr); - if (f) { - amount += val~load_grams(); - } - credits~udict_set_builder(256, addr, begin_cell().store_grams(amount)); - return (credits, ()); -} - -() process_new_stake(s_addr, msg_value, cs, query_id) impure inline_ref { - var (src_wc, src_addr) = parse_std_addr(s_addr); - var ds = get_data().begin_parse(); - var elect = ds~load_dict(); - if (elect.null?() | (src_wc + 1)) { - ;; no elections active, or source is not in masterchain - ;; bounce message - return return_stake(s_addr, query_id, 0); - } - ;; parse the remainder of new stake message - var validator_pubkey = cs~load_uint(256); - var stake_at = cs~load_uint(32); - var max_factor = cs~load_uint(32); - var adnl_addr = cs~load_uint(256); - var signature = cs~load_ref().begin_parse().preload_bits(512); - cs.end_parse(); - ifnot (check_data_signature(begin_cell() - .store_uint(0x654c5074, 32) - .store_uint(stake_at, 32) - .store_uint(max_factor, 32) - .store_uint(src_addr, 256) - .store_uint(adnl_addr, 256) - .end_cell().begin_parse(), signature, validator_pubkey)) { - ;; incorrect signature, return stake - return return_stake(s_addr, query_id, 1); - } - if (max_factor < 0x10000) { - ;; factor must be >= 1. = 65536/65536 - return return_stake(s_addr, query_id, 6); - } - ;; parse current election data - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - ;; elect_at~dump(); - msg_value -= 1000000000; ;; deduct GR$1 for sending confirmation - if ((msg_value << 12) < total_stake) { - ;; stake smaller than 1/4096 of the total accumulated stakes, return - return return_stake(s_addr, query_id, 2); - } - total_stake += msg_value; ;; (provisionally) increase total stake - if (stake_at != elect_at) { - ;; stake for some other elections, return - return return_stake(s_addr, query_id, 3); - } - if (finished) { - ;; elections already finished, return stake - return return_stake(s_addr, query_id, 0); - } - var (mem, found) = members.udict_get?(256, validator_pubkey); - if (found) { - ;; entry found, merge stakes - msg_value += mem~load_grams(); - mem~load_uint(64); ;; skip timestamp and max_factor - found = (src_addr != mem~load_uint(256)); - } - if (found) { - ;; can make stakes for a public key from one address only - return return_stake(s_addr, query_id, 4); - } - if (msg_value < min_stake) { - ;; stake too small, return it - return return_stake(s_addr, query_id, 5); - } - throw_unless(44, msg_value); - accept_message(); - ;; store stake in the dictionary - members~udict_set_builder(256, validator_pubkey, begin_cell() - .store_grams(msg_value) - .store_uint(now(), 32) - .store_uint(max_factor, 32) - .store_uint(src_addr, 256) - .store_uint(adnl_addr, 256)); - ;; gather and save election data - elect = pack_elect(elect_at, elect_close, min_stake, total_stake, members, false, false); - set_data(begin_cell().store_dict(elect).store_slice(ds).end_cell()); - ;; return confirmation message - if (query_id) { - return send_confirmation(s_addr, query_id, 0); - } - return (); -} - -(cell, int) unfreeze_without_bonuses(credits, freeze_dict, tot_stakes) inline_ref { - var total = var recovered = 0; - var pubkey = -1; - do { - (pubkey, var cs, var f) = freeze_dict.udict_get_next?(256, pubkey); - if (f) { - var (addr, weight, stake, banned) = (cs~load_uint(256), cs~load_uint(64), cs~load_grams(), cs~load_int(1)); - cs.end_parse(); - if (banned) { - recovered += stake; - } else { - credits~credit_to(addr, stake); - } - total += stake; - } - } until (~ f); - throw_unless(59, total == tot_stakes); - return (credits, recovered); -} - -(cell, int) unfreeze_with_bonuses(credits, freeze_dict, tot_stakes, tot_bonuses) inline_ref { - var total = var recovered = var returned_bonuses = 0; - var pubkey = -1; - do { - (pubkey, var cs, var f) = freeze_dict.udict_get_next?(256, pubkey); - if (f) { - var (addr, weight, stake, banned) = (cs~load_uint(256), cs~load_uint(64), cs~load_grams(), cs~load_int(1)); - cs.end_parse(); - if (banned) { - recovered += stake; - } else { - var bonus = muldiv(tot_bonuses, stake, tot_stakes); - returned_bonuses += bonus; - credits~credit_to(addr, stake + bonus); - } - total += stake; - } - } until (~ f); - throw_unless(59, (total == tot_stakes) & (returned_bonuses <= tot_bonuses)); - return (credits, recovered + tot_bonuses - returned_bonuses); -} - -_ unfreeze_all(credits, past_elections, elect_id) inline_ref { - var (fs, f) = past_elections~udict_delete_get?(32, elect_id); - ifnot (f) { - ;; no elections with this id - return (credits, past_elections, 0); - } - var (unfreeze_at, stake_held, vset_hash, fdict, tot_stakes, bonuses, complaints) = fs.unpack_past_election(); - var unused_prizes = (bonuses > 0) ? - credits~unfreeze_with_bonuses(fdict, tot_stakes, bonuses) : - credits~unfreeze_without_bonuses(fdict, tot_stakes); - return (credits, past_elections, unused_prizes); -} - -() config_set_confirmed(s_addr, cs, query_id, ok) impure inline_ref { - var (src_wc, src_addr) = parse_std_addr(s_addr); - var config_addr = config_param(0).begin_parse().preload_uint(256); - var ds = get_data().begin_parse(); - var elect = ds~load_dict(); - if ((src_wc + 1) | (src_addr != config_addr) | elect.null?()) { - ;; not from config smc, somebody's joke? - ;; or no elections active (or just completed) - return (); - } - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - if ((elect_at != query_id) | ~ finished) { - ;; not these elections, or elections not finished yet - return (); - } - accept_message(); - ifnot (ok) { - ;; cancel elections, return stakes - var (credits, past_elections, grams) = (ds~load_dict(), ds~load_dict(), ds~load_grams()); - (credits, past_elections, var unused_prizes) = unfreeze_all(credits, past_elections, elect_at); - set_data(begin_cell() - .store_int(false, 1) - .store_dict(credits) - .store_dict(past_elections) - .store_grams(grams + unused_prizes) - .store_slice(ds) - .end_cell()); - } - ;; ... do not remove elect until we see this set as the next elected validator set -} - -() process_simple_transfer(s_addr, msg_value) impure inline_ref { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - (int src_wc, int src_addr) = parse_std_addr(s_addr); - if (src_addr | (src_wc + 1) | (active_id == 0)) { - ;; simple transfer to us (credit "nobody's" account) - ;; (or no known active validator set) - grams += msg_value; - return store_data(elect, credits, past_elections, grams, active_id, active_hash); - } - ;; zero source address -1:00..00 (collecting validator fees) - var (fs, f) = past_elections.udict_get?(32, active_id); - ifnot (f) { - ;; active validator set not found (?) - grams += msg_value; - } else { - ;; credit active validator set bonuses - var (unfreeze_at, stake_held, hash, dict, total_stake, bonuses, complaints) = fs.unpack_past_election(); - bonuses += msg_value; - past_elections~udict_set_builder(32, active_id, - pack_past_election(unfreeze_at, stake_held, hash, dict, total_stake, bonuses, complaints)); - } - return store_data(elect, credits, past_elections, grams, active_id, active_hash); -} - -() recover_stake(op, s_addr, cs, query_id) impure inline_ref { - (int src_wc, int src_addr) = parse_std_addr(s_addr); - if (src_wc + 1) { - ;; not from masterchain, return error - return send_message_back(s_addr, 0xfffffffe, query_id, op, 0, 64); - } - var ds = get_data().begin_parse(); - var (elect, credits) = (ds~load_dict(), ds~load_dict()); - var (cs, f) = credits~udict_delete_get?(256, src_addr); - ifnot (f) { - ;; no credit for sender, return error - return send_message_back(s_addr, 0xfffffffe, query_id, op, 0, 64); - } - var amount = cs~load_grams(); - cs.end_parse(); - ;; save data - set_data(begin_cell().store_dict(elect).store_dict(credits).store_slice(ds).end_cell()); - ;; send amount to sender in a new message - send_raw_message(begin_cell() - .store_uint(0x18, 6) - .store_slice(s_addr) - .store_grams(amount) - .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(0xf96f7324, 32) - .store_uint(query_id, 64) - .end_cell(), 64); -} - -() after_code_upgrade(slice s_addr, slice cs, int query_id) impure method_id(1666) { - var op = 0x4e436f64; - return send_message_back(s_addr, 0xce436f64, query_id, op, 0, 64); -} - -int upgrade_code(s_addr, cs, query_id) inline_ref { - var c_addr = config_param(0); - if (c_addr.null?()) { - ;; no configuration smart contract known - return false; - } - var config_addr = c_addr.begin_parse().preload_uint(256); - var (src_wc, src_addr) = parse_std_addr(s_addr); - if ((src_wc + 1) | (src_addr != config_addr)) { - ;; not from configuration smart contract, return error - return false; - } - accept_message(); - var code = cs~load_ref(); - set_code(code); - ifnot(cs.slice_empty?()) { - set_c3(code.begin_parse().bless()); - after_code_upgrade(s_addr, cs, query_id); - throw(0); - } - return true; -} - -int register_complaint(s_addr, complaint, msg_value) { - var (src_wc, src_addr) = parse_std_addr(s_addr); - if (src_wc + 1) { ;; not from masterchain, return error - return -1; - } - if (complaint.slice_depth() >= 128) { - return -3; ;; invalid complaint - } - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var election_id = complaint~load_uint(32); - var (fs, f) = past_elections.udict_get?(32, election_id); - ifnot (f) { ;; election not found - return -2; - } - var expire_in = fs.preload_uint(32) - now(); - if (expire_in <= 0) { ;; already expired - return -4; - } - var (validator_pubkey, description, created_at, severity, reward_addr, paid, suggested_fine, suggested_fine_part) = unpack_complaint(complaint); - reward_addr = src_addr; - created_at = now(); - ;; compute complaint storage/creation price - var (deposit, bit_price, cell_price) = get_complaint_prices(); - var (_, bits, refs) = slice_compute_data_size(complaint, 4096); - var pps = (bits + 1024) * bit_price + (refs + 2) * cell_price; - paid = pps * expire_in + deposit; - if (paid + (1 << 30) < msg_value) { ;; not enough money - return -5; - } - ;; re-pack modified complaint - cell complaint = pack_complaint(validator_pubkey, description, created_at, severity, reward_addr, paid, suggested_fine, suggested_fine_part).end_cell(); - var (unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints) = unpack_past_election(fs); - var (fs, f) = frozen_dict.udict_get?(256, validator_pubkey); - ifnot (f) { ;; no such validator, cannot complain - return -6; - } - fs~skip_bits(256 + 64); ;; addr weight - var validator_stake = fs~load_grams(); - int fine = suggested_fine + muldiv(validator_stake, suggested_fine_part, 1 << 32); - if (fine > validator_stake) { ;; validator's stake is less than suggested fine - return -7; - } - if (fine <= paid) { ;; fine is less than the money paid for creating complaint - return -8; - } - ;; create complaint status - var cstatus = pack_complaint_status(complaint, null(), 0, 0); - ;; save complaint status into complaints - var cpl_id = complaint.cell_hash(); - ifnot (complaints~udict_add_builder?(256, cpl_id, cstatus)) { - return -9; ;; complaint already exists - } - ;; pack past election info - past_elections~udict_set_builder(32, election_id, pack_past_election(unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints)); - ;; pack persistent data - ;; next line can be commented, but it saves a lot of stack manipulations - var (elect, credits, _, grams, active_id, active_hash) = load_data(); - store_data(elect, credits, past_elections, grams, active_id, active_hash); - return paid; -} - -(cell, cell, int) punish(credits, frozen, complaint) inline_ref { - var (validator_pubkey, description, created_at, severity, reward_addr, paid, suggested_fine, suggested_fine_part) = complaint.begin_parse().unpack_complaint(); - var (cs, f) = frozen.udict_get?(256, validator_pubkey); - ifnot (f) { - ;; no validator to punish - return (credits, frozen, 0); - } - var (addr, weight, stake, banned) = (cs~load_uint(256), cs~load_uint(64), cs~load_grams(), cs~load_int(1)); - cs.end_parse(); - int fine = min(stake, suggested_fine + muldiv(stake, suggested_fine_part, 1 << 32)); - stake -= fine; - frozen~udict_set_builder(256, validator_pubkey, begin_cell() - .store_uint(addr, 256) - .store_uint(weight, 64) - .store_grams(stake) - .store_int(banned, 1)); - int reward = min(fine >> 3, paid * 8); - fine -= reward; - credits~credit_to(reward_addr, reward); - return (credits, frozen, fine); -} - -(cell, cell, int) register_vote(complaints, chash, idx, weight) inline_ref { - var (cstatus, found?) = complaints.udict_get?(256, chash); - ifnot (found?) { - ;; complaint not found - return (complaints, null(), -1); - } - var (cur_vset, total_weight, _) = get_current_vset(); - int cur_vset_id = cur_vset.cell_hash(); - var (complaint, voters, vset_id, weight_remaining) = unpack_complaint_status(cstatus); - if (vset_id != cur_vset_id) { - ;; complaint votes belong to a previous validator set, reset voting - vset_id = cur_vset_id; - voters = null(); - weight_remaining = muldiv(total_weight, 2, 3); - } - var (_, found?) = voters.udict_get?(16, idx); - if (found?) { - ;; already voted for this proposal, ignore vote - return (complaints, null(), 0); - } - ;; register vote - voters~udict_set_builder(16, idx, begin_cell().store_uint(now(), 32)); - int old_wr = weight_remaining; - weight_remaining -= weight; - old_wr ^= weight_remaining; - ;; save voters and weight_remaining - complaints~udict_set_builder(256, chash, pack_complaint_status(complaint, voters, vset_id, weight_remaining)); - if (old_wr >= 0) { - ;; not enough votes or already accepted - return (complaints, null(), 1); - } - ;; complaint wins, prepare punishment - return (complaints, complaint, 2); -} - -int proceed_register_vote(election_id, chash, idx, weight) impure inline_ref { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var (fs, f) = past_elections.udict_get?(32, election_id); - ifnot (f) { ;; election not found - return -2; - } - var (unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints) = unpack_past_election(fs); - (complaints, var accepted_complaint, var status) = register_vote(complaints, chash, idx, weight); - if (status <= 0) { - return status; - } - ifnot (accepted_complaint.null?()) { - (credits, frozen_dict, int fine) = punish(credits, frozen_dict, accepted_complaint); - grams += fine; - } - past_elections.udict_set_builder(32, election_id, pack_past_election(unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints)); - store_data(elect, credits, past_elections, grams, active_id, active_hash); - return status; -} - -() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { - ;; do nothing for internal messages - var cs = in_msg_cell.begin_parse(); - var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - if (flags & 1) { - ;; ignore all bounced messages - return (); - } - var s_addr = cs~load_msg_addr(); - if (in_msg.slice_empty?()) { - ;; inbound message has empty body - return process_simple_transfer(s_addr, msg_value); - } - int op = in_msg~load_uint(32); - if (op == 0) { - ;; simple transfer with comment, return - return process_simple_transfer(s_addr, msg_value); - } - int query_id = in_msg~load_uint(64); - if (op == 0x4e73744b) { - ;; new stake message - return process_new_stake(s_addr, msg_value, in_msg, query_id); - } - if (op == 0x47657424) { - ;; recover stake request - return recover_stake(op, s_addr, in_msg, query_id); - } - if (op == 0x4e436f64) { - ;; upgrade code (accepted only from configuration smart contract) - var ok = upgrade_code(s_addr, in_msg, query_id); - return send_message_back(s_addr, ok ? 0xce436f64 : 0xffffffff, query_id, op, 0, 64); - } - var cfg_ok = (op == 0xee764f4b); - if (cfg_ok | (op == 0xee764f6f)) { - ;; confirmation from configuration smart contract - return config_set_confirmed(s_addr, in_msg, query_id, cfg_ok); - } - if (op == 0x52674370) { - ;; new complaint - var price = register_complaint(s_addr, in_msg, msg_value); - int mode = 64; - int ans_tag = - price; - if (price >= 0) { - ;; ok, debit price - raw_reserve(price, 4); - ans_tag = 0; - mode = 128; - } - return send_message_back(s_addr, ans_tag + 0xf2676350, query_id, op, 0, mode); - } - if (op == 0x56744370) { - ;; vote for a complaint - var signature = in_msg~load_bits(512); - var msg_body = in_msg; - var (sign_tag, idx, elect_id, chash) = (in_msg~load_uint(32), in_msg~load_uint(16), in_msg~load_uint(32), in_msg~load_uint(256)); - in_msg.end_parse(); - throw_unless(37, sign_tag == 0x56744350); - var (vdescr, total_weight) = get_validator_descr(idx); - var (val_pubkey, weight) = unpack_validator_descr(vdescr); - throw_unless(34, check_data_signature(msg_body, signature, val_pubkey)); - int res = proceed_register_vote(elect_id, chash, idx, weight); - return send_message_back(s_addr, res + 0xd6745240, query_id, op, 0, 64); - } - - ifnot (op & (1 << 31)) { - ;; unknown query, return error - return send_message_back(s_addr, 0xffffffff, query_id, op, 0, 64); - } - ;; unknown answer, ignore - return (); -} - -int postpone_elections() impure { - return false; -} - -;; computes the total stake out of the first n entries of list l -_ compute_total_stake(l, n, m_stake) inline_ref { - int tot_stake = 0; - repeat (n) { - (var h, l) = uncons(l); - var stake = h.at(0); - var max_f = h.at(1); - stake = min(stake, (max_f * m_stake) >> 16); - tot_stake += stake; - } - return tot_stake; -} - -(cell, cell, int, cell, int, int) try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor) { - var cs = 16.config_param().begin_parse(); - var (max_validators, _, min_validators) = (cs~load_uint(16), cs~load_uint(16), cs~load_uint(16)); - cs.end_parse(); - min_validators = max(min_validators, 1); - int n = 0; - var sdict = new_dict(); - var pubkey = -1; - do { - (pubkey, var cs, var f) = members.udict_get_next?(256, pubkey); - if (f) { - var (stake, time, max_factor, addr, adnl_addr) = (cs~load_grams(), cs~load_uint(32), cs~load_uint(32), cs~load_uint(256), cs~load_uint(256)); - cs.end_parse(); - var key = begin_cell() - .store_uint(stake, 128) - .store_int(- time, 32) - .store_uint(pubkey, 256) - .end_cell().begin_parse(); - sdict~dict_set_builder(128 + 32 + 256, key, begin_cell() - .store_uint(min(max_factor, max_stake_factor), 32) - .store_uint(addr, 256) - .store_uint(adnl_addr, 256)); - n += 1; - } - } until (~ f); - n = min(n, max_validators); - if (n < min_validators) { - return (credits, new_dict(), 0, new_dict(), 0, 0); - } - var l = nil; - do { - var (key, cs, f) = sdict~dict::delete_get_min(128 + 32 + 256); - if (f) { - var (stake, _, pubkey) = (min(key~load_uint(128), max_stake), key~load_uint(32), key.preload_uint(256)); - var (max_f, _, adnl_addr) = (cs~load_uint(32), cs~load_uint(256), cs.preload_uint(256)); - l = cons([stake, max_f, pubkey, adnl_addr], l); - } - } until (~ f); - ;; l is the list of all stakes in decreasing order - int i = min_validators - 1; - var l1 = l; - repeat (i) { - l1 = cdr(l1); - } - var (best_stake, m) = (0, 0); - do { - var stake = l1~list_next().at(0); - i += 1; - if (stake >= min_stake) { - var tot_stake = compute_total_stake(l, i, stake); - if (tot_stake > best_stake) { - (best_stake, m) = (tot_stake, i); - } - } - } until (i >= n); - if ((m == 0) | (best_stake < min_total_stake)) { - return (credits, new_dict(), 0, new_dict(), 0, 0); - } - ;; we have to select first m validators from list l - l1 = touch(l); - ;; l1~dump(); ;; DEBUG - repeat (m - 1) { - l1 = cdr(l1); - } - var m_stake = car(l1).at(0); ;; minimal stake - ;; create both the new validator set and the refund set - int i = 0; - var tot_stake = 0; - var tot_weight = 0; - var vset = new_dict(); - var frozen = new_dict(); - do { - var [stake, max_f, pubkey, adnl_addr] = l~list_next(); - ;; lookup source address first - var (val, f) = members.udict_get?(256, pubkey); - throw_unless(61, f); - (_, _, var src_addr) = (val~load_grams(), val~load_uint(64), val.preload_uint(256)); - if (i < m) { - ;; one of the first m members, include into validator set - var true_stake = min(stake, (max_f * m_stake) >> 16); - stake -= true_stake; - ;; ed25519_pubkey#8e81278a pubkey:bits256 = SigPubKey; // 288 bits - ;; validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr; - var weight = (true_stake << 60) / best_stake; - tot_stake += true_stake; - tot_weight += weight; - var vinfo = begin_cell() - .store_uint(adnl_addr ? 0x73 : 0x53, 8) ;; validator_addr#73 or validator#53 - .store_uint(0x8e81278a, 32) ;; ed25519_pubkey#8e81278a - .store_uint(pubkey, 256) ;; pubkey:bits256 - .store_uint(weight, 64); ;; weight:uint64 - if (adnl_addr) { - vinfo~store_uint(adnl_addr, 256); ;; adnl_addr:bits256 - } - vset~udict_set_builder(16, i, vinfo); - frozen~udict_set_builder(256, pubkey, begin_cell() - .store_uint(src_addr, 256) - .store_uint(weight, 64) - .store_grams(true_stake) - .store_int(false, 1)); - } - if (stake) { - ;; non-zero unused part of the stake, credit to the source address - credits~credit_to(src_addr, stake); - } - i += 1; - } until (l.null?()); - throw_unless(49, tot_stake == best_stake); - return (credits, vset, tot_weight, frozen, tot_stake, m); -} - -int conduct_elections(ds, elect, credits) impure { - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - if (now() < elect_close) { - ;; elections not finished yet - return false; - } - if (config_param(0).null?()) { - ;; no configuration smart contract to send result to - return postpone_elections(); - } - var cs = config_param(17).begin_parse(); - min_stake = cs~load_grams(); - var max_stake = cs~load_grams(); - var min_total_stake = cs~load_grams(); - var max_stake_factor = cs~load_uint(32); - cs.end_parse(); - if (total_stake < min_total_stake) { - ;; insufficient total stake, postpone elections - return postpone_elections(); - } - if (failed) { - ;; do not retry failed elections until new stakes arrive - return postpone_elections(); - } - if (finished) { - ;; elections finished - return false; - } - (credits, var vdict, var total_weight, var frozen, var total_stakes, var cnt) = try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor); - ;; pack elections; if cnt==0, set failed=true, finished=false. - failed = (cnt == 0); - finished = ~ failed; - elect = pack_elect(elect_at, elect_close, min_stake, total_stake, members, failed, finished); - ifnot (cnt) { - ;; elections failed, set elect_failed to true - set_data(begin_cell().store_dict(elect).store_dict(credits).store_slice(ds).end_cell()); - return postpone_elections(); - } - ;; serialize a query to the configuration smart contract - ;; to install the computed validator set as the next validator set - var (elect_for, elect_begin_before, elect_end_before, stake_held) = get_validator_conf(); - var start = max(now() + elect_end_before - 60, elect_at); - var main_validators = config_param(16).begin_parse().skip_bits(16).preload_uint(16); - var vset = begin_cell() - .store_uint(0x12, 8) ;; validators_ext#12 - .store_uint(start, 32) ;; utime_since:uint32 - .store_uint(start + elect_for, 32) ;; utime_until:uint32 - .store_uint(cnt, 16) ;; total:(## 16) - .store_uint(min(cnt, main_validators), 16) ;; main:(## 16) - .store_uint(total_weight, 64) ;; total_weight:uint64 - .store_dict(vdict) ;; list:(HashmapE 16 ValidatorDescr) - .end_cell(); - var config_addr = config_param(0).begin_parse().preload_uint(256); - send_validator_set_to_config(config_addr, vset, elect_at); - ;; add frozen to the dictionary of past elections - var past_elections = ds~load_dict(); - past_elections~udict_set_builder(32, elect_at, pack_past_election( - start + elect_for + stake_held, stake_held, vset.cell_hash(), - frozen, total_stakes, 0, null())); - ;; store credits and frozen until end - set_data(begin_cell() - .store_dict(elect) - .store_dict(credits) - .store_dict(past_elections) - .store_slice(ds) - .end_cell()); - return true; -} - -int update_active_vset_id() impure { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var cur_hash = config_param(34).cell_hash(); - if (cur_hash == active_hash) { - ;; validator set unchanged - return false; - } - if (active_id) { - ;; active_id becomes inactive - var (fs, f) = past_elections.udict_get?(32, active_id); - if (f) { - ;; adjust unfreeze time of this validator set - var unfreeze_time = fs~load_uint(32); - var fs0 = fs; - var (stake_held, hash) = (fs~load_uint(32), fs~load_uint(256)); - throw_unless(57, hash == active_hash); - unfreeze_time = now() + stake_held; - past_elections~udict_set_builder(32, active_id, begin_cell() - .store_uint(unfreeze_time, 32) - .store_slice(fs0)); - } - } - ;; look up new active_id by hash - var id = -1; - do { - (id, var fs, var f) = past_elections.udict_get_next?(32, id); - if (f) { - var (tm, hash) = (fs~load_uint(64), fs~load_uint(256)); - if (hash == cur_hash) { - ;; parse more of this record - var (dict, total_stake, bonuses) = (fs~load_dict(), fs~load_grams(), fs~load_grams()); - ;; transfer 1/8 of accumulated everybody's grams to this validator set as bonuses - var amount = (grams >> 3); - grams -= amount; - bonuses += amount; - ;; serialize back - past_elections~udict_set_builder(32, id, begin_cell() - .store_uint(tm, 64) - .store_uint(hash, 256) - .store_dict(dict) - .store_grams(total_stake) - .store_grams(bonuses) - .store_slice(fs)); - ;; found - f = false; - } - } - } until (~ f); - active_id = (id.null?() ? 0 : id); - active_hash = cur_hash; - store_data(elect, credits, past_elections, grams, active_id, active_hash); - return true; -} - -int cell_hash_eq?(cell vset, int expected_vset_hash) inline_ref { - return vset.null?() ? false : cell_hash(vset) == expected_vset_hash; -} - -int validator_set_installed(ds, elect, credits) impure { - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - ifnot (finished) { - ;; elections not finished yet - return false; - } - var past_elections = ds~load_dict(); - var (fs, f) = past_elections.udict_get?(32, elect_at); - ifnot (f) { - ;; no election data in dictionary - return false; - } - ;; recover validator set hash - var vset_hash = fs.skip_bits(64).preload_uint(256); - if (config_param(34).cell_hash_eq?(vset_hash) | config_param(36).cell_hash_eq?(vset_hash)) { - ;; this validator set has been installed, forget elections - set_data(begin_cell() - .store_int(false, 1) ;; forget current elections - .store_dict(credits) - .store_dict(past_elections) - .store_slice(ds) - .end_cell()); - update_active_vset_id(); - return true; - } - return false; -} - -int check_unfreeze() impure { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - int id = -1; - do { - (id, var fs, var f) = past_elections.udict_get_next?(32, id); - if (f) { - var unfreeze_at = fs~load_uint(32); - if ((unfreeze_at <= now()) & (id != active_id)) { - ;; unfreeze! - (credits, past_elections, var unused_prizes) = unfreeze_all(credits, past_elections, id); - grams += unused_prizes; - ;; unfreeze only one at time, exit loop - store_data(elect, credits, past_elections, grams, active_id, active_hash); - ;; exit loop - f = false; - } - } - } until (~ f); - return ~ id.null?(); -} - -int announce_new_elections(ds, elect, credits) { - var next_vset = config_param(36); ;; next validator set - ifnot (next_vset.null?()) { - ;; next validator set exists, no elections needed - return false; - } - var elector_addr = config_param(1).begin_parse().preload_uint(256); - var (my_wc, my_addr) = my_address().parse_std_addr(); - if ((my_wc + 1) | (my_addr != elector_addr)) { - ;; this smart contract is not the elections smart contract anymore, no new elections - return false; - } - var cur_vset = config_param(34); ;; current validator set - if (cur_vset.null?()) { - return false; - } - var (elect_for, elect_begin_before, elect_end_before, stake_held) = get_validator_conf(); - var cur_valid_until = cur_vset.begin_parse().skip_bits(8 + 32).preload_uint(32); - var t = now(); - var t0 = cur_valid_until - elect_begin_before; - if (t < t0) { - ;; too early for the next elections - return false; - } - ;; less than elect_before_begin seconds left, create new elections - if (t - t0 < 60) { - ;; pretend that the elections started at t0 - t = t0; - } - ;; get stake parameters - (_, var min_stake) = config_param(17).begin_parse().load_grams(); - ;; announce new elections - var elect_at = t + elect_begin_before; - ;; elect_at~dump(); - var elect_close = elect_at - elect_end_before; - elect = pack_elect(elect_at, elect_close, min_stake, 0, new_dict(), false, false); - set_data(begin_cell().store_dict(elect).store_dict(credits).store_slice(ds).end_cell()); - return true; -} - -() run_ticktock(int is_tock) impure { - ;; check whether an election is being conducted - var ds = get_data().begin_parse(); - var (elect, credits) = (ds~load_dict(), ds~load_dict()); - ifnot (elect.null?()) { - ;; have an active election - throw_if(0, conduct_elections(ds, elect, credits)); ;; elections conducted, exit - throw_if(0, validator_set_installed(ds, elect, credits)); ;; validator set installed, current elections removed - } else { - throw_if(0, announce_new_elections(ds, elect, credits)); ;; new elections announced, exit - } - throw_if(0, update_active_vset_id()); ;; active validator set id updated, exit - check_unfreeze(); -} - -;; Get methods - -;; returns active election id or 0 -int active_election_id() method_id { - var elect = get_data().begin_parse().preload_dict(); - return elect.null?() ? 0 : elect.begin_parse().preload_uint(32); -} - -;; checks whether a public key participates in current elections -int participates_in(int validator_pubkey) method_id { - var elect = get_data().begin_parse().preload_dict(); - if (elect.null?()) { - return 0; - } - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - var (mem, found) = members.udict_get?(256, validator_pubkey); - return found ? mem~load_grams() : 0; -} - -;; returns the list of all participants of current elections with their stakes -_ participant_list() method_id { - var elect = get_data().begin_parse().preload_dict(); - if (elect.null?()) { - return nil; - } - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - var l = nil; - var id = (1 << 255) + ((1 << 255) - 1); - do { - (id, var fs, var f) = members.udict_get_prev?(256, id); - if (f) { - l = cons([id, fs~load_grams()], l); - } - } until (~ f); - return l; -} - -;; returns the list of all participants of current elections with their data -_ participant_list_extended() method_id { - var elect = get_data().begin_parse().preload_dict(); - if (elect.null?()) { - return (0, 0, 0, 0, nil, 0, 0); - } - var (elect_at, elect_close, min_stake, total_stake, members, failed, finished) = elect.unpack_elect(); - var l = nil; - var id = (1 << 255) + ((1 << 255) - 1); - do { - (id, var cs, var f) = members.udict_get_prev?(256, id); - if (f) { - var (stake, time, max_factor, addr, adnl_addr) = (cs~load_grams(), cs~load_uint(32), cs~load_uint(32), cs~load_uint(256), cs~load_uint(256)); - cs.end_parse(); - l = cons([id, [stake, max_factor, addr, adnl_addr]], l); - } - } until (~ f); - return (elect_at, elect_close, min_stake, total_stake, l, failed, finished); -} - -;; computes the return stake -int compute_returned_stake(int wallet_addr) method_id { - var cs = get_data().begin_parse(); - (_, var credits) = (cs~load_dict(), cs~load_dict()); - var (val, f) = credits.udict_get?(256, wallet_addr); - return f ? val~load_grams() : 0; -} - -;; returns the list of past election ids -tuple past_election_ids() method_id { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var id = (1 << 32); - var list = null(); - do { - (id, var fs, var f) = past_elections.udict_get_prev?(32, id); - if (f) { - list = cons(id, list); - } - } until (~ f); - return list; -} - -tuple past_elections() method_id { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var id = (1 << 32); - var list = null(); - do { - (id, var fs, var found) = past_elections.udict_get_prev?(32, id); - if (found) { - list = cons([id, unpack_past_election(fs)], list); - } - } until (~ found); - return list; -} - -tuple past_elections_list() method_id { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var id = (1 << 32); - var list = null(); - do { - (id, var fs, var found) = past_elections.udict_get_prev?(32, id); - if (found) { - var (unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints) = unpack_past_election(fs); - list = cons([id, unfreeze_at, vset_hash, stake_held], list); - } - } until (~ found); - return list; -} - -_ complete_unpack_complaint(slice cs) inline_ref { - var (complaint, voters, vset_id, weight_remaining) = cs.unpack_complaint_status(); - var voters_list = null(); - var voter_id = (1 << 32); - do { - (voter_id, _, var f) = voters.udict_get_prev?(16, voter_id); - if (f) { - voters_list = cons(voter_id, voters_list); - } - } until (~ f); - return [[complaint.begin_parse().unpack_complaint()], voters_list, vset_id, weight_remaining]; -} - -cell get_past_complaints(int election_id) inline_ref method_id { - var (elect, credits, past_elections, grams, active_id, active_hash) = load_data(); - var (fs, found?) = past_elections.udict_get?(32, election_id); - ifnot (found?) { - return null(); - } - var (unfreeze_at, stake_held, vset_hash, frozen_dict, total_stake, bonuses, complaints) = unpack_past_election(fs); - return complaints; -} - -_ show_complaint(int election_id, int chash) method_id { - var complaints = get_past_complaints(election_id); - var (cs, found) = complaints.udict_get?(256, chash); - return found ? complete_unpack_complaint(cs) : null(); -} - -tuple list_complaints(int election_id) method_id { - var complaints = get_past_complaints(election_id); - int id = (1 << 255) + ((1 << 255) - 1); - var list = null(); - do { - (id, var cs, var found?) = complaints.udict_get_prev?(256, id); - if (found?) { - list = cons(pair(id, complete_unpack_complaint(cs)), list); - } - } until (~ found?); - return list; -} - -int complaint_storage_price(int bits, int refs, int expire_in) method_id { - ;; compute complaint storage/creation price - var (deposit, bit_price, cell_price) = get_complaint_prices(); - var pps = (bits + 1024) * bit_price + (refs + 2) * cell_price; - var paid = pps * expire_in + deposit; - return paid + (1 << 30); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/envelope-complaint.fif b/submodules/ton/tonlib-src/crypto/smartcont/envelope-complaint.fif deleted file mode 100644 index fa7b857e..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/envelope-complaint.fif +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage -86400 3 * =: expire-in -false =: critical --1 =: old-hash - -begin-options - " [-x ] []" +cr +tab - +"Embeds a validator complaint loaded from file into an internal message body to be sent to the elector smart contract " - +"and saves it as an internal message body into .boc ('complaint-msg-body.boc' by default)" - disable-digit-options generic-help-setopt - "x" "--expires-in" { parse-int =: expire-in } short-long-option-arg - "Sets complaint expiration time in seconds (default " expire-in (.) $+ +")" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 2 < swap 3 > or ' usage if -3 :$1..n - -$1 parse-int dup =: election-id - 32 ufits not abort"invalid election id" -$2 =: boc-filename -$3 "complaint-msg-body.boc" replace-if-null =: savefile -expire-in now + =: expire-at - -boc-filename dup ."Loading complaint from file `" type ."`" cr -file>B B>boc dup =: complaint hash =: c-hash -complaint abort"Not a valid ValidatorComplaint" -complaint - -dup ."resulting internal message body: " B dup Bx. cr - -complaint -totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> " -drop dup Blen . ."BoC data bytes)" cr - -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif deleted file mode 100644 index 6fe3fbed..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif +++ /dev/null @@ -1,238 +0,0 @@ -"TonUtil.fif" include -"Asm.fif" include - -def? $1 { @' $1 } { "" } cond constant suffix -{ suffix $+ } : +suffix - -wc_master setworkchain --17 setglobalid // negative value means a test instance of the blockchain - -// Initial state of Workchain 0 (Basic workchain) - -0 mkemptyShardState - -cr ."initial basechain state is:" cr dup B dup Bx. cr -dup "basestate0" +suffix +".boc" tuck B>file -."(Initial basechain state saved to file " type .")" cr -Bhashu dup =: basestate0_fhash -."file hash=" dup x. space 256 u>B dup B>base64url type cr -"basestate0" +suffix +".fhash" B>file -hashu dup =: basestate0_rhash -."root hash=" dup x. space 256 u>B dup B>base64url type cr -"basestate0" +suffix +".rhash" B>file - -basestate0_rhash basestate0_fhash now 0 2 32 0 add-std-workchain -config.workchains! - -// SmartContract #1 (Simple wallet) - -<{ SETCP0 DUP IFNOTRET INC 32 THROWIF // return if recv_internal, fail unless recv_external - 512 INT LDSLICEX DUP 32 PLDU // sign cs cnt - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk - s1 s2 XCPU // sign cs cnt pubk cnt' cnt - EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - s2 PUSH HASHSU // sign cs cnt pubk hash - s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk - CHKSIGNU // pubk cs cnt ? - 34 THROWIFNOT // signature mismatch - ACCEPT - SWAP 32 LDU NIP 8 LDU LDREF ENDS // pubk cnt mode msg - SWAP SENDRAWMSG // pubk cnt ; ( message sent ) - INC NEWC 32 STU 256 STU ENDC c4 POPCTR -}>c -// code - // data -Libs{ - x{ABACABADABACABA} s>c public_lib - x{1234} x{5678} |_ s>c private_lib -}Libs // libraries -GR$1700000000 // balance -0 // split_depth -0 // ticktock -2 // mode: create -register_smc -dup make_special dup constant smc1_addr -Masterchain over -2dup ."wallet address = " .addr cr 2dup 6 .Addr cr -"main-wallet" +suffix +".addr" save-address-verbose - -// SmartContract #2 (Simple money giver for test network) -<{ SETCP0 DUP IFNOTRET INC 32 THROWIF // return if recv_internal, fail unless recv_external - 32 LDU SWAP // cs cnt - c4 PUSHCTR CTOS 32 LDU ENDS // cs cnt cnt' - TUCK EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - ACCEPT // cs cnt' - SWAP 8 LDU LDREF ENDS // cnt'' mode msg - GR$20 INT 3 INT RAWRESERVE // reserve all but 20 Grams from the balance - SWAP SENDRAWMSG - INC NEWC 32 STU ENDC c4 POPCTR // store cnt'' -}>c -// code - // data -empty_cell // libraries -GR$1000000 // initial balance (1m test Grams) -0 0 2 register_smc -dup make_special dup constant smc2_addr -Masterchain over -2dup ."free test gram giver address = " .addr cr 2dup 6 .Addr cr -"testgiver" +suffix +".addr" save-address-verbose - -// SmartContract #3 -PROGRAM{ - recv_internal x{} PROC - run_ticktock PROC:<{ - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS - NEWC ROT INC 32 STUR OVER 256 STUR ENDC - c4 POPCTR - // first 32 bits of persistent data have been increased - // remaining 256 bits with an address have been fetched - // create new empty message with 0.1 Grams to that address - NEWC b{00100010011111111} STSLICECONST TUCK 256 STU - 100000000 INT STGRAMS // store 0.1 Grams - 1 4 + 4 + 64 + 32 + 1+ 1+ INT STZEROES ENDC - // send raw message from Cell - ZERO SENDRAWMSG - -17 INT 256 STIR 130000000 INT STGRAMS - 107 INT STZEROES ENDC - ZERO // another message with 0.13 Grams to account -17 - NEWC b{11000100100000} "test" $>s |+ STSLICECONST - 123456789 INT STGRAMS - 107 INT STZEROES "Hello, world!" $>s STSLICECONST ENDC - ZERO SENDRAWMSG SENDRAWMSG // external message to address "test" - }> -}END>c -// code - // data -// empty_cell // libraries -Libs{ - x{ABACABADABACABA} s>c public_lib - x{1234} x{5678} |_ s>c public_lib -}Libs // libraries -0x333333333 // balance -0 // split_depth -3 // ticktock: tick -2 // mode: create -register_smc -dup make_special dup constant smc3_addr -."address = " x. cr - -// SmartContract #4 (elector) -"auto/elector-code.fif" include // code in separate source file - // data -GR$10 // balance: 10 grams -0 // split_depth -1 // ticktock: tick -2 // mode: create -register_smc -dup make_special dup constant smc4_addr dup constant elector_addr - -// Configuration Parameters - -// max-validators max-main-validators min-validators -// 9 3 2 config.validator_num! -1000 100 5 config.validator_num! -// min-stake max-stake min-total-stake max-factor -GR$10000 GR$10000000 GR$1000000 sg~10 config.validator_stake_limits! -// elected-for elect-start-before elect-end-before stakes-frozen-for -400000 200000 4000 400000 config.election_params! -// elector-addr -elector_addr config.elector_smc! - -1 sg* 100 sg* 1000 sg* 1000000 sg* config.storage_prices! -config.special! - -// gas_price gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit -- -1000 sg* 1000000 10000 10000000 GR$0.1 GR$1.0 config.gas_prices! -10000 sg* 1000000 10000 10000000 GR$0.1 GR$1.0 config.mc_gas_prices! -// lump_price bit_price cell_price ihr_factor first_frac next_frac -1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices! -10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices! -// mc-cc-lifetime sh-cc-lifetime sh-val-lifetime sh-val-num -250 250 1000 7 config.catchain_params! - -128 *Ki 512 *Ki 1 *Mi triple // [ underload soft hard ] : block bytes limit -100000 500000 1000000 triple // gas limits -1000 5000 10000 triple // lt limits -triple dup untriple config.mc_block_limits! -untriple config.block_limits! - -GR$1.7 GR$1 config.block_create_fees! -smc1_addr config.collector_smc! -smc1_addr config.minter_smc! - -1000000000000 -17 of-cc 666666666666 239 of-cc cc+ config.to_mint! - -"validator-keys" +suffix +".pub" file>B -{ dup Blen } { 32 B| swap dup ."Validator public key = " Bx. cr - 17 add-validator } while drop -// newkeypair nip dup ."Validator #1 public key = " Bx. cr -// 17 add-validator -// newkeypair nip dup ."Validator #2 public key = " Bx. cr -// 239 add-validator -now dup 1000000 + 0 config.validators! - -// SmartContract #5 (Config) -PROGRAM{ - recv_internal x{} PROC - recv_external PROC:<{ - 512 INT LDSLICEX DUP 32 LDU 32 PLDU // sign cs cnt valid-until - NOW LEQ 35 THROWIF // ( fail if now >= valid-until ) - c4 PUSH CTOS LDREF 32 LDU 256 LDU ENDS // sign cs cnt dict cnt' pubk - s1 s3 XCPU // sign cs cnt dict pubk cnt' cnt - EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - s3 PUSH HASHSU // sign cs cnt dict pubk hash - s0 s5 s5 XC2PU // pubk cs cnt dict hash sign pubk - CHKSIGNU // pubk cs cnt dict ? - 34 THROWIFNOT // signature mismatch - ACCEPT - ROT 64 LDU NIP 32 LDI LDREF ENDS // pubk cnt dict index value - s0 s2 XCHG 32 INT // pubk cnt value index dict 32 - DICTISETREF ROTREV // dict' pubk cnt - INC NEWC 32 STU 256 STU STREF ENDC c4 POP - }> - run_ticktock PROC:<{ - // store (now >> 8) into config param #-17, if the new value is different - c4 PUSH CTOS LDREF SWAP // s' D - NOW 8 RSHIFT# TUCK // s' t D t - NEWC 32 STU ENDC // s' t D c - -17 INT ROT 32 INT // s' t c -17 D 32 - DICTISETGETREF // s' t D' c' -1 or s' t D' 0 - IF:<{ CTOS 32 LDU ENDS }>ELSE<{ ZERO }> // s' t D' y' - ROT EQUAL IFNOT: // s' D' - NEWC STREF STSLICE ENDC // c - c4 POP - }> -}END>c -// code - // data -empty_cell // libraries -1 // balance -0 1 2 register_smc // tock -dup set_config_smc -Masterchain swap -."config smart contract address = " 2dup .addr cr 2dup 7 .Addr cr -"config-master" +suffix +".addr" save-address-verbose -// Other data - -create_state -cr cr ."new state is:" cr dup B dup Bx. cr -dup "zerostate" +suffix +".boc" tuck B>file -."(Initial masterchain state saved to file " type .")" cr -Bhashu dup =: zerostate_fhash -."file hash=" dup x. space 256 u>B dup B>base64url type cr -"zerostate" +suffix +".fhash" B>file -hashu dup =: zerostate_rhash ."root hash=" dup x. space 256 u>B dup B>base64url type cr -"zerostate" +suffix +".rhash" B>file -basestate0_rhash ."Basestate0 root hash=" dup x. space 256 u>B B>base64url type cr -basestate0_fhash ."Basestate0 file hash=" dup x. space 256 u>B B>base64url type cr -zerostate_rhash ."Zerostate root hash=" dup x. space 256 u>B B>base64url type cr -zerostate_fhash ."Zerostate file hash=" dup x. space 256 u>B B>base64url type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif deleted file mode 100644 index d98c7a26..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/create-state -s -"TonUtil.fif" include -"Asm.fif" include -"Lists.fif" include - -def? $1 { @' $1 } { "" } cond constant suffix -{ suffix $+ } : +suffix -256 1<<1- 15 / constant AllOnes - -wc_master setworkchain --239 setglobalid // negative value means a test instance of the blockchain - -// Initial state of Workchain 0 (Basic workchain) - -0 mkemptyShardState - -cr ."initial basechain state is:" cr dup B dup Bx. cr -dup "basestate0" +suffix +".boc" tuck B>file -."(Initial basechain state saved to file " type .")" cr -Bhashu dup =: basestate0_fhash -."file hash=" dup 64x. space 256 u>B dup B>base64url type cr -"basestate0" +suffix +".fhash" B>file -hashu dup =: basestate0_rhash -."root hash=" dup 64x. space 256 u>B dup B>base64url type cr -"basestate0" +suffix +".rhash" B>file - -// root-hash file-hash start-at actual-min-split min-split-depth max-split-depth wc-id -basestate0_rhash basestate0_fhash now 0 4 8 0 add-std-workchain -config.workchains! - -// SmartContract #1 (Simple wallet) - -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt - }> - INC 32 THROWIF // fail unless recv_external - 512 INT LDSLICEX DUP 32 PLDU // sign cs cnt - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk - s1 s2 XCPU // sign cs cnt pubk cnt' cnt - EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - s2 PUSH HASHSU // sign cs cnt pubk hash - s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk - CHKSIGNU // pubk cs cnt ? - 34 THROWIFNOT // signature mismatch - ACCEPT - SWAP 32 LDU NIP 8 LDU LDREF ENDS // pubk cnt mode msg - SWAP SENDRAWMSG // pubk cnt ; ( message sent ) - INC NEWC 32 STU 256 STU ENDC c4 POPCTR -}>c -// code - // data -Libs{ - x{ABACABADABACABA} s>c public_lib - x{1234} x{5678} |_ s>c private_lib -}Libs // libraries -GR$4999990000 // balance -0 // split_depth -0 // ticktock -AllOnes 0 * // address -6 // mode: create+setaddr -register_smc -dup make_special dup constant smc1_addr -Masterchain over -2dup ."wallet address = " .addr cr 2dup 6 .Addr cr -"main-wallet" +suffix +".addr" save-address-verbose - -// SmartContract #2 (Simple money giver for test network) -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt - }> - INC 32 THROWIF // fail unless recv_external - 32 LDU SWAP // cs cnt - c4 PUSHCTR CTOS 32 LDU ENDS // cs cnt cnt' - TUCK EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - ACCEPT // cs cnt' - SWAP 8 LDU LDREF ENDS // cnt'' mode msg - GR$20 INT 3 INT RAWRESERVE // reserve all but 20 Grams from the balance - SWAP SENDRAWMSG - INC NEWC 32 STU ENDC c4 POPCTR // store cnt'' -}>c -// code - // data -empty_cell // libraries -GR$1000 // initial balance (1k test Grams) -0 0 AllOnes 6 * 6 register_smc -dup make_special dup constant smc2_addr -Masterchain over -2dup ."free test gram giver address = " .addr cr 2dup 6 .Addr cr -"testgiver" +suffix +".addr" save-address-verbose - -// SmartContract #3 -PROGRAM{ - recv_internal x{} PROC - run_ticktock PROC:<{ - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS - NEWC ROT INC 32 STUR OVER 256 STUR ENDC - c4 POPCTR - // first 32 bits of persistent data have been increased - // remaining 256 bits with an address have been fetched - // create new empty message with 0.1 Grams to that address - NEWC b{00100010011111111} STSLICECONST TUCK 256 STU - 100000000 INT STGRAMS // store 0.1 Grams - 1 4 + 4 + 64 + 32 + 1+ 1+ INT STZEROES ENDC - // send raw message from Cell - ZERO SENDRAWMSG - -17 INT 256 STIR 130000000 INT STGRAMS - 107 INT STZEROES ENDC - ZERO // another message with 0.13 Grams to account -17 - NEWC b{11000100100000} "test" $>s |+ STSLICECONST - 123456789 INT STGRAMS - 107 INT STZEROES "Hello, world!" $>s STSLICECONST ENDC - ZERO SENDRAWMSG SENDRAWMSG // external message to address "test" - }> -}END>c -// code - // data -// empty_cell // libraries -Libs{ - x{ABACABADABACABA} s>c public_lib - x{1234} x{5678} |_ s>c public_lib -}Libs // libraries -GR$666 // balance -0 // split_depth -3 // ticktock: tick -2 // mode: create -register_smc -dup make_special dup constant smc3_addr -."address = " 64x. cr - -/* - * - * SmartContract #4 (elector) - * - */ -"auto/elector-code.fif" include // code in separate source file - // data: dict dict dict grams uint32 uint256 -empty_cell // libraries -GR$10 // balance: 10 grams -0 // split_depth -2 // ticktock: tick -AllOnes 3 * // address: -1:333...333 -6 // mode: create + setaddr -register_smc -dup make_special dup constant smc4_addr dup constant elector_addr -Masterchain swap -."elector smart contract address = " 2dup .addr cr 2dup 7 .Addr cr -"elector" +suffix +".addr" save-address-verbose - -/* - * - * Configuration Parameters - * - */ -// version capabilities -1 capCreateStats capBounceMsgBody or capReportVersion or capShortDequeue or config.version! -// max-validators max-main-validators min-validators -// 9 4 1 config.validator_num! -1000 100 13 config.validator_num! -// min-stake max-stake min-total-stake max-factor -GR$10000 GR$10000000 GR$500000 sg~3 config.validator_stake_limits! -// elected-for elect-start-before elect-end-before stakes-frozen-for -// 400000 200000 4000 400000 config.election_params! -// 4000 2000 500 1000 config.election_params! // DEBUG -65536 32768 8192 32768 config.election_params! // TestNet DEBUG -// config-addr = -1:5555...5555 -AllOnes 5 * constant config_addr -config_addr config.config_smc! -// elector-addr -elector_addr config.elector_smc! - -// 1 sg* 100 sg* 1000 sg* 1000000 sg* config.storage_prices! // old values (too high) -1 500 1000 500000 config.storage_prices! -config.special! - -// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit flat_gas_limit flat_gas_price -- -1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 1000 1000000 config.gas_prices! -10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 1000 10000000 config.mc_gas_prices! -// lump_price bit_price cell_price ihr_factor first_frac next_frac -1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices! -10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices! -// mc-cc-lifetime sh-cc-lifetime sh-val-lifetime sh-val-num mc-shuffle -250 250 1000 7 true config.catchain_params! -// round-candidates next-cand-delay-ms consensus-timeout-ms fast-attempts attempt-duration cc-max-deps max-block-size max-collated-size new-cc-ids -3 2000 16000 3 8 4 2 *Mi 2 *Mi true config.consensus_params! - - -128 *Ki 512 *Ki 1 *Mi triple // [ underload soft hard ] : block bytes limit -2000000 10000000 20000000 triple // gas limits -1000 5000 10000 triple // lt limits -triple dup untriple config.mc_block_limits! -untriple config.block_limits! - -GR$1.7 GR$1 config.block_create_fees! -// smc1_addr config.collector_smc! -smc1_addr config.minter_smc! - -1000000000000 -17 of-cc 666666666666 239 of-cc cc+ config.to_mint! - -( 0 1 9 10 12 14 15 16 17 18 20 21 22 23 24 25 28 34 ) config.mandatory_params! -( -999 -1000 -1001 0 1 9 10 12 14 15 16 17 32 34 36 ) config.critical_params! - -// [ min_tot_rounds max_tot_rounds min_wins max_losses min_store_sec max_store_sec bit_pps cell_pps ] -// first for ordinary proposals, then for critical proposals -_( 2 3 2 2 1000000 10000000 1 500 ) -_( 4 7 4 2 5000000 20000000 2 1000 ) -config.param_proposals_setup! - -// deposit bit_pps cell_pps -GR$100 1 500 config.complaint_prices! - -"validator-keys" +suffix +".pub" file>B -{ dup Blen } { 32 B| swap dup ."Validator public key = " Bx. cr - 17 add-validator } while drop -// newkeypair nip dup ."Validator #1 public key = " Bx. cr -// 17 add-validator -// newkeypair nip dup ."Validator #2 public key = " Bx. cr -// 239 add-validator -100000 =: orig_vset_valid_for // original validator set valid 100000 seconds -now dup orig_vset_valid_for + 0 config.validators! - -/* - * - * SmartContract #5 (Configuration smart contract) - * - */ -"auto/config-code.fif" include // code in separate source file - // data -empty_cell // libraries -GR$10 // balance -0 1 config_addr 6 register_smc // tock -dup set_config_smc -Masterchain swap -."config smart contract address = " 2dup .addr cr 2dup 7 .Addr cr -"config-master" +suffix +".addr" save-address-verbose -// Other data - -/* - * - * Initial wallets (test) - * - */ - -// pubkey amount `create-wallet1` or pubkey amount `create-wallet2` -PK'PuZPPXK5Rff9SvtoS7Y9lUuEixvy-J6aishYFj3Qn6P0pJMb GR$1000000000 create-wallet1 -PK'PuYiB1zAWzr4p8j6I681+sGUrRGcn6Ylf7vXl0xaUl/w6Xfg GR$1700000000 create-wallet0 - -/* - * - * Create state - * - */ - -create_state -cr cr ."new state is:" cr dup B dup Bx. cr -dup "zerostate" +suffix +".boc" tuck B>file -."(Initial masterchain state saved to file " type .")" cr -Bhashu dup =: zerostate_fhash -."file hash= " dup X. space 256 u>B dup B>base64url type cr -"zerostate" +suffix +".fhash" B>file -hashu dup =: zerostate_rhash ."root hash= " dup X. space 256 u>B dup B>base64url type cr -"zerostate" +suffix +".rhash" B>file -basestate0_rhash ."Basestate0 root hash= " dup X. space 256 u>B B>base64url type cr -basestate0_fhash ."Basestate0 file hash= " dup X. space 256 u>B B>base64url type cr -zerostate_rhash ."Zerostate root hash= " dup X. space 256 u>B B>base64url type cr -zerostate_fhash ."Zerostate file hash= " dup X. space 256 u>B B>base64url type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-code.fc deleted file mode 100644 index 8420c1d8..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-code.fc +++ /dev/null @@ -1,47 +0,0 @@ -;; Heavy-duty wallet for mass transfers (e.g., for cryptocurrency exchanges) -;; accepts orders for up to 254 internal messages (transfers) in one external message - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256)); - ds.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, subwallet_id == stored_subwallet); - throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key)); - var dict = cs~load_dict(); - cs.end_parse(); - accept_message(); - int i = -1; - do { - (i, var cs, var f) = dict.idict_get_next?(16, i); - if (f) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - } until (~ f); - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(stored_subwallet, 32) - .store_uint(public_key, 256) - .end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(64); - return cs.preload_uint(256); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-code.fc deleted file mode 100644 index 7dd65f9e..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-code.fc +++ /dev/null @@ -1,71 +0,0 @@ -;; Heavy-duty wallet for mass transfers (e.g., for cryptocurrency exchanges) -;; accepts orders for up to 254 internal messages (transfers) in one external message -;; this version does not use seqno for replay protection; instead, it remembers all recent query_ids -;; in this way several external messages with different query_id can be sent in parallel - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (subwallet_id, query_id) = (cs~load_uint(32), cs~load_uint(64)); - var bound = (now() << 32); - throw_if(35, query_id < bound); - var ds = get_data().begin_parse(); - var (stored_subwallet, last_cleaned, public_key, old_queries) = (ds~load_uint(32), ds~load_uint(64), ds~load_uint(256), ds~load_dict()); - ds.end_parse(); - (_, var found?) = old_queries.udict_get?(64, query_id); - throw_if(32, found?); - throw_unless(34, subwallet_id == stored_subwallet); - throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key)); - var dict = cs~load_dict(); - cs.end_parse(); - accept_message(); - int i = -1; - do { - (i, var cs, var f) = dict.idict_get_next?(16, i); - if (f) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - } until (~ f); - bound -= (64 << 32); ;; clean up records expired more than 64 seconds ago - old_queries~udict_set_builder(64, query_id, begin_cell()); - var queries = old_queries; - do { - var (old_queries', i, _, f) = old_queries.udict_delete_get_min(64); - f~touch(); - if (f) { - f = (i < bound); - } - if (f) { - old_queries = old_queries'; - last_cleaned = i; - } - } until (~ f); - set_data(begin_cell() - .store_uint(stored_subwallet, 32) - .store_uint(last_cleaned, 64) - .store_uint(public_key, 256) - .store_dict(old_queries) - .end_cell()); -} - -;; Get methods - -;; returns -1 for processed queries, 0 for unprocessed, 1 for unknown (forgotten) -int processed?(int query_id) method_id { - var ds = get_data().begin_parse(); - var (_, last_cleaned, _, old_queries) = (ds~load_uint(32), ds~load_uint(64), ds~load_uint(256), ds~load_dict()); - ds.end_parse(); - (_, var found) = old_queries.udict_get?(64, query_id); - return found ? true : - (query_id <= last_cleaned); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(32 + 64); - return cs.preload_uint(256); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-one.fif b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-one.fif deleted file mode 100644 index bd7fa5aa..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2-one.fif +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -"" =: comment // comment for simple transfers -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 =: timeout // external message expires in 60 seconds -variable extra-currencies -{ extra-currencies @ cc+ extra-currencies ! } : extra-cc+! - -begin-options - " [-x *] [-n|-b] [-t] [-B ] [-C ] []" +cr +tab - +"Creates one request to highload wallet created by new-highload-wallet-v2.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "x" "--extra" { $>xcc extra-cc+! } short-long-option-arg - "Indicates the amount of extra currencies to be transfered" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "B" "--body" { =: body-boc-file } short-long-option-arg - "Sets the payload of the transfer message" option-help - "C" "--comment" { =: comment } short-long-option-arg - "Sets the comment to be sent in the transfer message" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 4 < swap 5 > or ' usage if -5 :$1..n - -true constant bounce -$1 =: file-base -$2 bounce parse-load-address force-bounce or allow-bounce and =: bounce 2=: dest_addr -$3 parse-int =: subwallet-id -$4 $>cc extra-cc+! extra-currencies @ 2=: amount -$5 "wallet-query" replace-if-null =: savefile -{ subwallet-id (.) $+ } : +subwallet - -file-base +subwallet +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond -constant body-cell - -."Transferring " amount .GR+cc ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."subwallet-id=0x" subwallet-id x. -."timeout=" timeout . ."bounce=" bounce . cr -."Body of transfer message is " body-cell = abort"more than 254 orders" - orders @ 16 udict!+ not abort"cannot add order to dictionary" - orders ! order# 1+! -} : add-order -// b body -- b' -{ tuck -} : create-int-msg -// ng wc addr bnc -- -{ ."Transferring " 3 roll .GR ."to account " - -rot 2dup 4 pick 7 + .Addr ." = " .addr ." bounce=" . cr -} : .transfer -// addr$ ng -- c -{ swap parse-smc-addr force-bounce or allow-bounce and // ng wc addr bnc - 2over 2over .transfer - create-int-msg -} : create-simple-transfer -// c m -- c' -{ } : create-order - -// addr$ ng -- -{ create-simple-transfer send-mode create-order add-order } : send -{ bl word bl word $>GR send } : SEND - -// create internal message - -send-mode create-order add-order - -// create external message -now timeout + 32 << hashu 32 1<<1- and + =: query_id - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -."Query_id is " query_id dup . ."= 0x" X. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2.fif deleted file mode 100755 index fd71f52a..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet-v2.fif +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 =: timeout // external message expires in 60 seconds - -begin-options - " [-n|-b] [-t] []" +cr +tab - +"Creates a request with up to 254 orders loaded from to high-load (sub)wallet created by new-highload-v2-wallet.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" +cr - +" is a text file with lines `SEND `" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 3 < swap 4 > or ' usage if -4 :$1..n - -$1 =: file-base -$2 parse-int dup 32 fits ' usage ifnot =: subwallet-id // parse subwallet-id -{ subwallet-id (.) $+ } : +subwallet -$3 =: order-file -$4 "wallet-query" replace-if-null =: savefile - -file-base +subwallet +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -variable orders dictnew orders ! -variable order# order# 0! -// c -- -{ = abort"more than 254 orders" - orders @ 16 udict!+ not abort"cannot add order to dictionary" - orders ! order# 1+! -} : add-order -// b body -- b' -{ tuck -} : create-int-msg -// ng wc addr bnc -- -{ ."Transferring " 3 roll .GR ."to account " - -rot 2dup 4 pick 7 + .Addr ." = " .addr ." bounce=" . cr -} : .transfer -// addr$ ng -- c -{ swap parse-smc-addr force-bounce or allow-bounce and // ng wc addr bnc - 2over 2over .transfer - create-int-msg -} : create-simple-transfer -// c m -- c' -{ } : create-order - -// addr$ ng -- -{ create-simple-transfer send-mode create-order add-order } : send -{ bl word bl word $>GR send } : SEND - -// parse order file -order-file include - -// create external message -now timeout + 32 << hashu 32 1<<1- and + =: query_id - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -."Query_id is " query_id dup . ."= 0x" X. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif deleted file mode 100755 index 36e321ef..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 =: timeout // external message expires in 60 seconds - -begin-options - " [-n|-b] [-t] []" +cr +tab - +"Creates a request with up to 254 orders loaded from to high-load (sub)wallet created by new-highload-wallet.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" +cr - +" is a text file with lines `SEND `" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 4 < swap 5 > or ' usage if -5 :$1..n - -$1 =: file-base -$2 parse-int dup 32 fits ' usage ifnot =: subwallet-id // parse subwallet-id -{ subwallet-id (.) $+ } : +subwallet -$3 parse-int =: seqno -$4 =: order-file -$5 "wallet-query" replace-if-null =: savefile - -file-base +subwallet +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -variable orders dictnew orders ! -variable order# order# 0! -// c -- -{ = abort"more than 254 orders" - orders @ 16 udict!+ not abort"cannot add order to dictionary" - orders ! order# 1+! -} : add-order -// b body -- b' -{ tuck -} : create-int-msg -// ng wc addr bnc -- -{ ."Transferring " 3 roll .GR ."to account " - -rot 2dup 4 pick 7 + .Addr ." = " .addr ." bounce=" . cr -} : .transfer -// addr$ ng -- c -{ swap parse-smc-addr force-bounce or allow-bounce and // ng wc addr bnc - 2over 2over .transfer - create-int-msg -} : create-simple-transfer -// c m -- c' -{ } : create-order - -// addr$ ng -- -{ create-simple-transfer send-mode create-order add-order } : send -{ bl word bl word $>GR send } : SEND - -// parse order file -order-file include - -// create external message - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/manual-dns-manage.fif b/submodules/ton/tonlib-src/crypto/smartcont/manual-dns-manage.fif deleted file mode 100644 index ef18127c..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/manual-dns-manage.fif +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -60 =: timeout // external message expires in 60 seconds -"dns-query.boc" =: savefile - -begin-options - " [-t] [-o] [...]" +cr +tab - +"Creates a request to managed DNS smart contract created by new-manual-dns.fif, with private key loaded from file .pk " - +"and address from -dns.addr, and saves it into ('" savefile $+ +"' by default)" - +cr +" is an operation description, one of" +cr +tab - +"add cat (smc | next | adnl | text )" +cr +tab - +"delete cat " +cr +tab - +"drop " - disable-digit-options generic-help-setopt - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "o" "--output" { =: savefile } short-long-option-arg - "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 2 < ' usage if -2 :$1..n - -$1 =: file-base -$2 parse-int dup =: contract-id 32 fits ' usage ifnot -{ contract-id (.) $+ } : +contractid - -{ $* @ dup null? { second $@ ! } { drop } cond } : @skip -{ $* @ null? } : @end? -{ $* @ uncons $* ! } : @next -@next @next 2drop - -variable Actions -{ Actions @ cons Actions ! } : register-action - -{ @end? abort"subdomain name expected" @next dup $len 127 > abort"subdomain name too long" -} : parse-domain -{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer" - dup 16 fits not abort"category does not fit into 16 bit integer" - dup 0= abort"category must be non-zero" -} : parse-cat-num -{ @end? abort"`cat` expected" @next "cat" $= not abort"`cat` expected" parse-cat-num -} : parse-cat -{ @end? abort"smart contract address expected" - @next false parse-load-address drop triple -} : cl-parse-smc-addr -{ @end? abort"adnl address expected" - `adnl @next parse-adnl-addr pair -} : cl-parse-adnl-addr -{ @end? abort"subdomain record value expected" @next - dup "smc" $= { drop `smc cl-parse-smc-addr } { - dup "next" $= { drop `next cl-parse-smc-addr } { - dup "adnl" $= { drop cl-parse-adnl-addr } { - dup "text" $= { drop `text @next pair } { - "unknown record type "' swap $+ +"'" abort - } cond } cond } cond } cond -} : parse-value -{ ."Loading new code BoC from " dup type cr - file>B B>boc -} : load-new-code-from -{ @next dup "add" $= { drop `add parse-domain parse-cat parse-value 4 tuple register-action } { - dup "delete" $= { drop `delete parse-domain parse-cat triple register-action } { - dup "drop" $= { drop `drop parse-domain pair register-action } { - dup "upgrade" $= { drop `upgrade @next load-new-code-from pair register-action } { - "unknown action '" swap $+ +"'" abort - } cond } cond } cond } cond -} : parse-action -{ { @end? not } { parse-action } while } : parse-actions -parse-actions - -file-base +".pk" load-keypair nip constant wallet_pk -file-base +"-dns" +contractid +".addr" load-address -2dup 2constant smc_addr -."Managed manual DNS smart contract address = " 2dup .addr cr 6 .Addr cr - -."Actions: " Actions @ list-reverse .l cr - -// ( S -- S1 .. Sn n ) -{ 1 swap { dup "." $pos dup 0>= } { $| 1 $| nip rot 1+ swap } while drop swap -} : split-by-dots -// ( S -- s ) -{ dup $len dup 0= abort"subdomain cannot be empty" 126 > abort"subdomain too long" - dup 0 chr $pos 1+ abort"subdomain contains null characters" - split-by-dots s -// ( b V -- b' ) -{ dup first - dup `smc eq? { drop untriple 2swap drop x{9fd3} s, -rot Addr, 0 8 u, } { - dup `next eq? { drop untriple 2swap drop x{ba93} s, -rot Addr, } { - dup `adnl eq? { drop second swap x{ad01} s, swap 256 u, 0 8 u, } { - dup `text eq? { drop second swap x{1eda01} s, over $len 8 u, swap $, } { - abort"unknown value type" - } cond } cond } cond } cond -} : value, -{ subdomain>s dup sbits 3 >> - dup 63 > { drop s>c dict, } { rot swap 7 u, swap s, } cond -} : subdomain, -// ( A -- b ) -{ dup first - dup `add eq? { - drop 4 untuple -rot - b -// ( -- b ) -{ Actions @ dup null? { drop } { - uncons swap action>b { over null? not } { - b> swap uncons swap action>b rot ref, - } while nip } cond -} : serialize-actions -serialize-actions -dup brembits 888 < { b> -."Serialized actions are " hashu 32 1<<1- and + =: query_id - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -."Query_id is " query_id dup . ."= 0x" X. cr -."Query expires in " timeout . ."seconds" cr -savefile tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc deleted file mode 100644 index 243262b6..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc +++ /dev/null @@ -1,318 +0,0 @@ -;; Simple wallet smart contract - -_ unpack_state() inline_ref { - var ds = begin_parse(get_data()); - var res = (ds~load_uint(32), ds~load_uint(8), ds~load_uint(8), ds~load_uint(64), ds~load_dict(), ds~load_dict()); - ds.end_parse(); - return res; -} - -_ pack_state(cell pending_queries, cell owner_infos, int last_cleaned, int k, int n, int wallet_id) inline_ref { - return begin_cell() - .store_uint(wallet_id, 32) - .store_uint(n, 8) - .store_uint(k, 8) - .store_uint(last_cleaned, 64) - .store_dict(owner_infos) - .store_dict(pending_queries) - .end_cell(); -} - -_ pack_owner_info(int public_key, int flood) inline_ref { - return begin_cell() - .store_uint(public_key, 256) - .store_uint(flood, 8); -} - -_ unpack_owner_info(slice cs) inline_ref { - return (cs~load_uint(256), cs~load_uint(8)); -} - -(int, int) check_signatures(cell public_keys, cell signatures, int hash, int cnt_bits) inline_ref { - int cnt = 0; - - do { - slice cs = signatures.begin_parse(); - slice signature = cs~load_bits(512); - - int i = cs~load_uint(8); - signatures = cs~load_dict(); - - (slice public_key, var found?) = public_keys.udict_get?(8, i); - throw_unless(37, found?); - throw_unless(38, check_signature(hash, signature, public_key.preload_uint(256))); - - int mask = (1 << i); - int old_cnt_bits = cnt_bits; - cnt_bits |= mask; - int should_check = cnt_bits != old_cnt_bits; - cnt -= should_check; - } until (cell_null?(signatures)); - - return (cnt, cnt_bits); -} - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -(int, int, int, slice) unpack_query_data(slice in_msg, int n, slice query, var found?, int root_i) inline_ref { - if (found?) { - throw_unless(35, query~load_int(1)); - (int creator_i, int cnt, int cnt_bits, slice msg) = (query~load_uint(8), query~load_uint(8), query~load_uint(n), query); - throw_unless(36, slice_hash(msg) == slice_hash(in_msg)); - return (creator_i, cnt, cnt_bits, msg); - } - return (root_i, 0, 0, in_msg); -} - -(cell, ()) dec_flood(cell owner_infos, int creator_i) { - (slice owner_info, var found?) = owner_infos.udict_get?(8, creator_i); - (int public_key, int flood) = unpack_owner_info(owner_info); - owner_infos~udict_set_builder(8, creator_i, pack_owner_info(public_key, flood - 1)); - return (owner_infos, ()); -} - -() try_init() impure inline_ref { - ;; first query without signatures is always accepted - (int wallet_id, int n, int k, int last_cleaned, cell owner_infos, cell pending_queries) = unpack_state(); - throw_if(37, last_cleaned); - accept_message(); - set_data(pack_state(pending_queries, owner_infos, 1, k, n, wallet_id)); -} - -(cell, cell) update_pending_queries(cell pending_queries, cell owner_infos, slice msg, int query_id, int creator_i, int cnt, int cnt_bits, int n, int k) impure inline_ref { - if (cnt >= k) { - accept_message(); - while (msg.slice_refs()) { - var mode = msg~load_uint(8); - send_raw_message(msg~load_ref(), mode); - } - pending_queries~udict_set_builder(64, query_id, begin_cell().store_int(0, 1)); - owner_infos~dec_flood(creator_i); - } else { - pending_queries~udict_set_builder(64, query_id, begin_cell() - .store_uint(1, 1) - .store_uint(creator_i, 8) - .store_uint(cnt, 8) - .store_uint(cnt_bits, n) - .store_slice(msg)); - } - return (pending_queries, owner_infos); -} - -(int, int) calc_boc_size(int cells, int bits, slice root) { - cells += 1; - bits += root.slice_bits(); - - while (root.slice_refs()) { - (cells, bits) = calc_boc_size(cells, bits, root~load_ref().begin_parse()); - } - - return (cells, bits); -} - -() recv_external(slice in_msg) impure { - ;; empty message triggers init - if (slice_empty?(in_msg)) { - return try_init(); - } - - ;; Check root signature - slice root_signature = in_msg~load_bits(512); - int root_hash = slice_hash(in_msg); - int root_i = in_msg~load_uint(8); - - (int wallet_id, int n, int k, int last_cleaned, cell owner_infos, cell pending_queries) = unpack_state(); - last_cleaned -= last_cleaned == 0; - - (slice owner_info, var found?) = owner_infos.udict_get?(8, root_i); - throw_unless(31, found?); - (int public_key, int flood) = unpack_owner_info(owner_info); - throw_unless(32, check_signature(root_hash, root_signature, public_key)); - - cell signatures = in_msg~load_dict(); - - var hash = slice_hash(in_msg); - int query_wallet_id = in_msg~load_uint(32); - throw_unless(42, query_wallet_id == wallet_id); - - int query_id = in_msg~load_uint(64); - - (int cnt, int bits) = calc_boc_size(0, 0, in_msg); - throw_if(40, (cnt > 8) | (bits > 2048)); - - (slice query, var found?) = pending_queries.udict_get?(64, query_id); - - ifnot (found?) { - flood += 1; - throw_if(39, flood > 10); - } - - var bound = (now() << 32); - throw_if(33, query_id < bound); - - (int creator_i, int cnt, int cnt_bits, slice msg) = unpack_query_data(in_msg, n, query, found?, root_i); - int mask = 1 << root_i; - throw_if(34, cnt_bits & mask); - cnt_bits |= mask; - cnt += 1; - - throw_if(41, ~ found? & (cnt < k) & (bound + ((60 * 60) << 32) > query_id)); - - set_gas_limit(100000); - - ifnot (found?) { - owner_infos~udict_set_builder(8, root_i, pack_owner_info(public_key, flood)); - } - - (pending_queries, owner_infos) = update_pending_queries(pending_queries, owner_infos, msg, query_id, creator_i, cnt, cnt_bits, n, k); - set_data(pack_state(pending_queries, owner_infos, last_cleaned, k, n, wallet_id)); - - commit(); - - int need_save = 0; - ifnot (cell_null?(signatures) | (cnt >= k)) { - (int new_cnt, cnt_bits) = check_signatures(owner_infos, signatures, hash, cnt_bits); - cnt += new_cnt; - (pending_queries, owner_infos) = update_pending_queries(pending_queries, owner_infos, msg, query_id, creator_i, cnt, cnt_bits, n, k); - need_save = -1; - } - - accept_message(); - bound -= (64 << 32); ;; clean up records expired more than 64 seconds ago - int old_last_cleaned = last_cleaned; - do { - var (pending_queries', i, query, f) = pending_queries.udict_delete_get_min(64); - f~touch(); - if (f) { - f = (i < bound); - } - if (f) { - if (query~load_int(1)) { - owner_infos~dec_flood(query~load_uint(8)); - } - pending_queries = pending_queries'; - last_cleaned = i; - need_save = -1; - } - } until (~ f); - - if (need_save) { - set_data(pack_state(pending_queries, owner_infos, last_cleaned, k, n, wallet_id)); - } -} - -;; Get methods -;; returns -1 for processed queries, 0 for unprocessed, 1 for unknown (forgotten) -(int, int) get_query_state(int query_id) method_id { - (_, int n, _, int last_cleaned, _, cell pending_queries) = unpack_state(); - (slice cs, var found) = pending_queries.udict_get?(64, query_id); - if (found) { - if (cs~load_int(1)) { - cs~load_uint(8 + 8); - return (0, cs~load_uint(n)); - } else { - return (-1, 0); - } - } else { - return (-(query_id <= last_cleaned), 0); - } -} - -int processed?(int query_id) method_id { - (int x, _) = get_query_state(query_id); - return x; -} - -cell create_init_state(int wallet_id, int n, int k, cell owners_info) method_id { - return pack_state(new_dict(), owners_info, 0, k, n, wallet_id); -} - -cell merge_list(cell a, cell b) { - if (cell_null?(a)) { - return b; - } - if (cell_null?(b)) { - return a; - } - slice as = a.begin_parse(); - if (as.slice_refs() != 0) { - cell tail = merge_list(as~load_ref(), b); - return begin_cell().store_slice(as).store_ref(tail).end_cell(); - } - - as~skip_last_bits(1); - ;; as~skip_bits(1); - return begin_cell().store_slice(as).store_dict(b).end_cell(); - -} - -cell get_public_keys() method_id { - (_, _, _, _, cell public_keys, _) = unpack_state(); - return public_keys; -} - -(int, int) check_query_signatures(cell query) method_id { - slice cs = query.begin_parse(); - slice root_signature = cs~load_bits(512); - int root_hash = slice_hash(cs); - int root_i = cs~load_uint(8); - - cell public_keys = get_public_keys(); - (slice public_key, var found?) = public_keys.udict_get?(8, root_i); - throw_unless(31, found?); - throw_unless(32, check_signature(root_hash, root_signature, public_key.preload_uint(256))); - - int mask = 1 << root_i; - - cell signatures = cs~load_dict(); - if (cell_null?(signatures)) { - return (1, mask); - } - (int cnt, mask) = check_signatures(public_keys, signatures, slice_hash(cs), mask); - return (cnt + 1, mask); -} - -cell messages_by_mask(int mask) method_id { - (_, int n, _, _, _, cell pending_queries) = unpack_state(); - int i = -1; - cell a = new_dict(); - do { - (i, var cs, var f) = pending_queries.udict_get_next?(64, i); - if (f) { - if (cs~load_int(1)) { - int cnt_bits = cs.skip_bits(8 + 8).preload_uint(n); - if (cnt_bits & mask) { - a~udict_set_builder(64, i, begin_cell().store_slice(cs)); - } - } - } - } until (~ f); - return a; -} - -cell get_messages_unsigned_by_id(int id) method_id { - return messages_by_mask(1 << id); -} - -cell get_messages_unsigned() method_id { - return messages_by_mask(~ 0); -} - -(int, int) get_n_k() method_id { - (_, int n, int k, _, _, _) = unpack_state(); - return (n, k); -} - -cell merge_inner_queries(cell a, cell b) method_id { - slice ca = a.begin_parse(); - slice cb = b.begin_parse(); - cell list_a = ca~load_dict(); - cell list_b = cb~load_dict(); - throw_unless(31, slice_hash(ca) == slice_hash(cb)); - return begin_cell() - .store_dict(merge_list(list_a, list_b)) - .store_slice(ca) - .end_cell(); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-auto-dns.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-auto-dns.fif deleted file mode 100644 index 3d4848b4..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-auto-dns.fif +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -Basechain =: wc // create smart contract in basechain -"new-dns-query.boc" =: savefile -0 =: contract-id -variable dns-dict dictnew dns-dict ! - -begin-options - "
[-w] [-r] [-o]" +cr +tab - +"Creates a new automatic dns smart contract with 32-bit identifier controlled from wallet with address
" - +"and saves it into ('" savefile $+ +"' by default)" - disable-digit-options generic-help-setopt - "w" "--workchain" { parse-workchain-id =: wc } short-long-option-arg - "Selects workchain to create smart contract (" wc (.) $+ +" by default)" option-help - "r" "--random-id" { parse-int =: contract-id } short-long-option-arg - "Sets 'random' smart contract identifier (" contract-id (.) $+ +" by default)" option-help - "o" "--output" { =: savefile } short-long-option-arg - "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 6 <> ' usage if -6 :$1..n -$1 =: file-base -$2 false parse-load-address drop 2=: ctl-addr -$3 parse-int dup 0 10000000 in-range? ' usage ifnot =: reg-period -$4 $>GR =: reg-price -$5 parse-int dup 0< ' usage if =: ng-pb -$6 parse-int dup 0< ' usage if =: ng-pc -contract-id 32 fits ' usage ifnot -{ contract-id ?dup { (.) $+ } if } : +contractid - -."Creating new automatic DNS smart contract in workchain " wc . -."with random id " contract-id . cr -."Controlling wallet (smart contract) is " ctl-addr 6 .Addr cr -."Subdomain registration period is " reg-period . ."seconds" cr -."Subdomain registration price is " reg-price .GR -."+ " ng-pc . ."per cell + " ng-pb . ."per bit" cr - -// Create new automatic DNS; source code included from `auto/dns-auto-code.fif` -"auto/dns-auto-code.fif" include -// code - ref, // ctl - dns-dict @ dict, dictnew dict, // dom_dict gc - reg-period 30 u, reg-price Gram, ng-pc Gram, ng-pb Gram, // stdper ppc ppb - 0 64 u, // nhk lhk -b> // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."External message for initialization is " B dup Bx. cr -savefile tuck B>file -."(Saved dns smart-contract creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif deleted file mode 100755 index d0183b22..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new v2 high-load wallet in the specified workchain, with the controlling private key saved to or loaded from .pk " - ."('new-wallet.pk' by default)" cr - ." is the 32-bit identifier of this subwallet among all controlled by the same private key" cr 1 halt -} : usage -$# 2- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -$2 parse-int dup =: subwallet-id // parse subwallet-id -32 fits ' usage ifnot -{ subwallet-id (.) $+ } : +subwallet -def? $3 { @' $3 } { "new-wallet" } cond constant file-base -65536 constant timeout // init query times out in 65536 seconds - -."Creating new v2 high-load wallet in workchain " wc . -."with subwallet id " subwallet-id . cr - -// Create new high-load wallet; source code included from `auto/highload-wallet-v2-code.fif` -"auto/highload-wallet-v2-code.fif" include -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +subwallet +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet.fif deleted file mode 100755 index 9ead3ff1..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet.fif +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new high-load wallet in the specified workchain, with the controlling private key saved to or loaded from .pk " - ."('new-wallet.pk' by default)" cr - ." is the 32-bit identifier of this subwallet among all controlled by the same private key" cr 1 halt -} : usage -$# 2- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -$2 parse-int dup =: subwallet-id // parse subwallet-id -32 fits ' usage ifnot -{ subwallet-id (.) $+ } : +subwallet -def? $3 { @' $3 } { "new-wallet" } cond constant file-base - -."Creating new high-load wallet in workchain " wc . -."with subwallet id " subwallet-id . cr - -// Create new high-load wallet; source code included from `auto/highload-wallet-code.fif` -"auto/highload-wallet-code.fif" include -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +subwallet +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-manual-dns.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-manual-dns.fif deleted file mode 100644 index 47b57bbe..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-manual-dns.fif +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -Basechain =: wc // create smart contract in basechain -65536 =: timeout -"new-dns-query.boc" =: savefile -variable dns-dict dictnew dns-dict ! - -begin-options - " [-w] [-t] [-o]" +cr +tab - +"Creates a new manual dns smart contract with 32-bit identifier managed by private key .pk, " - +"and saves it into ('" savefile $+ +"' by default)" - disable-digit-options generic-help-setopt - "w" "--workchain" { parse-workchain-id =: wc } short-long-option-arg - "Selects workchain to create smart contract (" wc (.) $+ +" by default)" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout for the initialization message in seconds (" timeout (.) $+ +" by default)" option-help - "o" "--output" { =: savefile } short-long-option-arg - "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# 2 <> ' usage if -2 :$1..n -$1 =: file-base -$2 parse-int dup =: contract-id -32 fits ' usage ifnot -{ contract-id (.) $+ } : +contractid - -."Creating new manual DNS smart contract in workchain " wc . -."with contract id " contract-id . cr - -// Create new manual DNS; source code included from `auto/dns-manual-code.fif` -"auto/dns-manual-code.fif" include -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -savefile tuck B>file -."(Saved dns smart-contract creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-pinger.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-pinger.fif deleted file mode 100755 index 4caf7abc..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-pinger.fif +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " $0 type ." []" cr - ."Creates a new pinger in specified workchain, with destination address . " cr - ."Resulting initialization query is saved into -query.boc ('new-pinger-query.boc' by default)" cr 1 halt -} : usage - -$# dup 1 < swap 3 > or ' usage if -3 :$1..n - -Basechain 256 1<<1- 3 15 */ 2constant dest-addr - -Basechain constant wc // create a wallet in workchain 0 (basechain) -$1 parse-workchain-id =: wc // set workchain id from command line argument -$2 dup null? { drop } { false parse-load-address drop 2=: dest-addr } cond -$3 "new-pinger" replace-if-null constant file-base - -."Creating new pinger in workchain " wc . cr -."Address to ping is " dest-addr 2dup .addr ." = " 6 .Addr cr - -// Create new simple pinger -<{ SETCP0 DUP INC 1 RSHIFT# 32 THROWIF // fail unless recv_internal or recv_external - c4 PUSHCTR CTOS 32 LDU TUCK 8 LDI 256 LDU ENDS // body sel s seqno wc addr : destination address loaded - s4 PUSH IF:<{ - s2 s5 XCHG2 // addr sel s wc seqno body - 32 PLDU OVER EQUAL 33 THROWIFNOT // seqno mismatch? - ACCEPT // addr sel s wc seqno - INC NEWC 32 STU // addr sel s wc b - s1 s2 XCHG STSLICE // addr sel wc b' - ENDC c4 POPCTR // addr sel wc ; persistent data updated - ROT // sel wc addr - }> - // create new empty message with 0.1 Grams to that address - SWAP NEWC b{001000100} STSLICECONST 8 STI 256 STU - GR$10/9 INT STGRAMS // store 1.111..1 Grams - 1 4 + 4 + 64 + 32 + 1+ 1+ INT STZEROES ENDC - // send raw message from Cell - ZERO SENDRAWMSG -}>c -// code - // data -// no libraries - // create StateInit -dup ."StateInit: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved pinger creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet.fif deleted file mode 100644 index 881f8ad2..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet.fif +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a restricted wallet in the masterchain controlled by the private key corresponding to the specified public key" cr - ."and saves its address into .addr ('rwallet.addr' by default)" cr 1 halt -} : usage -$# 1- -2 and ' usage if - --1 =: wc -$1 parse-pubkey =: PubKey -def? $2 { @' $2 } { "rwallet" } cond constant file-base - -."Creating new restricted wallet in workchain " wc . ."controlled by public key " PubKey .pubkey cr - -// Create new restricted wallet; code taken from `auto/restricted-wallet-code.fif` -"auto/restricted-wallet-code.fif" include // code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif deleted file mode 100644 index 90f54495..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a restricted lockup wallet in the masterchain controlled by the private key corresponding to the specified public key" cr - ."and saves its address into .addr ('rwallet.addr' by default)" cr 1 halt -} : usage -$# 2- -2 and ' usage if - --1 =: wc -$1 parse-pubkey =: PubKey -$2 $>GR =: amount -def? $3 { @' $3 } { "rwallet" } cond constant file-base - -."Creating new restricted lockup wallet in workchain " wc . ."controlled by public key " PubKey .pubkey -." with nominal amount " amount .GR cr - -// D x t -- D' -{ idict! not abort"cannot add value" -} : rdict-entry -// balance -- dict -{ dictnew - over -32768 rdict-entry - over 3/4 */ 92 rdict-entry - over 1/2 */ 183 rdict-entry - swap 1/4 */ 366 rdict-entry - 0 548 rdict-entry -} : make-rdict - -// Create new restricted wallet; code taken from `auto/restricted-wallet2-code.fif` -"auto/restricted-wallet2-code.fif" include // code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet3.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet3.fif deleted file mode 100644 index d12dbe62..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet3.fif +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage -0 =: restrict-mode --1 =: wc -null =: subwallet-id -86400 =: expires-in -now =: start-at -0x5EA62080 =: start-at -0x4BA92D8A =: subwallet-base - -begin-options - " [-w][-r][-i][-t] []" +cr +tab - +"Creates a restricted lockup wallet v3 in the masterchain initialized by key loaded from " - +"and controlled by the private key corresponding to " +cr +tab - +"and saves its initialization query into new-.boc and its address into .addr ('rwallet.addr' by default)" - disable-digit-options generic-help-setopt - "r" "--restrict-mode" { parse-int =: restrict-mode } short-long-option-arg - "Selects a standard restriction mode: 1 for 18-month lockup, 2 for 4-year lockup" option-help - "w" "--workchain" { parse-int =: wc } short-long-option-arg - "Selects a workchain (" wc (.) $+ +" by default)" option-help - "i" "--subwallet-id" { parse-int =: subwallet-id } short-long-option-arg - "Sets 32-bit subwallet id (workchain plus " subwallet-base (.) $+ +" by default)" option-help - "x" "--expires-in" { parse-int =: expires-in } short-long-option-arg - "Expiration time of the initialization message (" expires-in (.) $+ - +" seconds by default)" option-help - "t" "--start-at" { parse-int =: start-at } short-long-option-arg - "Restriction start Unixtime (now by default)" option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 3 < swap 4 > or ' usage if -4 :$1..n - -$1 =: filename-base -$2 parse-pubkey =: PubKey -$3 $>GR =: amount -$4 "rwallet" replace-if-null =: savefile-base -subwallet-id subwallet-base wc + replace-if-null =: subwallet-id -expires-in now + =: expires-at - -"new-" savefile-base $+ +".boc" =: savefile -savefile-base +".addr" =: savefile-addr - -wc 8 fits not abort"invalid workchain id" -subwallet-id 32 fits not abort"invalid subwallet-id" -expires-at 32 ufits not abort"invalid expiration time" -start-at 32 ufits not abort"invalid restriction start time" -restrict-mode dup 1 < swap 2 > or abort"unknown restriction mode" -filename-base +".pk" load-keypair =: init_pk =: init_pubkey - -."Creating new restricted lockup wallet v3 in workchain " wc . -."with restriction mode " restrict-mode . ."and nominal amount " amount .GR cr -."controlled by public key " PubKey .pubkey ." and initialized by public key " init_pubkey 256 B>u@ .pubkey cr -."(subwallet id is " subwallet-id ._ .")" cr - -// D x t -- D' -{ idict! not abort"cannot add value" -} : rdict-entry -{ 86400 * } : days* -{ 365 * days* } : years* -// balance -- dict -{ dictnew - over 31 -1<< rdict-entry - over 3/4 */ 91 days* rdict-entry - over 1/2 */ 183 days* rdict-entry - swap 1/4 */ 365 days* rdict-entry - 0 548 days* rdict-entry -} : make-rdict1 -{ dictnew - over 31 -1<< rdict-entry - over .9 */ 0 rdict-entry - over .6775 */ 1 years* rdict-entry - over .445 */ 2 years* rdict-entry - swap .2225 */ 3 years* rdict-entry - 0 4 years* 86400 + rdict-entry -} : make-rdict2 - -amount -restrict-mode 1 = { make-rdict1 } { make-rdict2 } cond =: rdict - -."Restrictions start at " start-at ._ .": " cr -rdict 32 { swap . ."-> " Gram@ .GR cr true } idictforeach cr - -// Create new restricted wallet v3; code taken from `auto/restricted-wallet3-code.fif` -"auto/restricted-wallet3-code.fif" include // code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -savefile tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif deleted file mode 100755 index ad9789fa..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new money giver in specified workchain, with address saved to .addr" cr - ."('new-testgiver.addr' by default)" cr 1 halt -} : usage -$# 1- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -def? $2 { @' $2 } { "new-testgiver" } cond constant file-base - -."Creating new money giver in workchain " wc . cr -0 constant init_seqno - -// Create new simple money giver -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt - }> - INC 32 THROWIF // fail unless recv_external - 32 LDU SWAP // cs cnt - c4 PUSHCTR CTOS 32 LDU ENDS // cs cnt cnt' - TUCK EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - ACCEPT // cs cnt' - SWAP DUP SREFS // cnt' cs msg? - IF:<{ - 8 LDU LDREF -ROT // cnt'' cs mode msg - GR$20 INT 3 INT RAWRESERVE // reserve all but 20 Grams from the balance - SWAP SENDRAWMSG - }> - ENDS INC NEWC 32 STU ENDC c4 POPCTR // store cnt'' -}>c -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved money giver creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif deleted file mode 100755 index 0bb2bcd1..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new advanced wallet in specified workchain, with private key saved to or loaded from .pk" cr - ."('new-wallet.pk' by default)" cr 1 halt -} : usage -$# 1- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -def? $2 { @' $2 } { "new-wallet" } cond constant file-base - -."Creating new advanced wallet in workchain " wc . cr - -// Create new advanced wallet; code adapted from `auto/wallet-code.fif` -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk - }> - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs - c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key - s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno - EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno - s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash - s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key - ACCEPT - s0 s2 XCHG // public_key stored_seqno cs - WHILE:<{ - DUP SREFS // public_key stored_seqno cs _40 - }>DO<{ // public_key stored_seqno cs - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode - SENDRAWMSG // public_key stored_seqno cs - }> - ENDS INC // public_key seqno' - NEWC 32 STU 256 STU ENDC c4 POP -}>c // >libref -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v3.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v3.fif deleted file mode 100644 index 61e392a0..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v3.fif +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " $0 type ." []" cr - ."Creates a new advanced wallet with unique 32-bit identifier in specified workchain, with private key saved to or loaded from .pk" cr - ."('new-wallet.pk' by default)" cr 1 halt -} : usage -$# 2- -2 and ' usage if - -3 :$1..n -$1 parse-workchain-id =: wc // set workchain id from command line argument -$2 parse-int =: subwallet-id -$3 "new-wallet" replace-if-null =: file-base - -."Creating new advanced v3 wallet in workchain " wc . cr -."with unique wallet id " subwallet-id . cr - -// Create new advanced wallet; code adapted from `auto/wallet3-code.fif` -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 32 LDU NIP 256 PLDU CONDSEL // cnt or pubk - }> - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno - c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key - s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet - s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno - s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash - s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key - CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs - ACCEPT - WHILE:<{ - DUP SREFS // public_key stored_seqno stored_subwallet cs _51 - }>DO<{ // public_key stored_seqno stored_subwallet cs - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode - SENDRAWMSG - }> // public_key stored_seqno stored_subwallet cs - ENDS SWAP INC // public_key stored_subwallet seqno' - NEWC 32 STU 32 STU 256 STU ENDC c4 POP -}>c // >libref -// code - // data -null // no libraries - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif deleted file mode 100755 index b1aead90..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"Asm.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a new wallet in specified workchain, with private key saved to or loaded from .pk" cr - ."('new-wallet.pk' by default)" cr 1 halt -} : usage -$# 1- -2 and ' usage if - -$1 parse-workchain-id =: wc // set workchain id from command line argument -def? $2 { @' $2 } { "new-wallet" } cond constant file-base - -."Creating new wallet in workchain " wc . cr - -// Create new simple wallet -<{ SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk - }> - INC 32 THROWIF // fail unless recv_external - 512 INT LDSLICEX DUP 32 PLDU // sign cs cnt - c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk - s1 s2 XCPU // sign cs cnt pubk cnt' cnt - EQUAL 33 THROWIFNOT // ( seqno mismatch? ) - s2 PUSH HASHSU // sign cs cnt pubk hash - s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk - CHKSIGNU // pubk cs cnt ? - 34 THROWIFNOT // signature mismatch - ACCEPT - SWAP 32 LDU NIP - DUP SREFS IF:<{ - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF // pubk cnt mode msg cs - s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent ) - }> - ENDS - INC NEWC 32 STU 256 STU ENDC c4 POPCTR -}>c // >libref -// code - // data -null // no libraries -// Libs{ x{ABACABADABACABA} drop x{AAAA} s>c public_lib x{1234} x{5678} |_ s>c public_lib }Libs - // create StateInit -dup ."StateInit: " -dup ."signing message: " -dup ."External message for initialization is " B dup Bx. cr -file-base +"-query.boc" tuck B>file -."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/payment-channel-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/payment-channel-code.fc deleted file mode 100644 index b4b14d5c..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/payment-channel-code.fc +++ /dev/null @@ -1,357 +0,0 @@ -;; WARINIG: NOT READY FOR A PRODUCTION! - -int err:wrong_a_signature() asm "31 PUSHINT"; -int err:wrong_b_signature() asm "32 PUSHINT"; -int err:msg_value_too_small() asm "33 PUSHINT"; -int err:replay_protection() asm "34 PUSHINT"; -int err:no_timeout() asm "35 PUSHINT"; -int err:expected_init() asm "36 PUSHINT"; -int err:expected_close() asm "37 PUSHINT"; -int err:expected_payout() asm "37 PUSHINT"; -int err:no_promise_signature() asm "38 PUSHINT"; -int err:wrong_channel_id() asm "39 PUSHINT"; -int err:unknown_op() asm "40 PUSHINT"; -int err:not_enough_fee() asm "41 PUSHINT"; - -int op:pchan_cmd() asm "0x912838d1 PUSHINT"; - -int msg:init() asm "0x27317822 PUSHINT"; -int msg:close() asm "0xf28ae183 PUSHINT"; -int msg:timeout() asm "0x43278a28 PUSHINT"; -int msg:payout() asm "0x37fe7810 PUSHINT"; - -int state:init() asm "0 PUSHINT"; -int state:close() asm "1 PUSHINT"; -int state:payout() asm "2 PUSHINT"; - -int min_fee() asm "1000000000 PUSHINT"; - - -;; A - initial balance of Alice, -;; B - initial balance of B -;; -;; To determine balance we track nondecreasing list of promises -;; promise_A ;; promised by Alice to Bob -;; promise_B ;; promised by Bob to Alice -;; -;; diff - balance between Alice and Bob. 0 in the beginning -;; diff = promise_B - promise_A; -;; diff = clamp(diff, -A, +B); -;; -;; final_A = A + diff; -;; final_B = B + diff; - -;; Data pack/unpack -;; -_ unpack_data() inline_ref { - var cs = get_data().begin_parse(); - var res = (cs~load_ref(), cs~load_ref()); - cs.end_parse(); - return res; -} - -_ pack_data(cell config, cell state) impure inline_ref { - set_data(begin_cell().store_ref(config).store_ref(state).end_cell()); -} - -;; Config pack/unpack -;; -;; config$_ initTimeout:int exitTimeout:int a_key:int256 b_key:int256 a_addr b_addr channel_id:uint64 = Config; -;; -_ unpack_config(cell config) { - var cs = config.begin_parse(); - var res = ( - cs~load_uint(32), - cs~load_uint(32), - cs~load_uint(256), - cs~load_uint(256), - cs~load_ref().begin_parse(), - cs~load_ref().begin_parse(), - cs~load_uint(64), - cs~load_grams()); - cs.end_parse(); - return res; -} - -;; takes -;; signedMesage$_ a_sig:Maybe b_sig:Maybe msg:Message = SignedMessage; -;; checks signatures and unwap message. -(slice, (int, int)) unwrap_signatures(slice cs, int a_key, int b_key) { - int a? = cs~load_int(1); - slice a_sig = cs; - if (a?) { - a_sig = cs~load_ref().begin_parse().preload_bits(512); - } - var b? = cs~load_int(1); - slice b_sig = cs; - if (b?) { - b_sig = cs~load_ref().begin_parse().preload_bits(512); - } - int hash = cs.slice_hash(); - if (a?) { - throw_unless(err:wrong_a_signature(), check_signature(hash, a_sig, a_key)); - } - if (b?) { - throw_unless(err:wrong_b_signature(), check_signature(hash, b_sig, b_key)); - } - return (cs, (a?, b?)); -} - -;; process message, give state is stateInit -;; -;; stateInit signed_A?:Bool signed_B?:Bool min_A:Grams min_B:Grams expire_at:uint32 A:Grams B:Grams = State; -_ unpack_state_init(slice state) { - return ( - state~load_int(1), - state~load_int(1), - state~load_grams(), - state~load_grams(), - state~load_uint(32), - state~load_grams(), - state~load_grams()); - -} -_ pack_state_init(int signed_A?, int signed_B?, int min_A, int min_B, int expire_at, int A, int B) { - return begin_cell() - .store_int(state:init(), 3) - .store_int(signed_A?, 1) - .store_int(signed_B?, 1) - .store_grams(min_A) - .store_grams(min_B) - .store_uint(expire_at, 32) - .store_grams(A) - .store_grams(B).end_cell(); -} - -;; stateClosing$10 signed_A?:bool signed_B?:Bool promise_A:Grams promise_B:Grams exipire_at:uint32 A:Grams B:Grams = State; -_ unpack_state_close(slice state) { - return ( - state~load_int(1), - state~load_int(1), - state~load_grams(), - state~load_grams(), - state~load_uint(32), - state~load_grams(), - state~load_grams()); -} - -_ pack_state_close(int signed_A?, int signed_B?, int promise_A, int promise_B, int expire_at, int A, int B) { - return begin_cell() - .store_int(state:close(), 3) - .store_int(signed_A?, 1) - .store_int(signed_B?, 1) - .store_grams(promise_A) - .store_grams(promise_B) - .store_uint(expire_at, 32) - .store_grams(A) - .store_grams(B).end_cell(); -} - -_ send_payout(slice s_addr, int amount, int channel_id, int flags) impure { - send_raw_message(begin_cell() - .store_uint(0x10, 6) - .store_slice(s_addr) - .store_grams(amount) - .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) - .store_uint(msg:payout(), 32) - .store_uint(channel_id, 64) - .end_cell(), flags); -} - - -cell do_payout(int promise_A, int promise_B, int A, int B, slice a_addr, slice b_addr, int channel_id) impure { - accept_message(); - - int diff = promise_B - promise_A; - if (diff < - A) { - diff = - A; - } - if (diff > B) { - diff = B; - } - A += diff; - B -= diff; - - send_payout(b_addr, B, channel_id, 3); - send_payout(a_addr, A, channel_id, 3 + 128); - - return begin_cell() - .store_int(state:payout(), 3) - .store_grams(A) - .store_grams(B) - .end_cell(); -} - - -;; -;; init$000 inc_A:Grams inc_B:Grams min_A:Grams min_B:Grams = Message; -;; -cell with_init(slice state, int msg_value, slice msg, int msg_signed_A?, int msg_signed_B?, - slice a_addr, slice b_addr, int init_timeout, int channel_id, int min_A_extra) { - ;; parse state - (int signed_A?, int signed_B?, int min_A, int min_B, int expire_at, int A, int B) = unpack_state_init(state); - - if (expire_at == 0) { - expire_at = now() + init_timeout; - } - - int op = msg~load_uint(32); - if (op == msg:timeout()) { - throw_unless(err:no_timeout(), expire_at < now()); - return do_payout(0, 0, A, B, a_addr, b_addr, channel_id); - } - throw_unless(err:expected_init(), op == msg:init()); - - ;; unpack init message - (int inc_A, int inc_B, int upd_min_A, int upd_min_B, int got_channel_id) = - (msg~load_grams(), msg~load_grams(), msg~load_grams(), msg~load_grams(), msg~load_uint(64)); - throw_unless(err:wrong_channel_id(), got_channel_id == channel_id); - - ;; TODO: we should reserve some part of the value for comission - throw_if(err:msg_value_too_small(), msg_value < inc_A + inc_B); - throw_unless(err:replay_protection(), (msg_signed_A? < signed_A?) | (msg_signed_B? < signed_B?)); - - A += inc_A; - B += inc_B; - - signed_A? |= msg_signed_A?; - if (min_A < upd_min_A) { - min_A = upd_min_A; - } - - signed_B? |= msg_signed_B?; - if (min_B < upd_min_B) { - min_B = upd_min_B; - } - - if (signed_A? & signed_B?) { - A -= min_A_extra; - if ((min_A > A) | (min_B > B)) { - return do_payout(0, 0, A, B, a_addr, b_addr, channel_id); - } - - return pack_state_close(0, 0, 0, 0, 0, A, B); - } - - return pack_state_init(signed_A?, signed_B?, min_A, min_B, expire_at, A, B); -} - -;; close$001 extra_A:Grams extra_B:Grams sig:Maybe promise_A:Grams promise_B:Grams = Message; - -cell with_close(slice cs, slice msg, int msg_signed_A?, int msg_signed_B?, int a_key, int b_key, - slice a_addr, slice b_addr, int expire_timeout, int channel_id) { - ;; parse state - (int signed_A?, int signed_B?, int promise_A, int promise_B, int expire_at, int A, int B) = unpack_state_close(cs); - - if (expire_at == 0) { - expire_at = now() + expire_timeout; - } - - int op = msg~load_uint(32); - if (op == msg:timeout()) { - throw_unless(err:no_timeout(), expire_at < now()); - return do_payout(promise_A, promise_B, A, B, a_addr, b_addr, channel_id); - } - throw_unless(err:expected_close(), op == msg:close()); - - ;; also ensures that (msg_signed_A? | msg_signed_B?) is true - throw_unless(err:replay_protection(), (msg_signed_A? < signed_A?) | (msg_signed_B? < signed_B?)); - signed_A? |= msg_signed_A?; - signed_B? |= msg_signed_B?; - - ;; unpack close message - (int extra_A, int extra_B) = (msg~load_grams(), msg~load_grams()); - int has_sig = msg~load_int(1); - if (has_sig) { - slice sig = msg~load_ref().begin_parse().preload_bits(512); - int hash = msg.slice_hash(); - ifnot (msg_signed_A?) { - throw_unless(err:wrong_a_signature(), check_signature(hash, sig, a_key)); - extra_A = 0; - } - ifnot (msg_signed_B?) { - throw_unless(err:wrong_b_signature(), check_signature(hash, sig, b_key)); - extra_B = 0; - } - } else { - throw_unless(err:no_promise_signature(), msg_signed_A? & msg_signed_B?); - extra_A = 0; - extra_B = 0; - } - (int got_channel_id, int update_promise_A, int update_promise_B) = (msg~load_uint(64), msg~load_grams(), msg~load_grams()); - throw_unless(err:wrong_channel_id(), got_channel_id == channel_id); - - - accept_message(); - update_promise_A += extra_A; - if (promise_A < update_promise_A) { - promise_A = update_promise_A; - } - update_promise_B += extra_B; - if (promise_B < update_promise_B) { - promise_B = update_promise_B; - } - - if (signed_A? & signed_B?) { - return do_payout(promise_A, promise_B, A, B, a_addr, b_addr, channel_id); - } - return pack_state_close(signed_A?, signed_B?, promise_A, promise_B, expire_at, A, B); -} - -() with_payout(slice cs, slice msg, slice a_addr, slice b_addr, int channel_id) impure { - int op = msg~load_uint(32); - throw_unless(err:expected_payout(), op == msg:payout()); - (int A, int B) = (cs~load_grams(), cs~load_grams()); - throw_unless(err:not_enough_fee(), A + B + 1000000000 < get_balance().pair_first()); - accept_message(); - send_payout(b_addr, B, channel_id, 3); - send_payout(a_addr, A, channel_id, 3 + 128); -} - -() recv_any(int msg_value, slice msg) impure { - if (msg.slice_empty?()) { - return(); - } - ;; op is not signed, but we don't need it to be signed. - int op = msg~load_uint(32); - if (op <= 1) { - ;; simple transfer with comment, return - ;; external message will be aborted - ;; internal message will be accepted - return (); - } - throw_unless(err:unknown_op(), op == op:pchan_cmd()); - - (cell config, cell state) = unpack_data(); - (int init_timeout, int close_timeout, int a_key, int b_key, - slice a_addr, slice b_addr, int channel_id, int min_A_extra) = config.unpack_config(); - (int msg_signed_A?, int msg_signed_B?) = msg~unwrap_signatures(a_key, b_key); - - slice cs = state.begin_parse(); - int state_type = cs~load_uint(3); - - if (state_type == state:init()) { ;; init - state = with_init(cs, msg_value, msg, msg_signed_A?, msg_signed_B?, a_addr, b_addr, init_timeout, channel_id, min_A_extra); - } if (state_type == state:close()) { - state = with_close(cs, msg, msg_signed_A?, msg_signed_B?, a_key, b_key, a_addr, b_addr, close_timeout, channel_id); - } if (state_type == state:payout()) { - with_payout(cs, msg, a_addr, b_addr, channel_id); - } - - pack_data(config, state); -} - -() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { - ;; TODO: uncomment when supported in tests - ;; var cs = in_msg_cell.begin_parse(); - ;; var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - ;; if (flags & 1) { - ;; ;; ignore all bounced messages - ;; return (); - ;; } - recv_any(msg_value, in_msg); -} - -() recv_external(slice in_msg) impure { - recv_any(0, in_msg); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif b/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif deleted file mode 100755 index 871b3855..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates the message body to be sent from a validator controlling smart contract (wallet) to recover its share of unfrozen stakes and bonuses." cr - ."The result is saved into (`recover-query.boc` by default) and output in hexadecimal form, to be sent later as the body of a message from the wallet to elections smart contract, along with a small value (say, one Gram) to cover forwarding and processing fees" cr 1 halt -} : usage - -$# dup 0 < swap 1 > or ' usage if -def? $1 { @' $1 } { "recover-query.boc" } cond constant output_fname -now constant query_id -."query_id for stake recovery message is set to " query_id . cr - - -cr ."Message body is " dup B output_fname tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc deleted file mode 100644 index a3168340..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc +++ /dev/null @@ -1,73 +0,0 @@ -;; Restricted wallet (a variant of wallet-code.fc) -;; until configuration parameter -13 is set, accepts messages only to elector smc - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -_ restricted?() inline { - var p = config_param(-13); - return null?(p) ? true : begin_parse(p).preload_uint(32) > now(); -} - -_ check_destination(msg, dest) inline_ref { - var cs = msg.begin_parse(); - var flags = cs~load_uint(4); - if (flags & 8) { - ;; external messages are always valid - return true; - } - var (s_addr, d_addr) = (cs~load_msg_addr(), cs~load_msg_addr()); - var (dest_wc, dest_addr) = parse_std_addr(d_addr); - return (dest_wc == -1) & (dest_addr == dest); -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, public_key) = (ds~load_uint(32), ds~load_uint(256)); - ds.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - ifnot (msg_seqno) { - accept_message(); - set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); - return (); - } - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - var restrict = restricted?(); - var elector = config_param(1).begin_parse().preload_uint(256); - cs~touch(); - while (cs.slice_refs()) { - var mode = cs~load_uint(8); - var msg = cs~load_ref(); - var ok = true; - if (restrict) { - ok = check_destination(msg, elector); - } - if (ok) { - send_raw_message(msg, mode); - } - } - cs.end_parse(); - set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(32); - return cs.preload_uint(256); -} - -int balance() method_id { - return restricted?() ? 0 : get_balance().pair_first(); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc deleted file mode 100644 index fbad6c09..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc +++ /dev/null @@ -1,88 +0,0 @@ -;; Restricted wallet (a variant of wallet-code.fc) -;; restricts access to parts of balance until certain dates - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -_ seconds_passed(int start_at, int utime) inline_ref { - ifnot (start_at) { - var p = config_param(-13); - start_at = null?(p) ? 0 : begin_parse(p).preload_uint(32); - } - return start_at ? utime - start_at : -1; -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, public_key, start_at, rdict) = (ds~load_uint(32), ds~load_uint(256), ds~load_uint(32), ds~load_dict()); - ds.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - ifnot (msg_seqno) { - accept_message(); - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(public_key, 256) - .store_uint(start_at, 32) - .store_dict(rdict) - .end_cell()); - return (); - } - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - var ts = seconds_passed(start_at, now()); - var (_, value, found) = rdict.idict_get_preveq?(32, ts); - if (found) { - raw_reserve(value~load_grams(), 2); - } - cs~touch(); - while (cs.slice_refs()) { - var mode = cs~load_uint(8); - var msg = cs~load_ref(); - send_raw_message(msg, mode); - } - cs.end_parse(); - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(public_key, 256) - .store_uint(start_at, 32) - .store_dict(rdict) - .end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(32); - return cs.preload_uint(256); -} - -int compute_balance_at(int utime) inline_ref { - var ds = get_data().begin_parse().skip_bits(32 + 256); - var (start_at, rdict) = (ds~load_uint(32), ds~load_dict()); - ds.end_parse(); - var ts = seconds_passed(start_at, utime); - var balance = get_balance().pair_first(); - var (_, value, found) = rdict.idict_get_preveq?(32, ts); - if (found) { - balance = max(balance - value~load_grams(), 0); - } - return balance; -} - -int balance_at(int utime) method_id { - return compute_balance_at(utime); -} - -int balance() method_id { - return compute_balance_at(now()); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet3-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet3-code.fc deleted file mode 100644 index aab86065..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet3-code.fc +++ /dev/null @@ -1,103 +0,0 @@ -;; Restricted wallet initialized by a third party (a variant of restricted-wallet2-code.fc) -;; restricts access to parts of balance until certain dates - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -_ seconds_passed(int start_at, int utime) inline_ref { - ifnot (start_at) { - var p = config_param(-13); - start_at = null?(p) ? 0 : begin_parse(p).preload_uint(32); - } - return start_at ? utime - start_at : -1; -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256)); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, subwallet_id == stored_subwallet); - throw_unless(36, check_signature(slice_hash(in_msg), signature, public_key)); - ifnot (msg_seqno) { - public_key = ds~load_uint(256); ;; load "final" public key - ds.end_parse(); - cs~touch(); - var (start_at, rdict) = (cs~load_uint(32), cs~load_dict()); - cs.end_parse(); - accept_message(); - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(stored_subwallet, 32) - .store_uint(public_key, 256) - .store_uint(start_at, 32) - .store_dict(rdict) - .end_cell()); - return (); - } - var (start_at, rdict) = (ds~load_uint(32), ds~load_dict()); - ds.end_parse(); - accept_message(); - var ts = seconds_passed(start_at, now()); - var (_, value, found) = rdict.idict_get_preveq?(32, ts); - if (found) { - raw_reserve(value~load_grams(), 2); - } - cs~touch(); - while (cs.slice_refs()) { - var mode = cs~load_uint(8); - var msg = cs~load_ref(); - send_raw_message(msg, mode); - } - cs.end_parse(); - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(stored_subwallet, 32) - .store_uint(public_key, 256) - .store_uint(start_at, 32) - .store_dict(rdict) - .end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int wallet_id() method_id { - var ds = get_data().begin_parse(); - ds~load_uint(32); - return ds.preload_uint(32); -} - -int get_public_key() method_id { - var ds = get_data().begin_parse(); - ds~load_uint(32 + 32); - return ds.preload_uint(256); -} - -int compute_balance_at(int utime) inline_ref { - var ds = get_data().begin_parse().skip_bits(32 + 32 + 256); - var (start_at, rdict) = (ds~load_uint(32), ds~load_dict()); - ds.end_parse(); - var ts = seconds_passed(start_at, utime); - var balance = get_balance().pair_first(); - var (_, value, found) = rdict.idict_get_preveq?(32, ts); - if (found) { - balance = max(balance - value~load_grams(), 0); - } - return balance; -} - -int balance_at(int utime) method_id { - return compute_balance_at(utime); -} - -int balance() method_id { - return compute_balance_at(now()); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif b/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif deleted file mode 100755 index c421a879..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " $0 type ." " cr - ."Shows the address of a simple wallet created by new-wallet.fif, with address in .addr " - ."and private key in file .pk" cr 1 halt -} : usage -$# 1 > ' usage if -1 :$1..n -$1 "new-wallet" replace-if-null =: file-base - -file-base +".addr" dup ."Loading wallet address from " type cr file>B 32 B| -dup Blen { 32 B>i@ } { drop Basechain } cond constant wallet_wc -256 B>u@ dup constant wallet_addr -."Source wallet address = " wallet_wc swap 2dup .addr cr -."Non-bounceable address (for init only): " 2dup 7 .Addr cr -."Bounceable address (for later access): " 6 .Addr cr - -file-base +".pk" dup file-exists? { - dup file>B dup Blen 32 <> abort"Private key must be exactly 32 bytes long" - tuck =: wallet_pk ."Private key available in file " type cr - priv>pub 256 B>u@ - dup ."Corresponding public key is " .pubkey ." = " 64X. cr -} { ."Private key file " type ." not found" cr } cond diff --git a/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-code.fc deleted file mode 100644 index a43b8b92..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-code.fc +++ /dev/null @@ -1,25 +0,0 @@ -;; Simple wallet smart contract - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - int msg_seqno = cs~load_uint(32); - var cs2 = begin_parse(get_data()); - var stored_seqno = cs2~load_uint(32); - var public_key = cs2~load_uint(256); - cs2.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - cs~touch(); - if (cs.slice_refs()) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - cs.end_parse(); - set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc deleted file mode 100644 index fb43e833..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc +++ /dev/null @@ -1,68 +0,0 @@ -;; Simple wallet smart contract - -cell create_state(int seqno, int public_key) { - return begin_cell().store_uint(seqno, 32).store_uint(public_key, 256).end_cell(); -} - -(int, int) load_state() { - var cs2 = begin_parse(get_data()); - return (cs2~load_uint(32), cs2~load_uint(256)); -} - -() save_state(int seqno, int public_key) impure { - set_data(create_state(seqno, public_key)); -} - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -slice do_verify_message(slice in_msg, int seqno, int public_key) { - var signature = in_msg~load_bits(512); - var cs = in_msg; - int msg_seqno = cs~load_uint(32); - throw_unless(33, msg_seqno == seqno); - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - return cs; -} - -() recv_external(slice in_msg) impure { - (int stored_seqno, int public_key) = load_state(); - var cs = do_verify_message(in_msg, stored_seqno, public_key); - accept_message(); - cs~touch(); - if (cs.slice_refs()) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - cs.end_parse(); - save_state(stored_seqno + 1, public_key); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var (seqno, public_key) = load_state(); - return public_key; -} - -cell create_init_state(int public_key) method_id { - return create_state(0, public_key); -} - -cell prepare_send_message_with_seqno(int mode, cell msg, int seqno) method_id { - return begin_cell().store_uint(seqno, 32).store_uint(mode, 8).store_ref(msg).end_cell(); -} - -cell prepare_send_message(int mode, cell msg) method_id { - return prepare_send_message_with_seqno(mode, msg, seqno()); -} - -slice verify_message(slice msg) method_id { - var (stored_seqno, public_key) = load_state(); - return do_verify_message(msg, stored_seqno, public_key); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc b/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc deleted file mode 100644 index 0b98eeb4..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc +++ /dev/null @@ -1,208 +0,0 @@ -;; Standard library for funC -;; - -forall X -> tuple cons(X head, tuple tail) asm "CONS"; -forall X -> (X, tuple) uncons(tuple list) asm "UNCONS"; -forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS"; -forall X -> X car(tuple list) asm "CAR"; -tuple cdr(tuple list) asm "CDR"; -tuple empty_tuple() asm "NIL"; -forall X -> tuple tpush(tuple t, X value) asm "TPUSH"; -forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH"; -forall X -> [X] single(X x) asm "SINGLE"; -forall X -> X unsingle([X] t) asm "UNSINGLE"; -forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR"; -forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR"; -forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE"; -forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE"; -forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE"; -forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE"; -forall X -> X first(tuple t) asm "FIRST"; -forall X -> X second(tuple t) asm "SECOND"; -forall X -> X third(tuple t) asm "THIRD"; -forall X -> X fourth(tuple t) asm "3 INDEX"; -forall X, Y -> X pair_first([X, Y] p) asm "FIRST"; -forall X, Y -> Y pair_second([X, Y] p) asm "SECOND"; -forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST"; -forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND"; -forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD"; -forall X -> X null() asm "PUSHNULL"; -forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP"; - -int now() asm "NOW"; -slice my_address() asm "MYADDR"; -[int, cell] get_balance() asm "BALANCE"; -int cur_lt() asm "LTIME"; -int block_lt() asm "BLOCKLT"; - -int cell_hash(cell c) asm "HASHCU"; -int slice_hash(slice s) asm "HASHSU"; -int string_hash(slice s) asm "SHA256U"; - -int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU"; -int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS"; - -(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE"; -(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE"; -(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT"; -(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT"; - -;; () throw_if(int excno, int cond) impure asm "THROWARGIF"; - -() dump_stack() impure asm "DUMPSTK"; - -cell get_data() asm "c4 PUSH"; -() set_data(cell c) impure asm "c4 POP"; -cont get_c3() impure asm "c3 PUSH"; -() set_c3(cont c) impure asm "c3 POP"; -cont bless(slice s) impure asm "BLESS"; - -() accept_message() impure asm "ACCEPT"; -() set_gas_limit(int limit) impure asm "SETGASLIMIT"; -() commit() impure asm "COMMIT"; -() buy_gas(int gram) impure asm "BUYGAS"; - -int min(int x, int y) asm "MIN"; -int max(int x, int y) asm "MAX"; -(int, int) minmax(int x, int y) asm "MINMAX"; -int abs(int x) asm "ABS"; - -slice begin_parse(cell c) asm "CTOS"; -() end_parse(slice s) impure asm "ENDS"; -(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF"; -cell preload_ref(slice s) asm "PLDREF"; -;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX"; -;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX"; -;; int preload_int(slice s, int len) asm "PLDIX"; -;; int preload_uint(slice s, int len) asm "PLDUX"; -;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX"; -;; slice preload_bits(slice s, int len) asm "PLDSLICEX"; -(slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS"; -slice skip_bits(slice s, int len) asm "SDSKIPFIRST"; -(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST"; -slice first_bits(slice s, int len) asm "SDCUTFIRST"; -slice skip_last_bits(slice s, int len) asm "SDSKIPLAST"; -(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST"; -slice slice_last(slice s, int len) asm "SDCUTLAST"; -(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT"; -cell preload_dict(slice s) asm "PLDDICT"; -slice skip_dict(slice s) asm "SKIPDICT"; - -(slice, cell) load_maybe_ref(slice s) asm( -> 1 0) "LDOPTREF"; -cell preload_maybe_ref(slice s) asm "PLDOPTREF"; -builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF"; - -int cell_depth(cell c) asm "CDEPTH"; - -int slice_refs(slice s) asm "SREFS"; -int slice_bits(slice s) asm "SBITS"; -(int, int) slice_bits_refs(slice s) asm "SBITREFS"; -int slice_empty?(slice s) asm "SEMPTY"; -int slice_data_empty?(slice s) asm "SDEMPTY"; -int slice_refs_empty?(slice s) asm "SREMPTY"; -int slice_depth(slice s) asm "SDEPTH"; - -int builder_refs(builder b) asm "BREFS"; -int builder_bits(builder b) asm "BBITS"; -int builder_depth(builder b) asm "BDEPTH"; - -builder begin_cell() asm "NEWC"; -cell end_cell(builder b) asm "ENDC"; -builder store_ref(builder b, cell c) asm(c b) "STREF"; -;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX"; -;; builder store_int(builder b, int x, int len) asm(x b len) "STIX"; -builder store_slice(builder b, slice s) asm "STSLICER"; -builder store_grams(builder b, int x) asm "STGRAMS"; -builder store_dict(builder b, cell c) asm(c b) "STDICT"; - -(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR"; -tuple parse_addr(slice s) asm "PARSEMSGADDR"; -(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR"; -(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR"; - -cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; -cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF"; -(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF"; -cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF"; -(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF"; -(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF"; -(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF"; -(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF"; -(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL"; -(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL"; -(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT"; -(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT"; -(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT"; -(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT"; -(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT"; -(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT"; -cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET"; -(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET"; -cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET"; -(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET"; -cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET"; -(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET"; -(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD"; -(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE"; -(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD"; -(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE"; -cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB"; -(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB"; -cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB"; -(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB"; -cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB"; -(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB"; -(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB"; -(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB"; -(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB"; -(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB"; -(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2"; -(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2"; -(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2"; -(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2"; -(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2"; -(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2"; -(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2"; -(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2"; -(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2"; -(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2"; -(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2"; -(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2"; -(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2"; -(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2"; -(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2"; -(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2"; -(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2"; -(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2"; -cell new_dict() asm "NEWDICT"; -int dict_empty?(cell c) asm "DICTEMPTY"; - -(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2"; -(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET"; -(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL"; - -cell config_param(int x) asm "CONFIGOPTPARAM"; -int cell_null?(cell c) asm "ISNULL"; - -() raw_reserve(int amount, int mode) impure asm "RAWRESERVE"; -() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX"; -() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG"; -() set_code(cell new_code) impure asm "SETCODE"; - -int random() impure asm "RANDU256"; -int rand(int range) impure asm "RAND"; -int get_seed() impure asm "RANDSEED"; -int set_seed() impure asm "SETRAND"; -() randomize(int x) impure asm "ADDRAND"; -() randomize_lt() impure asm "LTIME" "ADDRAND"; diff --git a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif b/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif deleted file mode 100755 index c48735ac..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a request to TestGiver and saves it into .boc" cr - ."('testgiver-query.boc' by default)" cr 1 halt -} : usage - -$# 3 - -2 and ' usage if - -// "testgiver.addr" load-address -Masterchain 0xfcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 -2constant giver_addr - ."Test giver address = " giver_addr 2dup .addr cr 6 .Addr cr - -$1 true parse-load-address =: bounce 2=: dest_addr -$2 parse-int =: seqno -$3 $>GR =: amount -def? $4 { @' $4 } { "testgiver-query" } cond constant savefile - -."Requesting " amount .GR ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."seqno=0x" seqno x. ."bounce=" bounce . cr - -// create a message (NB: 01b00.., b = bounce) - - -dup ."enveloping message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif deleted file mode 100755 index 39243632..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " $0 type ." []" cr - ."Creates a request to simple configuration smart contract requesting to change configuration smart contract code to the one currently stored in auto/config-code.fif, " - ."with private key loaded from file .pk, " - ."and saves it into .boc ('config-query.boc' by default)" cr 1 halt -} : usage -$# dup 2 < swap 3 > or ' usage if - -"config-master" constant file-base -0 constant qseqno --1 constant idx -true constant bounce -"auto/config-code.fif" constant config-source -100 constant interval // valid for 100 seconds - -3 :$1..n -$1 =: file-base -$2 parse-int =: qseqno -$3 "config-query" replace-if-null constant savefile - -file-base +".addr" load-address -2dup 2constant config_addr -."Configuration smart contract address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant config_pk - -."Loading new configuration smart contract code from file " config-source type cr -"Asm.fif" include -config-source include -dup -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif deleted file mode 100755 index ed13271f..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a request to simple configuration smart contract created by mc0.fif requesting to change configuration parameter to , " - ."with private key loaded from file .pk, " - ."and saves it into .boc ('config-query.boc' by default)" cr 1 halt -} : usage -$# dup 4 < swap 5 > or ' usage if - -"config-master" constant file-base -0 constant seqno --1 constant idx -true constant bounce -"new-value.boc" constant boc-filename -100 constant interval // valid for 100 seconds - -$1 =: file-base -$2 parse-int =: seqno -$3 parse-int =: idx -$4 =: boc-filename -def? $5 { @' $5 } { "config-query" } cond constant savefile - -file-base +".addr" load-address -2dup 2constant config_addr -."Configuration smart contract address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant config_pk - -."Loading new value of configuration parameter " idx . ."from file " boc-filename type cr -boc-filename file>B B>boc -dup -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif deleted file mode 100755 index b9ce501f..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a request to simple configuration smart contract requesting to change elector smart contract code to the one currently stored in auto/elector-code.fif, " - ."with private key loaded from file .pk, " - ."and saves it into .boc ('config-query.boc' by default)" cr 1 halt -} : usage -$# dup 2 < swap 3 > or ' usage if - -"config-master" constant file-base -0 constant seqno --1 constant idx -true constant bounce -"auto/elector-code.fif" constant elector-source -100 constant interval // valid for 100 seconds - -$1 =: file-base -$2 parse-int =: seqno -def? $3 { @' $3 } { "config-query" } cond constant savefile - -file-base +".addr" load-address -2dup 2constant config_addr -."Configuration smart contract address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant config_pk - -."Loading new elector smart contract code from file " elector-source type cr -"Asm.fif" include -elector-source include -dup -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif deleted file mode 100755 index a220b421..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a request to participate in validator elections starting at on behalf of smart-contract with address (prefix with '@' to load address from file) and hexadecimal adnl address (empty string or '0' for none)." cr - ."The result is saved into and output in hexadecimal form, to be signed later by the validator public key" cr 1 halt -} : usage - -$# dup 3 < swap 5 > or ' usage if -$1 true parse-load-address drop swap 1+ abort"only masterchain smartcontracts may participate in validator elections" -constant src_addr -$2 (number) 1 <> { 0 } if dup 0<= abort" must be a positive integer" -constant elect_time -$3 (number) dup 0= abort" must be a real number 1..100" -1 = { 16 << } { 16 < or abort" must be a real number 1..100" -constant max_factor -def? $4 { @' $4 dup $len 1 > { parse-adnl-address } { drop 0 } cond } ' 0 cond -constant adnl_addr -def? $5 { @' $5 } { "validator-to-sign.bin" } cond constant output_fname - -."Creating a request to participate in validator elections at time " elect_time . -."from smart contract " -1 src_addr 2dup 1 .Addr ." = " .addr -." with maximal stake factor with respect to the minimal stake " max_factor ._ -."/65536 and validator ADNL address " adnl_addr 64x. cr - -B{654c5074} elect_time 32 u>B B+ max_factor 32 u>B B+ src_addr 256 u>B B+ adnl_addr 256 u>B B+ -dup Bx. cr -dup B>base64url type cr -output_fname tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif deleted file mode 100755 index 4e681f07..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include - -{ ."usage: " @' $0 type ." []" cr - ."Creates a message body for participating in validator elections starting at on behalf of smart-contract with address (prefix with '@' to load address from file) and hexadecimal adnl address (empty string or '0' for none)." cr - ." is the main public key of the future validator (as a Base64 string), and is the signature of the previously created validator request by that key (also Base64)" cr - ."The result is saved into (`validator-query.boc` by default) and output in hexadecimal form, to be sent later as the body of a message from to elections smart contract, along with the desired stake" cr 1 halt -} : usage - -$# dup 6 < swap 7 > or ' usage if -$1 true parse-load-address drop swap 1+ abort"only masterchain smartcontracts may participate in validator elections" -constant src_addr -$2 (number) 1 <> { 0 } if dup 0<= abort" must be a positive integer" -constant elect_time -$3 (number) dup 0= abort" must be a real number 1..100" -1 = { 16 << } { 16 < or abort" must be a real number 1..100" -constant max_factor -$4 dup $len 1 > { parse-adnl-address } { drop 0 } cond constant adnl_addr -$5 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long" - 32 B>u@+ 0xC6B41348 <> abort"invalid Ed25519 public key: unknown magic number" - constant pubkey -$6 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long" -constant signature -def? $7 { @' $7 } { "validator-query.boc" } cond constant output_fname - -."Creating a request to participate in validator elections at time " elect_time . -."from smart contract " -1 src_addr 2dup 1 .Addr ." = " .addr -." with maximal stake factor with respect to the minimal stake " max_factor ._ -."/65536 and validator ADNL address " adnl_addr 64x. cr - -B{654c5074} elect_time 32 u>B B+ max_factor 32 u>B B+ src_addr 256 u>B B+ adnl_addr 256 u>B B+ -."String to sign is: " dup Bx. cr constant to_sign - -to_sign signature pubkey ed25519_chksign not abort"Ed25519 signature is invalid" -."Provided a valid Ed25519 signature " signature Bx. ." with validator public key " pubkey Bx. cr -now dup constant query_id ."query_id set to " . cr - - ref, b> -cr ."Message body is " dup B output_fname tuck B>file ."Saved to file " type cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/wallet-code.fc deleted file mode 100644 index 9d4cddb7..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet-code.fc +++ /dev/null @@ -1,37 +0,0 @@ -;; Simple wallet smart contract - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, public_key) = (ds~load_uint(32), ds~load_uint(256)); - ds.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - cs~touch(); - while (cs.slice_refs()) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - cs.end_parse(); - set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(32); - return cs.preload_uint(256); -} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif deleted file mode 100755 index fd5f6ae7..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -"" =: comment // comment for simple transfers -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 =: timeout // external message expires in 60 seconds -variable extra-currencies -{ extra-currencies @ cc+ extra-currencies ! } : extra-cc+! - -begin-options - " [-x *] [-n|-b] [-t] [-B ] [-C ] []" +cr +tab - +"Creates a request to advanced wallet created by new-wallet-v2.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "x" "--extra" { $>xcc extra-cc+! } short-long-option-arg - "Indicates the amount of extra currencies to be transfered" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "B" "--body" { =: body-boc-file } short-long-option-arg - "Sets the payload of the transfer message" option-help - "C" "--comment" { =: comment } short-long-option-arg - "Sets the comment to be sent in the transfer message" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 4 < swap 5 > or ' usage if -5 :$1..n -true constant bounce -$1 =: file-base -$2 bounce parse-load-address force-bounce or allow-bounce and =: bounce 2=: dest_addr -$3 parse-int =: seqno -$4 $>cc extra-cc+! extra-currencies @ 2=: amount -$5 "wallet-query" replace-if-null =: savefile - -file-base +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond -constant body-cell - -."Transferring " amount .GR+cc ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."seqno=0x" seqno x. ."bounce=" bounce . cr -."Body of transfer message is " body-cell - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."Query expires in " timeout . ."seconds" cr -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v3.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet-v3.fif deleted file mode 100644 index a81ffb05..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v3.fif +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -"" =: comment // comment for simple transfers -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -60 =: timeout // external message expires in 60 seconds -variable extra-currencies -{ extra-currencies @ cc+ extra-currencies ! } : extra-cc+! - -begin-options - " [-x *] [-n|-b] [-t] [-B ] [-C ] []" +cr +tab - +"Creates a request to advanced wallet created by new-wallet-v3.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "x" "--extra" { $>xcc extra-cc+! } short-long-option-arg - "Indicates the amount of extra currencies to be transfered" option-help - "t" "--timeout" { parse-int =: timeout } short-long-option-arg - "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help - "B" "--body" { =: body-boc-file } short-long-option-arg - "Sets the payload of the transfer message" option-help - "C" "--comment" { =: comment } short-long-option-arg - "Sets the comment to be sent in the transfer message" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 5 < swap 6 > or ' usage if -6 :$1..n - -true constant bounce -$1 =: file-base -$2 bounce parse-load-address force-bounce or allow-bounce and =: bounce 2=: dest_addr -$3 parse-int =: subwallet_id -$4 parse-int =: seqno -$5 $>cc extra-cc+! extra-currencies @ 2=: amount -$6 "wallet-query" replace-if-null =: savefile - -file-base +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond -constant body-cell - -."Transferring " amount .GR+cc ."to account " -dest_addr 2dup bounce 7 + .Addr ." = " .addr -."subwallet_id=0x" subwallet_id x. -."seqno=0x" seqno x. ."bounce=" bounce . cr -."Body of transfer message is " body-cell - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."Query expires in " timeout . ."seconds" cr -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif deleted file mode 100755 index 5fc9141d..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/fift -s -"TonUtil.fif" include -"GetOpt.fif" include - -{ show-options-help 1 halt } : usage - -"" =: comment // comment for simple transfers -true =: allow-bounce -false =: force-bounce -3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors -variable extra-currencies -{ extra-currencies @ cc+ extra-currencies ! } : extra-cc+! - -begin-options - " [-x *] [-n|-b] [-B ] [-C ] []" +cr +tab - +"Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file .pk " - +"and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" - disable-digit-options generic-help-setopt - "n" "--no-bounce" { false =: allow-bounce } short-long-option - "Clears bounce flag" option-help - "b" "--force-bounce" { true =: force-bounce } short-long-option - "Forces bounce flag" option-help - "x" "--extra" { $>xcc extra-cc+! } short-long-option-arg - "Indicates the amount of extra currencies to be transfered" option-help - "B" "--body" { =: body-boc-file } short-long-option-arg - "Sets the payload of the transfer message" option-help - "C" "--comment" { =: comment } short-long-option-arg - "Sets the comment to be sent in the transfer message" option-help - "I" "--with-init" { =: init-file } short-long-option-arg - "Indicates filename with BoC containing StateInit for internal message" option-help - "m" "--mode" { parse-int =: send-mode } short-long-option-arg - "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)" - option-help - "h" "--help" { usage } short-long-option - "Shows a help message" option-help -parse-options - -$# dup 4 < swap 5 > or ' usage if -5 :$1..n -true =: bounce -$1 =: file-base -$2 bounce parse-load-address allow-bounce and force-bounce or =: bounce 2=: dest_addr -$3 parse-int =: seqno -$4 $>cc extra-cc+! extra-currencies @ 2=: amount -$5 "wallet-query" replace-if-null =: savefile -allow-bounce not force-bounce and abort"cannot have bounce flag both set and cleared" -// "" 1 { 69091 * 1+ 65535 and tuck 2521 / 65 + hold swap } 1000 times drop =: comment - -file-base +".addr" load-address -2dup 2constant wallet_addr -."Source wallet address = " 2dup .addr cr 6 .Addr cr -file-base +".pk" load-keypair nip constant wallet_pk - -def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond -constant body-cell - -def? init-file { @' init-file file>B B>boc - -dup ."signing message: " -dup ."resulting external message: " B dup Bx. cr -savefile +".boc" tuck B>file -."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet3-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/wallet3-code.fc deleted file mode 100644 index 964b35cd..00000000 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet3-code.fc +++ /dev/null @@ -1,41 +0,0 @@ -;; Simple wallet smart contract - -() recv_internal(slice in_msg) impure { - ;; do nothing for internal messages -} - -() recv_external(slice in_msg) impure { - var signature = in_msg~load_bits(512); - var cs = in_msg; - var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); - throw_if(35, valid_until <= now()); - var ds = get_data().begin_parse(); - var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256)); - ds.end_parse(); - throw_unless(33, msg_seqno == stored_seqno); - throw_unless(34, subwallet_id == stored_subwallet); - throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key)); - accept_message(); - cs~touch(); - while (cs.slice_refs()) { - var mode = cs~load_uint(8); - send_raw_message(cs~load_ref(), mode); - } - set_data(begin_cell() - .store_uint(stored_seqno + 1, 32) - .store_uint(stored_subwallet, 32) - .store_uint(public_key, 256) - .end_cell()); -} - -;; Get methods - -int seqno() method_id { - return get_data().begin_parse().preload_uint(32); -} - -int get_public_key() method_id { - var cs = get_data().begin_parse(); - cs~load_uint(64); - return cs.preload_uint(256); -} diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp deleted file mode 100644 index 91b2edf7..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "GenericAccount.h" - -#include "block/block-auto.h" -#include "block/block-parse.h" -namespace ton { - -namespace smc { -td::Ref pack_grams(td::uint64 amount) { - vm::CellBuilder cb; - block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(amount)); - return vm::load_cell_slice_ref(cb.finalize()); -} - -bool unpack_grams(td::Ref cs, td::uint64& amount) { - td::RefInt256 got; - if (!block::tlb::t_Grams.as_integer_to(cs, got)) { - return false; - } - if (!got->unsigned_fits_bits(63)) { - return false; - } - auto x = got->to_long(); - if (x < 0) { - return false; - } - amount = x; - return true; -} -} // namespace smc - -td::Ref GenericAccount::get_init_state(td::Ref code, td::Ref data) noexcept { - return vm::CellBuilder() - .store_zeroes(2) - .store_ones(2) - .store_zeroes(1) - .store_ref(std::move(code)) - .store_ref(std::move(data)) - .finalize(); -} -block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id, - const td::Ref& init_state) noexcept { - return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/); -} - -void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms) { - td::BigInt256 dest_addr; - dest_addr.import_bits(dest_address.addr.as_bitslice()); - cb.store_zeroes(1) - .store_ones(1) - .store_long(dest_address.bounceable, 1) - .store_zeroes(3) - .store_ones(1) - .store_zeroes(2) - .store_long(dest_address.workchain, 8) - .store_int256(dest_addr, 256); - block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms)); - cb.store_zeroes(9 + 64 + 32); -} - -td::Ref GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref new_state, - td::Ref body) noexcept { - block::gen::Message::Record message; - /*info*/ { - block::gen::CommonMsgInfo::Record_ext_in_msg_info info; - /* src */ - tlb::csr_pack(info.src, block::gen::MsgAddressExt::Record_addr_none{}); - /* dest */ { - block::gen::MsgAddressInt::Record_addr_std dest; - dest.anycast = vm::CellBuilder().store_zeroes(1).as_cellslice_ref(); - dest.workchain_id = address.workchain; - dest.address = address.addr; - - tlb::csr_pack(info.dest, dest); - } - /* import_fee */ { - vm::CellBuilder cb; - block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(0)); - info.import_fee = cb.as_cellslice_ref(); - } - - tlb::csr_pack(message.info, info); - } - /* init */ { - if (new_state.not_null()) { - // Just(Left(new_state)) - message.init = vm::CellBuilder() - .store_ones(1) - .store_zeroes(1) - .append_cellslice(vm::load_cell_slice(new_state)) - .as_cellslice_ref(); - } else { - message.init = vm::CellBuilder().store_zeroes(1).as_cellslice_ref(); - CHECK(message.init.not_null()); - } - } - /* body */ { - message.body = vm::CellBuilder().store_zeroes(1).append_cellslice(vm::load_cell_slice_ref(body)).as_cellslice_ref(); - } - - td::Ref res; - tlb::type_pack_cell(res, block::gen::t_Message_Any, message); - CHECK(res.not_null()); - - return res; -} -td::Result GenericAccount::get_public_key(const SmartContract& sc) { - auto answer = sc.run_get_method("get_public_key"); - if (!answer.success) { - return td::Status::Error("get_public_key failed"); - } - auto do_get_public_key = [&]() -> td::Result { - auto key = answer.stack.write().pop_int_finite(); - td::SecureString bytes(32); - if (!key->export_bytes(bytes.as_mutable_slice().ubegin(), bytes.size(), false)) { - return td::Status::Error("get_public_key failed"); - } - return td::Ed25519::PublicKey(std::move(bytes)); - }; - return TRY_VM(do_get_public_key()); -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h deleted file mode 100644 index 6100b6dd..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells.h" -#include "block/block.h" -#include "Ed25519.h" -#include "SmartContract.h" - -namespace ton { -namespace smc { -td::Ref pack_grams(td::uint64 amount); -bool unpack_grams(td::Ref cs, td::uint64& amount); -} // namespace smc -class GenericAccount { - public: - static td::Ref get_init_state(td::Ref code, td::Ref data) noexcept; - static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref& init_state) noexcept; - static td::Ref create_ext_message(const block::StdAddress& address, td::Ref new_state, - td::Ref body) noexcept; - static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms); - - static td::Result get_public_key(const SmartContract& sc); -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.cpp deleted file mode 100644 index 7996d095..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "HighloadWallet.h" -#include "GenericAccount.h" -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include "vm/cells/CellString.h" -#include "td/utils/base64.h" - -#include - -namespace ton { -td::optional HighloadWallet::guess_revision(const vm::Cell::Hash& code_hash) { - for (td::int32 i = 1; i <= 2; i++) { - if (get_init_code(i)->get_hash() == code_hash) { - return i; - } - } - return {}; -} -td::optional HighloadWallet::guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) { - for (td::int32 i = 1; i <= 2; i++) { - if (GenericAccount::get_address(address.workchain, get_init_state(public_key, wallet_id, i)) == address) { - return i; - } - } - return {}; -} -td::Ref HighloadWallet::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision) noexcept { - auto code = get_init_code(revision); - auto data = get_init_data(public_key, wallet_id); - return GenericAccount::get_init_state(std::move(code), std::move(data)); -} - -td::Ref HighloadWallet::get_init_message(const td::Ed25519::PrivateKey& private_key, - td::uint32 wallet_id) noexcept { - td::uint32 seqno = 0; - td::uint32 valid_until = std::numeric_limits::max(); - auto append_message = [&](auto&& cb) -> vm::CellBuilder& { - cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_long(seqno, 32); - CHECK(cb.store_maybe_ref({})); - return cb; - }; - auto signature = private_key.sign(append_message(vm::CellBuilder()).finalize()->get_hash().as_slice()).move_as_ok(); - - return append_message(vm::CellBuilder().store_bytes(signature)).finalize(); -} - -td::Ref HighloadWallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 seqno, td::uint32 valid_until, - td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - vm::Dictionary messages(16); - for (size_t i = 0; i < gifts.size(); i++) { - auto& gift = gifts[i]; - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - auto message_inner = create_int_message(gift); - vm::CellBuilder cb; - cb.store_long(send_mode, 8).store_ref(message_inner); - auto key = messages.integer_key(td::make_refint(i), 16, false); - messages.set_builder(key.bits(), 16, cb); - } - - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_long(seqno, 32); - CHECK(cb.store_maybe_ref(messages.get_root_cell())); - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); -} - -td::Ref HighloadWallet::get_init_code(td::int32 revision) noexcept { - return SmartContractCode::get_code(SmartContractCode::HighloadWalletV1, revision); -} - -vm::CellHash HighloadWallet::get_init_code_hash() noexcept { - return get_init_code(0)->get_hash(); -} - -td::Ref HighloadWallet::get_init_data(const td::Ed25519::PublicKey& public_key, - td::uint32 wallet_id) noexcept { - return vm::CellBuilder() - .store_long(0, 32) - .store_long(wallet_id, 32) - .store_bytes(public_key.as_octet_string()) - .finalize(); -} - -td::Result HighloadWallet::get_seqno() const { - return TRY_VM(get_seqno_or_throw()); -} - -td::Result HighloadWallet::get_seqno_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); -} - -td::Result HighloadWallet::get_wallet_id() const { - return TRY_VM(get_wallet_id_or_throw()); -} - -td::Result HighloadWallet::get_wallet_id_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(32); - return static_cast(cs.fetch_ulong(32)); -} - -td::Result HighloadWallet::get_public_key() const { - return TRY_VM(get_public_key_or_throw()); -} - -td::Result HighloadWallet::get_public_key_or_throw() const { - if (state_.data.is_null()) { - return td::Status::Error("data is null"); - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(64); - td::SecureString res(td::Ed25519::PublicKey::LENGTH); - cs.fetch_bytes(res.as_mutable_slice().ubegin(), td::narrow_cast(res.size())); - return td::Ed25519::PublicKey(std::move(res)); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.h deleted file mode 100644 index ce37af49..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWallet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "vm/cells.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -namespace ton { -class HighloadWallet : public ton::SmartContract, public WalletInterface { - public: - explicit HighloadWallet(State state) : ton::SmartContract(std::move(state)) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 254; - static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision) noexcept; - static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id) noexcept; - static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 seqno, td::uint32 valid_until, td::Span gifts) noexcept; - - static td::Ref get_init_code(td::int32 revision) noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept; - static td::optional guess_revision(const vm::Cell::Hash& code_hash); - static td::optional guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); - td::Result get_seqno() const; - td::Result get_wallet_id() const; - - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(seqno, get_seqno()); - TRY_RESULT(wallet_id, get_wallet_id()); - return make_a_gift_message(private_key, wallet_id, seqno, valid_until, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - td::Result get_public_key() const override; - - private: - td::Result get_seqno_or_throw() const; - td::Result get_wallet_id_or_throw() const; - td::Result get_public_key_or_throw() const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.cpp deleted file mode 100644 index bae249b4..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "HighloadWalletV2.h" -#include "GenericAccount.h" -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include "vm/cells/CellString.h" -#include "td/utils/base64.h" - -#include - -namespace ton { -td::optional HighloadWalletV2::guess_revision(const vm::Cell::Hash& code_hash) { - for (td::int32 i = 1; i <= 2; i++) { - if (get_init_code(i)->get_hash() == code_hash) { - return i; - } - } - return {}; -} -td::optional HighloadWalletV2::guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, - td::uint32 wallet_id) { - for (td::int32 i = 1; i <= 2; i++) { - if (GenericAccount::get_address(address.workchain, get_init_state(public_key, wallet_id, i)) == address) { - return i; - } - } - return {}; -} -td::Ref HighloadWalletV2::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision) noexcept { - auto code = get_init_code(revision); - auto data = get_init_data(public_key, wallet_id); - return GenericAccount::get_init_state(std::move(code), std::move(data)); -} - -td::Ref HighloadWalletV2::get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 valid_until) noexcept { - td::uint32 id = -1; - auto append_message = [&](auto&& cb) -> vm::CellBuilder& { - cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_long(id, 32); - CHECK(cb.store_maybe_ref({})); - return cb; - }; - auto signature = private_key.sign(append_message(vm::CellBuilder()).finalize()->get_hash().as_slice()).move_as_ok(); - - return append_message(vm::CellBuilder().store_bytes(signature)).finalize(); -} - -td::Ref HighloadWalletV2::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, - td::uint32 wallet_id, td::uint32 valid_until, - td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - vm::Dictionary messages(16); - for (size_t i = 0; i < gifts.size(); i++) { - auto& gift = gifts[i]; - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - vm::CellBuilder cb; - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - auto key = messages.integer_key(td::make_refint(i), 16, false); - messages.set_builder(key.bits(), 16, cb); - } - std::string hash; - { - vm::CellBuilder cb; - CHECK(cb.store_maybe_ref(messages.get_root_cell())); - hash = cb.finalize()->get_hash().as_slice().substr(28, 4).str(); - } - - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_bytes(hash); - CHECK(cb.store_maybe_ref(messages.get_root_cell())); - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); -} - -td::Ref HighloadWalletV2::get_init_code(td::int32 revision) noexcept { - return SmartContractCode::get_code(SmartContractCode::HighloadWalletV2, revision); -} - -vm::CellHash HighloadWalletV2::get_init_code_hash() noexcept { - return get_init_code(0)->get_hash(); -} - -td::Ref HighloadWalletV2::get_init_data(const td::Ed25519::PublicKey& public_key, - td::uint32 wallet_id) noexcept { - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(0, 64).store_bytes(public_key.as_octet_string()); - CHECK(cb.store_maybe_ref({})); - return cb.finalize(); -} - -td::Result HighloadWalletV2::get_wallet_id() const { - return TRY_VM(get_wallet_id_or_throw()); -} - -td::Result HighloadWalletV2::get_wallet_id_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - return static_cast(cs.fetch_ulong(32)); -} - -td::Result HighloadWalletV2::get_public_key() const { - return TRY_VM(get_public_key_or_throw()); -} - -td::Result HighloadWalletV2::get_public_key_or_throw() const { - if (state_.data.is_null()) { - return td::Status::Error("data is null"); - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(96); - td::SecureString res(td::Ed25519::PublicKey::LENGTH); - cs.fetch_bytes(res.as_mutable_slice().ubegin(), td::narrow_cast(res.size())); - return td::Ed25519::PublicKey(std::move(res)); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.h b/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.h deleted file mode 100644 index 975cf644..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/HighloadWalletV2.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "vm/cells.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -namespace ton { -class HighloadWalletV2 : public ton::SmartContract, public WalletInterface { - public: - explicit HighloadWalletV2(State state) : ton::SmartContract(std::move(state)) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 254; - static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision) noexcept; - static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 valid_until) noexcept; - - static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 valid_until, td::Span gifts) noexcept; - - static td::Ref get_init_code(td::int32 revision) noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept; - static td::optional guess_revision(const vm::Cell::Hash& code_hash); - static td::optional guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); - - td::Result get_wallet_id() const; - - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(wallet_id, get_wallet_id()); - return make_a_gift_message(private_key, wallet_id, valid_until, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - td::Result get_public_key() const override; - - private: - td::Result get_wallet_id_or_throw() const; - td::Result get_public_key_or_throw() const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.cpp deleted file mode 100644 index 00f1becb..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "ManualDns.h" - -#include "smc-envelope/SmartContractCode.h" - -#include "vm/dict.h" - -#include "td/utils/format.h" -#include "td/utils/overloaded.h" -#include "td/utils/Parser.h" -#include "td/utils/Random.h" - -#include "block/block-auto.h" -#include "block/block-parse.h" - -#include "common/util.h" - -namespace ton { -td::StringBuilder& operator<<(td::StringBuilder& sb, const ManualDns::EntryData& data) { - switch (data.type) { - case ManualDns::EntryData::Type::Empty: - return sb << "DELETED"; - case ManualDns::EntryData::Type::Text: - return sb << "TEXT:" << data.data.get().text; - case ManualDns::EntryData::Type::NextResolver: - return sb << "NEXT:" << data.data.get().resolver.rserialize(); - case ManualDns::EntryData::Type::AdnlAddress: - return sb << "ADNL:" - << td::adnl_id_encode(data.data.get().adnl_address.as_slice()) - .move_as_ok(); - case ManualDns::EntryData::Type::SmcAddress: - return sb << "SMC:" << data.data.get().smc_address.rserialize(); - } - return sb << ""; -} - -//proto_list_nil$0 = ProtoList; -//proto_list_next$1 head:Protocol tail:ProtoList = ProtoList; -//proto_http#4854 = Protocol; - -//cap_list_nil$0 = SmcCapList; -//cap_list_next$1 head:SmcCapability tail:SmcCapList = SmcCapList; -//cap_method_seqno#5371 = SmcCapability; -//cap_method_pubkey#71f4 = SmcCapability; -//cap_is_wallet#2177 = SmcCapability; -//cap_name#ff name:Text = SmcCapability; -// -td::Result> DnsInterface::EntryData::as_cell() const { - td::Ref res; - td::Status error; - data.visit(td::overloaded( - [&](const EntryDataText& text) { - block::gen::DNSRecord::Record_dns_text dns; - vm::CellBuilder cb; - vm::CellText::store(cb, text.text); - dns.x = vm::load_cell_slice_ref(cb.finalize()); - tlb::pack_cell(res, dns); - }, - [&](const EntryDataNextResolver& resolver) { - block::gen::DNSRecord::Record_dns_next_resolver dns; - vm::CellBuilder cb; - block::tlb::t_MsgAddressInt.store_std_address(cb, resolver.resolver.workchain, resolver.resolver.addr); - dns.resolver = vm::load_cell_slice_ref(cb.finalize()); - tlb::pack_cell(res, dns); - }, - [&](const EntryDataAdnlAddress& adnl_address) { - block::gen::DNSRecord::Record_dns_adnl_address dns; - dns.adnl_addr = adnl_address.adnl_address; - dns.flags = 0; - tlb::pack_cell(res, dns); - }, - [&](const EntryDataSmcAddress& smc_address) { - block::gen::DNSRecord::Record_dns_smc_address dns; - vm::CellBuilder cb; - block::tlb::t_MsgAddressInt.store_std_address(cb, smc_address.smc_address.workchain, - smc_address.smc_address.addr); - dns.smc_addr = vm::load_cell_slice_ref(cb.finalize()); - tlb::pack_cell(res, dns); - })); - if (error.is_error()) { - return error; - } - if (res.is_null()) { - return td::Status::Error("Entry data is emtpy"); - } - return res; - //dns_text#1eda _:Text = DNSRecord; - - //dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord; // usually in record #-1 - //dns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 } proto_list:flags . 0?ProtoList = DNSRecord; // often in record #2 - - //dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 } cap_list:flags . 0?SmcCapList = DNSRecord; // often in record #1 -} - -td::Result DnsInterface::EntryData::from_cellslice(vm::CellSlice& cs) { - switch (block::gen::t_DNSRecord.get_tag(cs)) { - case block::gen::DNSRecord::dns_text: { - block::gen::DNSRecord::Record_dns_text dns; - tlb::unpack(cs, dns); - TRY_RESULT(text, vm::CellText::load(dns.x.write())); - return EntryData::text(std::move(text)); - } - case block::gen::DNSRecord::dns_next_resolver: { - block::gen::DNSRecord::Record_dns_next_resolver dns; - tlb::unpack(cs, dns); - ton::WorkchainId wc; - ton::StdSmcAddress addr; - if (!block::tlb::t_MsgAddressInt.extract_std_address(dns.resolver, wc, addr)) { - return td::Status::Error("Invalid address"); - } - return EntryData::next_resolver(block::StdAddress(wc, addr)); - } - case block::gen::DNSRecord::dns_adnl_address: { - block::gen::DNSRecord::Record_dns_adnl_address dns; - tlb::unpack(cs, dns); - return EntryData::adnl_address(dns.adnl_addr); - } - case block::gen::DNSRecord::dns_smc_address: { - block::gen::DNSRecord::Record_dns_smc_address dns; - tlb::unpack(cs, dns); - ton::WorkchainId wc; - ton::StdSmcAddress addr; - if (!block::tlb::t_MsgAddressInt.extract_std_address(dns.smc_addr, wc, addr)) { - return td::Status::Error("Invalid address"); - } - return EntryData::smc_address(block::StdAddress(wc, addr)); - } - } - return td::Status::Error("Unknown entry data"); -} - -SmartContract::Args DnsInterface::resolve_args_raw(td::Slice encoded_name, td::int16 category) { - SmartContract::Args res; - res.set_method_id("dnsresolve"); - res.set_stack( - {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes(encoded_name).finalize()), td::make_refint(category)}); - return res; -} - -td::Result DnsInterface::resolve_args(td::Slice name, td::int32 category_big) { - TRY_RESULT(category, td::narrow_cast_safe(category_big)); - if (name.size() > get_default_max_name_size()) { - return td::Status::Error("Name is too long"); - } - auto encoded_name = encode_name(name); - return resolve_args_raw(encoded_name, category); -} - -td::Result> DnsInterface::resolve(td::Slice name, td::int32 category) const { - TRY_RESULT(raw_entries, resolve_raw(name, category)); - std::vector entries; - entries.reserve(raw_entries.size()); - for (auto& raw_entry : raw_entries) { - Entry entry; - entry.name = std::move(raw_entry.name); - entry.category = raw_entry.category; - auto cs = vm::load_cell_slice(raw_entry.data); - TRY_RESULT(data, EntryData::from_cellslice(cs)); - entry.data = std::move(data); - entries.push_back(std::move(entry)); - } - return entries; -} - -/* - External message structure: - [Bytes<512b>:signature] [UInt<32b>:seqno] [UInt<6b>:operation] - [Either b0: inline name (<= 58-x Bytes) or b1: reference-stored name) - x depends on operation - Use of 6-bit op instead of 32-bit allows to save 4 bytes for inline name - Inline [Name] structure: [UInt<6b>:length] [Bytes:data] - Operations (continuation of message): - 00 Contract initialization message (only if seqno = 0) (x=-) - 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-) - [Cell<1r>:new_domains_table] - 51 OSet: replace owner public key with a new one (x=-) - [UInt<256b>:new_public_key] -*/ -// creation -td::Ref ManualDns::create(td::Ref data, int revision) { - return td::Ref( - true, State{ton::SmartContractCode::get_code(ton::SmartContractCode::ManualDns, revision), std::move(data)}); -} - -td::Ref ManualDns::create(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, int revision) { - return create(create_init_data_fast(public_key, wallet_id), revision); -} - -td::optional ManualDns::guess_revision(const vm::Cell::Hash& code_hash) { - for (auto i : ton::SmartContractCode::get_revisions(ton::SmartContractCode::ManualDns)) { - if (ton::SmartContractCode::get_code(ton::SmartContractCode::ManualDns, i)->get_hash() == code_hash) { - return i; - } - } - return {}; -} -td::optional ManualDns::guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) { - for (auto i : {-1, 1}) { - auto dns = ton::ManualDns::create(public_key, wallet_id, i); - if (dns->get_address() == address) { - return i; - } - } - return {}; -} - -td::Result ManualDns::get_wallet_id() const { - return TRY_VM(get_wallet_id_or_throw()); -} -td::Result ManualDns::get_wallet_id_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); -} - -td::Result> ManualDns::create_set_value_unsigned(td::int16 category, td::Slice name, - td::Ref data) const { - //11 VSet: set specified value to specified subdomain->category (x=2) - //[Int<16b>:category] [Name:subdomain] [Cell<1r>:value] - vm::CellBuilder cb; - cb.store_long(11, 6); - if (name.size() <= 58 - 2) { - cb.store_long(category, 16); - cb.store_long(0, 1); - cb.store_long(name.size(), 6); - cb.store_bytes(name); - } else { - cb.store_long(category, 16); - cb.store_long(1, 1); - cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); - } - cb.store_maybe_ref(std::move(data)); - return cb.finalize(); -} -td::Result> ManualDns::create_delete_value_unsigned(td::int16 category, td::Slice name) const { - //12 VDel: delete specified subdomain->category (x=2) - //[Int<16b>:category] [Name:subdomain] - vm::CellBuilder cb; - cb.store_long(12, 6); - if (name.size() <= 58 - 2) { - cb.store_long(category, 16); - cb.store_long(0, 1); - cb.store_long(name.size(), 6); - cb.store_bytes(name); - } else { - cb.store_long(category, 16); - cb.store_long(1, 1); - cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); - } - return cb.finalize(); -} - -td::Result> ManualDns::create_delete_all_unsigned() const { - // 32 TDel: nullify ENTIRE DOMAIN TABLE (x=-) - vm::CellBuilder cb; - cb.store_long(32, 6); - return cb.finalize(); -} - -td::Result> ManualDns::create_set_all_unsigned(td::Span entries) const { - vm::PrefixDictionary pdict(1023); - for (auto& action : entries) { - auto name_key = encode_name(action.name); - int zero_cnt = 0; - for (auto c : name_key) { - if (c == 0) { - zero_cnt++; - } - } - auto new_name_key = vm::load_cell_slice(vm::CellBuilder().store_long(zero_cnt, 7).store_bytes(name_key).finalize()); - auto ptr = new_name_key.data_bits(); - auto ptr_size = new_name_key.size(); - auto o_dict = pdict.lookup(ptr, ptr_size); - td::Ref dict_root; - if (o_dict.not_null()) { - o_dict->prefetch_maybe_ref(dict_root); - } - vm::Dictionary dict(dict_root, 16); - if (!action.data.value().is_null()) { - auto key = dict.integer_key(td::make_refint(action.category), 16); - dict.set_ref(key.bits(), 16, action.data.value()); - } - pdict.set(ptr, ptr_size, dict.get_root()); - } - - vm::CellBuilder cb; - cb.store_long(31, 6); - - cb.store_maybe_ref(pdict.get_root_cell()); - - return cb.finalize(); -} - -//21 DSet: replace entire category dictionary of domain with provided (x=0) -//[Name:subdomain] [Cell<1r>:new_cat_table] -//22 DDel: delete entire category dictionary of specified domain (x=0) -//[Name:subdomain] -td::Result> ManualDns::create_delete_name_unsigned(td::Slice name) const { - vm::CellBuilder cb; - cb.store_long(22, 6); - if (name.size() <= 58) { - cb.store_long(0, 1); - cb.store_long(name.size(), 6); - cb.store_bytes(name); - } else { - cb.store_long(1, 1); - cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); - } - return cb.finalize(); -} -td::Result> ManualDns::create_set_name_unsigned(td::Slice name, td::Span entries) const { - vm::CellBuilder cb; - cb.store_long(21, 6); - if (name.size() <= 58) { - cb.store_long(0, 1); - cb.store_long(name.size(), 6); - cb.store_bytes(name); - } else { - cb.store_long(1, 1); - cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); - } - - vm::Dictionary dict(16); - - for (auto& action : entries) { - if (action.data.value().is_null()) { - continue; - } - auto key = dict.integer_key(td::make_refint(action.category), 16); - dict.set_ref(key.bits(), 16, action.data.value()); - } - cb.store_maybe_ref(dict.get_root_cell()); - - return cb.finalize(); -} - -td::Result> ManualDns::prepare(td::Ref data, td::uint32 valid_until) const { - TRY_RESULT(wallet_id, get_wallet_id()); - auto hash = data->get_hash().as_slice().substr(28, 4).str(); - - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(valid_until, 32); - //cb.store_bytes(hash); - cb.store_long(td::Random::secure_uint32(), 32); - cb.append_cellslice(vm::load_cell_slice(data)); - return cb.finalize(); -} - -td::Result> ManualDns::sign(const td::Ed25519::PrivateKey& private_key, td::Ref data) { - auto signature = private_key.sign(data->get_hash().as_slice()).move_as_ok(); - vm::CellBuilder cb; - cb.store_bytes(signature.as_slice()); - cb.append_cellslice(vm::load_cell_slice(data)); - return cb.finalize(); -} - -td::Result> ManualDns::create_init_query(const td::Ed25519::PrivateKey& private_key, - td::uint32 valid_until) const { - vm::CellBuilder cb; - cb.store_long(0, 6); - - TRY_RESULT(prepared, prepare(cb.finalize(), valid_until)); - return sign(private_key, std::move(prepared)); -} - -td::Ref ManualDns::create_init_data_fast(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) { - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(0, 64).store_bytes(public_key.as_octet_string()); - CHECK(cb.store_maybe_ref({})); - CHECK(cb.store_maybe_ref({})); - return cb.finalize(); -} - -size_t ManualDns::get_max_name_size() const { - return get_default_max_name_size(); -} - -td::Result> ManualDns::resolve_raw(td::Slice name, td::int32 category_big) const { - return TRY_VM(resolve_raw_or_throw(name, category_big)); -} -td::Result> ManualDns::resolve_raw_or_throw(td::Slice name, - td::int32 category_big) const { - TRY_RESULT(category, td::narrow_cast_safe(category_big)); - if (name.size() > get_max_name_size()) { - return td::Status::Error("Name is too long"); - } - auto encoded_name = encode_name(name); - auto res = run_get_method(resolve_args_raw(encoded_name, category)); - if (!res.success) { - return td::Status::Error("get method failed"); - } - std::vector vec; - auto data = res.stack.write().pop_maybe_cell(); - if (data.is_null()) { - return vec; - } - size_t prefix_size = res.stack.write().pop_smallint_range((int)encoded_name.size() * 8); - if (prefix_size % 8 != 0) { - return td::Status::Error("Prefix size is not divisible by 8"); - } - prefix_size /= 8; - if (prefix_size < encoded_name.size()) { - vec.push_back({decode_name(td::Slice(encoded_name).substr(0, prefix_size)), -1, data}); - } else { - if (category == 0) { - vm::Dictionary dict(std::move(data), 16); - dict.check_for_each([&](auto cs, auto x, auto y) { - td::BigInt256 cat; - cat.import_bits(x, y, true); - vec.push_back({name.str(), td::narrow_cast(cat.to_long()), cs->prefetch_ref()}); - return true; - }); - } else { - vec.push_back({name.str(), category, data}); - } - } - - return vec; -} - -td::Result> ManualDns::create_update_query(CombinedActions& combined) const { - if (combined.name.empty()) { - if (combined.actions.value().empty()) { - return create_delete_all_unsigned(); - } - return create_set_all_unsigned(combined.actions.value()); - } - if (combined.category == 0) { - if (!combined.actions) { - return create_delete_name_unsigned(encode_name(combined.name)); - } - return create_set_name_unsigned(encode_name(combined.name), combined.actions.value()); - } - CHECK(combined.actions.value().size() == 1); - auto& action = combined.actions.value()[0]; - if (action.data) { - return create_set_value_unsigned(action.category, encode_name(action.name), action.data.value()); - } else { - return create_delete_value_unsigned(action.category, encode_name(action.name)); - } -} - -td::Result> ManualDns::create_update_query(td::Ed25519::PrivateKey& pk, td::Span actions, - td::uint32 valid_until) const { - auto combined = combine_actions(actions); - std::vector> queries; - for (auto& c : combined) { - TRY_RESULT(q, create_update_query(c)); - queries.push_back(std::move(q)); - } - - td::Ref combined_query; - for (auto& query : td::reversed(queries)) { - if (combined_query.is_null()) { - combined_query = std::move(query); - } else { - auto next = vm::load_cell_slice(combined_query); - combined_query = vm::CellBuilder() - .append_cellslice(vm::load_cell_slice(query)) - .store_ref(vm::CellBuilder().append_cellslice(next).finalize()) - .finalize(); - } - } - - TRY_RESULT(prepared, prepare(std::move(combined_query), valid_until)); - return sign(pk, std::move(prepared)); -} - -std::string DnsInterface::encode_name(td::Slice name) { - std::string res; - while (!name.empty()) { - auto pos = name.rfind('.'); - if (pos == name.npos) { - res += name.str(); - name = td::Slice(); - } else { - res += name.substr(pos + 1).str(); - name.truncate(pos); - } - res += '\0'; - } - return res; -} - -std::string DnsInterface::decode_name(td::Slice name) { - std::string res; - if (!name.empty() && name.back() == 0) { - name.remove_suffix(1); - } - while (!name.empty()) { - auto pos = name.rfind('\0'); - if (!res.empty()) { - res += '.'; - } - if (pos == name.npos) { - res += name.str(); - name = td::Slice(); - } else { - res += name.substr(pos + 1).str(); - name.truncate(pos); - } - } - return res; -} - -std::string ManualDns::serialize_data(const EntryData& data) { - std::string res; - data.data.visit(td::overloaded([&](const ton::ManualDns::EntryDataText& text) { res = "UNSUPPORTED"; }, - [&](const ton::ManualDns::EntryDataNextResolver& resolver) { res = "UNSUPPORTED"; }, - [&](const ton::ManualDns::EntryDataAdnlAddress& adnl_address) { res = "UNSUPPORTED"; }, - [&](const ton::ManualDns::EntryDataSmcAddress& text) { res = "UNSUPPORTED"; })); - return res; -} - -td::Result> ManualDns::parse_data(td::Slice cmd) { - td::ConstParser parser(cmd); - parser.skip_whitespaces(); - auto type = parser.read_till(':'); - parser.skip(':'); - if (type == "TEXT") { - return ManualDns::EntryData::text(parser.read_all().str()); - } else if (type == "ADNL") { - TRY_RESULT(address, td::adnl_id_decode(parser.read_all())); - return ManualDns::EntryData::adnl_address(address); - } else if (type == "SMC") { - TRY_RESULT(address, block::StdAddress::parse(parser.read_all())); - return ManualDns::EntryData::smc_address(address); - } else if (type == "NEXT") { - TRY_RESULT(address, block::StdAddress::parse(parser.read_all())); - return ManualDns::EntryData::next_resolver(address); - } else if (parser.data() == "DELETED") { - return {}; - } - return td::Status::Error(PSLICE() << "Unknown entry type: " << type); -} - -td::Result ManualDns::parse_line(td::Slice cmd) { - // Cmd = - // set name category data | - // delete.name name | - // delete.all - // data = - // TEXT: | - // SMC: | - // NEXT: | - // ADNL: - // DELETED - td::ConstParser parser(cmd); - auto type = parser.read_word(); - if (type == "set") { - auto name = parser.read_word(); - auto category_str = parser.read_word(); - TRY_RESULT(category, td::to_integer_safe(category_str)); - TRY_RESULT(data, parse_data(parser.read_all())); - return ManualDns::ActionExt{name.str(), category, std::move(data)}; - } else if (type == "delete.name") { - auto name = parser.read_word(); - if (name.empty()) { - return td::Status::Error("name is empty"); - } - return ManualDns::ActionExt{name.str(), 0, {}}; - } else if (type == "delete.all") { - return ManualDns::ActionExt{"", 0, {}}; - } - return td::Status::Error(PSLICE() << "Unknown command: " << type); -} - -td::Result> ManualDns::parse(td::Slice cmd) { - auto lines = td::full_split(cmd, '\n'); - std::vector res; - res.reserve(lines.size()); - for (auto& line : lines) { - td::ConstParser parser(line); - parser.skip_whitespaces(); - if (parser.empty()) { - continue; - } - TRY_RESULT(action, parse_line(parser.read_all())); - res.push_back(std::move(action)); - } - return res; -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.h b/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.h deleted file mode 100644 index fbf12e74..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/ManualDns.h +++ /dev/null @@ -1,335 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/Variant.h" -#include "td/utils/Status.h" -#include "vm/cells/Cell.h" -#include "vm/cells/CellSlice.h" -#include "vm/cells/CellString.h" - -#include "smc-envelope/SmartContract.h" - -#include "Ed25519.h" - -#include - -namespace ton { -class DnsInterface { - public: - struct EntryDataText { - std::string text; - bool operator==(const EntryDataText& other) const { - return text == other.text; - } - }; - - struct EntryDataNextResolver { - block::StdAddress resolver; - bool operator==(const EntryDataNextResolver& other) const { - return resolver == other.resolver; - } - }; - - struct EntryDataAdnlAddress { - ton::Bits256 adnl_address; - // TODO: proto - bool operator==(const EntryDataAdnlAddress& other) const { - return adnl_address == other.adnl_address; - } - }; - - struct EntryDataSmcAddress { - block::StdAddress smc_address; - bool operator==(const EntryDataSmcAddress& other) const { - return smc_address == other.smc_address; - } - // TODO: capability - }; - - struct EntryData { - enum Type { Empty, Text, NextResolver, AdnlAddress, SmcAddress } type{Empty}; - td::Variant data; - - static EntryData text(std::string text) { - return {Text, EntryDataText{text}}; - } - static EntryData next_resolver(block::StdAddress resolver) { - return {NextResolver, EntryDataNextResolver{resolver}}; - } - static EntryData adnl_address(ton::Bits256 adnl_address) { - return {AdnlAddress, EntryDataAdnlAddress{adnl_address}}; - } - static EntryData smc_address(block::StdAddress smc_address) { - return {SmcAddress, EntryDataSmcAddress{smc_address}}; - } - - bool operator==(const EntryData& other) const { - return data == other.data; - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const EntryData& data); - - td::Result> as_cell() const; - static td::Result from_cellslice(vm::CellSlice& cs); - }; - - struct Entry { - std::string name; - td::int16 category; - EntryData data; - auto key() const { - return std::tie(name, category); - } - bool operator<(const Entry& other) const { - return key() < other.key(); - } - bool operator==(const Entry& other) const { - return key() == other.key() && data == other.data; - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Entry& entry) { - sb << entry.name << ":" << entry.category << ":" << entry.data; - return sb; - } - }; - struct RawEntry { - std::string name; - td::int16 category; - td::Ref data; - }; - - struct ActionExt { - std::string name; - td::int16 category; - td::optional data; - static td::Result parse(td::Slice); - }; - - struct Action { - std::string name; - td::int16 category; - td::optional> data; - - bool does_create_category() const { - CHECK(!name.empty()); - CHECK(category != 0); - return static_cast(data); - } - bool does_change_empty() const { - CHECK(!name.empty()); - CHECK(category != 0); - return static_cast(data) && data.value().not_null(); - } - void make_non_empty() { - CHECK(!name.empty()); - CHECK(category != 0); - if (!data) { - data = td::Ref(); - } - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Action& action) { - sb << action.name << ":" << action.category << ":"; - if (action.data) { - if (action.data.value().is_null()) { - sb << ""; - } else { - sb << ""; - } - } else { - sb << ""; - } - return sb; - } - }; - - virtual ~DnsInterface() { - } - virtual size_t get_max_name_size() const = 0; - virtual td::Result> resolve_raw(td::Slice name, td::int32 category) const = 0; - virtual td::Result> create_update_query( - td::Ed25519::PrivateKey& pk, td::Span actions, - td::uint32 valid_until = std::numeric_limits::max()) const = 0; - - td::Result> resolve(td::Slice name, td::int32 category) const; - - static std::string encode_name(td::Slice name); - static std::string decode_name(td::Slice name); - - static size_t get_default_max_name_size() { - return 128; - } - static SmartContract::Args resolve_args_raw(td::Slice encoded_name, td::int16 category); - static td::Result resolve_args(td::Slice name, td::int32 category); -}; - -class ManualDns : public ton::SmartContract, public DnsInterface { - public: - ManualDns(State state) : SmartContract(std::move(state)) { - } - - ManualDns* make_copy() const override { - return new ManualDns{state_}; - } - - // creation - static td::Ref create(State state) { - return td::Ref(true, std::move(state)); - } - static td::Ref create(td::Ref data = {}, int revision = 0); - static td::Ref create(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, int revision = 0); - - static std::string serialize_data(const EntryData& data); - static td::Result> parse_data(td::Slice cmd); - static td::Result parse_line(td::Slice cmd); - static td::Result> parse(td::Slice cmd); - - static td::optional guess_revision(const vm::Cell::Hash& code_hash); - static td::optional guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); - - td::Ref create_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 valid_until) const { - return create_init_data_fast(public_key, valid_until); - } - - td::Result get_wallet_id() const; - td::Result get_wallet_id_or_throw() const; - - td::Result> create_set_value_unsigned(td::int16 category, td::Slice name, - td::Ref data) const; - td::Result> create_delete_value_unsigned(td::int16 category, td::Slice name) const; - td::Result> create_delete_all_unsigned() const; - td::Result> create_set_all_unsigned(td::Span entries) const; - td::Result> create_delete_name_unsigned(td::Slice name) const; - td::Result> create_set_name_unsigned(td::Slice name, td::Span entries) const; - - td::Result> prepare(td::Ref data, td::uint32 valid_until) const; - - static td::Result> sign(const td::Ed25519::PrivateKey& private_key, td::Ref data); - static td::Ref create_init_data_fast(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); - - size_t get_max_name_size() const override; - td::Result> resolve_raw(td::Slice name, td::int32 category_big) const override; - td::Result> resolve_raw_or_throw(td::Slice name, td::int32 category_big) const; - - td::Result> create_init_query( - const td::Ed25519::PrivateKey& private_key, - td::uint32 valid_until = std::numeric_limits::max()) const; - td::Result> create_update_query( - td::Ed25519::PrivateKey& pk, td::Span actions, - td::uint32 valid_until = std::numeric_limits::max()) const override; - - template - struct CombinedActions { - std::string name; - td::int16 category{0}; - td::optional> actions; - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const CombinedActions& action) { - sb << action.name << ":" << action.category << ":"; - if (action.actions) { - sb << "" << action.actions.value().size(); - } else { - sb << ""; - } - return sb; - } - }; - - template - static std::vector> combine_actions(td::Span actions) { - struct Info { - std::set known_category; - std::vector actions; - bool closed{false}; - bool non_empty{false}; - }; - - std::map mp; - std::vector> res; - for (auto& action : td::reversed(actions)) { - if (action.name.empty()) { - CombinedActions set_all; - set_all.actions = std::vector(); - for (auto& it : mp) { - for (auto& e : it.second.actions) { - if (e.does_create_category()) { - set_all.actions.value().push_back(std::move(e)); - } - } - } - res.push_back(std::move(set_all)); - return res; - } - - Info& info = mp[action.name]; - if (info.closed) { - continue; - } - if (action.category != 0 && action.does_create_category()) { - info.non_empty = true; - } - if (!info.known_category.insert(action.category).second) { - continue; - } - if (action.category == 0) { - info.closed = true; - auto old_actions = std::move(info.actions); - bool is_empty = true; - for (auto& action : old_actions) { - if (is_empty && action.does_create_category()) { - info.actions.push_back(std::move(action)); - is_empty = false; - } else if (!is_empty && action.does_change_empty()) { - info.actions.push_back(std::move(action)); - } - } - } else { - info.actions.push_back(std::move(action)); - } - } - - for (auto& it : mp) { - auto& info = it.second; - if (info.closed) { - CombinedActions ca; - ca.name = it.first; - ca.category = 0; - if (!info.actions.empty() || info.non_empty) { - ca.actions = std::move(info.actions); - } - res.push_back(std::move(ca)); - } else { - bool need_non_empty = info.non_empty; - for (auto& a : info.actions) { - if (need_non_empty) { - a.make_non_empty(); - need_non_empty = false; - } - CombinedActions ca; - ca.name = a.name; - ca.category = a.category; - ca.actions = std::vector(); - ca.actions.value().push_back(std::move(a)); - res.push_back(ca); - } - } - } - return res; - } - td::Result> create_update_query(CombinedActions& combined) const; -}; - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp deleted file mode 100644 index 5a9fab6a..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "MultisigWallet.h" - -#include "SmartContractCode.h" - -#include "vm/dict.h" - -#include "td/utils/misc.h" - -namespace ton { - -MultisigWallet::QueryBuilder::QueryBuilder(td::uint32 wallet_id, td::int64 query_id, td::Ref msg, int mode) { - msg_ = vm::CellBuilder() - .store_long(wallet_id, 32) - .store_long(query_id, 64) - .store_long(mode, 8) - .store_ref(std::move(msg)) - .finalize(); -} -void MultisigWallet::QueryBuilder::sign(td::int32 id, td::Ed25519::PrivateKey& pk) { - CHECK(id < td::narrow_cast(mask_.size())); - auto signature = pk.sign(msg_->get_hash().as_slice()).move_as_ok(); - mask_.set(id); - vm::CellBuilder cb; - cb.store_bytes(signature.as_slice()); - cb.store_long(id, 8); - cb.ensure_throw(cb.store_maybe_ref(std::move(dict_))); - dict_ = cb.finalize(); -} - -td::Ref MultisigWallet::QueryBuilder::create_inner() const { - vm::CellBuilder cb; - cb.ensure_throw(cb.store_maybe_ref(dict_)); - return cb.append_cellslice(vm::load_cell_slice(msg_)).finalize(); -} - -td::Ref MultisigWallet::QueryBuilder::create(td::int32 id, td::Ed25519::PrivateKey& pk) const { - auto cell = create_inner(); - vm::CellBuilder cb; - cb.store_long(id, 8); - cb.append_cellslice(vm::load_cell_slice(cell)); - cell = cb.finalize(); - - auto signature = pk.sign(cell->get_hash().as_slice()).move_as_ok(); - vm::CellBuilder cb2; - cb2.store_bytes(signature.as_slice()); - cb2.append_cellslice(vm::load_cell_slice(cell)); - return cb2.finalize(); -} - -td::Ref MultisigWallet::create(td::Ref data) { - return td::Ref( - true, State{ton::SmartContractCode::get_code(ton::SmartContractCode::Multisig), std::move(data)}); -} - -int MultisigWallet::processed(td::uint64 query_id) const { - auto res = run_get_method("processed?", {td::make_refint(query_id)}); - return res.stack.write().pop_smallint_range(1, -1); -} - -MultisigWallet::QueryState MultisigWallet::get_query_state(td::uint64 query_id) const { - auto ans = run_get_method("get_query_state", {td::make_refint(query_id)}); - - auto mask = ans.stack.write().pop_int(); - auto state = ans.stack.write().pop_smallint_range(1, -1); - - QueryState res; - if (state == 1) { - res.state = QueryState::Unknown; - } else if (state == 0) { - res.state = QueryState::NotReady; - for (size_t i = 0; i < res.mask.size(); i++) { - if (mask->get_bit(static_cast(i))) { - res.mask.set(i); - } - } - } else { - res.state = QueryState::Sent; - } - return res; -} - -std::vector MultisigWallet::get_public_keys() const { - auto ans = run_get_method("get_public_keys"); - auto dict_root = ans.stack.write().pop_cell(); - vm::Dictionary dict(std::move(dict_root), 8); - std::vector res; - dict.check_for_each([&](auto cs, auto x, auto y) { - td::SecureString key(32); - cs->prefetch_bytes(key.as_mutable_slice().ubegin(), td::narrow_cast(key.size())); - res.push_back(std::move(key)); - return true; - }); - return res; -} - -td::Ref MultisigWallet::create_init_data(td::uint32 wallet_id, std::vector public_keys, - int k) const { - vm::Dictionary pk(8); - for (size_t i = 0; i < public_keys.size(); i++) { - auto key = pk.integer_key(td::make_refint(i), 8, false); - pk.set_builder(key.bits(), 8, vm::CellBuilder().store_bytes(public_keys[i].as_slice()).store_long(0, 8)); - } - auto res = run_get_method("create_init_state", {td::make_refint(wallet_id), td::make_refint(public_keys.size()), - td::make_refint(k), pk.get_root_cell()}); - CHECK(res.code == 0); - return res.stack.write().pop_cell(); -} - -td::Ref MultisigWallet::create_init_data_fast(td::uint32 wallet_id, std::vector public_keys, - int k) { - vm::Dictionary pk(8); - for (size_t i = 0; i < public_keys.size(); i++) { - auto key = pk.integer_key(td::make_refint(i), 8, false); - pk.set_builder(key.bits(), 8, vm::CellBuilder().store_bytes(public_keys[i].as_slice()).store_long(0, 8)); - } - - vm::CellBuilder cb; - cb.store_long(wallet_id, 32); - cb.store_long(public_keys.size(), 8).store_long(k, 8).store_long(0, 64); - cb.ensure_throw(cb.store_maybe_ref(pk.get_root_cell())); - cb.ensure_throw(cb.store_maybe_ref({})); - return cb.finalize(); -} - -td::Ref MultisigWallet::merge_queries(td::Ref a, td::Ref b) const { - auto res = run_get_method("merge_queries", {a, b}); - return res.stack.write().pop_cell(); -} - -MultisigWallet::Mask MultisigWallet::to_mask(td::RefInt256 mask) const { - Mask res_mask; - for (size_t i = 0; i < res_mask.size(); i++) { - if (mask->get_bit(static_cast(i))) { - res_mask.set(i); - } - } - return res_mask; -} - -std::pair MultisigWallet::check_query_signatures(td::Ref a) const { - auto ans = run_get_method("check_query_signatures", {a}); - - auto mask = ans.stack.write().pop_int(); - auto cnt = ans.stack.write().pop_smallint_range(128); - return std::make_pair(cnt, to_mask(mask)); -} - -std::pair MultisigWallet::get_n_k() const { - auto ans = run_get_method("get_n_k"); - auto k = ans.stack.write().pop_smallint_range(128); - auto n = ans.stack.write().pop_smallint_range(128); - return std::make_pair(n, k); -} - -std::vector MultisigWallet::get_unsigned_messaged(int id) const { - SmartContract::Answer ans; - if (id == -1) { - ans = run_get_method("get_messages_unsigned"); - } else { - ans = run_get_method("get_messages_unsigned_by_id", {td::make_refint(id)}); - } - auto n_k = get_n_k(); - - auto cell = ans.stack.write().pop_maybe_cell(); - vm::Dictionary dict(std::move(cell), 64); - std::vector res; - dict.check_for_each([&](auto cs, auto ptr, auto ptr_bits) { - cs.write().skip_first(8 + 8); - Message message; - td::BigInt256 query_id; - query_id.import_bits(ptr, ptr_bits, false); - message.query_id = static_cast(query_id.to_long()); - message.signed_by = to_mask(cs.write().fetch_int256(n_k.first, false)); - message.message = cs.write().fetch_ref(); - res.push_back(std::move(message)); - return true; - }); - return res; -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h deleted file mode 100644 index 96da297a..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells.h" - -#include "SmartContract.h" -#include "Ed25519.h" - -#include - -namespace ton { -class MultisigWallet : public ton::SmartContract { - public: - MultisigWallet(State state) : SmartContract(std::move(state)) { - } - - using Mask = std::bitset<128>; - struct QueryState { - enum State { Unknown, NotReady, Sent } state = Unknown; - Mask mask; - }; - - class QueryBuilder { - public: - QueryBuilder(td::uint32 wallet_id, td::int64 query_id, td::Ref msg, int mode = 3); - void sign(td::int32 id, td::Ed25519::PrivateKey& pk); - - td::Ref create_inner() const; - td::Ref create(td::int32 id, td::Ed25519::PrivateKey& pk) const; - Mask get_mask() const { - return mask_; - } - - private: - vm::Ref dict_; - td::Ref msg_; - Mask mask_; - }; - - MultisigWallet* make_copy() const override { - return new MultisigWallet{state_}; - } - - // creation - static td::Ref create(td::Ref data = {}); - - td::Ref create_init_data(td::uint32 wallet_id, std::vector public_keys, int k) const; - static td::Ref create_init_data_fast(td::uint32 wallet_id, std::vector public_keys, - int k); - - // get methods - int processed(td::uint64 query_id) const; - QueryState get_query_state(td::uint64 query_id) const; - std::vector get_public_keys() const; - td::Ref merge_queries(td::Ref a, td::Ref b) const; - std::pair check_query_signatures(td::Ref a) const; - std::pair get_n_k() const; - Mask to_mask(td::RefInt256 mask) const; - - struct Message { - td::uint64 query_id; - Mask signed_by; - td::Ref message; - }; - std::vector get_unsigned_messaged(int id = -1) const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.cpp deleted file mode 100644 index e70e23c1..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "PaymentChannel.h" -#include "GenericAccount.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "Ed25519.h" -#include "block/block-auto.h" -#include "block/block-parse.h" - -#include "SmartContract.h" -#include "SmartContractCode.h" - -namespace ton { -using smc::pack_grams; -using smc::unpack_grams; -namespace pchan { - -td::Ref Config::serialize() const { - block::gen::ChanConfig::Record rec; - - vm::CellBuilder a_addr_cb; - block::tlb::t_MsgAddressInt.store_std_address(a_addr_cb, a_addr); - rec.a_addr = a_addr_cb.finalize_novm(); - - vm::CellBuilder b_addr_cb; - block::tlb::t_MsgAddressInt.store_std_address(b_addr_cb, b_addr); - rec.b_addr = b_addr_cb.finalize_novm(); - - rec.a_key.as_slice().copy_from(a_key); - rec.b_key.as_slice().copy_from(b_key); - rec.init_timeout = init_timeout; - rec.close_timeout = close_timeout; - rec.channel_id = channel_id; - rec.min_A_extra = pack_grams(min_A_extra); - - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::Ref MsgInit::serialize() const { - block::gen::ChanMsg::Record_chan_msg_init rec; - rec.min_A = pack_grams(min_A); - rec.min_B = pack_grams(min_B); - rec.inc_A = pack_grams(inc_A); - rec.inc_B = pack_grams(inc_B); - rec.channel_id = channel_id; - - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::Ref Promise::serialize() const { - block::gen::ChanPromise::Record rec; - rec.channel_id = channel_id; - rec.promise_A = pack_grams(promise_A); - rec.promise_B = pack_grams(promise_B); - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::SecureString sign(const td::Ref& msg, const td::Ed25519::PrivateKey* key) { - return key->sign(msg->get_hash().as_slice()).move_as_ok(); -} - -td::Ref maybe_sign(const td::Ref& msg, const td::Ed25519::PrivateKey* key) { - if (!key) { - return {}; - } - return vm::CellBuilder().store_bytes(sign(msg, key).as_slice()).finalize(); -} - -td::Ref maybe_ref(td::Ref msg) { - vm::CellBuilder cb; - CHECK(cb.store_maybe_ref(msg)); - return vm::load_cell_slice_ref(cb.finalize()); -} - -td::Ref MsgClose::serialize() const { - block::gen::ChanMsg::Record_chan_msg_close rec; - rec.extra_A = pack_grams(extra_A); - rec.extra_B = pack_grams(extra_B); - rec.promise = signed_promise; - - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::Ref MsgTimeout::serialize() const { - block::gen::ChanMsg::Record_chan_msg_timeout rec; - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::Ref MsgPayout::serialize() const { - block::gen::ChanMsg::Record_chan_msg_payout rec; - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::SecureString SignedPromise::signature(const td::Ed25519::PrivateKey* key, const td::Ref& promise) { - return sign(promise, key); -} -td::Ref SignedPromise::create_and_serialize(td::Slice signature, const td::Ref& promise) { - block::gen::ChanSignedPromise::Record rec; - rec.promise = vm::load_cell_slice_ref(promise); - LOG(ERROR) << "signature.size() = " << signature.size(); - rec.sig = maybe_ref(vm::CellBuilder().store_bytes(signature).finalize()); - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} -td::Ref SignedPromise::create_and_serialize(const td::Ed25519::PrivateKey* key, - const td::Ref& promise) { - block::gen::ChanSignedPromise::Record rec; - rec.promise = vm::load_cell_slice_ref(promise); - rec.sig = maybe_ref(maybe_sign(promise, key)); - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -bool SignedPromise::unpack(td::Ref cell) { - block::gen::ChanSignedPromise::Record rec; - if (!tlb::unpack_cell(cell, rec)) { - return false; - } - block::gen::ChanPromise::Record rec_promise; - if (!tlb::csr_unpack(rec.promise, rec_promise)) { - return false; - } - promise.channel_id = rec_promise.channel_id; - if (!unpack_grams(rec_promise.promise_A, promise.promise_A)) { - return false; - } - if (!unpack_grams(rec_promise.promise_B, promise.promise_B)) { - return false; - } - td::Ref sig_cell; - if (!rec.sig->prefetch_maybe_ref(sig_cell)) { - return false; - } - td::SecureString signature(64); - vm::CellSlice cs = vm::load_cell_slice(sig_cell); - if (!cs.prefetch_bytes(signature.as_mutable_slice())) { - return false; - } - o_signature = std::move(signature); - return true; -} - -td::Ref StateInit::serialize() const { - block::gen::ChanState::Record_chan_state_init rec; - rec.expire_at = expire_at; - rec.min_A = pack_grams(min_A); - rec.min_B = pack_grams(min_B); - rec.A = pack_grams(A); - rec.B = pack_grams(B); - rec.signed_A = signed_A; - rec.signed_B = signed_B; - td::Ref res; - CHECK(tlb::pack_cell(res, rec)); - return res; -} - -td::Ref Data::serialize() const { - block::gen::ChanData::Record rec; - rec.config = config; - rec.state = state; - td::Ref res; - CHECK(block::gen::t_ChanData.cell_pack(res, rec)); - return res; -} - -td::Ref Data::init_state() { - return StateInit().serialize(); -} -} // namespace pchan - -td::Result PaymentChannel::get_info() const { - block::gen::ChanData::Record data_rec; - if (!tlb::unpack_cell(get_state().data, data_rec)) { - return td::Status::Error("Can't unpack data"); - } - block::gen::ChanConfig::Record config_rec; - if (!tlb::unpack_cell(data_rec.config, config_rec)) { - return td::Status::Error("Can't unpack config"); - } - pchan::Config config; - config.a_key = td::SecureString(config_rec.a_key.as_slice()); - config.b_key = td::SecureString(config_rec.b_key.as_slice()); - block::tlb::t_MsgAddressInt.extract_std_address(vm::load_cell_slice_ref(config_rec.a_addr), config.a_addr); - block::tlb::t_MsgAddressInt.extract_std_address(vm::load_cell_slice_ref(config_rec.b_addr), config.b_addr); - config.init_timeout = static_cast(config_rec.init_timeout); - config.close_timeout = static_cast(config_rec.close_timeout); - config.channel_id = static_cast(config_rec.channel_id); - - auto state_cs = vm::load_cell_slice(data_rec.state); - Info res; - switch (block::gen::t_ChanState.check_tag(state_cs)) { - case block::gen::ChanState::chan_state_init: { - pchan::StateInit state; - block::gen::ChanState::Record_chan_state_init state_rec; - if (!tlb::unpack_cell(data_rec.state, state_rec)) { - return td::Status::Error("Can't unpack state"); - } - bool ok = unpack_grams(state_rec.A, state.A) && unpack_grams(state_rec.B, state.B) && - unpack_grams(state_rec.min_A, state.min_A) && unpack_grams(state_rec.min_B, state.min_B); - state.expire_at = state_rec.expire_at; - state.signed_A = state_rec.signed_A; - state.signed_B = state_rec.signed_B; - if (!ok) { - return td::Status::Error("Can't unpack state"); - } - res.state = std::move(state); - break; - } - case block::gen::ChanState::chan_state_close: { - pchan::StateClose state; - block::gen::ChanState::Record_chan_state_close state_rec; - if (!tlb::unpack_cell(data_rec.state, state_rec)) { - return td::Status::Error("Can't unpack state"); - } - bool ok = unpack_grams(state_rec.A, state.A) && unpack_grams(state_rec.B, state.B) && - unpack_grams(state_rec.promise_A, state.promise_A) && - unpack_grams(state_rec.promise_B, state.promise_B); - state.expire_at = state_rec.expire_at; - state.signed_A = state_rec.signed_A; - state.signed_B = state_rec.signed_B; - if (!ok) { - return td::Status::Error("Can't unpack state"); - } - res.state = std::move(state); - break; - } - case block::gen::ChanState::chan_state_payout: { - pchan::StatePayout state; - block::gen::ChanState::Record_chan_state_payout state_rec; - if (!tlb::unpack_cell(data_rec.state, state_rec)) { - return td::Status::Error("Can't unpack state"); - } - bool ok = unpack_grams(state_rec.A, state.A) && unpack_grams(state_rec.B, state.B); - if (!ok) { - return td::Status::Error("Can't unpack state"); - } - res.state = std::move(state); - break; - } - default: - return td::Status::Error("Can't unpack state"); - } - - res.config = std::move(config); - res.description = block::gen::t_ChanState.as_string_ref(data_rec.state); - - return std::move(res); -} // namespace ton - -td::optional PaymentChannel::guess_revision(const vm::Cell::Hash& code_hash) { - for (auto i : ton::SmartContractCode::get_revisions(ton::SmartContractCode::PaymentChannel)) { - auto code = SmartContractCode::get_code(SmartContractCode::PaymentChannel, i); - if (code->get_hash() == code_hash) { - return i; - } - } - return {}; -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.h b/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.h deleted file mode 100644 index db6b159e..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/PaymentChannel.h +++ /dev/null @@ -1,263 +0,0 @@ -#pragma once -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "Ed25519.h" -#include "block/block-auto.h" -#include "block/block-parse.h" - -#include "td/utils/Variant.h" - -#include "SmartContract.h" -#include "SmartContractCode.h" - -namespace ton { -namespace pchan { - -// -// Payment channels -// -struct Config { - td::uint32 init_timeout{0}; - td::uint32 close_timeout{0}; - td::SecureString a_key; - td::SecureString b_key; - block::StdAddress a_addr; - block::StdAddress b_addr; - td::uint64 channel_id{0}; - td::uint64 min_A_extra{0}; - - td::Ref serialize() const; -}; - -struct MsgInit { - td::uint64 inc_A{0}; - td::uint64 inc_B{0}; - td::uint64 min_A{0}; - td::uint64 min_B{0}; - td::uint64 channel_id{0}; - - td::Ref serialize() const; -}; - -struct Promise { - td::uint64 channel_id; - td::uint64 promise_A{0}; - td::uint64 promise_B{0}; - td::Ref serialize() const; -}; - -td::Ref maybe_sign(const td::Ref& msg, const td::Ed25519::PrivateKey* key); -td::Ref maybe_ref(td::Ref msg); - -struct MsgClose { - td::uint64 extra_A{0}; - td::uint64 extra_B{0}; - td::Ref signed_promise; - td::Ref serialize() const; -}; - -struct MsgTimeout { - td::Ref serialize() const; -}; - -struct MsgPayout { - td::Ref serialize() const; -}; - -struct SignedPromise { - Promise promise; - td::optional o_signature; - - bool unpack(td::Ref cell); - static td::SecureString signature(const td::Ed25519::PrivateKey* key, const td::Ref& promise); - static td::Ref create_and_serialize(td::Slice signature, const td::Ref& promise); - static td::Ref create_and_serialize(const td::Ed25519::PrivateKey* key, const td::Ref& promise); -}; - -struct StateInit { - bool signed_A{false}; - bool signed_B{false}; - td::uint64 min_A{0}; - td::uint64 min_B{0}; - td::uint64 A{0}; - td::uint64 B{0}; - td::uint32 expire_at{0}; - - td::Ref serialize() const; -}; - -struct StateClose { - bool signed_A{false}; - bool signed_B{false}; - td::uint64 promise_A{0}; - td::uint64 promise_B{0}; - td::uint64 A{0}; - td::uint64 B{0}; - td::uint32 expire_at{0}; -}; - -struct StatePayout { - td::uint64 A{0}; - td::uint64 B{0}; -}; - -struct Data { - td::Ref config; - td::Ref state; - - static td::Ref init_state(); - - td::Ref serialize() const; -}; - -template -struct MsgBuilder { - td::Ed25519::PrivateKey* a_key{nullptr}; - td::Ed25519::PrivateKey* b_key{nullptr}; - - T&& with_a_key(td::Ed25519::PrivateKey* key) && { - a_key = key; - return static_cast(*this); - } - T&& with_b_key(td::Ed25519::PrivateKey* key) && { - b_key = key; - return static_cast(*this); - } - - td::Ref finalize() && { - block::gen::ChanSignedMsg::Record rec; - auto msg = static_cast(*this).msg.serialize(); - rec.msg = vm::load_cell_slice_ref(msg); - rec.sig_A = maybe_ref(maybe_sign(msg, a_key)); - rec.sig_B = maybe_ref(maybe_sign(msg, b_key)); - block::gen::ChanOp::Record op_rec; - CHECK(tlb::csr_pack(op_rec.msg, rec)); - LOG(ERROR) << op_rec.msg->size(); - td::Ref res; - CHECK(tlb::pack_cell(res, op_rec)); - return res; - } -}; - -struct MsgInitBuilder : public MsgBuilder { - MsgInit msg; - - MsgInitBuilder&& min_A(td::uint64 value) && { - msg.min_A = value; - return std::move(*this); - } - MsgInitBuilder&& min_B(td::uint64 value) && { - msg.min_B = value; - return std::move(*this); - } - MsgInitBuilder&& inc_A(td::uint64 value) && { - msg.inc_A = value; - return std::move(*this); - } - MsgInitBuilder&& inc_B(td::uint64 value) && { - msg.inc_B = value; - return std::move(*this); - } - MsgInitBuilder&& channel_id(td::uint64 value) && { - msg.channel_id = value; - return std::move(*this); - } -}; - -struct MsgTimeoutBuilder : public MsgBuilder { - MsgTimeout msg; -}; - -struct MsgPayoutBuilder : public MsgBuilder { - MsgPayout msg; -}; - -struct MsgCloseBuilder : public MsgBuilder { - MsgClose msg; - - MsgCloseBuilder&& extra_A(td::uint64 value) && { - msg.extra_A = value; - return std::move(*this); - } - MsgCloseBuilder&& extra_B(td::uint64 value) && { - msg.extra_B = value; - return std::move(*this); - } - MsgCloseBuilder&& signed_promise(td::Ref signed_promise) && { - msg.signed_promise = vm::load_cell_slice_ref(signed_promise); - return std::move(*this); - } -}; - -struct SignedPromiseBuilder { - Promise promise; - td::optional o_signature; - td::Ed25519::PrivateKey* key{nullptr}; - - SignedPromiseBuilder& with_key(td::Ed25519::PrivateKey* key) { - this->key = key; - return *this; - } - SignedPromiseBuilder& promise_A(td::uint64 value) { - promise.promise_A = value; - return *this; - } - SignedPromiseBuilder& promise_B(td::uint64 value) { - promise.promise_B = value; - return *this; - } - SignedPromiseBuilder& channel_id(td::uint64 value) { - promise.channel_id = value; - return *this; - } - SignedPromiseBuilder& signature(td::SecureString signature) { - o_signature = std::move(signature); - return *this; - } - - bool check_signature(td::Slice signature, const td::Ed25519::PublicKey& pk) { - return pk.verify_signature(promise.serialize()->get_hash().as_slice(), signature).is_ok(); - } - td::SecureString calc_signature() { - CHECK(key); - return SignedPromise::signature(key, promise.serialize()); - } - td::Ref finalize() { - if (o_signature) { - return SignedPromise::create_and_serialize(o_signature.value().copy(), promise.serialize()); - } else { - return SignedPromise::create_and_serialize(key, promise.serialize()); - } - } -}; - -} // namespace pchan - -class PaymentChannel : public SmartContract { - public: - PaymentChannel(State state) : SmartContract(std::move(state)) { - } - - struct Info { - pchan::Config config; - td::Variant state; - std::string description; - }; - td::Result get_info() const; - - static td::Ref create(State state) { - return td::Ref(true, std::move(state)); - } - static td::optional guess_revision(const vm::Cell::Hash& code_hash); - static td::Ref create(const pchan::Config& config, td::int32 revision) { - State state; - state.code = SmartContractCode::get_code(SmartContractCode::PaymentChannel, revision); - pchan::Data data; - data.config = config.serialize(); - pchan::StateInit init; - data.state = init.serialize(); - state.data = data.serialize(); - return create(std::move(state)); - } -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp deleted file mode 100644 index 79a2a823..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "SmartContract.h" - -#include "GenericAccount.h" - -#include "block/block.h" -#include "block/block-auto.h" -#include "vm/cellslice.h" -#include "vm/cp0.h" -#include "vm/memo.h" -#include "vm/vm.h" - -#include "td/utils/crypto.h" - -namespace ton { -namespace { - -td::Ref prepare_vm_stack(td::RefInt256 amount, td::Ref body) { - td::Ref stack_ref{true}; - td::RefInt256 acc_addr{true}; - //CHECK(acc_addr.write().import_bits(account.addr.cbits(), 256)); - vm::Stack& stack = stack_ref.write(); - stack.push_int(td::make_refint(10000000000)); - stack.push_int(std::move(amount)); - stack.push_cell(vm::CellBuilder().finalize()); - stack.push_cellslice(std::move(body)); - return stack_ref; -} - -td::Ref prepare_vm_c7(td::uint32 now, td::uint64 balance) { - // TODO: fix initialization of c7 - td::BitArray<256> rand_seed; - rand_seed.as_slice().fill(0); - td::RefInt256 rand_seed_int{true}; - rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false); - auto tuple = vm::make_tuple_ref( - td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea - td::make_refint(0), // actions:Integer - td::make_refint(0), // msgs_sent:Integer - td::make_refint(now), // unixtime:Integer - td::make_refint(0), // block_lt:Integer - td::make_refint(0), // trans_lt:Integer - std::move(rand_seed_int), // rand_seed:Integer - block::CurrencyCollection(balance).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] - vm::load_cell_slice_ref(vm::CellBuilder().finalize()) // myself:MsgAddressInt - //vm::StackEntry::maybe(td::Ref()) - ); // global_config:(Maybe Cell) ] = SmartContractInfo; - //LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); - return vm::make_tuple_ref(std::move(tuple)); -} - -static int output_actions_count(td::Ref list) { - int i = -1; - do { - ++i; - list = load_cell_slice(std::move(list)).prefetch_ref(); - } while (list.not_null()); - return i; -} - -SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref stack, td::Ref c7, - vm::GasLimits gas, bool ignore_chksig) { - auto gas_credit = gas.gas_credit; - vm::init_op_cp0(); - vm::DictionaryBase::get_empty_dictionary(); - - class Logger : public td::LogInterface { - public: - void append(td::CSlice slice) override { - res.append(slice.data(), slice.size()); - } - std::string res; - }; - Logger logger; - vm::VmLog log{&logger, td::LogOptions::plain()}; - - if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { - log.log_options.level = 4; - log.log_options.fix_newlines = true; - log.log_mask |= vm::VmLog::DumpStack; - } else { - log.log_options.level = 0; - log.log_mask = 0; - } - - SmartContract::Answer res; - if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { - std::ostringstream os; - stack->dump(os, 2); - LOG(DEBUG) << "VM stack:\n" << os.str(); - } - vm::VmState vm{state.code, std::move(stack), gas, 1, state.data, log}; - vm.set_c7(std::move(c7)); - vm.set_chksig_always_succeed(ignore_chksig); - try { - res.code = ~vm.run(); - } catch (...) { - LOG(FATAL) << "catch unhandled exception"; - } - res.new_state = std::move(state); - res.stack = vm.get_stack_ref(); - gas = vm.get_gas_limits(); - res.gas_used = gas.gas_consumed(); - res.accepted = gas.gas_credit == 0; - res.success = (res.accepted && (unsigned)res.code <= 1); - if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { - LOG(DEBUG) << "VM log\n" << logger.res; - std::ostringstream os; - res.stack->dump(os, 2); - LOG(DEBUG) << "VM stack:\n" << os.str(); - LOG(DEBUG) << "VM exit code: " << res.code; - LOG(DEBUG) << "VM accepted: " << res.accepted; - LOG(DEBUG) << "VM success: " << res.success; - } - if (res.success) { - res.new_state.data = vm.get_c4(); - res.actions = vm.get_d(5); - LOG(DEBUG) << "output actions:\n" - << block::gen::OutList{output_actions_count(res.actions)}.as_string_ref(res.actions); - } - LOG_IF(ERROR, gas_credit != 0 && (res.accepted && !res.success)) - << "Accepted but failed with code " << res.code << "\n" - << res.gas_used << "\n"; - return res; -} -} // namespace - -td::Result SmartContract::Args::get_serialized_stack() { - if (!stack) { - return td::Status::Error("Args has no stack"); - } - vm::FakeVmStateLimits fstate(1000); // limit recursive (de)serialization calls - vm::VmStateInterface::Guard guard(&fstate); - // serialize parameters - vm::CellBuilder cb; - td::Ref cell; - if (!(stack.value()->serialize(cb) && cb.finalize_to(cell))) { - return td::Status::Error("Cannot serialize stack in args"); - } - return vm::std_boc_serialize(std::move(cell)); -} - -td::Ref SmartContract::empty_slice() { - return vm::load_cell_slice_ref(vm::CellBuilder().finalize()); -} - -size_t SmartContract::code_size() const { - return vm::std_boc_serialize(state_.code).ok().size(); -} -size_t SmartContract::data_size() const { - return vm::std_boc_serialize(state_.data).ok().size(); -} - -block::StdAddress SmartContract::get_address(WorkchainId workchain_id) const { - return GenericAccount::get_address(workchain_id, get_init_state()); -} - -td::Ref SmartContract::get_init_state() const { - return GenericAccount::get_init_state(get_state().code, get_state().data); -} - -SmartContract::Answer SmartContract::run_method(Args args) { - td::uint32 now = 0; - if (args.now) { - now = args.now.unwrap(); - } - if (!args.c7) { - args.c7 = prepare_vm_c7(now, args.balance); - } - if (!args.limits) { - bool is_internal = args.get_method_id().ok() == 0; - - args.limits = vm::GasLimits{is_internal ? (long long)args.amount * 1000 : (long long)0, (long long)1000000, - is_internal ? 0 : (long long)10000}; - } - CHECK(args.stack); - CHECK(args.method_id); - args.stack.value().write().push_smallint(args.method_id.unwrap()); - auto res = - run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig); - state_ = res.new_state; - return res; -} - -SmartContract::Answer SmartContract::run_get_method(Args args) const { - td::uint32 now = 0; - if (args.now) { - now = args.now.unwrap(); - } - if (!args.c7) { - args.c7 = prepare_vm_c7(now, args.balance); - } - if (!args.limits) { - args.limits = vm::GasLimits{1000000}; - } - if (!args.stack) { - args.stack = td::Ref(true); - } - CHECK(args.method_id); - args.stack.value().write().push_smallint(args.method_id.unwrap()); - return run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig); -} - -SmartContract::Answer SmartContract::run_get_method(td::Slice method, Args args) const { - return run_get_method(args.set_method_id(method)); -} - -SmartContract::Answer SmartContract::send_external_message(td::Ref cell, Args args) { - return run_method( - args.set_stack(prepare_vm_stack(td::make_refint(0), vm::load_cell_slice_ref(cell))).set_method_id(-1)); -} -SmartContract::Answer SmartContract::send_internal_message(td::Ref cell, Args args) { - return run_method( - args.set_stack(prepare_vm_stack(td::make_refint(args.amount), vm::load_cell_slice_ref(cell))).set_method_id(0)); -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h deleted file mode 100644 index 89f5c8c7..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "vm/cells.h" -#include "vm/stack.hpp" -#include "vm/vm.h" - -#include "td/utils/optional.h" -#include "td/utils/crypto.h" - -#include "block/block.h" - -namespace ton { -class SmartContract : public td::CntObject { - static td::Ref empty_slice(); - - public: - struct State { - td::Ref code; - td::Ref data; - }; - - SmartContract(State state) : state_(std::move(state)) { - } - - struct Answer { - SmartContract::State new_state; - bool accepted; - bool success; - td::Ref stack; - td::Ref actions; - td::int32 code; - td::int64 gas_used; - }; - - struct Args { - td::optional method_id; - td::optional limits; - td::optional> c7; - td::optional> stack; - td::optional now; - bool ignore_chksig{false}; - td::uint64 amount{0}; - td::uint64 balance{0}; - - Args() { - } - Args(std::initializer_list stack) - : stack(td::Ref(true, std::vector(std::move(stack)))) { - } - Args&& set_now(int now) { - this->now = now; - return std::move(*this); - } - Args&& set_method_id(td::Slice method_name) { - unsigned crc = td::crc16(method_name); - return set_method_id((crc & 0xffff) | 0x10000); - } - Args&& set_method_id(td::int32 method_id) { - this->method_id = method_id; - return std::move(*this); - } - Args&& set_limits(vm::GasLimits limits) { - this->limits = std::move(limits); - return std::move(*this); - } - Args&& set_c7(td::Ref c7) { - this->c7 = std::move(c7); - return std::move(*this); - } - Args&& set_stack(std::vector stack) { - this->stack = td::Ref(true, std::move(stack)); - return std::move(*this); - } - Args&& set_stack(td::Ref stack) { - this->stack = std::move(stack); - return std::move(*this); - } - Args&& set_ignore_chksig(bool ignore_chksig) { - this->ignore_chksig = ignore_chksig; - return std::move(*this); - } - Args&& set_amount(td::uint64 amount) { - this->amount = amount; - return std::move(*this); - } - Args&& set_balance(td::uint64 balance) { - this->balance = balance; - return std::move(*this); - } - - td::Result get_method_id() const { - if (!method_id) { - return td::Status::Error("Args has no method id"); - } - return method_id.value(); - } - td::Result get_serialized_stack(); - }; - - Answer run_method(Args args = {}); - Answer run_get_method(Args args = {}) const; - Answer run_get_method(td::Slice method, Args args = {}) const; - Answer send_external_message(td::Ref cell, Args args = {}); - Answer send_internal_message(td::Ref cell, Args args = {}); - - size_t code_size() const; - size_t data_size() const; - static td::Ref create(State state) { - return td::Ref{true, std::move(state)}; - } - - block::StdAddress get_address(WorkchainId workchain_id = basechainId) const; - td::Ref get_init_state() const; - - const State& get_state() const { - return state_; - } - CntObject* make_copy() const override { - return new SmartContract(state_); - } - - protected: - State state_; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp deleted file mode 100644 index 5ae940a1..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include - -#include "td/utils/base64.h" - -namespace ton { -namespace { -// WALLET_REVISION = 2; -// WALLET2_REVISION = 2; -// WALLET3_REVISION = 2; -// HIGHLOAD_WALLET_REVISION = 2; -// HIGHLOAD_WALLET2_REVISION = 2; -// DNS_REVISION = 1; -const auto& get_map() { - static auto map = [] { - std::map, std::less<>> map; - auto with_tvm_code = [&](auto name, td::Slice code_str) { - map[name] = vm::std_boc_deserialize(td::base64_decode(code_str).move_as_ok()).move_as_ok(); - }; -#include "smartcont/auto/multisig-code.cpp" -#include "smartcont/auto/simple-wallet-ext-code.cpp" -#include "smartcont/auto/simple-wallet-code.cpp" -#include "smartcont/auto/wallet-code.cpp" -#include "smartcont/auto/highload-wallet-code.cpp" -#include "smartcont/auto/highload-wallet-v2-code.cpp" -#include "smartcont/auto/dns-manual-code.cpp" -#include "smartcont/auto/payment-channel-code.cpp" -#include "smartcont/auto/restricted-wallet3-code.cpp" - - with_tvm_code("highload-wallet-r1", - "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/" - "0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/" - "8ntVAAE0DAAEaCZL9qJoa4WPw=="); - with_tvm_code("highload-wallet-r2", - "te6ccgEBCAEAlwABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC48oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/" - "0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhYhgBD0eG+lIJgC0wfUMAH7AJEy4gGz5lsBpMjLH8sfy//" - "J7VQABNAwAgFIBgcAF7s5ztRNDTPzHXC/+AARuMl+1E0NcLH4"); - with_tvm_code("highload-wallet-v2-r1", - "te6ccgEBBwEA1gABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//" - "QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+" - "hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/" - "mPoCaKkQQCB6BzfQmMktv8ld0fFADgggED0lm+hb6EyURCUMFMDud4gkzM2AZIyMOKz"); - with_tvm_code("highload-wallet-v2-r2", - "te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQHq8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//" - "QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44WIYAQ9HhvpSCYAtMH1DAB+wCRMuIBs+" - "ZbgyWhyEA0gED0Q4rmMcgSyx8Tyz/L//QAye1UCAAE0DACASAGBwAXvZznaiaGmvmOuF/8AEG+X5dqJoaY+Y6Z/p/" - "5j6AmipEEAgegc30JjJLb/JXdHxQANCCAQPSWb6UyURCUMFMDud4gkzM2AZIyMOKz"); - with_tvm_code("simple-wallet-r1", - "te6ccgEEAQEAAAAAUwAAov8AIN0gggFMl7qXMO1E0NcLH+Ck8mCBAgDXGCDXCx/tRNDTH9P/" - "0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVA=="); - with_tvm_code("simple-wallet-r2", - "te6ccgEBAQEAXwAAuv8AIN0gggFMl7ohggEznLqxnHGw7UTQ0x/XC//jBOCk8mCBAgDXGCDXCx/tRNDTH9P/" - "0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVA=="); - with_tvm_code("wallet-r1", - "te6ccgEBAQEAVwAAqv8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/0VExuvKhA/" - "kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQ="); - with_tvm_code("wallet-r2", - "te6ccgEBAQEAYwAAwv8AIN0gggFMl7ohggEznLqxnHGw7UTQ0x/XC//jBOCk8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/" - "0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQ="); - with_tvm_code("wallet3-r1", - "te6ccgEBAQEAYgAAwP8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/" - "9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVA=="); - with_tvm_code("wallet3-r2", - "te6ccgEBAQEAcQAA3v8AIN0gggFMl7ohggEznLqxn3Gw7UTQ0x/THzHXC//jBOCk8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/" - "T/9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVA=="); - with_tvm_code( - "dns-manual-r1", - "te6ccgECGAEAAtAAART/APSkE/S88sgLAQIBIAIDAgFIBAUC7PLbPAWDCNcYIPkBAdMf0z/" - "4I6ofUyC58mNTKoBA9A5voTHyYFKUuvKiVBNG+RDyo/gAItcLBcAzmDQBdtch0/" - "8wjoVa2zxAA+" - "IDgyWhyEAHgED0Q44aIIBA9JZvpTJREJQwUwe53iCTMzUBkjIw4rPmNVUD8AQREgICxQYHAgEgDA0CAc8ICQAIqoJfAwIBSAoLACHWQK5Y+" - "J5Z/l//oAegBk9qpAAFF8DgABcyPQAydBBM/Rw8qGAAF72c52omhpr5jrhf/" - "AIBIA4PABG7Nz7UTQ1wsfgD+" - "7owwh10kglF8DcG3hIHew8l4ieNci1wsHnnDIUATPFhPLB8nQAqYI3iDACJRfA3Bt4Ns8FF8EI3ADqwKY0wcBwAAToQLkIG2OnF8DIcjLBiTPF" - "snQhAlUQgHbPAWlFbIgwQEVQzDmMzUilF8FcG3hMgHHAJMxfwHfAtdJpvmBEVEAAYIcAAkjEB4AKAEPRqABztRNDTH9M/0//" - "0BPQE0QE2cFmOlNs8IMcBnCDXSpPUMNCTMn8C4t4i5jAxEwT20wUhwQqOLCGRMeEhwAGXMdMH1AL7AOABwAmOFNQh+wTtQwLQ7R7tU1RiA/" - "EGgvIA4PIt4HAiwRSUMNIPAd5tbSTBHoreJMEUjpElhAkj2zwzApUyxwDyo5Fb4t4kwAuOEzQC9ARQJIAQ9G4wECOECVnwAQHgJMAMiuAwFBUW" - "FwCEMQLTAAHAAZPUAdCY0wUBqgLXGAHiINdJwg/" - "ypiB41yLXCwfyaHBTEddJqTYCmNMHAcAAEqEB5DDIywYBzxbJ0FADACBZ9KhvpSCUAvQEMJIybeICACg0A4AQ9FqZECOECUBE8AEBkjAx4gBmM" - "SLAFZwy9AQQI4QJUELwAQHgIsAWmDIChAn0czAB4DAyIMAfkzD0BODAIJJtAeDyLG0B"); - with_tvm_code( - "restricted-wallet3-r1", - "te6ccgECEgEAAUsAART/APSkE/S88sgLAQIBIAIDAgFIBAUD+PKDCNcYINMf0x/THwL4I7vyY+1E0NMf0x/T/" - "1NDuvKhUWK68qIG+QFUEHb5EPKkAY4fMwHT/9EB0x/0BNH4AAOkyMsfFMsfy/8Syx/0AMntVOEC0x/" - "0BNH4ACH4I9s8IYAg9HtvpTGW+gAwcvsCkTDiApMg10qK6NECpMgPEBEABNAwAgEgBgcCASAICQIBSAwNAgFuCgsAEbjJftRNDXCx+" - "AAXrc52omhpn5jrhf/AABesePaiaGmPmOuFj8ABDbbYHwR7Z5AOAQm1B1tnkA4BTu1E0IEBQNch0x/" - "0BNEC2zz4J28QAoAg9HtvpTGX+gAwoXC2CZEw4g8AOiGOETGA8/gzIG6SMHCU0NcLH+IB3yGSAaGSW3/iAAzTB9QC+wAAHssfFMsfEsv/yx/" - "0AMntVA=="); - return map; - }(); - return map; -} -} // namespace - -td::Result> SmartContractCode::load(td::Slice name) { - auto& map = get_map(); - auto it = map.find(name); - if (it == map.end()) { - return td::Status::Error(PSLICE() << "Can't load td::Ref " << name); - } - return it->second; -} - -td::Span SmartContractCode::get_revisions(Type type) { - switch (type) { - case Type::WalletV1: { - static int res[] = {1, 2}; - return res; - } - case Type::WalletV2: { - static int res[] = {1, 2}; - return res; - } - case Type::WalletV3: { - static int res[] = {1, 2}; - return res; - } - case Type::WalletV1Ext: { - static int res[] = {-1}; - return res; - } - case Type::HighloadWalletV1: { - static int res[] = {-1, 1, 2}; - return res; - } - case Type::HighloadWalletV2: { - static int res[] = {-1, 1, 2}; - return res; - } - case Type::Multisig: { - static int res[] = {-1}; - return res; - } - case Type::ManualDns: { - static int res[] = {-1, 1}; - return res; - } - case Type::PaymentChannel: { - static int res[] = {-1}; - return res; - } - case Type::RestrictedWallet: { - static int res[] = {1}; - return res; - } - } - UNREACHABLE(); - return {}; -} - -td::Result SmartContractCode::validate_revision(Type type, int revision) { - auto revisions = get_revisions(type); - if (revision == -1) { - if (revisions[0] == -1) { - return -1; - } - return revisions[revisions.size() - 1]; - } - if (revision == 0) { - return revisions[revisions.size() - 1]; - } - for (auto x : revisions) { - if (x == revision) { - return revision; - } - } - return td::Status::Error("No such revision"); -} - -td::Ref SmartContractCode::get_code(Type type, int ext_revision) { - auto revision = validate_revision(type, ext_revision).move_as_ok(); - auto basename = [](Type type) -> td::Slice { - switch (type) { - case Type::WalletV1: - return "simple-wallet"; - case Type::WalletV2: - return "wallet"; - case Type::WalletV3: - return "wallet3"; - case Type::WalletV1Ext: - return "simple-wallet-ext"; - case Type::HighloadWalletV1: - return "highload-wallet"; - case Type::HighloadWalletV2: - return "highload-wallet-v2"; - case Type::Multisig: - return "multisig"; - case Type::ManualDns: - return "dns-manual"; - case Type::PaymentChannel: - return "payment-channel"; - case Type::RestrictedWallet: - return "restricted-wallet3"; - } - UNREACHABLE(); - return ""; - }(type); - if (revision == -1) { - return load(basename).move_as_ok(); - } - return load(PSLICE() << basename << "-r" << revision).move_as_ok(); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h deleted file mode 100644 index e9ca1c54..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells.h" - -#include "td/utils/Span.h" - -namespace ton { -class SmartContractCode { - public: - static td::Result> load(td::Slice name); - - enum Type { - WalletV1 = 1, - WalletV1Ext, - WalletV2, - WalletV3, - HighloadWalletV1, - HighloadWalletV2, - ManualDns, - Multisig, - PaymentChannel, - RestrictedWallet - }; - static td::Span get_revisions(Type type); - static td::Result validate_revision(Type type, int revision); - static td::Ref get_code(Type type, int revision = 0); -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp deleted file mode 100644 index 2a169183..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "TestGiver.h" -#include "GenericAccount.h" - -#include "td/utils/base64.h" - -namespace ton { -const block::StdAddress& TestGiver::address() noexcept { - static block::StdAddress res = - block::StdAddress::parse("kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny").move_as_ok(); - //static block::StdAddress res = - //block::StdAddress::parse("kf9tswzQaryeJ4aAYLy_phLhx4afF1aEvpUVak-2BuA0CmZi").move_as_ok(); - return res; -} - -vm::CellHash TestGiver::get_init_code_hash() noexcept { - return vm::CellHash::from_slice(td::base64_decode("wDkZp0yR4xo+9+BnuAPfGVjBzK6FPzqdv2DwRq3z3KE=").move_as_ok()); - //return vm::CellHash::from_slice(td::base64_decode("YV/IANhoI22HVeatFh6S5LbCHp+5OilARfzW+VQPZgQ=").move_as_ok()); -} - -td::Ref TestGiver::make_a_gift_message_static(td::uint32 seqno, td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - - vm::CellBuilder cb; - cb.store_long(seqno, 32); - - for (auto& gift : gifts) { - td::int32 send_mode = 1; - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - } - - return cb.finalize(); -} - -td::Result TestGiver::get_seqno() const { - return TRY_VM(get_seqno_or_throw()); -} - -td::Result TestGiver::get_seqno_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - auto seqno = vm::load_cell_slice(state_.data).fetch_ulong(32); - if (seqno == vm::CellSlice::fetch_ulong_eof) { - return td::Status::Error("Failed to parse seq_no"); - } - return static_cast(seqno); -} -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h deleted file mode 100644 index b51ac7db..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "block/block.h" -#include "vm/cells/CellString.h" -namespace ton { -class TestGiver : public SmartContract, public WalletInterface { - public: - explicit TestGiver(State state) : ton::SmartContract(std::move(state)) { - } - TestGiver() : ton::SmartContract({}) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 1; - static const block::StdAddress& address() noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref make_a_gift_message_static(td::uint32 seqno, td::Span) noexcept; - - td::Result get_seqno() const; - - using WalletInterface::get_init_message; - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(seqno, get_seqno()); - return make_a_gift_message_static(seqno, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - - private: - td::Result get_seqno_or_throw() const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp deleted file mode 100644 index 41a66b68..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . -Copyright 2017-2020 Telegram Systems LLP -*/ -#include "TestWallet.h" -#include "GenericAccount.h" - -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include "td/utils/base64.h" - -namespace ton { -td::Ref TestWallet::get_init_state(const td::Ed25519::PublicKey& public_key, td::int32 revision) noexcept { - auto code = get_init_code(revision); - auto data = get_init_data(public_key); - return GenericAccount::get_init_state(std::move(code), std::move(data)); -} - -td::Ref TestWallet::get_init_message_new(const td::Ed25519::PrivateKey& private_key) noexcept { - std::string seq_no(4, 0); - auto signature = - private_key.sign(vm::CellBuilder().store_bytes(seq_no).finalize()->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).store_bytes(seq_no).finalize(); -} - -td::Ref TestWallet::make_a_gift_message_static(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, - td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - - vm::CellBuilder cb; - cb.store_long(seqno, 32); - - for (auto& gift : gifts) { - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - } - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); -} - -td::Ref TestWallet::get_init_code(td::int32 revision) noexcept { - return ton::SmartContractCode::get_code(ton::SmartContractCode::WalletV1, revision); -} - -vm::CellHash TestWallet::get_init_code_hash() noexcept { - return get_init_code()->get_hash(); -} - -td::Ref TestWallet::get_data(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) noexcept { - return vm::CellBuilder().store_long(seqno, 32).store_bytes(public_key.as_octet_string()).finalize(); -} - -td::Ref TestWallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept { - return get_data(public_key, 0); -} - -td::Result TestWallet::get_seqno() const { - return TRY_VM(get_seqno_or_throw()); -} - -td::Result TestWallet::get_seqno_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - auto seqno = vm::load_cell_slice(state_.data).fetch_ulong(32); - if (seqno == vm::CellSlice::fetch_ulong_eof) { - return td::Status::Error("Failed to parse seq_no"); - } - return static_cast(seqno); -} - -td::Result TestWallet::get_public_key() const { - return TRY_VM(get_public_key_or_throw()); -} - -td::Result TestWallet::get_public_key_or_throw() const { - if (state_.data.is_null()) { - return td::Status::Error("data is null"); - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(32); - td::SecureString res(td::Ed25519::PublicKey::LENGTH); - cs.fetch_bytes(res.as_mutable_slice().ubegin(), td::narrow_cast(res.size())); - return td::Ed25519::PublicKey(std::move(res)); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h deleted file mode 100644 index 38e0f12b..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "vm/cells.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -namespace ton { -class TestWallet : public ton::SmartContract, public WalletInterface { - public: - explicit TestWallet(State state) : ton::SmartContract(std::move(state)) { - } - explicit TestWallet(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) - : TestWallet(State{get_init_code(), get_data(public_key, seqno)}) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 1; - static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::int32 revision = 0) noexcept; - static td::Ref get_init_message_new(const td::Ed25519::PrivateKey& private_key) noexcept; - static td::Ref make_a_gift_message_static(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, - td::Span gifts) noexcept; - - static td::Ref get_init_code(td::int32 revision = 0) noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref get_data(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) noexcept; - static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key) noexcept; - - td::Result get_seqno() const; - - using WalletInterface::get_init_message; - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(seqno, get_seqno()); - return make_a_gift_message_static(private_key, seqno, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - - td::Result get_public_key() const override; - - private: - td::Result get_seqno_or_throw() const; - td::Result get_public_key_or_throw() const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp deleted file mode 100644 index fac4f1a6..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "Wallet.h" -#include "GenericAccount.h" -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include "vm/cells/CellString.h" -#include "td/utils/base64.h" - -#include - -namespace ton { -td::Ref Wallet::get_init_state(const td::Ed25519::PublicKey& public_key, td::int32 revision) noexcept { - auto code = get_init_code(revision); - auto data = get_init_data(public_key); - return GenericAccount::get_init_state(std::move(code), std::move(data)); -} - -td::Ref Wallet::get_init_message_new(const td::Ed25519::PrivateKey& private_key) noexcept { - td::uint32 seqno = 0; - td::uint32 valid_until = std::numeric_limits::max(); - auto signature = - private_key - .sign(vm::CellBuilder().store_long(seqno, 32).store_long(valid_until, 32).finalize()->get_hash().as_slice()) - .move_as_ok(); - return vm::CellBuilder().store_bytes(signature).store_long(seqno, 32).store_long(valid_until, 32).finalize(); -} - -td::Ref Wallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, - td::uint32 valid_until, td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - - vm::CellBuilder cb; - cb.store_long(seqno, 32).store_long(valid_until, 32); - - for (auto& gift : gifts) { - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - } - - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); -} - -td::Ref Wallet::get_init_code(td::int32 revision) noexcept { - return SmartContractCode::get_code(ton::SmartContractCode::WalletV2, revision); -} - -vm::CellHash Wallet::get_init_code_hash() noexcept { - return get_init_code()->get_hash(); -} - -td::Ref Wallet::get_data(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) noexcept { - return vm::CellBuilder().store_long(seqno, 32).store_bytes(public_key.as_octet_string()).finalize(); -} - -td::Ref Wallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept { - return get_data(public_key, 0); -} - -td::Result Wallet::get_seqno() const { - return TRY_VM(get_seqno_or_throw()); -} - -td::Result Wallet::get_seqno_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); -} - -td::Result Wallet::get_public_key() const { - return TRY_VM(get_public_key_or_throw()); -} - -td::Result Wallet::get_public_key_or_throw() const { - if (state_.data.is_null()) { - return td::Status::Error("data is null"); - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(32); - td::SecureString res(td::Ed25519::PublicKey::LENGTH); - cs.fetch_bytes(res.as_mutable_slice().ubegin(), td::narrow_cast(res.size())); - return td::Ed25519::PublicKey(std::move(res)); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h deleted file mode 100644 index db074f6a..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "vm/cells.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -namespace ton { -class Wallet : public ton::SmartContract, public WalletInterface { - public: - explicit Wallet(State state) : ton::SmartContract(std::move(state)) { - } - explicit Wallet(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) - : Wallet(State{get_init_code(), get_data(public_key, seqno)}) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 4; - static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::int32 revision = 0) noexcept; - static td::Ref get_init_message_new(const td::Ed25519::PrivateKey& private_key) noexcept; - static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, - td::uint32 valid_until, td::Span gifts) noexcept; - - static td::Ref get_init_code(td::int32 revision = 0) noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key) noexcept; - static td::Ref get_data(const td::Ed25519::PublicKey& public_key, td::uint32 seqno) noexcept; - - td::Result get_seqno() const; - - using WalletInterface::get_init_message; - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(seqno, get_seqno()); - return make_a_gift_message(private_key, seqno, valid_until, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - - td::Result get_public_key() const override; - - private: - td::Result get_seqno_or_throw() const; - td::Result get_public_key_or_throw() const; -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletInterface.h b/submodules/ton/tonlib-src/crypto/smc-envelope/WalletInterface.h deleted file mode 100644 index d4113a6f..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletInterface.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -#include "SmartContract.h" -#include "GenericAccount.h" - -namespace ton { -class WalletInterface { - public: - struct Gift { - block::StdAddress destination; - td::int64 gramms; - - bool is_encrypted{false}; - std::string message; - - td::Ref body; - td::Ref init_state; - }; - - virtual ~WalletInterface() { - } - - virtual size_t get_max_gifts_size() const = 0; - virtual td::Result> make_a_gift_message(const td::Ed25519::PrivateKey &private_key, - td::uint32 valid_until, td::Span gifts) const = 0; - virtual td::Result get_public_key() const { - return td::Status::Error("Unsupported"); - } - - td::Result> get_init_message( - const td::Ed25519::PrivateKey &private_key, - td::uint32 valid_until = std::numeric_limits::max()) const { - return make_a_gift_message(private_key, valid_until, {}); - } - static td::Ref create_int_message(const Gift &gift) { - vm::CellBuilder cbi; - GenericAccount::store_int_message(cbi, gift.destination, gift.gramms < 0 ? 0 : gift.gramms); - if (gift.init_state.not_null()) { - cbi.store_ones(2); - cbi.store_ref(gift.init_state); - } else { - cbi.store_zeroes(1); - } - cbi.store_zeroes(1); - store_gift_message(cbi, gift); - return cbi.finalize(); - } - static void store_gift_message(vm::CellBuilder &cb, const Gift &gift) { - if (gift.body.not_null()) { - auto body = vm::load_cell_slice(gift.body); - //TODO: handle error - CHECK(cb.append_cellslice_bool(body)); - return; - } - - if (gift.is_encrypted) { - cb.store_long(1, 32); - } else { - cb.store_long(0, 32); - } - vm::CellString::store(cb, gift.message, 35 * 8).ensure(); - } -}; - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.cpp deleted file mode 100644 index 5bd7cfcd..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "WalletV3.h" -#include "GenericAccount.h" -#include "SmartContractCode.h" - -#include "vm/boc.h" -#include "vm/cells/CellString.h" -#include "td/utils/base64.h" - -#include - -namespace ton { -td::Ref WalletV3::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision) noexcept { - auto code = get_init_code(revision); - auto data = get_init_data(public_key, wallet_id); - return GenericAccount::get_init_state(std::move(code), std::move(data)); -} - -td::optional WalletV3::guess_revision(const vm::Cell::Hash& code_hash) { - for (td::int32 i = 1; i <= 2; i++) { - if (get_init_code(i)->get_hash() == code_hash) { - return i; - } - } - return {}; -} -td::optional WalletV3::guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) { - for (td::int32 i = 1; i <= 2; i++) { - if (GenericAccount::get_address(address.workchain, get_init_state(public_key, wallet_id, i)) == address) { - return i; - } - } - return {}; -} - -td::Ref WalletV3::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 seqno, td::uint32 valid_until, - td::Span gifts) noexcept { - CHECK(gifts.size() <= max_gifts_size); - - vm::CellBuilder cb; - cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_long(seqno, 32); - - for (auto& gift : gifts) { - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - } - - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); -} - -td::Ref WalletV3::get_init_code(td::int32 revision) noexcept { - return SmartContractCode::get_code(ton::SmartContractCode::WalletV3, revision); -} - -vm::CellHash WalletV3::get_init_code_hash() noexcept { - return get_init_code()->get_hash(); -} - -td::Ref WalletV3::get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::uint32 seqno) noexcept { - return vm::CellBuilder() - .store_long(seqno, 32) - .store_long(wallet_id, 32) - .store_bytes(public_key.as_octet_string()) - .finalize(); -} - -td::Result WalletV3::get_seqno() const { - return TRY_VM(get_seqno_or_throw()); -} - -td::Result WalletV3::get_seqno_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); -} - -td::Result WalletV3::get_wallet_id() const { - return TRY_VM(get_wallet_id_or_throw()); -} - -td::Result WalletV3::get_wallet_id_or_throw() const { - if (state_.data.is_null()) { - return 0; - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(32); - return static_cast(cs.fetch_ulong(32)); -} - -td::Result WalletV3::get_public_key() const { - return TRY_VM(get_public_key_or_throw()); -} - -td::Result WalletV3::get_public_key_or_throw() const { - if (state_.data.is_null()) { - return td::Status::Error("data is null"); - } - //FIXME use get method - auto cs = vm::load_cell_slice(state_.data); - cs.skip_first(64); - td::SecureString res(td::Ed25519::PublicKey::LENGTH); - cs.fetch_bytes(res.as_mutable_slice().ubegin(), td::narrow_cast(res.size())); - return td::Ed25519::PublicKey(std::move(res)); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.h b/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.h deleted file mode 100644 index b3e332dd..00000000 --- a/submodules/ton/tonlib-src/crypto/smc-envelope/WalletV3.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/WalletInterface.h" -#include "vm/cells.h" -#include "Ed25519.h" -#include "block/block.h" -#include "vm/cells/CellString.h" - -namespace ton { -class WalletV3 : public ton::SmartContract, public WalletInterface { - public: - explicit WalletV3(State state) : ton::SmartContract(std::move(state)) { - } - explicit WalletV3(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, td::uint32 seqno = 0) - : WalletV3(State{get_init_code(), get_init_data(public_key, wallet_id, seqno)}) { - } - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 4; - - static td::optional guess_revision(const vm::Cell::Hash& code_hash); - static td::optional guess_revision(const block::StdAddress& address, - const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); - static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::int32 revision = 0) noexcept; - static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id, - td::uint32 seqno, td::uint32 valid_until, td::Span gifts) noexcept; - - static td::Ref get_init_code(td::int32 revision = 0) noexcept; - static vm::CellHash get_init_code_hash() noexcept; - static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, - td::uint32 seqno = 0) noexcept; - - td::Result get_seqno() const; - td::Result get_wallet_id() const; - - using WalletInterface::get_init_message; - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - TRY_RESULT(seqno, get_seqno()); - TRY_RESULT(wallet_id, get_wallet_id()); - return make_a_gift_message(private_key, wallet_id, seqno, valid_until, gifts); - } - size_t get_max_gifts_size() const override { - return max_gifts_size; - } - td::Result get_public_key() const override; - - private: - td::Result get_seqno_or_throw() const; - td::Result get_wallet_id_or_throw() const; - td::Result get_public_key_or_throw() const; -}; -} // namespace ton - -#include "smc-envelope/SmartContractCode.h" -#include "smc-envelope/GenericAccount.h" -#include "block/block-parse.h" -#include -namespace ton { -template -class WalletBase : public SmartContract, public WalletInterface { - public: - using Traits = TraitsT; - using InitData = typename Traits::InitData; - - explicit WalletBase(State state) : SmartContract(std::move(state)) { - } - static td::Ref create(State state) { - return td::Ref(true, std::move(state)); - } - static td::Ref get_init_code(int revision) { - return SmartContractCode::get_code(get_code_type(), revision); - }; - size_t get_max_gifts_size() const override { - return Traits::max_gifts_size; - } - static SmartContractCode::Type get_code_type() { - return Traits::code_type; - } - static td::optional guess_revision(const vm::Cell::Hash& code_hash) { - for (auto i : ton::SmartContractCode::get_revisions(get_code_type())) { - auto code = SmartContractCode::get_code(get_code_type(), i); - if (code->get_hash() == code_hash) { - return i; - } - } - return {}; - } - - static td::Ref create(const InitData& init_data, int revision) { - return td::Ref(true, State{get_init_code(revision), WalletT::get_init_data(init_data)}); - } - - td::Result get_seqno() const { - return TRY_VM([&]() -> td::Result { - Answer answer = this->run_get_method("seqno"); - if (!answer.success) { - return td::Status::Error("seqno get method failed"); - } - return static_cast(answer.stack.write().pop_long_range(std::numeric_limits::max())); - }()); - } - td::Result get_wallet_id() const { - return TRY_VM([&]() -> td::Result { - Answer answer = this->run_get_method("wallet_id"); - if (!answer.success) { - return td::Status::Error("seqno get method failed"); - } - return static_cast(answer.stack.write().pop_long_range(std::numeric_limits::max())); - }()); - } - - td::Result get_balance(td::uint64 account_balance, td::uint32 now) const { - return TRY_VM([&]() -> td::Result { - Answer answer = this->run_get_method(Args().set_method_id("balance").set_balance(account_balance).set_now(now)); - if (!answer.success) { - return td::Status::Error("balance get method failed"); - } - return static_cast(answer.stack.write().pop_long()); - }()); - } - - td::Result get_public_key() const override { - return TRY_VM([&]() -> td::Result { - Answer answer = this->run_get_method("get_public_key"); - if (!answer.success) { - return td::Status::Error("get_public_key get method failed"); - } - auto key_int = answer.stack.write().pop_int(); - LOG(ERROR) << key_int->bit_size(false); - td::SecureString bytes(32); - if (!key_int->export_bytes(bytes.as_mutable_slice().ubegin(), bytes.size(), false)) { - return td::Status::Error("not a public key"); - } - return td::Ed25519::PublicKey(std::move(bytes)); - }()); - }; -}; - -struct RestrictedWalletTraits { - struct InitData { - td::SecureString init_key; - td::SecureString main_key; - td::uint32 wallet_id{0}; - }; - - static constexpr unsigned max_message_size = vm::CellString::max_bytes; - static constexpr unsigned max_gifts_size = 4; - static constexpr auto code_type = SmartContractCode::RestrictedWallet; -}; - -class RestrictedWallet : public WalletBase { - public: - struct Config { - td::uint32 start_at{0}; - std::vector> limits; - }; - - explicit RestrictedWallet(State state) : WalletBase(std::move(state)) { - } - - td::Result get_config() const { - return TRY_VM([this]() -> td::Result { - auto cs = vm::load_cell_slice(get_state().data); - Config config; - td::Ref dict_root; - auto ok = cs.advance(32 + 32 + 256) && cs.fetch_uint_to(32, config.start_at) && cs.fetch_maybe_ref(dict_root); - vm::Dictionary dict(std::move(dict_root), 32); - dict.check_for_each([&](auto cs, auto ptr, auto ptr_bits) { - auto r_seconds = td::narrow_cast_safe(dict.key_as_integer(ptr, true)->to_long()); - if (r_seconds.is_error()) { - ok = false; - return ok; - } - td::uint64 value; - ok &= smc::unpack_grams(cs, value); - config.limits.emplace_back(r_seconds.ok(), value); - return ok; - }); - if (!ok) { - return td::Status::Error("Can't parse config"); - } - std::sort(config.limits.begin(), config.limits.end()); - return config; - }()); - } - - static td::Ref get_init_data(const InitData& init_data) { - vm::CellBuilder cb; - cb.store_long(0, 32); - cb.store_long(init_data.wallet_id, 32); - CHECK(init_data.init_key.size() == 32); - CHECK(init_data.main_key.size() == 32); - cb.store_bytes(init_data.init_key.as_slice()); - cb.store_bytes(init_data.main_key.as_slice()); - return cb.finalize(); - } - - td::Result> get_init_message(const td::Ed25519::PrivateKey& init_private_key, - td::uint32 valid_until, const Config& config) const { - vm::CellBuilder cb; - TRY_RESULT(seqno, get_seqno()); - TRY_RESULT(wallet_id, get_wallet_id()); - LOG(ERROR) << "seqno: " << seqno << " wallet_id: " << wallet_id; - if (seqno != 0) { - return td::Status::Error("Wallet is already inited"); - } - - cb.store_long(wallet_id, 32); - cb.store_long(valid_until, 32); - cb.store_long(seqno, 32); - - cb.store_long(config.start_at, 32); - vm::Dictionary dict(32); - - auto add = [&](td::int32 till, td::uint64 value) { - auto key = dict.integer_key(td::make_refint(till), 32, true); - vm::CellBuilder gcb; - block::tlb::t_Grams.store_integer_value(gcb, td::BigInt256(value)); - dict.set_builder(key.bits(), 32, gcb); - }; - for (auto limit : config.limits) { - add(limit.first, limit.second); - } - cb.store_maybe_ref(dict.get_root_cell()); - - auto message_outer = cb.finalize(); - auto signature = init_private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); - } - - td::Result> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until, - td::Span gifts) const override { - CHECK(gifts.size() <= Traits::max_gifts_size); - - vm::CellBuilder cb; - TRY_RESULT(seqno, get_seqno()); - TRY_RESULT(wallet_id, get_wallet_id()); - if (seqno == 0) { - return td::Status::Error("Wallet is not inited yet"); - } - cb.store_long(wallet_id, 32); - cb.store_long(valid_until, 32); - cb.store_long(seqno, 32); - - for (auto& gift : gifts) { - td::int32 send_mode = 3; - if (gift.gramms == -1) { - send_mode += 128; - } - cb.store_long(send_mode, 8).store_ref(create_int_message(gift)); - } - - auto message_outer = cb.finalize(); - auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); - } -}; -} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp b/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp deleted file mode 100644 index 45e8891f..00000000 --- a/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "crypto/Ed25519.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Slice.h" -#include "td/utils/tests.h" -#include "td/utils/JsonBuilder.h" - -#include "wycheproof.h" - -#include -#include - -unsigned char fixed_privkey[32] = "abacabadabacabaeabacabadabacaba"; -unsigned char fixed_pubkey[32] = {0x6f, 0x9e, 0x5b, 0xde, 0xce, 0x87, 0x21, 0xeb, 0x57, 0x37, 0xfb, - 0xb5, 0x92, 0x28, 0xba, 0x07, 0xf7, 0x88, 0x0f, 0x73, 0xce, 0x5b, - 0xfa, 0xa1, 0xb7, 0x15, 0x73, 0x03, 0xd4, 0x20, 0x1e, 0x74}; - -unsigned char rfc8032_secret_key1[32] = {0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a, - 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32, - 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60}; - -unsigned char rfc8032_public_key1[32] = {0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe, - 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, - 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a}; - -unsigned char rfc8032_signature1[64] = { - 0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a, - 0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55, - 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, - 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b, -}; - -unsigned char rfc8032_secret_key2[32] = { - 0xc5, 0xaa, 0x8d, 0xf4, 0x3f, 0x9f, 0x83, 0x7b, 0xed, 0xb7, 0x44, 0x2f, 0x31, 0xdc, 0xb7, 0xb1, - 0x66, 0xd3, 0x85, 0x35, 0x07, 0x6f, 0x09, 0x4b, 0x85, 0xce, 0x3a, 0x2e, 0x0b, 0x44, 0x58, 0xf7, -}; - -unsigned char rfc8032_public_key2[32] = { - 0xfc, 0x51, 0xcd, 0x8e, 0x62, 0x18, 0xa1, 0xa3, 0x8d, 0xa4, 0x7e, 0xd0, 0x02, 0x30, 0xf0, 0x58, - 0x08, 0x16, 0xed, 0x13, 0xba, 0x33, 0x03, 0xac, 0x5d, 0xeb, 0x91, 0x15, 0x48, 0x90, 0x80, 0x25, -}; - -unsigned char rfc8032_message2[2] = {0xaf, 0x82}; - -unsigned char rfc8032_signature2[64] = { - 0x62, 0x91, 0xd6, 0x57, 0xde, 0xec, 0x24, 0x02, 0x48, 0x27, 0xe6, 0x9c, 0x3a, 0xbe, 0x01, 0xa3, - 0x0c, 0xe5, 0x48, 0xa2, 0x84, 0x74, 0x3a, 0x44, 0x5e, 0x36, 0x80, 0xd7, 0xdb, 0x5a, 0xc3, 0xac, - 0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59, - 0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, 0xc0, 0x27, 0xbe, 0xce, 0xea, 0x1e, 0xc4, 0x0a, -}; - -TEST(Crypto, ed25519) { - td::Ed25519::generate_private_key().ensure(); - - auto PK1 = td::Ed25519::generate_private_key().move_as_ok(); - auto PK2 = td::Ed25519::PrivateKey(td::SecureString(td::Slice(fixed_privkey, 32))); - LOG(ERROR) << "PK1 = " << td::buffer_to_hex(PK1.as_octet_string()); - auto priv2_export = PK2.as_octet_string(); - LOG(ERROR) << "PK2 = " << td::buffer_to_hex(priv2_export); - auto PK3 = td::Ed25519::PrivateKey(std::move(priv2_export)); - - auto PubK1 = PK1.get_public_key().move_as_ok(); - LOG(ERROR) << "PubK1 = " << td::buffer_to_hex(PubK1.as_octet_string()); - auto PubK2 = PK2.get_public_key().move_as_ok(); - LOG(ERROR) << "PubK2 = " << td::buffer_to_hex(PubK2.as_octet_string()); - CHECK(td::Slice(fixed_pubkey, 32) == PubK2.as_octet_string()); - auto PubK3 = PK3.get_public_key().move_as_ok(); - LOG(ERROR) << "PubK3 = " << td::buffer_to_hex(PubK3.as_octet_string()); - CHECK(td::Slice(fixed_pubkey, 32) == PubK3.as_octet_string()); - LOG(ERROR) << "PubK1 = " << td::buffer_to_hex(PubK1.as_octet_string()); - - auto secret22 = td::Ed25519::compute_shared_secret(PubK3, PK2).move_as_ok(); - LOG(ERROR) << "secret(PK2, PubK2)=" << td::buffer_to_hex(secret22); - - auto secret12 = td::Ed25519::compute_shared_secret(PubK3, PK1).move_as_ok(); - LOG(ERROR) << "secret(PK1, PubK2)=" << td::buffer_to_hex(secret12); - auto secret21 = td::Ed25519::compute_shared_secret(PubK1, PK2).move_as_ok(); - LOG(ERROR) << "secret(PK2, PubK1)=" << td::buffer_to_hex(secret21); - CHECK(secret12 == secret21); - - // for (int i = 0; i < 1000; i++) { - // td::Ed25519::compute_shared_secret(PubK2, PK1).ensure(); - // td::Ed25519::compute_shared_secret(PubK1, PK2).ensure(); - // } - - auto signature = PK1.sign("abc").move_as_ok(); - LOG(ERROR) << "PK1.signature=" << td::buffer_to_hex(signature); - - // signature[63] ^= 1; - auto ok = PubK1.verify_signature("abc", signature); - LOG(ERROR) << "PubK1.check_signature=" << ok; - ok.ensure(); - - td::Ed25519::PrivateKey PK4(td::SecureString(td::Slice(rfc8032_secret_key1, 32))); - auto PubK4 = PK4.get_public_key().move_as_ok(); - LOG(ERROR) << "PK4.private_key = " << td::buffer_to_hex(PK4.as_octet_string()); - LOG(ERROR) << "PK4.public_key = " << td::buffer_to_hex(PubK4.as_octet_string()); - CHECK(td::Slice(rfc8032_public_key1, 32) == PubK4.as_octet_string()); - signature = PK4.sign("").move_as_ok(); - LOG(ERROR) << "PK4.signature('') = " << td::buffer_to_hex(signature); - CHECK(signature == td::Slice(rfc8032_signature1, 64)); - - td::Ed25519::PrivateKey PK5(td::SecureString(td::Slice(rfc8032_secret_key2, 32))); - auto PubK5 = PK5.get_public_key().move_as_ok(); - LOG(ERROR) << "PK5.private_key = " << td::buffer_to_hex(PK5.as_octet_string()); - LOG(ERROR) << "PK5.public_key = " << td::buffer_to_hex(PubK5.as_octet_string()); - CHECK(td::Slice(rfc8032_public_key2, 32) == PubK5.as_octet_string()); - signature = PK5.sign(td::Slice(rfc8032_message2, 2)).move_as_ok(); - LOG(ERROR) << "PK5.signature('') = " << td::buffer_to_hex(signature); - CHECK(signature == td::Slice(rfc8032_signature2, 64)); - - // for (int i = 0; i < 100000; i++) { - // PK5.sign(td::Slice(rfc8032_message2, 2)); - // } - // for (int i = 0; i < 1000; i++) { - // PubK5.verify_signature(td::Slice(rfc8032_message2, 2), signature).ensure(); - // } - - /* - unsigned char temp_pubkey[32]; - crypto::Ed25519::TempKeyGenerator TKG; // use one generator a lot of times - - TKG.create_temp_shared_secret(temp_pubkey, secret12, PubK1, (const unsigned char*)"abc", 3); - LOG(ERROR) << "secret12=" << td::buffer_to_hex(secret12) << "; temp_pubkey=" << td::buffer_to_hex(temp_pubkey); - - PK1.compute_temp_shared_secret(secret21, temp_pubkey); - LOG(ERROR) << "secret21=" << td::buffer_to_hex(secret21); - assert(!std::memcmp(secret12, secret21, 32)); -*/ -} - -TEST(Crypto, wycheproof) { - std::vector> bad_tests; - auto json_str = wycheproof_ed25519(); - auto value = td::json_decode(json_str).move_as_ok(); - auto &root = value.get_object(); - auto test_groups_o = get_json_object_field(root, "testGroups", td::JsonValue::Type::Array, false).move_as_ok(); - auto &test_groups = test_groups_o.get_array(); - auto from_hexc = [](char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - return c - 'a' + 10; - }; - auto from_hex = [&](td::Slice s) { - CHECK(s.size() % 2 == 0); - std::string res(s.size() / 2, 0); - for (size_t i = 0; i < s.size(); i += 2) { - res[i / 2] = char(from_hexc(s[i]) * 16 + from_hexc(s[i + 1])); - } - return res; - }; - for (auto &test_o : test_groups) { - auto &test = test_o.get_object(); - auto key_o = get_json_object_field(test, "key", td::JsonValue::Type::Object, false).move_as_ok(); - auto sk_str = td::get_json_object_string_field(key_o.get_object(), "sk", false).move_as_ok(); - auto pk_str = td::get_json_object_string_field(key_o.get_object(), "pk", false).move_as_ok(); - auto pk = td::Ed25519::PublicKey(td::SecureString(from_hex(pk_str))); - auto sk = td::Ed25519::PrivateKey(td::SecureString(from_hex(sk_str))); - CHECK(sk.get_public_key().move_as_ok().as_octet_string().as_slice() == pk.as_octet_string().as_slice()); - - //auto key = - //td::Ed25519::PrivateKey::from_pem( - //td::SecureString(td::get_json_object_string_field(test, "keyPem", false).move_as_ok()), td::SecureString()) - //.move_as_ok(); - - auto tests_o = get_json_object_field(test, "tests", td::JsonValue::Type::Array, false).move_as_ok(); - auto &tests = tests_o.get_array(); - for (auto &test_o : tests) { - auto &test = test_o.get_object(); - auto id = td::get_json_object_string_field(test, "tcId", false).move_as_ok(); - auto comment = td::get_json_object_string_field(test, "comment", false).move_as_ok(); - auto sig = from_hex(td::get_json_object_string_field(test, "sig", false).move_as_ok()); - auto msg = from_hex(td::get_json_object_string_field(test, "msg", false).move_as_ok()); - auto result = td::get_json_object_string_field(test, "result", false).move_as_ok(); - auto has_result = pk.verify_signature(msg, sig).is_ok() ? "valid" : "invalid"; - if (result != has_result) { - bad_tests.push_back({id, comment}); - } - } - } - if (bad_tests.empty()) { - return; - } - LOG(ERROR) << "FAILED: " << td::format::as_array(bad_tests); -} - -TEST(Crypto, almost_zero) { - td::SecureString pub(32); - td::SecureString sig(64); - td::SecureString msg(1); - - pub.as_mutable_slice().ubegin()[31] = static_cast(128); - for (td::int32 j = 0; j < 256; j++) { - msg.as_mutable_slice()[0] = (char)j; - if (td::Ed25519::PublicKey(pub.copy()).verify_signature(msg, sig).is_ok()) { - LOG(ERROR) << "FAILED: " << j; - break; - } - } -} diff --git a/submodules/ton/tonlib-src/crypto/test/fift.cpp b/submodules/ton/tonlib-src/crypto/test/fift.cpp deleted file mode 100644 index 466ad4e7..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "fift/words.h" -#include "fift/Fift.h" -#include "fift/utils.h" - -#include "td/utils/tests.h" -#include "td/utils/PathView.h" -#include "td/utils/port/path.h" -#include "td/utils/filesystem.h" - -std::string current_dir() { - return td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str(); -} - -std::string load_test(std::string name) { - return td::read_file_str(current_dir() + "fift/" + name).move_as_ok(); -} - -td::Status run_fift(std::string name, bool preload_fift = true) { - TRY_RESULT(res, fift::mem_run_fift(load_test(name))); - REGRESSION_VERIFY(res.output); - return td::Status::OK(); -} - -TEST(Fift, testvm) { - run_fift("testvm.fif"); -} -TEST(Fift, testvm2) { - run_fift("testvm2.fif"); -} -TEST(Fift, testvm3) { - run_fift("testvm3.fif"); -} -TEST(Fift, testvm4) { - run_fift("testvm2.fif"); -} -TEST(Fift, testvm4a) { - run_fift("testvm4a.fif"); -} -TEST(Fift, testvm4b) { - run_fift("testvm4b.fif"); -} -TEST(Fift, testvm4c) { - run_fift("testvm4c.fif"); -} -TEST(Fift, testvm4d) { - run_fift("testvm4d.fif"); -} -TEST(Fift, testvm5) { - run_fift("testvm5.fif"); -} -TEST(Fift, testvm6) { - run_fift("testvm6.fif"); -} -TEST(Fift, testvm7) { - run_fift("testvm7.fif"); -} -TEST(Fift, testvm8) { - run_fift("testvm8.fif"); -} -TEST(Fift, testvmprog) { - run_fift("testvmprog.fif"); -} -TEST(Fift, bug) { - run_fift("bug.fif"); -} -TEST(Fift, contfrac) { - run_fift("contfrac.fif"); -} -TEST(Fift, test) { - run_fift("test.fif"); -} -TEST(Fift, bug_div) { - run_fift("bug_div.fif"); -} - -TEST(Fift, bug_ufits) { - run_fift("bug_ufits.fif"); -} - -TEST(Fift, test_dict) { - run_fift("testdict.fif"); -} - -TEST(Fift, test_fixed) { - run_fift("fixed.fif"); -} - -TEST(Fift, test_sort) { - run_fift("sort.fif"); -} - -TEST(Fift, test_sort2) { - run_fift("sort2.fif"); -} diff --git a/submodules/ton/tonlib-src/crypto/test/fift/bug.fif b/submodules/ton/tonlib-src/crypto/test/fift/bug.fif deleted file mode 100644 index 24440fed..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/bug.fif +++ /dev/null @@ -1,3 +0,0 @@ -10000000000000000000000000000000000000000000000000000000 dup . -dup 1 */ . - diff --git a/submodules/ton/tonlib-src/crypto/test/fift/bug_div.fif b/submodules/ton/tonlib-src/crypto/test/fift/bug_div.fif deleted file mode 100644 index 27ad386a..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/bug_div.fif +++ /dev/null @@ -1,12 +0,0 @@ -"Asm.fif" include - -1000 1 /r - -x{7A71A905} runvmcode - -<{ 1000 INT 1 INT DIVR }>s -dup csr. -runvmcode - -.s - diff --git a/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif b/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif deleted file mode 100644 index 6c607ea2..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif +++ /dev/null @@ -1 +0,0 @@ -100000000000000000 dup =: amount 56 ufits . amount 56 ufits . diff --git a/submodules/ton/tonlib-src/crypto/test/fift/cmdline.fif b/submodules/ton/tonlib-src/crypto/test/fift/cmdline.fif deleted file mode 100755 index 1194a428..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/cmdline.fif +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/fift -s -{ ."usage: " $0 type ." " cr - ."Computes the product of two integers." cr bye } : usage -{ ' usage if } : ?usage -$# 2 <> ?usage -$1 (number) 1- ?usage -$2 (number) 1- ?usage -* . cr diff --git a/submodules/ton/tonlib-src/crypto/test/fift/contfrac.fif b/submodules/ton/tonlib-src/crypto/test/fift/contfrac.fif deleted file mode 100644 index 585f9e18..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/contfrac.fif +++ /dev/null @@ -1,18 +0,0 @@ -{ dup 2over rot } : 3dup -{ 2drop drop } : 3drop -{ { 5 roll } 3 times } : 3swap -{ -rot over + rot over + -rot over + rot } : step1 -{ negate -rot negate swap negate } : step2 -{ 0 3 -roll { 3dup step1 dup 0> } { 3swap 3drop 3 roll 1+ 3 -roll } while 3drop step2 } : nsteps1 -{ ' nsteps1 swap times 3drop } : qcontfrac -{ -1 0 2swap qcontfrac } : sqrtcontfrac -{ rot 2 pick * + swap } : revstep1 -{ 1 0 rot ' revstep1 swap times } : computecontfrac -1 { 10 * } 74 times constant One -{ 100 sqrtcontfrac 100 computecontfrac */r } : *sqrtint -{ One swap *sqrtint } : sqrtint -2 sqrtint . -3 sqrtint . -6 sqrtint . -7 sqrtint . -239 sqrtint . diff --git a/submodules/ton/tonlib-src/crypto/test/fift/fixed.fif b/submodules/ton/tonlib-src/crypto/test/fift/fixed.fif deleted file mode 100644 index 779920cc..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/fixed.fif +++ /dev/null @@ -1,19 +0,0 @@ -1 { 10 * } 70 times constant One -{ bl word (number) dup 0= abort"invalid fixed-point constant" - 1- { One swap */r } { One * } cond 1 'nop } ::_ F$ -' + : F+ -' - : F- -{ One */r } : F* -{ One swap */r } : F/ -{ One dup rot */r } : Finv -{ One { 2dup F/ F+ 2/ } 9 times nip } : Fsqrt -{ ' Fsqrt 128 times One F- 128 << } : Fln -{ dup abs <# ' # 70 times char . hold #s rot sign #> - nip -trailing0 type space } : .F -F$17/12 .F -F$3.14159265 .F -{ 1 0 rot { -rot over + swap rot 2dup >= } until drop -} : fib-gtr -One fib-gtr F/ .F -F$2 Fsqrt .F -F$2 Fln .F diff --git a/submodules/ton/tonlib-src/crypto/test/fift/sort.fif b/submodules/ton/tonlib-src/crypto/test/fift/sort.fif deleted file mode 100644 index ac66cd60..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/sort.fif +++ /dev/null @@ -1,27 +0,0 @@ -{ null null rot - { dup null? not } - { uncons swap rot cons -rot } while drop -} : split -variable 'sort variable 'merge variable 'compare -{ 'sort @ execute } : sort -{ 'merge @ execute } : merge -{ 'compare @ execute } : compare -' < 'compare ! -{ dup null? { drop } { - over null? { nip } { - over car over car compare ' swap if - uncons rot merge cons - } cond - } cond -} 'merge ! -{ dup null? { - dup cdr null? { - split sort swap sort merge - } ifnot - } ifnot -} 'sort ! -3 1 4 1 5 9 2 6 5 9 list -dup .l cr sort .l cr -"once" "upon" "a" "time" "there" "lived" "a" "very" "little" "kitten" 10 list -{ $cmp 0< } 'compare ! -dup .l cr sort .l cr diff --git a/submodules/ton/tonlib-src/crypto/test/fift/sort2.fif b/submodules/ton/tonlib-src/crypto/test/fift/sort2.fif deleted file mode 100644 index 5611b179..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/sort2.fif +++ /dev/null @@ -1,28 +0,0 @@ -{ hole dup 1 { @ execute } does create 1 ' ! does create } : defvect -defvect sort :sort -defvect merge :merge -defvect less :less -' < :less -{ null null rot - { dup null? not } - { uncons swap rot cons -rot } while drop -} : split -{ dup null? { drop } { - over null? { nip } { - over car over car less ' swap if - uncons rot merge cons - } cond - } cond -} :merge -{ dup null? { - dup cdr null? { - split sort swap sort merge - } ifnot - } ifnot -} :sort -3 1 4 1 5 9 2 6 5 9 list -dup .l cr sort .l cr -"once" "upon" "a" "time" "there" "lived" "a" "very" "little" "kitten" 10 list -{ $cmp 0< } :less -dup .l cr sort .l cr - diff --git a/submodules/ton/tonlib-src/crypto/test/fift/test-stack-copy.fif b/submodules/ton/tonlib-src/crypto/test/fift/test-stack-copy.fif deleted file mode 100644 index 4fb10a34..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/test-stack-copy.fif +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/fift -s -"Asm.fif" include -2500 =: N -{ 5 * } : *K -N 100 / =: N/100 -N 10 / =: N/10 -{ { EXECUTE } 100 times } : 100EXECUTE -{ DUP { 2DUP } 7 times } : 15DUP -{ { 2DUP } 50 times } : 100DUP -{ { 15 -1 SETCONTARGS 15DUP } 10 times } : 10SET&DUP -<{ - CONT:<{ }> - 15DUP - N/10 INT REPEAT:<{ 10SET&DUP }> - N/100 *K INT REPEAT:<{ 100DUP }> - N/100 *K INT REPEAT:<{ 100EXECUTE }> -}>s =: Code - -Code csr. -Code 1000000 gasrunvmcode diff --git a/submodules/ton/tonlib-src/crypto/test/fift/test.fif b/submodules/ton/tonlib-src/crypto/test/fift/test.fif deleted file mode 100644 index 3221117c..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/test.fif +++ /dev/null @@ -1,24 +0,0 @@ -{ bl word 1 2 ' (create) } "::" 1 (create) -{ bl word 0 2 ' (create) } :: : -{ bl word 2 2 ' (create) } :: :_ -{ bl word 3 2 ' (create) } :: ::_ -{ bl word 0 (create) } : create -{ char " word 1 ' type } ::_ ." -{ char " word 1 { swap { abort } if drop } } ::_ abort" -{ dup * } : square -6 square . -{ swap ({) over 2+ -roll swap (compile) (}) } : does -{ 1 'nop does create } : constant -10 constant ten -ten . -ten ten * . -{ 1 ' emit does create } : emits -42 emits star -34 emits quote -30000 emits figna -star star quote figna quote -{ 0 word drop 0 'nop } ::_ // -star quote // end-to-line comment -{ 1 ' * does create } : mulby -3 mulby 3* -4 3* . diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testcc.fif b/submodules/ton/tonlib-src/crypto/test/fift/testcc.fif deleted file mode 100644 index 4cbd781c..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testcc.fif +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/create-state -s -{ dup tlb-type-lookup { nip } { "unknown TLB type " swap $+ abort } cond } : $>tlb -{ bl word $>tlb 1 'nop } ::_ tlb: -{ dup null? { drop true } { - " } cond cr } : cshow -{ ."X = " over dup .cc space .cc-valid cr - ."Y = " dup dup .cc space .cc-valid cr - ."X + Y = " 2dup CC+? cshow - ."X - Y = " 2dup CC-? cshow - ."Y - X = " 2dup swap CC-? cshow - ."X + X = " over dup CC+? cshow - ."Y + Y = " dup dup CC+? cshow - ."X - X = " over dup CC-? cshow - ."Y - Y = " dup dup CC-? cshow - 2drop ."********************" cr -} : one-test -CX{666666666666*$239+1000000000000*$-17} =: X -X CX{666666666666*$239+4444*$-17} one-test -X CX{666666666665*$239+4444*$-17} one-test -X CX{666666666667*$239+4444*$-17} one-test -X CX{666666666666*$239} one-test -X CX{666666666665*$239} one-test -X CX{666666666667*$239} one-test -X CX{1111*$1} one-test -X CX{0*$-17} one-test -X cc0 1 0 +newccpair one-test -X cc0 239 0 +newccpair one-test diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testdb.fif b/submodules/ton/tonlib-src/crypto/test/fift/testdb.fif deleted file mode 100644 index cbaa9817..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testdb.fif +++ /dev/null @@ -1,102 +0,0 @@ -"Asm.fif" include - -PROGRAM{ - -NEWPROC load_dict -NEWPROC generate_dict -NEWPROC save_dict - -NEWPROC do_get -NEWPROC do_set -NEWPROC do_erase - -main PROC:<{ - DUP 1 INT EQUAL IF:<{ - DROP - do_get CALL - }>ELSE<{ - DUP 2 INT EQUAL IF:<{ - DROP - do_set CALL - }>ELSE<{ - DUP 3 INT EQUAL IF:<{ - DROP - do_erase CALL - }> }> }> - -1 INT -}> - -do_get PROC:<{ - load_dict CALL - 32 INT - DICTIGET -}> - -do_set PROC:<{ - load_dict CALL - 32 INT - DICTISET - save_dict CALL -}> - -do_erase PROC:<{ - load_dict CALL - 32 INT - DICTIDEL - DROP - save_dict CALL -}> - -generate_dict PROC:<{ - 4 INT 100 INT REPEAT:<{ - DUP 2DUP MUL ROT 617 INT ADD 1000 INT MOD - }> - DROP 100 INT - NEWDICT - SWAP REPEAT:<{ - s0 s2 XCHG - NEWC - 16 STU - s0 s2 XCHG - 32 INT - DICTISETB - }> -}> - -load_dict PROC:<{ - PUSHROOT - CTOS DUP SEMPTY IF:<{ - DROP - generate_dict CALL - }> -}> - -save_dict PROC:<{ - NEWC - STSLICE - ENDC - POPROOT -}> - -}END>s constant pmc_prog - -{ 1 2 rot pmc_prog } : task_pmc_get -{ 2 3 rot pmc_prog } : task_pmc_set -{ 3 2 rot pmc_prog } : task_pmc_erase - -{ task_pmc_get dbrunvm 2drop } : pmc_get -{ task_pmc_set dbrunvm 2drop } : pmc_set -{ task_pmc_erase dbrunvm 2drop } : pmc_erase - - " .val ."; " true } dictforeach drop cr } : show-dict -{ key-bits { swap . ."-> " .val ."; " true } idictforeach drop cr } : show-idict -{ key-bits { swap . ."-> " .val ."; " true } dictforeachrev drop cr } : show-rev-dict -{ key-bits { swap . ."-> " .val ."; " true } idictforeachrev drop cr } : show-rev-idict -{ key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-dict-diff -{ key-bits { val@ swap val@ + val, true } dictmerge } : dict-sum -{ key-bits { val@ 2* val, true } dictmap } : dict-twice -{ key-bits { val@ 2 /mod { 2drop false } { val, true } cond } dictmap } : dict-half -{ key-bits { val@ + val, true } dictmapext } : dict-add-x -{ null swap key-bits { val@ pair swap cons true } dictforeach drop } : dict>list-rev -{ dict>list-rev list-reverse } : dict>list -( _( 13 169 ) _( 17 289 ) _( 10 100 ) ) mkdict =: Dict -_( 4 16 ) _( 9 81 ) Dict +dictpair +dictpair =: Dict1 -_( 4 20 ) _( 101 10201 ) Dict +dictpair +dictpair =: Dict2 -."Dict1 = " Dict1 show-dict -Dict1 dict>list .l cr -Dict1 " .val ."; " true } dictforeach drop cr } : show-dict -{ key-bits { swap . ."-> " .val ."; " true } idictforeach drop cr } : show-idict -{ key-bits { swap . ."-> " .val ."; " true } dictforeachrev drop cr } : show-rev-dict -{ key-bits { swap . ."-> " .val ."; " true } idictforeachrev drop cr } : show-rev-idict -{ key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-dict-diff -{ key-bits { swap . ."-> " .val ."; " true } rot dictforeachfromx drop cr } : show-dict-from -{ key-bits { val@ swap val@ + val, true } dictmerge } : dict-sum -{ key-bits { val@ 2* val, true } dictmap } : dict-twice -{ key-bits { val@ 2 /mod { 2drop false } { val, true } cond } dictmap } : dict-half -{ key-bits { val@ + val, true } dictmapext } : dict-add-x -{ null swap key-bits { val@ pair swap cons true } dictforeach drop } : dict>list-rev -{ dict>list-rev list-reverse } : dict>list -( _( 13 169 ) _( 17 289 ) _( 10 100 ) ) mkdict =: Dict -_( 4 16 ) _( 9 81 ) Dict +dictpair +dictpair =: Dict1 -_( 4 20 ) _( 101 10201 ) Dict +dictpair +dictpair =: Dict2 -_( 65533 9 ) Dict2 +dictpair =: Dict3 -."Dict1 = " Dict1 show-idict -."Dict2 = " Dict2 show-idict -."Dict3 = " Dict3 show-idict -variable D -{ D ! } : D! -{ ."D = " D @ show-idict } : show-D -{ D @ 2 show-dict-from } : show-D-from -{ D @ 6 show-dict-from } : show-D-from+ -{ D @ 18 show-dict-from } : show-D-from-hint -{ D @ 22 show-dict-from } : show-D-from-hint+ -variable hint hint 0! -{ ."D[" dup ._ ."..] = " show-D-from } : test-from -{ ."D[" dup ._ ."+..] = " show-D-from+ } : test-from+ -{ hint @ ."(hint=" dup ._ .") D[" over ._ ."..] = " show-D-from-hint } : test-from-hint -{ hint @ ."(hint=" dup ._ .") D[" over ._ ."+..] = " show-D-from-hint+ } : test-from-hint+ -{ -16 { 2dup swap execute 1+ } 120 times 2drop } : range-run -{ hint ! ' test-from-hint range-run ' test-from-hint+ range-run } : range-test-hint - -{ ."------- BIG TEST -------" cr show-D - ' test-from range-run ' test-from+ range-run - 0 range-test-hint 13 range-test-hint 7 range-test-hint 100 range-test-hint -} : big-test -Dict1 D! -big-test -Dict2 D! -big-test -Dict3 D! -big-test diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm.fif deleted file mode 100644 index a8396597..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm.fif +++ /dev/null @@ -1,10 +0,0 @@ -{ bl word 0 (create) } : create -{ swap ({) over 2+ -roll swap (compile) (}) } : does -{ 1 'nop does create } : constant -1 2 3 .s runvm .s -100 19 7 x{92A9069620C004F2F571F321A0} runvmcode .s -19 0 x{92A9069620C004F2F571F321A0} runvmcode .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm3.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm3.fif deleted file mode 100644 index d35369da..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm3.fif +++ /dev/null @@ -1,8 +0,0 @@ - x{C8} - x{62_} - x{A68054C_} |_ - x{A08090C_} |_ |_ - x{BEFDF21} |_ -dup csr. s>c -13 x{218010F40C} runvmcode .s drop swap csr. - diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm4.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm4.fif deleted file mode 100644 index f6cd5a2e..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm4.fif +++ /dev/null @@ -1,14 +0,0 @@ -169 13 -239 dup dup * swap -289 17 -3 -x{6D01E502C8CB0F028010F442} runvmcode .s drop dup dup 15 boc+>B .s -B>boc .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm4a.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm4a.fif deleted file mode 100644 index 390faeb6..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm4a.fif +++ /dev/null @@ -1,5 +0,0 @@ -169 13 -239 dup dup * swap -289 17 -3 -x{6D01E502C8CB0F028010F442} runvmcode drop dup dup 15 boc+>B .s -"dict1000.boc" B>file -"dict1000.boc" file>B -B>boc .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm4c.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm4c.fif deleted file mode 100644 index 7e32cb55..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm4c.fif +++ /dev/null @@ -1,52 +0,0 @@ -"Asm.fif" include -<{ NEWDICT SWAP REPEAT: - s2 XCHG0 NEWC 16 STU s2 XCHG0 - 16 INT DICTISETB }>s -dup csr. constant mkdict(16,16).code -{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16) - -<{ ZERO WHILE:<{ SWAP 16 INT DICTIREMMAX }>DO<{ // n d' x i - SWAP 16 LDU ENDS // n d' i s - 2SWAP SWAP INC - }> DROP -}>s dup csr. constant explode_dict(16,16).code -{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16) -{ xdict(16,16) ."{ " { swap . ."-> " . ."; " } swap times ."}" cr } : .dict(16,16) -{ xdict(16,16) { dup 0< not { ."+" } if ._ 64 + emit } swap times space } : .v -169 13 -239 dup dup * swap -289 17 -3 -mkdict(16,16) constant dict - -{ 16 { 16 i@+ s> 1+ 16 i, true } dictmap } : dict:1+ -{ 16 { 16 i@+ s> swap 16 i@+ s> + 16 i, true } dictmerge } : dict:+ - -dict dict:1+ dup s -dup csr. constant mkdict(16,16).code - -{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16) - -<{ ZERO WHILE:<{ SWAP 16 INT DICTIREMMAX }>DO<{ // n d' x i - SWAP 16 LDU ENDS // n d' i s - 2SWAP SWAP INC - }> DROP -}>s dup csr. constant explode_dict(16,16).code - -{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16) -{ xdict(16,16) ."{ " { swap . ."-> " . ."; " } swap times ."}" cr } : .dict(16,16) - -{ 16 { 16 i@+ s> 1+ 16 i, true } dictmap } : dict:1+ -{ 16 { 16 i@+ s> swap 16 i@+ s> + 16 i, true } dictmerge } : dict:+ - -{ 1 swap dup 1 { 2dup dup * + 2 swap 2swap 1+ } 100 times nip mkdict(16,16) } : mdisqpb - -0 mdisqpb 0 { 1+ tuck dup * mdisqpb tuck dict:+ dict:+ swap } 100 times drop -dup s -dup csr. constant mkdict(16,16).code - -{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16) - -<{ ZERO WHILE:<{ SWAP 16 INT DICTUREMMAX }>DO<{ // n d' x i - SWAP 16 LDU ENDS // n d' i s - 2SWAP SWAP INC - }> DROP -}>s dup csr. constant explode_dict(16,16).code - -{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16) -{ xdict(16,16) ."{ " { swap x. ."-> " x. ."; " } swap times ."}" } : .dict(16,16) - -{ 16 { 16 u@+ s> 1+ 16 u, true } dictmap } : dict:1+ -{ 16 { 16 u@+ s> swap 16 u@+ s> + 16 u, true } dictmerge } : dict:+ - -0x1000 0x1000 -0x1234 0x1234 -0x1357 0x1357 -0xABCD 0xABCD -0xBFFF 0xBFFF -5 mkdict(16,16) constant D -D dup dict>s csr. .dict(16,16) ." <-- D" cr - -D <{ 0 INT 0 INT ROT 16 INT SUBDICTUGET }>s dup csr. runvmcode drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,_)" cr - -D <{ 0x1 INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,0001)" cr - -D <{ 0x10 INT 8 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00010000)" cr - -D <{ 0x12 INT 8 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00010010)" cr - -D <{ 0x1357 INT 16 INT ROT OVER SUBDICTUGET }>s runvmcode drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,x1357)" cr - -D <{ 0 INT 2 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00)" cr - -D <{ 1 INT 2 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,01)" cr - -D <{ 0 INT 1 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,0)" cr - -D <{ 1 INT 1 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1)" cr - -D <{ 0xA INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1010)" cr - -D <{ 0xB INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop -dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1011)" cr diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm5.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm5.fif deleted file mode 100644 index 9578fc55..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm5.fif +++ /dev/null @@ -1,11 +0,0 @@ -"Asm.fif" include -<{ 2SWAP ADD s2 POP FALSE }>s b{00} -<{ 2SWAP MUL s2 POP FALSE }>s b{1} -<{ 2SWAP SUB s2 POP FALSE }>s b{01} -3 -<{ NEWDICT SWAP REPEAT: 8 INT PFXDICTADD 11 THROWIFNOT }>s runvmcode -abort"cannot create prefix code dictionary" -dup dict>s csr. -<{ <{ rot 8 PFXDICTSWITCH TRUE }>UNTIL SDEMPTY 11 THROWIFNOT }>s -dup csr. -1 2 3 4 5 b{001011} 6 roll runvmcode .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm6.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm6.fif deleted file mode 100644 index 6b57eea0..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm6.fif +++ /dev/null @@ -1,66 +0,0 @@ -"Asm.fif" include - -<{ 1 INT 70 INT - REPEAT:<{ 10 MULCONST }> - 1 INT DUP <{ TUCK ADD DUP s3 PUSH GREATER }>UNTIL - MULDIVR - }>s -dup csr. - -runvmcode .s - -<{ 1 INT 70 INT REPEAT:<{ 10 MULCONST }> - 1 INT DUP <{ TUCK ADD TUCK ADD SWAP DUP s3 PUSH GREATER }>UNTIL - MULDIVR - }>s -dup csr. - -runvmcode .s - -<{ WHILE:<{ - DUP DEC - }>DO<{ - DUP DUP 1 INT AND IF:<{ - 3 MULCONST INC - }>ELSE<{ - 1 RSHIFT# - }> - }> -}>s -dup csr. - -<{ WHILE:<{ - DUP DEC - }>DO: - DUP DUP 1 INT AND IF:<{ - 3 MULCONST INC - }>ELSE: - 1 RSHIFT# -}>s - -dup csr. -nip - -17 swap runvmcode .s - -<{ CONT:<{ - TUCK DIVR SWAP DUP MUL NEGATE SWAP ZERO ONE - <{ SWAP s2 s1 PUSH2 DIVR ADD SWAP 2 ADDCONST - 2SWAP OVER DIVR 2SWAP s2 PUSH ISZERO }>UNTIL - DROP s2 POP DROP - }> - 8 PUSHPOW2 70 INT REPEAT:<{ 10 MULCONST }> - DUP 2 LSHIFT# 5 INT s3 PUSH EXECUTE - s0 s2 XCHG 239 INT SWAP EXECUTE SUB - 6 RSHIFTR# -}>s dup csr. - -runvmcode .s - -<{ 8 PUSHPOW2 70 INT REPEAT:<{ 10 MULCONST }> - ZERO DUP - <{ s2 PUSH ADD -ROT INC TUCK DIVR -ROT SWAP s2 PUSH ISZERO }>UNTIL - NIP NIP 8 RSHIFTR# -}>s dup csr. - -runvmcode .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm7.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm7.fif deleted file mode 100644 index 796c771c..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm7.fif +++ /dev/null @@ -1,47 +0,0 @@ -"Asm.fif" include -<{ -1 INT ZERO ROT - 100 INT REPEAT:<{ - ZERO WHILE:<{ - 3 3 BLKPUSH - // -ROT OVER ADD ROT OVER ADD -ROT OVER ADD ROT - s2 s1 PUXC ADD TUCK ADD s2 s1 PUXC ADD SWAP - DUP ISPOS - }>DO<{ - s4 POP s4 POP s4 POP INC - }> - 3 BLKDROP - s3 XCHG0 NEGATE s2 XCHG0 NEGATE SWAP NEGATE s2 XCHG0 - }> - 3 BLKDROP -}>s dup csr. -// 61 swap runvmcode .s -drop - -<{ -1 INT ZERO ROT ONE ZERO s0 s1 PUSH2 - <{ 3 6 BLKPUSH // a b c m11 m12 m21 m22 a' b' c' - s2 s1 PUXC ADD TUCK ADD s2 s1 PUXC ADD SWAP - DUP ISPOS IF:<{ - s7 POP s7 POP s7 POP // a' b' c' m11 m12 m21 m22 - s2 PUSH ADD SWAP s3 PUSH ADD SWAP - }>ELSE<{ - 3 BLKDROP // a b c m11 m12 m21 m22 - 2SWAP - 3 4 BLKSWAP // m m m m a b c - NEGATE SWAP NEGATE // .. a -c -b - ROT NEGATE // -c -b -a - 4 3 BLKSWAP - }> - DUP 250 QFITS ISNAN - }>UNTIL - 2DROP s3 POP s3 POP DROP -}>s dup csr. -1 { 10 * } 75 times constant One -{ One swap */r } : frac*One -61 over runvmcode drop frac*One swap -2 over runvmcode drop frac*One swap -3 over runvmcode drop frac*One swap -5 over runvmcode drop frac*One swap -6 over runvmcode drop frac*One swap -7 over runvmcode drop frac*One swap -8 over runvmcode drop frac*One swap -.s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm8.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm8.fif deleted file mode 100644 index fba2f51b..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm8.fif +++ /dev/null @@ -1,5 +0,0 @@ -"Asm.fif" include -<{ 7 INT -4 INT NEWC 64 STI 4 STU ENDC - CTOS 64 LDI 4 LDU ENDS }>s -dup csr. -runvmcode .s diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm9.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm9.fif deleted file mode 100644 index 81306b06..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm9.fif +++ /dev/null @@ -1,7 +0,0 @@ -"Asm.fif" include -<{ 2 INT 3 INT 9 INT NULL CONS CONS CONS }>s dup csr. runvmcode .s -drop =: L -<{ ZERO WHILE:<{ OVER ISNULL NOT }>DO<{ SWAP SECOND SWAP INC }> NIP }>s dup csr. =: ListLength -L ListLength runvmcode .s 2drop -<{ CONT:<{ DUP ISNULL IF:<{ 2DROP ZERO }>ELSE: CDR OVER EXECUTE INC }> TUCK JMPX }>s dup csr. =: ListLengthRec -L ListLengthRec runvmcode .s 2drop diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvmprog.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvmprog.fif deleted file mode 100644 index c2f19f77..00000000 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvmprog.fif +++ /dev/null @@ -1,40 +0,0 @@ -"Asm.fif" include - -PROGRAM{ - -NEWPROC add -NEWPROC sub -NEWPROC mul - -sub <{ s3 s3 XCHG2 SUB s2 XCHG0 SUB }>s PROC - -// compute (5+i)^4 * (239-i) -main PROC:<{ - 5 INT 1 INT // 5+i - 2DUP - mul CALL - 2DUP - mul CALL - 239 INT -1 INT - mul JMP -}> - -add PROC:<{ - s1 s2 XCHG - ADD -ROT ADD SWAP -}> - -// a b c d -- ac-bd ad+bc : complex number multiplication -mul PROC:<{ - s3 s1 PUSH2 // a b c d a c - MUL // a b c d ac - s3 s1 PUSH2 // a b c d ac b d - MUL // a b c d ac bd - SUB // a b c d ac-bd - s4 s4 XCHG2 // ac-bd b c a d - MUL // ac-bd b c ad - -ROT MUL ADD -}> - -}END>s -dup csr. runvmdict .s diff --git a/submodules/ton/tonlib-src/crypto/test/test-cells.cpp b/submodules/ton/tonlib-src/crypto/test/test-cells.cpp deleted file mode 100644 index 327f73c6..00000000 --- a/submodules/ton/tonlib-src/crypto/test/test-cells.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "common/bigexp.h" -#include "common/bitstring.h" -#include "common/util.h" -#include "vm/cells.h" -#include "vm/cellslice.h" - -#include "td/utils/tests.h" -#include "td/utils/crypto.h" -#include "td/utils/misc.h" - -static std::stringstream create_ss() { - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss.setf(std::ios_base::fixed, std::ios_base::floatfield); - ss.precision(6); - return ss; -} -static std::stringstream os = create_ss(); - -void show_total_cells(std::ostream& stream) { - stream << "total cells = " << vm::DataCell::get_total_data_cells() << std::endl; -} - -TEST(Cells, simple) { - os = create_ss(); - using namespace td::literals; - vm::CellBuilder cb1, cb2; - cb1.store_bytes("Hello, ", 7).reserve_slice(48) = td::BitSlice{(const unsigned char*)"world!", 48}; - cb2.store_bits(td::BitSlice{(const unsigned char*)"\xd0", 4}) - .store_long(17239, 16) - .store_long(-17, 11) - .store_long(1000000239, 32) - .store_long(1000000239LL * 1000000239) - .store_int256("-1000000000000000000000000239"_i256, 91); - cb1.store_ref(cb2.finalize_copy()); - show_total_cells(os); - cb2.store_bytes("<->", 3); - td::Ref c1{cb1.finalize_copy()}, c2{cb2.finalize_copy()}; - unsigned char hbuff[vm::Cell::hash_bytes]; - os << "cb1 = " << cb1 << "; hash=" << td::buffer_to_hex(td::Slice(cb1.compute_hash(hbuff), 32)) << "; c1 = " << *c1 - << std::endl; - os << "cb2 = " << cb2 << "; hash=" << td::buffer_to_hex(td::Slice(cb2.compute_hash(hbuff), 32)) << "; c2 = " << *c2 - << std::endl; - show_total_cells(os); - - vm::CellSlice cr1(c1); - cr1.dump(os); - os << "fetch_octet() = " << cr1.fetch_octet() << std::endl; - cr1.dump(os); - os << "fetch_octet() = " << cr1.fetch_octet() << std::endl; - cr1.dump(os); - os << "fetch_octet() = " << cr1.fetch_octet() << std::endl; - cr1.dump(os); - os << "fetch_octet() = " << cr1.fetch_octet() << std::endl; - cr1.dump(os); - os << "fetch_ref()=" << td::buffer_to_hex(cr1.prefetch_ref()->get_hash().as_slice()) << std::endl; - - vm::CellSlice cr(vm::NoVm(), cr1.fetch_ref()); - cr.dump(os); - os << "prefetch_ulong(4)=" << cr.prefetch_ulong(4) << std::endl; - cr.dump(os); - os << "fetch_ulong(4)=" << cr.fetch_ulong(4) << std::endl; - cr.dump(os); - os << "fetch_long(16)=" << cr.fetch_long(16) << std::endl; - cr.dump(os); - os << "prefetch_long(11)=" << cr.prefetch_long(11) << std::endl; - cr.dump(os); - os << "fetch_int256(11)=" << cr.fetch_int256(11) << std::endl; - cr.dump(os); - os << "fetch_long(32)=" << cr.fetch_long(32) << std::endl; - cr.dump(os); - os << "prefetch_long(64)=" << cr.prefetch_long(64) << std::endl; - cr.dump(os); - os << "fetch_long(64)=" << cr.fetch_long(64) << std::endl; - cr.dump(os); - os << "prefetch_int256(91)=" << cr.prefetch_int256(91) << std::endl; - cr.dump(os); - os << "fetch_int256(91)=" << cr.fetch_int256(91) << std::endl; - cr.dump(os); - os << "fetch_long(24)=" << cr.fetch_long(24) << std::endl; - cr.dump(os); - cr.clear(); - - REGRESSION_VERIFY(os.str()); -} - -void test_two_bitstrings(const td::BitSlice& bs1, const td::BitSlice& bs2) { - using td::to_binary; - using td::to_hex; - os << "bs1 = " << bs1.to_binary() << " = " << bs1.to_hex() << std::endl; - os << "bs2 = " << to_binary(bs2) << " = " << to_hex(bs2) << std::endl; - td::BitString st{bs1}; - //td::BitString st; - //st.append(bs1); - os << "st = " << to_binary(st) << " = " << to_hex(st) << std::endl; - st.append(bs2); - os << "st = " << to_binary(st) << " = " << to_hex(st) << std::endl; - ASSERT_EQ(to_binary(st), to_binary(bs1) + to_binary(bs2)); - auto bs3 = st.subslice(bs1.size(), bs2.size()); - os << "bs3 = " << to_binary(bs3) << " = " << to_hex(bs3) << std::endl; - ASSERT_EQ(to_binary(bs3), to_binary(bs2)); - ASSERT_EQ(to_hex(bs3), to_hex(bs2)); - bs1.dump(os); - bs2.dump(os); - bs3.dump(os); - std::string bs2_bin = to_binary(bs2); - for (unsigned i = 0; i <= bs2.size(); i++) { - for (unsigned j = 0; j <= bs2.size() - i; j++) { - auto bs4 = bs2.subslice(i, j); - auto bs5 = bs3.subslice(i, j); - if (!(to_binary(bs4) == to_binary(bs5) && to_hex(bs4) == to_hex(bs5) && to_binary(bs4) == bs2_bin.substr(i, j))) { - bs4.dump(os); - bs5.dump(os); - os << "bs2.subslice(" << i << ", " << j << ") = " << to_binary(bs4) << " = " << to_hex(bs4) << std::endl; - os << "bs3.subslice(" << i << ", " << j << ") = " << to_binary(bs5) << " = " << to_hex(bs5) << std::endl; - } - ASSERT_EQ(to_binary(bs4), to_binary(bs5)); - ASSERT_EQ(to_hex(bs4), to_hex(bs5)); - ASSERT_EQ(to_binary(bs4), bs2_bin.substr(i, j)); - } - } -} - -void test_one_bitstring(const td::BitSlice& bs) { - std::string bs_bin = bs.to_binary(); - for (unsigned i1 = 0; i1 <= bs.size(); i1++) { - for (unsigned j1 = 0; j1 <= bs.size() - i1; j1++) { - auto bs1 = bs.subslice(i1, j1); - ASSERT_EQ(bs1.to_binary(), bs_bin.substr(i1, j1)); - for (unsigned i2 = 0; i2 <= bs.size() && i2 < 8; i2++) { - for (unsigned j2 = 0; j2 <= bs.size() - i2; j2++) { - os << "(" << i1 << "," << j1 << ")+(" << i2 << "," << j2 << ")" << std::endl; - auto bs2 = bs.subslice(i2, j2); - ASSERT_EQ(bs2.to_binary(), bs_bin.substr(i2, j2)); - test_two_bitstrings(bs1, bs2); - } - } - } - } -} - -void test_bitstring_fill(unsigned n, unsigned p, unsigned k) { - td::BitString bs{n * 2}; - std::string s; - auto sl1 = td::BitSlice{(const unsigned char*)"\x40", 2}; - for (unsigned i = 0; i < n; i++) { - bs.append(sl1); - s += "01"; - } - os << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl; - ASSERT_EQ(td::to_binary(bs), s); - unsigned q = k %= p; - for (unsigned i = 0; i < p; i++) { - unsigned a = (q * n * 2) / p; - unsigned b = ((q + 1) * n * 2) / p; - bs.subslice_write(a, b - a) = (q & 1); - std::fill(s.begin() + a, s.begin() + b, (q & 1) + '0'); - os << "Step " << i << " (" << a << "," << b << "): " << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl; - ASSERT_EQ(td::to_binary(bs), s); - q = (q + k) % p; - } - bs.subslice_write(4, 16) = td::BitSlice{(const unsigned char*)"\x69\x96", 16}; - os << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl; - std::string t = "0110100110010110"; - std::copy(t.begin(), t.end(), s.begin() + 4); - ASSERT_EQ(td::to_binary(bs), s); -} - -TEST(Bitstrings, main) { - os = create_ss(); - auto test = td::BitSlice{(const unsigned char*)"test", 32}; - ASSERT_EQ(test.to_hex(), "74657374"); - test_two_bitstrings({(const unsigned char*)"\xf1\xd0", 12}, test); - test_two_bitstrings({(const unsigned char*)"\x9f", 3}, {(const unsigned char*)"t", 3}); - test_bitstring_fill(17 * 3, 17, 4); - //test_one_bitstring({(const unsigned char*)"SuperTest", 72}); - REGRESSION_VERIFY(os.str()); -} - -void test_parse_dec(std::string s) { - td::BigInt256 x, y; - os << "s=\"" << s << "\"" << std::endl; - x.parse_dec_slow(s); - y.parse_dec(s); - x.dump(os); - y.dump(os); - ASSERT_TRUE(x == y); - std::string s1 = x.to_dec_string(); - os << s1 << std::endl; - ASSERT_EQ(s, s1); - std::string s2 = x.to_hex_string(); - os << s2 << std::endl; - std::string s3 = x.to_hex_string_slow(); - os << s3 << std::endl; - ASSERT_EQ(s2, s3); -} - -void test_pow2(int exponent) { - td::BigInt256 x; - x.set_pow2(exponent); - os << "2^" << exponent << " = " << x.to_dec_string() << " = 0x" << x.to_hex_string() << std::endl; - x.dump(os); -} - -void test_fits(const td::BigInt256& x) { - int m = 0, n = 0; - const int limit = 300; - os << "x=" << x.to_dec_string() << "; log2(|x|)=" << std::log2(std::abs(x.to_double())) << std::endl; - x.dump(os); - while (m < limit && !x.unsigned_fits_bits(m)) { - m++; - } - for (int i = m; i < limit; i++) { - ASSERT_TRUE(x.unsigned_fits_bits(i)); - } - int su = x.bit_size(false); - while (n < limit && !x.signed_fits_bits(n)) { - n++; - } - for (int i = n; i < limit; i++) { - ASSERT_TRUE(x.signed_fits_bits(i)); - } - int ss = x.bit_size(); - os << "x=" << x.to_dec_string() << "=0x" << x.to_hex_string() << "; x=" << x.to_double() - << "; log2(|x|)=" << std::log2(std::abs(x.to_double())) << "; unsigned: " << m << "=" << su - << " bits; signed: " << n << "=" << ss << " bits" << std::endl; - ASSERT_TRUE(su == m || (su == 0x7fffffff && m == limit)); - ASSERT_EQ(ss, n); - ASSERT_EQ(x.to_hex_string(), x.to_hex_string_slow()); - td::BigInt256 y, z; - ASSERT_TRUE(y.parse_hex(x.to_hex_string()) && y == x); - ASSERT_TRUE(z.parse_dec(x.to_dec_string()) && z == x); -} - -void test_divmod(const td::BigInt256& x, const td::BigInt256& y) { - td::BigInt256 q, r(x); - os << "x = " << x << " = "; - x.dump(os); - os << "y = " << y << " = "; - y.dump(os); - if (!r.mod_div_bool(y, q)) { - os << "division error!\n"; - ASSERT_TRUE(0); - } else { - q.dump(os); - r.dump(os); - if (!q.normalize_bool() || !r.normalize_bool()) { - os << "cannot normalize q or r!\n"; - ASSERT_TRUE(0); - } else { - os << "q = " << q << "; r = " << r << std::endl; - if (y.sgn() > 0) { - ASSERT_TRUE(r.sgn() >= 0); - ASSERT_TRUE(r.cmp(y) < 0); - } else { - ASSERT_TRUE(r.sgn() <= 0); - ASSERT_TRUE(r.cmp(y) > 0); - } - r.add_mul(q, y); - ASSERT_TRUE(r.normalize() == x); - } - } -} - -void test_export_int(const td::BigInt256& x, bool sgnd = true) { - os << "x = " << x.to_hex_string() << std::endl; - int bad = 0, ok = 0; - for (int i = 1; i <= 33; i++) { - unsigned char buff[33]; - std::memset(buff, 0xcc, sizeof(buff)); - if (!x.export_bytes(buff, i, sgnd)) { - ASSERT_EQ(bad, i - 1); - bad = i; - continue; - } else if (++ok < 5) { - if (bad == i - 1) { - os << "export(" << bad << ", " << sgnd << ") = (bad)" << std::endl; - } - os << "export(" << i << ", " << sgnd << ") ="; - char tmp[33 * 3 + 1]; - for (int j = 0; j < i; j++) { - sprintf(tmp + 3 * j, " %02x", buff[j]); - } - os << tmp << std::endl; - td::BigInt256 y; - ASSERT_TRUE(y.import_bytes(buff, i, sgnd)); - os << "import() = " << y.to_hex_string() << std::endl; - ASSERT_TRUE(!x.cmp_un(y)); - } - } - if (!ok) { - os << "export(" << bad << ", " << sgnd << ") = (bad)" << std::endl; - } -} - -TEST(Bigint, main) { - os = create_ss(); - using namespace td::literals; - td::BigInt256 x, y, z; - test_parse_dec("0"); - test_parse_dec("1"); - test_parse_dec("-1"); - test_parse_dec("123"); - test_parse_dec("-239"); - test_parse_dec("-115792089237316195423570985008687907853269984665640564039457584007913129639936"); - test_parse_dec("115792089237316195423570985008687907853269984665640564039457584007913129639935"); - test_parse_dec("143126893554044595713052252685501316785002612509329899766666973726012466208042"); - test_parse_dec("100000000000000000000000000000000000000000000000000000000000000000000000000001"); - x.parse_dec("11111111111111111111111111111111111111111111111111111111111111111111111111111"); - y.parse_dec("22222222222222222222222222222222222"); - x += y; - os << x.to_dec_string() << std::endl; - x -= y; - os << x.to_dec_string() << std::endl; - x -= y; - os << x.to_dec_string() << std::endl; - y -= x; - os << y.to_dec_string() << std::endl; - y += x; - os << x.to_dec_string() << std::endl; - x.parse_dec("10000000000000000000000000000001"); - y.parse_dec("11111111111111111111111111111111"); - z.add_mul(x, y); - os << x.to_dec_string() << " * " << y.to_dec_string() << " = " << z.to_dec_string() << std::endl; - test_pow2(0); - test_pow2(1); - test_pow2(54); - test_pow2(55); - test_pow2(56); - test_pow2(57); - test_pow2(4 * 56 - 2); - test_pow2(4 * 56 - 1); - test_pow2(4 * 56); - test_pow2(4 * 56 + 1); - test_pow2(255); - test_pow2(256); - test_fits("1111111111111111111111111111"_i256); - test_fits( - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff"_x256); - for (int i = 10; i >= -10; --i) { - test_fits(td::BigInt256(i)); - } - test_export_int("10000000000000000000000000000000000000"_i256); - for (int k = 127; k <= 129; k++) { - x.set_pow2(k).add_tiny(-1); - test_export_int(x, true); - test_export_int(x, false); - x.add_tiny(1); - test_export_int(x, true); - test_export_int(x, false); - x.add_tiny(1); - test_export_int(x, true); - test_export_int(x, false); - x.negate(); - test_export_int(x, true); - test_export_int(x, false); - x.add_tiny(1); - test_export_int(x, true); - test_export_int(x, false); - x.add_tiny(1); - test_export_int(x, true); - test_export_int(x, false); - } - for (x = 1, y.set_pow2(256).divmod_tiny(3); x.cmp(y) < 0; x.mul_tiny(3).normalize()) { - test_export_int(x, true); - x.negate(); - test_export_int(x, true); - x.negate(); - } - test_export_int("7fffffffffffffffffffffffffffffff"_x256); - test_export_int("ffffffffffffffffffffffffffffffff"_x256); - test_export_int("7fffffffffffffffffffffffffffffff"_x256); - test_export_int("ffffffffffffffffffffffffffffffff"_x256); - for (int i = 0; i <= 257; i++) { - x.set_pow2(i).add_tiny(-3); - for (int j = -3; j <= 3; j++) { - x.negate().normalize(); - os << "-2^" << i << "+" << -j << ": "; - test_fits(x); - x.negate().normalize(); - os << "2^" << i << "+" << j << ": "; - test_fits(x); - x.add_tiny(1); - } - } - - for (auto t : {"fffffffffffffffffffffffffffffffffffffff"_x256, td::BigInt256{-1}, - "123456789abcdef0123456789abcdef0123456789abcdef"_x256, "-8000000000000000000000000001"_x256}) { - for (int i = 0; i <= 256; i++) { - (x = t).mod_pow2(i).dump(os); - os << "mod 2^" << i << " : " << x.to_hex_string() << std::endl; - } - } - - test_divmod(x.set_pow2(224), "10000000000000"_i256); - test_divmod(x.set_pow2(256), "100000000000000000000000000000000000000000"_i256); - test_divmod(x.set_pow2(256), "100000000000000000000000000000000000000000000"_i256); - test_divmod(x.set_pow2(80), "-100000000000000000000000000000000000000000000"_i256); - test_divmod(x.set_pow2(256), y.set_pow2(128).add_tiny(-1)); - test_divmod(x.set_pow2(224), y.set_pow2(112).add_tiny(-1)); - test_divmod(x.set_pow2(222), y.set_pow2(111).add_tiny(-1)); - test_divmod(td::BigInt256(-1), y.set_pow2(256)); - test_divmod("10000000000000000000000000000000000000000000000000000000000000000"_i256, - "142857142857142857142857142857142857"_i256); - test_divmod("100000000"_i256, "-253"_i256); - test_divmod("-100000000"_i256, "-253"_i256); - test_divmod("-100000000"_i256, "253"_i256); - - test_divmod(x.set_pow2(222), td::BigInt256{std::numeric_limits::min()}); - test_divmod(x.set_pow2(222).negate(), td::BigInt256{std::numeric_limits::min()}); - REGRESSION_VERIFY(os.str()); -} - -TEST(RefInt, main) { - os = create_ss(); - using namespace td::literals; - auto x = "10000000000000000000000"_ri256; - td::RefInt256 y{true, -239}, z{false}; - auto v = x + y; - std::move(v); - os << x << " + " << y << " = " << x + y << std::endl; - os << x << " - " << y << " = " << x - y << std::endl; - os << x << " * " << y << " = " << x * y << std::endl; - os << x << " / " << y << " = " << x / y << std::endl; - os << x << " % " << y << " = " << x % y << std::endl; - os << x << " + " << y << " = " << x + y << std::endl; - os << "10000000000000000000000000000000000000000"_ri256 / "27182818284590"_ri256 << std::endl; - { - auto w(x + y); - z = w; - } - os << "(x-y)*(x+y) = " << (x - y) * (x + y) << std::endl; - os << "z = " << z << std::endl; - z = x; - x += y; - os << "new x = " << x << " = 0x" << hex_string(x) << std::endl; - os << "z = (old x) = " << std::move(z) << std::endl; - os << "x + y = " << std::move(x) + std::move(y) << std::endl; - z = "10000000000000000000000000000000000000000000000000000000000000000000000"_ri256; - //z = td::RefInt256{true} - //z.unique_write()->set_pow2(256); - x = td::RefInt256{true, 0}; - int i = 1; - while (z->sgn() > 0) { - x += z; - z.write().add_tiny(i >> 1).divmod_tiny(i); - ++i; - } - x.write().normalize(); - os << x << " = " << hex_string(x) << std::endl; - REGRESSION_VERIFY(os.str()); -} - -TEST(crc16, main) { - os = create_ss(); - std::string s = "EMSI_FCK"; - unsigned crc16 = td::crc16(td::Slice{s}); - os << "s = `" << s << "`; crc16 = " << std::hex << crc16 << std::dec << std::endl; - REGRESSION_VERIFY(os.str()); -} - -TEST(base64, main) { - os = create_ss(); - std::vector arr = {"TEST STRING NUMBER ONE", "TEST STRING NUMBER FOUR", "TEST STRING NUMBER THREE"}; - for (std::string s : arr) { - std::string t = td::str_base64_encode(s); - std::string u = td::str_base64_decode(t); - os << "`" << s << "` -> `" << t << "` -> `" << u << "`" << std::endl; - os << (s == u) << std::endl; - } - std::string s; - int k = 0; - for (int i = 0; i < 1024; i++) { - s.push_back((char)(k >> 8)); - k = 69069 * k + 1; - } - std::string t = td::str_base64_encode(s); - std::string u = td::str_base64_decode(t, true); - os << t << std::endl; - os << (s == u) << std::endl; - t = td::str_base64_encode(s, true); - u = td::str_base64_decode(t, true); - os << t << std::endl; - os << (s == u) << std::endl; - u = td::sha256(td::Slice{s}); - for (int i = 0; i < 32; i++) { - os << std::hex << ((u[i] >> 4) & 15) << (u[i] & 15); - } - os << std::dec << std::endl; - REGRESSION_VERIFY(os.str()); -} - -void check_bits256_scan(std::ostream& stream, td::Bits256 a, td::Bits256 b) { - auto c = a ^ b; - auto bit = c.count_leading_zeroes(); - auto bit2 = a.count_matching(b); - // stream << a.to_hex() << " and " << b.to_hex() << " match in " << bit << " or " << bit2 << " first bits" << std::endl; - // std::cerr << a.to_hex() << " and " << b.to_hex() << " match in " << bit << " or " << bit2 << " first bits (a XOR b = " << c.to_hex() << ")" << std::endl; - CHECK((int)bit >= 0 && bit <= 256); - for (td::uint32 i = 0; i < bit; i++) { - CHECK(a[i] == b[i]); - } - CHECK(bit == 256 || a[bit] != b[bit]); - CHECK(bit == bit2); -} - -void check_bits_scan(std::ostream& stream, td::ConstBitPtr a, bool value) { - auto bit = (unsigned)a.scan(value, 256); - CHECK((int)bit >= 0 && bit <= 256); - for (td::uint32 i = 0; i < bit; i++) { - CHECK(a[i] == value); - } - CHECK(bit == 256 || a[bit] != value); -} - -TEST(bits256_scan, main) { - os = create_ss(); - td::Bits256 a, b; - int k = 0; - unsigned char r[1024]; - for (auto& c : r) { - c = (k & 0x80) ? (unsigned char)(k >> 8) : 0; - k = 69069 * k + 1; - } - for (k = 0; k < 32; k++) { - a = td::ConstBitPtr{r + 32 * k}; - for (int j = 0; j < 32; j++) { - b = td::ConstBitPtr{r + 32 * j}; - check_bits256_scan(os, a, b); - } - b = a; - unsigned i = r[7 + k]; - b[i] = b[i] ^ true; - check_bits256_scan(os, a, b); - } - for (k = 0; k < 256; k++) { - check_bits_scan(os, td::ConstBitPtr{r} + k, false); - check_bits_scan(os, td::ConstBitPtr{r} + k, true); - } - os << "bits256_scan test OK"; - REGRESSION_VERIFY(os.str()); -} - -bool check_exp(std::ostream& stream, const td::NegExpBinTable& tab, double x) { - long long xx = llround(x * (1LL << 52)); - td::BigInt256 yy; - if (!tab.nexpf(yy, -xx, 52)) { - stream << "cannot compute exp(" << x << ") = exp(" << xx << " * 2^(-52))" << std::endl; - return false; - } - double y = yy.to_double() * exp2(-252); - double y0 = exp(x); - bool ok = (fabs(y - y0) < 1e-15); - if (!ok) { - stream << "exp(" << x << ") = exp(" << xx << " * 2^(-52)) = " << yy << " / 2^252 = " << y << " (correct value is " - << y0 << ") " << (ok ? "match" : "incorrect") << std::endl; - } - return ok; -} - -TEST(bigexp, main) { - os = create_ss(); - td::NegExpBinTable tab(252, 32, -128); - bool ok = true; - if (!tab.is_valid()) { - os << "cannot initialize td::NegExpBinTable(252, 32, -128)" << std::endl; - ok = false; - } else { - // for (int i = -128; i < 32; i++) { - // os << "exp(-2^" << i << ") = " << tab.exp_pw2_ref(i) << " / 2^252 = " << tab.exp_pw2_ref(i)->to_double() * exp2(-252) << " (correct value is " << exp(-exp2(i)) << ")" << std::endl; - // } - ok &= check_exp(os, tab, -2.39); - ok &= check_exp(os, tab, 0); - ok &= check_exp(os, tab, -1); - ok &= check_exp(os, tab, -2); - ok &= check_exp(os, tab, -16); - ok &= check_exp(os, tab, -17); - ok &= check_exp(os, tab, -0.5); - ok &= check_exp(os, tab, -0.25); - ok &= check_exp(os, tab, -3.1415926535); - ok &= check_exp(os, tab, -1e-9); - } - if (ok) { - os << "bigexp test OK\n"; - } else { - os << "bigexp test FAILED\n"; - } - REGRESSION_VERIFY(os.str()); -} - -bool check_intexp(std::ostream& stream, td::uint64 x, unsigned k, td::uint64 yc = 0) { - td::uint64 y = td::umulnexps32(x, k); - long long delta = (long long)(y - yc); - bool ok = (y <= x && std::abs(delta) <= 1); - if (!ok) { - stream << x << "*exp(-" << k << "/65536) = " << y << " (correct value " << yc << ", delta = " << delta << ")" - << std::endl; - } - return ok; -} - -TEST(uint64_exp, main) { - os = create_ss(); - bool ok = true; - ok &= check_intexp(os, 3167801306015831286, 4003, 2980099890648636481); - ok &= check_intexp(os, 1583900653007915643, 4003, 1490049945324318240); - ok &= check_intexp(os, 9094494907266047891, 17239, 6990995826652297465); - ok &= check_intexp(os, 5487867407433215099, 239017, 143048684491504152); - ok &= check_intexp(os, 46462010749955243, 239017, 1211095134625318); // up - ok &= check_intexp(os, 390263500024095125, 2700001, 1); - ok &= check_intexp(os, 390263500024095124, 2700001, 1); - ok &= check_intexp(os, std::numeric_limits::max(), 2952601, 1); - ok &= check_intexp(os, std::numeric_limits::max(), 2952696, 1); - ok &= check_intexp(os, std::numeric_limits::max(), 2952697, 0); - ok &= check_intexp(os, std::numeric_limits::max(), 2952800, 0); - ok &= check_intexp(os, std::numeric_limits::max(), 295269700, 0); - ok &= check_intexp(os, std::numeric_limits::max(), 2000018, 1028453); - ok &= check_intexp(os, 1ULL << 60, 2770991, 1); - ok &= check_intexp(os, 1ULL << 60, 2770992, 0); - if (ok) { - os << "uint64_exp test OK\n"; - } else { - os << "uint64_exp test FAILED\n"; - } - REGRESSION_VERIFY(os.str()); -} diff --git a/submodules/ton/tonlib-src/crypto/test/test-db.cpp b/submodules/ton/tonlib-src/crypto/test/test-db.cpp deleted file mode 100644 index 361c9947..00000000 --- a/submodules/ton/tonlib-src/crypto/test/test-db.cpp +++ /dev/null @@ -1,2314 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/boc.h" -#include "vm/cellslice.h" -#include "vm/cells.h" -#include "common/AtomicRef.h" -#include "vm/cells/MerkleProof.h" -#include "vm/cells/MerkleUpdate.h" -#include "vm/db/BlobView.h" -#include "vm/db/CellStorage.h" -#include "vm/db/CellHashTable.h" -#include "vm/db/TonDb.h" -#include "vm/db/StaticBagOfCellsDb.h" - -#include "td/utils/base64.h" -#include "td/utils/benchmark.h" -#include "td/utils/crypto.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/Timer.h" -#include "td/utils/filesystem.h" -#include "td/utils/port/path.h" -#include "td/utils/format.h" -#include "td/utils/misc.h" -#include "td/utils/optional.h" -#include "td/utils/tests.h" -#include "td/utils/tl_parsers.h" -#include "td/utils/tl_helpers.h" - -#include "td/db/RocksDb.h" -#include "td/db/MemoryKeyValue.h" - -#include -#include - -#include - -#include "openssl/digest.hpp" - -namespace vm { - -std::vector do_get_serialization_modes() { - std::vector res; - for (int i = 0; i < 32; i++) { - if ((i & BagOfCells::Mode::WithCacheBits) && !(i & BagOfCells::Mode::WithIndex)) { - continue; - } - res.push_back(i); - } - return res; -} -const std::vector &get_serialization_modes() { - static auto modes = do_get_serialization_modes(); - return modes; -} - -template -int get_random_serialization_mode(T &rnd) { - auto &modes = get_serialization_modes(); - return modes[rnd.fast(0, (int)modes.size() - 1)]; -} - -class BenchSha256 : public td::Benchmark { - public: - std::string get_description() const override { - return "SHA256"; - } - - void run(int n) override { - int res = 0; - for (int i = 0; i < n; i++) { - digest::SHA256 hasher; - hasher.feed("abcd", 4); - unsigned char buf[32]; - hasher.extract(buf); - res += buf[0]; - } - td::do_not_optimize_away(res); - } -}; -class BenchSha256Reuse : public td::Benchmark { - public: - std::string get_description() const override { - return "SHA256 reuse"; - } - - void run(int n) override { - int res = 0; - digest::SHA256 hasher; - for (int i = 0; i < n; i++) { - hasher.reset(); - hasher.feed("abcd", 4); - unsigned char buf[32]; - hasher.extract(buf); - res += buf[0]; - } - td::do_not_optimize_away(res); - } -}; -class BenchSha256Low : public td::Benchmark { - public: - std::string get_description() const override { - return "SHA256 low level"; - } - - void run(int n) override { - int res = 0; - SHA256_CTX ctx; - for (int i = 0; i < n; i++) { - SHA256_Init(&ctx); - SHA256_Update(&ctx, "abcd", 4); - unsigned char buf[32]; - SHA256_Final(buf, &ctx); - res += buf[0]; - } - td::do_not_optimize_away(res); - } -}; -class BenchSha256Tdlib : public td::Benchmark { - public: - std::string get_description() const override { - return "SHA256 TDLib"; - } - - void run(int n) override { - int res = 0; - static TD_THREAD_LOCAL td::Sha256State *ctx; - for (int i = 0; i < n; i++) { - td::init_thread_local(ctx); - ctx->init(); - ctx->feed("abcd"); - unsigned char buf[32]; - ctx->extract(td::MutableSlice(buf, 32), false); - res += buf[0]; - } - td::do_not_optimize_away(res); - } -}; -TEST(Cell, sha_benchmark) { - bench(BenchSha256Tdlib()); - bench(BenchSha256Low()); - bench(BenchSha256Reuse()); - bench(BenchSha256()); -} - -std::string serialize_boc(Ref cell, int mode = 31) { - CHECK(cell.not_null()); - vm::BagOfCells boc; - boc.add_root(std::move(cell)); - boc.import_cells().ensure(); - auto res = boc.serialize_to_string(mode); - CHECK(res.size() != 0); - return res; -} -std::string serialize_boc(td::Span> cells, int mode = 31) { - CHECK(!cells.empty()); - vm::BagOfCells boc; - for (auto cell : cells) { - boc.add_root(std::move(cell)); - } - boc.import_cells().ensure(); - auto res = boc.serialize_to_string(mode); - CHECK(res.size() != 0); - return res; -} - -Ref deserialize_boc(td::Slice serialized) { - vm::BagOfCells boc; - boc.deserialize(serialized).ensure(); - return boc.get_root_cell(); -} -std::vector> deserialize_boc_multiple(td::Slice serialized) { - vm::BagOfCells boc; - boc.deserialize(serialized).ensure(); - std::vector> res; - for (int i = 0; i < boc.get_root_count(); i++) { - res.push_back(boc.get_root_cell(i)); - } - return res; -} - -class CellExplorer { - public: - struct Op { - enum { Pop, ReadCellSlice } type; - bool should_load; - int children_mask; - }; - struct Exploration { - std::vector ops; - std::string log; - std::set visited; - std::vector> visited_cells; - }; - - static Exploration explore(Ref root, std::vector ops) { - CellExplorer e(root); - for (auto op : ops) { - e.do_op(op); - } - return e.get_exploration(); - } - - template - static Exploration random_explore(Ref root, T &rnd) { - CellExplorer e(root); - int it = 0; - int cnt = rnd.fast(1, 100); - while (it++ < cnt && e.do_random_op(rnd)) { - } - return e.get_exploration(); - } - - private: - CellExplorer(Ref root) { - if (root.not_null()) { - cells_.push_back(std::move(root)); - } - } - - std::vector> cells_; - Ref cs_; - std::vector ops_; - std::set visited_; - std::map> visited_cells_; - td::StringBuilder log_{{}, true}; - - void do_op(Op op) { - ops_.push_back(op); - log_op(op); - switch (op.type) { - case op.Pop: { - CHECK(!cells_.empty()); - CHECK(cs_.is_null()); - auto cell = std::move(cells_.back()); - cells_.pop_back(); - visited_cells_.emplace(cell->get_hash(), cell); - log_cell(cell); - if (op.should_load) { - log_loaded_cell(cell); - visited_.insert(cell->get_hash()); - // It is ok to visit the same vertex multiple times - cs_ = Ref{true, NoVm(), std::move(cell)}; - } - break; - } - case op.ReadCellSlice: { - CHECK(cs_.not_null()); - log_cell_slice(cs_); - for (unsigned i = 0; i < cs_->size_refs(); i++) { - if ((op.children_mask >> i) % 2 != 0) { - cells_.push_back(cs_->prefetch_ref(i)); - } - } - cs_ = {}; - break; - } - } - } - - template - bool do_random_op(T &rnd) { - if (cs_.not_null()) { - int children_mask = 0; - if (cs_->size_refs() != 0 && rnd.fast(0, 3) != 0) { - //children_mask = rnd.fast(1, (1 << cs_->size_refs()) - 1); - children_mask = (1 << cs_->size_refs()) - 1; - } - do_op({Op::ReadCellSlice, false, children_mask}); - return true; - } - if (!cells_.empty()) { - do_op({Op::Pop, rnd.fast(0, 30) != 0, 0}); - return true; - } - return false; - } - - Exploration get_exploration() { - std::vector> visited_cells; - for (auto &it : visited_cells_) { - visited_cells.push_back(it.second); - } - return {std::move(ops_), log_.as_cslice().str(), std::move(visited_), std::move(visited_cells)}; - } - - void log_op(Op op) { - switch (op.type) { - case op.Pop: - log_ << "pop" << (op.should_load ? " and load" : "") << "\n"; - break; - case op.ReadCellSlice: - log_ << "read slice " << op.children_mask << "\n"; - break; - } - } - void log_cell(const Ref &cell) { - log_ << cell->get_level_mask().get_mask() << " " << cell->get_hash() << "\n"; - } - void log_loaded_cell(const Ref &cell) { - log_ << "depth: "; - for (unsigned i = 0; i <= cell->get_level(); i++) { - log_ << cell->get_depth(i) << " "; - } - log_ << "\n"; - } - void log_cell_slice(const Ref &cs) { - log_ << cs->special_type() << " " << cs->size() << " " << cs->size_refs() << " " - << td::bitstring::bits_to_hex(cs->data_bits(), cs->size()) << "\n"; - } -}; - -class RandomBagOfCells { - public: - template - RandomBagOfCells(size_t size, T &rnd, bool with_prunned_branches, std::vector> cells) { - std::map depth; - - for (auto &cell : cells) { - nodes_.emplace_back(cell, calc_depth(cell, depth)); - } - - for (size_t i = 0; i < size; i++) { - add_random_cell(rnd, with_prunned_branches); - } - } - - Ref get_root() { - CHECK(!nodes_.empty()); - // Fix root to be zero level - while (nodes_.back().cell->get_level() != 0) { - nodes_.emplace_back(CellBuilder::create_merkle_proof(nodes_.back().cell), nodes_.back().merkle_depth + 1); - } - return nodes_.back().cell; - } - template - std::vector> get_random_roots(size_t size, T &rnd) { - CHECK(!nodes_.empty()); - std::vector> res(size); - for (auto &c : res) { - c = nodes_[rnd.fast(0, static_cast(nodes_.size()) - 1)].cell; - } - return res; - } - - size_t get_size() const { - return nodes_.size(); - } - - template - void add_random_cell(T &rnd, bool with_prunned_branches = true) { - int cnt = 0; - while (true) { - CellBuilder cb; - int next_cnt = rnd.fast(0, Cell::max_refs); - int merkle_depth = 0; - for (int j = 0; j < next_cnt && !nodes_.empty(); j++) { - int to = rnd.fast(j == 0 && nodes_.size() > 3 ? (int)nodes_.size() - 3 : 0, (int)nodes_.size() - 1); - merkle_depth = td::max(merkle_depth, nodes_.at(to).merkle_depth); - cb.store_ref(nodes_[to].cell); - } - int size = rnd.fast(0, 4); - for (int j = 0; j < size; j++) { - cb.store_bytes(&"ab"[rnd.fast(0, 1)], 1); - } - if (rnd.fast(0, 4) == 4) { - cb.store_bits(rnd.fast(0, 1) ? "\xff" : "\x55", rnd.fast(1, 7)); - } - Ref cell = cb.finalize(); - auto cell_level = cell->get_level(); - if (with_prunned_branches) { - if (rnd.fast(0, 5) == 0 && cell_level + 1 < Cell::max_level) { - cell = CellBuilder::create_pruned_branch(std::move(cell), cell_level + 1); - } - if (merkle_depth + 1 + cell->get_level() < Cell::max_level && rnd.fast(0, 10) == 0) { - cell = CellBuilder::create_merkle_proof(std::move(cell)); - merkle_depth++; - } - } - if (merkle_depth + cell->get_level() >= Cell::max_level) { - cnt++; - CHECK(cnt < 1000); - continue; - } - CHECK(cell.not_null()); - nodes_.emplace_back(std::move(cell), merkle_depth); - break; - } - } - - private: - struct Node { - Node() = default; - Node(Ref cell, int merkle_depth) : cell(std::move(cell)), merkle_depth(merkle_depth) { - } - Ref cell; - int merkle_depth; - }; - std::vector nodes_; - - auto calc_depth(const Ref &root, std::map &depth) -> int { - auto it_flag = depth.emplace(root->get_hash(), 0); - if (!it_flag.second) { - return it_flag.first->second; - } - auto res = 0; - CellSlice cs(NoVm(), root); - for (unsigned i = 0; i < cs.size_refs(); i++) { - res = std::max(res, calc_depth(cs.prefetch_ref(i), depth)); - } - if (cs.special_type() == Cell::SpecialType::MerkleProof) { - res++; - } - depth[root->get_hash()] = res; - return res; - }; -}; - -template -void random_shuffle(td::MutableSpan v, td::Random::Xorshift128plus &rnd) { - for (std::size_t i = 1; i < v.size(); i++) { - auto pos = static_cast(rnd() % (i + 1)); - std::swap(v[i], v[pos]); - } -} -Ref gen_random_cell(int size, td::Random::Xorshift128plus &rnd, bool with_prunned_branches = true, - std::vector> cells = {}) { - if (!cells.empty()) { - random_shuffle(td::MutableSpan>(cells), rnd); - cells.resize(cells.size() % rnd()); - } - return RandomBagOfCells(size, rnd, with_prunned_branches, std::move(cells)).get_root(); -} -std::vector> gen_random_cells(int roots, int size, td::Random::Xorshift128plus &rnd, - bool with_prunned_branches = true, std::vector> cells = {}) { - if (!cells.empty()) { - random_shuffle(td::MutableSpan>(cells), rnd); - cells.resize(cells.size() % rnd()); - } - return RandomBagOfCells(size, rnd, with_prunned_branches, std::move(cells)).get_random_roots(roots, rnd); -} - -TEST(Cell, MerkleProof) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - bool with_prunned_branches = true; - auto cell = gen_random_cell(rnd.fast(1, 1000), rnd, with_prunned_branches); - auto exploration = CellExplorer::random_explore(cell, rnd); - - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - auto exploration2 = CellExplorer::explore(usage_cell, exploration.ops); - ASSERT_EQ(exploration.log, exploration2.log); - - auto is_prunned = [&](const Ref &cell) { return exploration.visited.count(cell->get_hash()) == 0; }; - auto proof = MerkleProof::generate(cell, is_prunned); - // CellBuilder::virtualize(proof, 1); - //ASSERT_EQ(1u, proof->get_level()); - auto virtualized_proof = MerkleProof::virtualize(proof, 1); - auto exploration3 = CellExplorer::explore(virtualized_proof, exploration.ops); - ASSERT_EQ(exploration.log, exploration3.log); - - auto proof2 = MerkleProof::generate(cell, usage_tree.get()); - CHECK(proof2->get_depth() == proof->get_depth()); - auto virtualized_proof2 = MerkleProof::virtualize(proof2, 1); - auto exploration4 = CellExplorer::explore(virtualized_proof2, exploration.ops); - ASSERT_EQ(exploration.log, exploration4.log); - } -}; - -TEST(Cell, MerkleProofCombine) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - bool with_prunned_branches = true; - auto cell = gen_random_cell(rnd.fast(1, 1000), rnd, with_prunned_branches); - auto exploration1 = CellExplorer::random_explore(cell, rnd); - auto exploration2 = CellExplorer::random_explore(cell, rnd); - - Ref proof1; - { - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - CellExplorer::explore(usage_cell, exploration1.ops); - proof1 = MerkleProof::generate(cell, usage_tree.get()); - - auto virtualized_proof = MerkleProof::virtualize(proof1, 1); - auto exploration = CellExplorer::explore(virtualized_proof, exploration1.ops); - ASSERT_EQ(exploration.log, exploration1.log); - } - - Ref proof2; - { - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - CellExplorer::explore(usage_cell, exploration2.ops); - proof2 = MerkleProof::generate(cell, usage_tree.get()); - - auto virtualized_proof = MerkleProof::virtualize(proof2, 1); - auto exploration = CellExplorer::explore(virtualized_proof, exploration2.ops); - ASSERT_EQ(exploration.log, exploration2.log); - } - - Ref proof12; - { - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - CellExplorer::explore(usage_cell, exploration1.ops); - CellExplorer::explore(usage_cell, exploration2.ops); - proof12 = MerkleProof::generate(cell, usage_tree.get()); - - auto virtualized_proof = MerkleProof::virtualize(proof12, 1); - auto exploration_a = CellExplorer::explore(virtualized_proof, exploration1.ops); - auto exploration_b = CellExplorer::explore(virtualized_proof, exploration2.ops); - ASSERT_EQ(exploration_a.log, exploration1.log); - ASSERT_EQ(exploration_b.log, exploration2.log); - } - - { - auto check = [&](auto proof_union) { - auto virtualized_proof = MerkleProof::virtualize(proof_union, 1); - auto exploration_a = CellExplorer::explore(virtualized_proof, exploration1.ops); - auto exploration_b = CellExplorer::explore(virtualized_proof, exploration2.ops); - ASSERT_EQ(exploration_a.log, exploration1.log); - ASSERT_EQ(exploration_b.log, exploration2.log); - }; - auto proof_union = MerkleProof::combine(proof1, proof2); - ASSERT_EQ(proof_union->get_hash(), proof12->get_hash()); - check(proof_union); - - auto proof_union_fast = MerkleProof::combine_fast(proof1, proof2); - check(proof_union_fast); - } - { - auto cell = MerkleProof::virtualize(proof12, 1); - - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - CellExplorer::explore(usage_cell, exploration1.ops); - auto proof = MerkleProof::generate(cell, usage_tree.get()); - - auto virtualized_proof = MerkleProof::virtualize(proof, 2); - auto exploration = CellExplorer::explore(virtualized_proof, exploration1.ops); - ASSERT_EQ(exploration.log, exploration1.log); - if (proof->get_hash() != proof1->get_hash()) { - CellSlice(NoVm(), proof12).print_rec(std::cerr); - CellSlice(NoVm(), proof).print_rec(std::cerr); - CellSlice(NoVm(), proof1).print_rec(std::cerr); - LOG(ERROR) << proof->get_level() << " " << proof->get_hash().to_hex(); - LOG(ERROR) << proof->get_level() << " " << proof1->get_hash().to_hex(); - LOG(FATAL) << "?"; - } - } - } -}; - -int X = 20; -Ref gen_random_cell(int size, Ref from, td::Random::Xorshift128plus &rnd, - bool with_prunned_branches = true) { - auto exploration = CellExplorer::random_explore(from, rnd); - return gen_random_cell(size, rnd, with_prunned_branches, std::move(exploration.visited_cells)); -} -auto gen_merkle_update(Ref cell, td::Random::Xorshift128plus &rnd, bool with_prunned_branches) { - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr()); - auto new_cell = gen_random_cell(rnd.fast(1, X), usage_cell, rnd, with_prunned_branches); - auto update = MerkleUpdate::generate(cell, new_cell, usage_tree.get()); - return std::make_tuple(new_cell, update, usage_tree); -}; - -void check_merkle_update(Ref A, Ref B, Ref AB) { - CHECK(AB.not_null()); - CHECK(A.not_null()); - MerkleUpdate::may_apply(A, AB).ensure(); - MerkleUpdate::validate(AB).ensure(); - auto got_B = MerkleUpdate::apply(A, AB); - ASSERT_EQ(B->get_hash(), got_B->get_hash()); -}; - -TEST(Cell, MerkleUpdate) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - bool with_prunned_branches = true; - auto A = gen_random_cell(rnd.fast(1, 1000), rnd, with_prunned_branches); - - Ref B; - Ref AB; - std::tie(B, AB, std::ignore) = gen_merkle_update(A, rnd, with_prunned_branches); - check_merkle_update(A, B, AB); - } -}; - -TEST(Cell, MerkleUpdateCombine) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - bool with_prunned_branches = true; - auto A = gen_random_cell(rnd.fast(1, X), rnd, with_prunned_branches); - - Ref B; - Ref AB; - std::tie(B, AB, std::ignore) = gen_merkle_update(A, rnd, with_prunned_branches); - check_merkle_update(A, B, AB); - - Ref C; - Ref BC; - std::tie(C, BC, std::ignore) = gen_merkle_update(B, rnd, with_prunned_branches); - check_merkle_update(B, C, BC); - - check_merkle_update(A, C, MerkleUpdate::combine(AB, BC)); - } -}; - -class BenchCellBuilder : public td::Benchmark { - public: - std::string get_description() const override { - return "BenchCellBuilder"; - } - - void run(int n) override { - td::Random::Xorshift128plus rnd(123); - std::string data(128, ' '); - for (auto &c : data) { - c = static_cast(rnd()); - } - - for (int i = 0; i < n; i++) { - CellBuilder cb; - cb.store_bytes(data.data(), rnd() & 127); - cb.finalize(false); - } - } -}; -TEST(TonDb, BenchCellBuilder) { - td::bench(BenchCellBuilder()); -} -class BenchCellBuilder2 : public td::Benchmark { - public: - std::string get_description() const override { - return "BenchCellBuilder"; - } - - void run(int n) override { - td::Random::Xorshift128plus rnd(123); - - for (int i = 0; i < n; i++) { - gen_random_cell(rnd.fast(1, 1000), rnd); - } - } -}; -TEST(TonDb, BenchCellBuilder2) { - td::bench(BenchCellBuilder2()); -} -class BenchCellBuilder3 : public td::Benchmark { - public: - std::string get_description() const override { - return "BenchCellBuilder"; - } - - void run(int n) override { - td::Random::Xorshift128plus rnd(123); - - for (int i = 0; i < n; i++) { - auto cell = gen_random_cell(rnd.fast(1, 1000), rnd, false); - auto cell_hash = cell->get_hash().to_hex(); - - int mode = get_random_serialization_mode(rnd); - - auto serialized = serialize_boc(std::move(cell), mode); - CHECK(serialized.size() != 0); - - auto loaded_cell = deserialize_boc(serialized); - ASSERT_EQ(cell_hash, loaded_cell->get_hash().to_hex()); - - auto new_serialized = serialize_boc(std::move(loaded_cell), mode); - ASSERT_EQ(serialized, new_serialized); - } - } -}; -TEST(TonDb, BenchCellBuilder3) { - td::bench(BenchCellBuilder3()); -} - -TEST(TonDb, BocFuzz) { - vm::std_boc_deserialize(td::base64_decode("te6ccgEBAQEAAgAoAAA=").move_as_ok()).ensure_error(); - vm::std_boc_deserialize(td::base64_decode("te6ccgQBQQdQAAAAAAEAte6ccgQBB1BBAAAAAAEAAAAAAP/" - "wAACJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJicmJiYmJiYmJiYmJiQ0NDQ0NDQ0NDQ0NDQ0ND" - "Q0NiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiQAA//AAAO4=") - .move_as_ok()); - vm::std_boc_deserialize(td::base64_decode("SEkh/w==").move_as_ok()).ensure_error(); - vm::std_boc_deserialize( - td::base64_decode( - "te6ccqwBMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAKCEAAAAgAQ==") - .move_as_ok()) - .ensure_error(); -} -void test_parse_prefix(td::Slice boc) { - for (size_t i = 0; i <= boc.size(); i++) { - auto prefix = boc.substr(0, i); - vm::BagOfCells::Info info; - auto res = info.parse_serialized_header(prefix); - if (res > 0) { - break; - } - CHECK(res != 0); - CHECK(-res > (int)i); - } -} - -TEST(TonDb, Boc) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - auto cell = gen_random_cell(rnd.fast(1, 1000), rnd); - auto cell_hash = cell->get_hash(); - auto mode = get_random_serialization_mode(rnd); - - auto serialized = serialize_boc(std::move(cell), mode); - CHECK(serialized.size() != 0); - - test_parse_prefix(serialized); - - auto loaded_cell = deserialize_boc(serialized); - ASSERT_EQ(cell_hash, loaded_cell->get_hash()); - - auto new_serialized = serialize_boc(std::move(loaded_cell), mode); - ASSERT_EQ(serialized, new_serialized); - } -}; -TEST(TonDb, BocMultipleRoots) { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 200; t++) { - auto cells = gen_random_cells(rnd.fast(1, 10), rnd.fast(1, 1000), rnd); - std::vector cell_hashes; - for (size_t i = 0; i < cells.size(); i++) { - cell_hashes.push_back(cells[i]->get_hash()); - } - auto mode = get_random_serialization_mode(rnd); - auto serialized = serialize_boc(cells, mode); - CHECK(serialized.size() != 0); - - auto loaded_cells = deserialize_boc_multiple(serialized); - ASSERT_EQ(cell_hashes.size(), loaded_cells.size()); - - for (size_t i = 0; i < cell_hashes.size(); i++) { - ASSERT_EQ(cell_hashes[i], loaded_cells[i]->get_hash()); - } - auto new_serialized = serialize_boc(std::move(loaded_cells), mode); - ASSERT_EQ(serialized, new_serialized); - } -}; - -TEST(TonDb, DynamicBoc) { - td::Random::Xorshift128plus rnd{123}; - std::string old_root_hash; - std::string old_root_serialization; - auto kv = std::make_shared(); - auto dboc = DynamicBagOfCellsDb::create(); - dboc->set_loader(std::make_unique(kv)); - for (int t = 1000; t >= 0; t--) { - if (rnd() % 10 == 0) { - dboc = DynamicBagOfCellsDb::create(); - } - dboc->set_loader(std::make_unique(kv)); - Ref old_root; - if (!old_root_hash.empty()) { - old_root = dboc->load_cell(old_root_hash).move_as_ok(); - auto serialization = serialize_boc(old_root); - ASSERT_EQ(old_root_serialization, serialization); - } - - auto cell = gen_random_cell(rnd.fast(1, 1000), rnd); - old_root_hash = cell->get_hash().as_slice().str(); - old_root_serialization = serialize_boc(cell); - - // Check that DynamicBagOfCells properly loads cells - cell = vm::StaticBagOfCellsDbLazy::create(vm::BufferSliceBlobView::create(td::BufferSlice(old_root_serialization))) - .move_as_ok() - ->get_root_cell(0) - .move_as_ok(); - - dboc->dec(old_root); - if (t != 0) { - dboc->inc(cell); - } - dboc->prepare_commit(); - { - CellStorer cell_storer(*kv); - dboc->commit(cell_storer); - } - } - ASSERT_EQ(0u, kv->count("").ok()); -}; - -TEST(TonDb, DynamicBoc2) { - int VERBOSITY_NAME(boc) = VERBOSITY_NAME(DEBUG) + 10; - td::Random::Xorshift128plus rnd{123}; - int total_roots = 10000; - int max_roots = 20; - std::vector root_hashes(max_roots); - std::vector> roots(max_roots); - int last_commit_at = 0; - int first_root_id = 0; - int last_root_id = 0; - auto kv = std::make_shared(); - auto dboc = DynamicBagOfCellsDb::create(); - dboc->set_loader(std::make_unique(kv)); - - auto add_root = [&](Ref root) { - dboc->inc(root); - root_hashes[last_root_id % max_roots] = (root->get_hash().as_slice().str()); - roots[last_root_id % max_roots] = root; - last_root_id++; - }; - - auto get_root = [&](int root_id) { - VLOG(boc) << " from older root #" << root_id; - auto from_root = roots[root_id % max_roots]; - if (from_root.is_null()) { - VLOG(boc) << " from db"; - auto from_root_hash = root_hashes[root_id % max_roots]; - from_root = dboc->load_cell(from_root_hash).move_as_ok(); - } else { - VLOG(boc) << "FROM MEMORY"; - } - return from_root; - }; - auto new_root = [&] { - if (last_root_id == total_roots) { - return; - } - if (last_root_id - first_root_id >= max_roots) { - return; - } - VLOG(boc) << "add root"; - Ref from_root; - if (first_root_id != last_root_id) { - from_root = get_root(rnd.fast(first_root_id, last_root_id - 1)); - } - VLOG(boc) << " ..."; - add_root(gen_random_cell(rnd.fast(1, 20), from_root, rnd)); - VLOG(boc) << " OK"; - }; - - auto commit = [&] { - VLOG(boc) << "commit"; - dboc->prepare_commit(); - { - CellStorer cell_storer(*kv); - dboc->commit(cell_storer); - } - dboc->set_loader(std::make_unique(kv)); - for (int i = last_commit_at; i < last_root_id; i++) { - roots[i % max_roots].clear(); - } - last_commit_at = last_root_id; - }; - auto reset = [&] { - VLOG(boc) << "reset"; - commit(); - dboc = DynamicBagOfCellsDb::create(); - dboc->set_loader(std::make_unique(kv)); - }; - - auto delete_root = [&] { - VLOG(boc) << "Delete root"; - if (first_root_id == last_root_id) { - return; - } - dboc->dec(get_root(first_root_id)); - first_root_id++; - VLOG(boc) << " OK"; - }; - - td::RandomSteps steps({{new_root, 10}, {delete_root, 9}, {commit, 2}, {reset, 1}}); - while (first_root_id != total_roots) { - VLOG(boc) << first_root_id << " " << last_root_id << " " << kv->count("").ok(); - steps.step(rnd); - } - commit(); - ASSERT_EQ(0u, kv->count("").ok()); -} - -template -td::Status test_boc_deserializer(std::vector> cells, int mode) { - auto total_data_cells_before = vm::DataCell::get_total_data_cells(); - SCOPE_EXIT { - auto total_data_cells_after = vm::DataCell::get_total_data_cells(); - ASSERT_EQ(total_data_cells_before, total_data_cells_after); - }; - auto serialized = serialize_boc(cells, mode); - CHECK(serialized.size() != 0); - - TRY_RESULT(boc_deserializer, BocDeserializerT::create(serialized)); - TRY_RESULT(root_count, boc_deserializer->get_root_count()); - ASSERT_EQ(cells.size(), root_count); - - std::vector> loaded_cells; - for (size_t root_i = 0; root_i < root_count; root_i++) { - TRY_RESULT(loaded_cell, boc_deserializer->get_root_cell(root_i)); - auto cell = cells[root_i]; - ASSERT_EQ(cell->get_level(), loaded_cell->get_level()); - for (int i = 0; i <= (int)cell->get_level(); i++) { - ASSERT_EQ(cell->get_hash(i), loaded_cell->get_hash(i)); - } - ASSERT_EQ(loaded_cell->get_hash(cell->get_level()), loaded_cell->get_hash()); - loaded_cells.push_back(std::move(loaded_cell)); - } - - auto new_serialized = serialize_boc(std::move(loaded_cells), mode); - ASSERT_EQ(serialized, new_serialized); - return td::Status::OK(); -} - -template -td::Status test_boc_deserializer_threads(Ref cell, int mode, td::Random::Xorshift128plus &rnd, - size_t threads_n = 4) { - auto serialized = serialize_boc(cell, mode); - CHECK(serialized.size() != 0); - std::vector explorations; - for (size_t i = 0; i < threads_n; i++) { - explorations.push_back(CellExplorer::random_explore(cell, rnd)); - } - TRY_RESULT(boc_deserializer, BocDeserializerT::create(serialized)); - TRY_RESULT(root_count, boc_deserializer->get_root_count()); - ASSERT_EQ(1u, root_count); - TRY_RESULT(loaded_cell, boc_deserializer->get_root_cell(0)); - std::vector threads; - for (auto &exploration : explorations) { - threads.emplace_back([&] { - auto exploration2 = CellExplorer::explore(loaded_cell, exploration.ops); - ASSERT_EQ(exploration.log, exploration2.log); - }); - } - for (auto &thread : threads) { - thread.join(); - } - - return td::Status::OK(); -} - -td::Status test_boc_deserializer_full(std::vector> cells) { - for (auto mode : get_serialization_modes()) { - TRY_STATUS(vm::test_boc_deserializer(cells, mode)); - TRY_STATUS(vm::test_boc_deserializer(cells, mode)); - } - return td::Status::OK(); -} -td::Status test_boc_deserializer_full(Ref cell) { - return test_boc_deserializer_full(std::vector>{std::move(cell)}); -} - -template -void test_boc_deserializer() { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 1000; t++) { - auto cells = gen_random_cells(rnd.fast(1, 10), static_cast(rnd() % 1000 + 1), rnd); - for (auto mode : get_serialization_modes()) { - test_boc_deserializer(cells, mode).ensure(); - } - } -} - -TEST(TonDb, BocDeserializerBaseline) { - test_boc_deserializer(); -} - -TEST(TonDb, BocDeserializerSimple) { - test_boc_deserializer(); -} - -template -void test_boc_deserializer_threads() { - td::Random::Xorshift128plus rnd{123}; - for (int t = 0; t < 20; t++) { - auto cell = gen_random_cell(static_cast(rnd() % 1000 + 1), rnd); - for (auto mode : get_serialization_modes()) { - test_boc_deserializer_threads(cell, mode, rnd).ensure(); - } - } -} - -TEST(TonDb, BocDeserializerSimpleThreads) { - test_boc_deserializer_threads(); -} - -class CompactArray { - public: - CompactArray(size_t size) { - root_ = create(size, 0); - size_ = size; - } - CompactArray(size_t size, Ref root) { - root_ = std::move(root); - size_ = size; - } - CompactArray(td::Span span) { - root_ = create(span); - size_ = span.size(); - } - CompactArray(CompactArray &&other) = default; - CompactArray &operator=(CompactArray &&other) = default; - - td::Slice hash() const { - return root()->get_hash().as_slice(); - } - void set(size_t pos, td::uint64 value) { - root_ = set(root_, size_, pos, value); - } - td::uint64 get(size_t pos) { - return get(root_, size_, pos, nullptr); - } - - const Ref &root() const { - return root_; - } - size_t size() const { - return size_; - } - - Ref merkle_proof(std::vector keys) { - std::set hashes; - for (auto key : keys) { - get(root_, size_, key, &hashes); - } - - auto is_prunned = [&](const Ref &cell) { return hashes.count(cell->get_hash()) == 0; }; - return MerkleProof::generate_raw(root_, is_prunned); - } - - private: - Ref root_; - size_t size_; - - static Ref create_list(td::uint64 value) { - CellBuilder cb; - cb.store_long(value, 64); - return cb.finalize(); - } - static Ref create_node(Ref left, Ref right) { - CellBuilder cb; - cb.store_ref(std::move(left)); - cb.store_ref(std::move(right)); - return cb.finalize(); - } - static Ref create(size_t size, td::uint64 value) { - if (size == 1) { - return create_list(value); - } - return create_node(create(size / 2, value), create((size + 1) / 2, value)); - } - static Ref create(td::Span value) { - if (value.size() == 1) { - return create_list(value[0]); - } - return create_node(create(value.substr(0, value.size() / 2)), create(value.substr(value.size() / 2))); - } - - static td::uint64 get(Ref any_cell, size_t size, size_t pos, std::set *hashes) { - if (hashes) { - hashes->insert(any_cell->get_hash()); - } - CellSlice cs(NoVm(), any_cell); - assert(pos < size); - if (size == 1) { - return cs.fetch_long(64); - } - auto left = cs.fetch_ref(); - if (pos < size / 2) { - return get(left, size / 2, pos, hashes); - } - pos -= size / 2; - auto right = cs.fetch_ref(); - return get(right, (size + 1) / 2, pos, hashes); - } - - static Ref set(Ref any_cell, size_t size, size_t pos, td::uint64 value) { - CellSlice cs(NoVm(), any_cell); - assert(pos < size); - if (size == 1) { - return create_list(value); - } - //LOG(ERROR) << cell->size_refs() << " " << cell->size_bits(); - auto left = cs.fetch_ref(); - auto right = cs.fetch_ref(); - if (pos < size / 2) { - left = set(left, size / 2, pos, value); - } else { - pos -= size / 2; - right = set(right, (size + 1) / 2, pos, value); - } - return create_node(left, right); - } -}; - -class FastCompactArray { - public: - FastCompactArray(size_t size) : v_(size) { - } - void set(size_t pos, td::uint64 value) { - v_.at(pos) = value; - } - td::uint64 get(size_t pos) { - return v_.at(pos); - } - td::Span as_span() const { - return v_; - } - - private: - std::vector v_; -}; - -TEST(Cell, BocHands) { - serialize_boc(CellBuilder{}.store_bytes("AAAAAAAA").finalize()); - auto a = CellBuilder{}.store_bytes("abcd").store_ref(CellBuilder{}.store_bytes("???").finalize()).finalize(); - a = CellBuilder{} - .store_bits("XXX", 3) - .store_ref(CellBuilder::create_pruned_branch(std::move(a), Cell::max_level)) - .finalize(); - auto serialized = serialize_boc(a); - deserialize_boc(serialized); - deserialize_boc(serialize_boc(std::vector>{a, a})); - - // CHECK backward compatibility with - // serialized_boc_idx and serialized_boc_idx_crc32c - //auto serialized_idx_crc_x = serialize_boc(a, BagOfCells::WithIndex | BagOfCells::WithCRC32C); - //LOG(ERROR) << td::format::escaped(serialized_idx_crc_x); - std::string serialized_idx_crc = - td::Slice( - "\254\303\247(\001\001\002\001\000*\004*\201\001P\001\210H\001\004\024\271\313\264\253\277\265\350dN\250{," - "\372\021\012:I\354\322|\255\245\330\204+&\345\214\026\300\064\000\001\032\231\063\274") - .str(); - //auto serialized_idx_x = serialize_boc(a, BagOfCells::WithIndex); - //LOG(ERROR) << td::format::escaped(serialized_idx_x); - std::string serialized_idx = - td::Slice( - "h\377e\363\001\001\002\001\000*\004*\201\001P\001\210H\001\004\024\271\313\264\253\277\265\350dN\250{," - "\372\021\012:I\354\322|\255\245\330\204+&\345\214\026\300\064\000\001") - .str(); - - ASSERT_EQ(serialized, serialize_boc(deserialize_boc(serialized_idx))); - ASSERT_EQ(serialized, serialize_boc(deserialize_boc(serialized_idx_crc))); -} - -TEST(Cell, MerkleProofHands) { - // data has a reference, because we do not prune lists - auto data = CellBuilder{}.store_bytes("pruned data").store_ref(CellBuilder{}.finalize()).finalize(); - auto prunned_data = CellBuilder::create_pruned_branch(data, data->get_level() + 1); - ASSERT_EQ(1u, prunned_data->get_level()); - ASSERT_EQ(prunned_data->get_hash(0), data->get_hash(0)); - ASSERT_EQ(data->get_hash(0), data->get_hash(1)); - ASSERT_TRUE(prunned_data->get_hash(1) != prunned_data->get_hash(0)); - - auto node = CellBuilder{}.store_bytes("protected data").store_ref(data).finalize(); - auto proof = CellBuilder{}.store_bits(node->get_data(), node->get_bits()).store_ref(prunned_data).finalize(); - ASSERT_EQ(0u, node->get_level()); - ASSERT_EQ(1u, proof->get_level()); - ASSERT_EQ(proof->get_hash(0), node->get_hash(0)); - ASSERT_TRUE(proof->get_hash(1) != node->get_hash(1)); - test_boc_deserializer_full(proof).ensure(); - - auto merkle_proof = CellBuilder::create_merkle_proof(proof); - ASSERT_EQ(0u, merkle_proof->get_level()); - test_boc_deserializer_full(merkle_proof).ensure(); - - { - auto virtual_node = proof->virtualize({0, 1}); - ASSERT_EQ(0u, virtual_node->get_level()); - ASSERT_EQ(1u, virtual_node->get_virtualization()); - CellSlice cs{NoVm(), virtual_node}; - auto virtual_data = cs.fetch_ref(); - ASSERT_EQ(0u, virtual_data->get_level()); - ASSERT_EQ(1u, virtual_data->get_virtualization()); - ASSERT_EQ(data->get_hash(), virtual_data->get_hash()); - - auto virtual_node_copy = - CellBuilder{}.store_bits(node->get_data(), node->get_bits()).store_ref(virtual_data).finalize(); - ASSERT_EQ(0u, virtual_node_copy->get_level()); - ASSERT_EQ(1u, virtual_node_copy->get_virtualization()); - ASSERT_EQ(virtual_node->get_hash(), virtual_node_copy->get_hash()); - - { - auto two_nodes = CellBuilder{}.store_ref(virtual_node).store_ref(node).finalize(); - ASSERT_EQ(0u, two_nodes->get_level()); - ASSERT_EQ(1u, two_nodes->get_virtualization()); - CellSlice cs2(NoVm(), two_nodes); - ASSERT_EQ(1u, cs2.prefetch_ref(0)->get_virtualization()); - ASSERT_EQ(0u, cs2.prefetch_ref(1)->get_virtualization()); - } - } - LOG(ERROR) << td::NamedThreadSafeCounter::get_default(); -} - -TEST(Cell, MerkleProofArrayHands) { - // create simple array - CompactArray arr(17); - for (size_t i = 0; i < arr.size(); i++) { - arr.set(i, i / 3); - } - - // create merke proof for 4 5 6 and 16th elements - std::vector keys = {4, 5, 6, 16}; - auto proof = arr.merkle_proof(keys); - - ASSERT_EQ(1u, proof->get_level()); - ASSERT_EQ(proof->get_hash(0), arr.root()->get_hash(0)); - ASSERT_TRUE(proof->get_hash(1) != arr.root()->get_hash(1)); - ASSERT_EQ(arr.root()->get_hash(0), arr.root()->get_hash(1)); - - CompactArray new_arr(arr.size(), proof->virtualize({0, 1})); - for (auto k : keys) { - ASSERT_EQ(arr.get(k), new_arr.get(k)); - } - test_boc_deserializer_full(proof).ensure(); - test_boc_deserializer_full(CellBuilder::create_merkle_proof(proof)).ensure(); -} - -TEST(Cell, MerkleProofCombineArray) { - size_t n = 1 << 15; - std::vector data; - for (size_t i = 0; i < n; i++) { - data.push_back(i / 3); - } - CompactArray arr(data); - - td::Ref root = vm::CellBuilder::create_merkle_proof(arr.merkle_proof({})); - td::Timer timer; - for (size_t i = 0; i < n; i++) { - auto new_root = vm::CellBuilder::create_merkle_proof(arr.merkle_proof({i})); - root = vm::MerkleProof::combine_fast(root, new_root); - if ((i - 1) % 100 == 0) { - LOG(ERROR) << timer; - timer = {}; - } - } - - CompactArray arr2(n, vm::MerkleProof::virtualize(root, 1)); - for (size_t i = 0; i < n; i++) { - CHECK(arr.get(i) == arr2.get(i)); - } -} - -TEST(Cell, MerkleProofCombineArray2) { - auto a = vm::CellBuilder().store_long(1, 8).finalize(); - auto b = vm::CellBuilder().store_long(2, 8).finalize(); - auto c = vm::CellBuilder().store_long(3, 8).finalize(); - auto d = vm::CellBuilder().store_long(4, 8).finalize(); - auto left = vm::CellBuilder().store_ref(a).store_ref(b).finalize(); - auto right = vm::CellBuilder().store_ref(c).store_ref(d).finalize(); - auto x = vm::CellBuilder().store_ref(left).store_ref(right).finalize(); - size_t n = 18; - //TODO: n = 100, currently TL - for (size_t i = 0; i < n; i++) { - x = vm::CellBuilder().store_ref(x).store_ref(x).finalize(); - } - - td::Ref root; - auto apply_op = [&](auto op) { - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(x, usage_tree->root_ptr()); - root = usage_cell; - op(); - return MerkleProof::generate(root, usage_tree.get()); - }; - - auto first = apply_op([&] { - auto x = root; - while (true) { - auto cs = vm::load_cell_slice(x); - if (cs.size_refs() == 0) { - break; - } - x = cs.prefetch_ref(0); - } - }); - auto second = apply_op([&] { - auto x = root; - while (true) { - auto cs = vm::load_cell_slice(x); - if (cs.size_refs() == 0) { - break; - } - x = cs.prefetch_ref(1); - } - }); - - { - td::Timer t; - auto x = vm::MerkleProof::combine(first, second); - LOG(ERROR) << "slow " << t; - } - { - td::Timer t; - auto x = vm::MerkleProof::combine_fast(first, second); - LOG(ERROR) << "fast " << t; - } -} - -TEST(Cell, MerkleUpdateHands) { - auto data = CellBuilder{}.store_bytes("pruned data").store_ref(CellBuilder{}.finalize()).finalize(); - auto node = CellBuilder{}.store_bytes("protected data").store_ref(data).finalize(); - auto other_node = CellBuilder{}.store_bytes("other protected data").store_ref(data).finalize(); - auto usage_tree = std::make_shared(); - auto other_usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(node, usage_tree->root_ptr()); - auto child = CellSlice(vm::NoVm(), usage_cell).prefetch_ref(0); - auto new_node = CellBuilder{}.store_bytes("new data").store_ref(child).finalize(); - auto new_child = CellSlice(vm::NoVm(), new_node).prefetch_ref(0); - auto update = MerkleUpdate::generate(usage_cell, new_node, usage_tree.get()); - - MerkleUpdate::may_apply(node, update).ensure(); - MerkleUpdate::validate(update).ensure(); - auto x = MerkleUpdate::apply(node, update); - ASSERT_TRUE(serialize_boc(new_node) == serialize_boc(x)); - - MerkleUpdate::may_apply(other_node, update).ensure_error(); - ASSERT_TRUE(MerkleUpdate::apply(other_node, update).is_null()); - auto other_update = CellBuilder::create_merkle_update(CellBuilder::create_pruned_branch(other_node, 1), - CellBuilder::create_pruned_branch(new_node, 1)); - MerkleUpdate::may_apply(node, other_update).ensure_error(); - MerkleUpdate::validate(other_update).ensure_error(); - ASSERT_TRUE(MerkleUpdate::apply(other_node, other_update).is_null()); - auto bad_update = CellBuilder::create_merkle_update(CellBuilder::create_pruned_branch(new_node, 1), - CellBuilder::create_pruned_branch(other_node, 1)); - CHECK(MerkleUpdate::combine(update, bad_update).is_null()); -} - -TEST(Cell, MerkleUpdateArray) { - // create simple array - size_t n = 1 << 20; - std::vector data; - for (size_t i = 0; i < n; i++) { - data.push_back(i / 3); - } - CompactArray arr(data); - auto root = arr.root(); - auto usage_tree = std::make_shared(); - auto usage_cell = UsageCell::create(root, usage_tree->root_ptr()); - arr = CompactArray(n, usage_cell); - arr.set(n / 2, 0); - arr.set(n / 2 + 1, 1); - arr.set(n / 2 + 2, 2414221111); - arr.set(n / 2 + 3, 2); - - auto update = MerkleUpdate::generate(usage_cell, arr.root(), usage_tree.get()); - CellStorageStat stat; - stat.compute_used_storage(update, false); - ASSERT_EQ(stat.cells, 81u); - //CellSlice(NoVm(), update).print_rec(std::cerr); - - check_merkle_update(root, arr.root(), update); -} - -TEST(Cell, MerkleUpdateCombineArray) { - size_t n = 1 << 10; - std::vector data; - for (size_t i = 0; i < n; i++) { - data.push_back(i / 3); - } - CompactArray arr(data); - auto from = arr.root(); - std::shared_ptr usage_tree; - Ref usage_cell; - - std::vector> updates; - - auto apply_op = [&](auto op) { - auto A = arr.root(); - usage_tree = std::make_shared(); - usage_cell = UsageCell::create(arr.root(), usage_tree->root_ptr()); - arr = CompactArray(n, usage_cell); - op(); - updates.push_back(MerkleUpdate::generate(A, arr.root(), usage_tree.get())); - }; - - auto combine_all = [&]() { - while (updates.size() > 1) { - size_t i = updates.size() - 2; - updates[i] = MerkleUpdate::combine(updates[i], updates[i + 1]); - updates.pop_back(); - CellStorageStat stat; - stat.compute_used_storage(updates[i], false); - } - }; - auto validate = [&](size_t size) { - combine_all(); - check_merkle_update(from, arr.root(), updates.at(0)); - CellStorageStat stat; - stat.compute_used_storage(updates[0], false); - if (size != 0) { - ASSERT_EQ(size, stat.cells); - } - }; - apply_op([] {}); - validate(3); - apply_op([] {}); - apply_op([] {}); - apply_op([] {}); - validate(3); - - apply_op([&] { - for (size_t i = 0; i < n; i++) { - arr.set(i, i / 3 + 10); - } - }); - apply_op([&] { - for (size_t i = 0; i < n; i++) { - arr.set(i, i / 3); - } - }); - validate(3); - - for (size_t i = 0; i + 1 < n; i++) { - apply_op([&] { - arr.set(i, i / 3 + 1); - if (i != 0) { - arr.set(i - 1, (i - 1) / 3); - } - }); - } - - validate(41); -} - -} // namespace vm - -class BenchBocSerializerImport : public td::Benchmark { - public: - BenchBocSerializerImport() { - std::vector v(array_size); - td::Random::Xorshift128plus rnd{123}; - for (auto &x : v) { - x = rnd(); - } - arr = vm::CompactArray(v); - //serialization_ = td::BufferSlice(boc.serialize_to_string(15)); - } - std::string get_description() const override { - return "BenchBocSerializer"; - } - - void run(int n) override { - for (int i = 0; i < n; i++) { - vm::BagOfCells boc; - boc.add_root(arr.root()); - boc.import_cells().ensure(); - } - } - - private: - td::BufferSlice serialization_; - static constexpr td::uint32 array_size = 1024; - vm::CompactArray arr{1}; -}; - -class BenchBocSerializerSerialize : public td::Benchmark { - public: - BenchBocSerializerSerialize() { - std::vector v(array_size); - td::Random::Xorshift128plus rnd{123}; - for (auto &x : v) { - x = rnd(); - } - arr = vm::CompactArray(v); - boc.add_root(arr.root()); - boc.import_cells().ensure(); - } - std::string get_description() const override { - return "BenchBocSerializer"; - } - - void run(int n) override { - for (int i = 0; i < n; i++) { - boc.serialize_to_string(31); - } - } - - private: - td::BufferSlice serialization_; - static constexpr td::uint32 array_size = 1024; - vm::CompactArray arr{1}; - vm::BagOfCells boc; -}; - -struct BenchBocDeserializerConfig { - enum BlobType { File, Memory, FileMemoryMap, RocksDb } blob_type; - int k{100}; - enum Mode { Prefix, Range, Random } mode{Random}; - bool with_index{true}; - int threads_n{1}; -}; - -td::StringBuilder &operator<<(td::StringBuilder &sb, const BenchBocDeserializerConfig &config) { - sb << "load from "; - switch (config.blob_type) { - case BenchBocDeserializerConfig::File: - sb << "file"; - break; - case BenchBocDeserializerConfig::Memory: - sb << "memory"; - break; - case BenchBocDeserializerConfig::FileMemoryMap: - sb << "file mmap"; - break; - case BenchBocDeserializerConfig::RocksDb: - sb << "rocksdb"; - break; - } - sb << td::tag("k", config.k) << " "; - switch (config.mode) { - case BenchBocDeserializerConfig::Prefix: - sb << "prefix"; - break; - case BenchBocDeserializerConfig::Range: - sb << "range"; - break; - case BenchBocDeserializerConfig::Random: - sb << "random"; - break; - } - sb << " " << (config.with_index ? "with" : "without") << " index"; - sb << " " << config.threads_n << " threads"; - return sb; -} - -template -class BenchBocDeserializer : public td::Benchmark { - public: - BenchBocDeserializer(std::string name, BenchBocDeserializerConfig config) : name_(std::move(name)), config_(config) { - td::PerfWarningTimer perf("A", 1); - fast_array_ = vm::FastCompactArray(array_size); - td::Random::Xorshift128plus rnd{123}; - for (td::uint32 i = 0; i < array_size; i++) { - auto val = rnd(); - fast_array_.set(i, val); - } - vm::CompactArray arr(fast_array_.as_span()); - auto db_path = "serialization_rocksdb"; - if (config.blob_type == BenchBocDeserializerConfig::RocksDb) { - { - td::RocksDb::destroy(td::Slice(db_path)).ensure(); - auto db = vm::TonDbImpl::open(td::Slice(db_path)).move_as_ok(); - auto txn = db->begin_transaction(); - auto smt = txn->begin_smartcontract(); - SCOPE_EXIT { - db->commit_transaction(std::move(txn)); - }; - SCOPE_EXIT { - txn->commit_smartcontract(std::move(smt)); - }; - smt->set_root(arr.root()); - } - db_ = vm::TonDbImpl::open(td::Slice(db_path)).move_as_ok(); - } else { - serialization_ = td::BufferSlice(serialize_boc( - arr.root(), vm::BagOfCells::WithIntHashes | vm::BagOfCells::WithTopHash | - (config.with_index ? vm::BagOfCells::WithIndex | vm::BagOfCells::WithCacheBits : 0))); - - if (config.blob_type == BenchBocDeserializerConfig::File || - config.blob_type == BenchBocDeserializerConfig::FileMemoryMap) { - td::unlink("serialization").ignore(); - td::write_file("serialization", serialization_.as_slice()).ensure(); - } - } - root_ = arr.root(); - } - std::string get_description() const override { - return PSTRING() << "BocDeserializer " << name_ << " " << config_; - } - - vm::Ref load_root() { - if (config_.blob_type == BenchBocDeserializerConfig::RocksDb) { - auto txn = db_->begin_transaction(); - auto smt = txn->begin_smartcontract(); - SCOPE_EXIT { - db_->abort_transaction(std::move(txn)); - }; - SCOPE_EXIT { - txn->commit_smartcontract(std::move(smt)); - }; - LOG(ERROR) << "load root from rocksdb"; - return smt->get_root(); - } - auto blob = [&] { - switch (config_.blob_type) { - case BenchBocDeserializerConfig::File: - return vm::FileBlobView::create("serialization").move_as_ok(); - case BenchBocDeserializerConfig::Memory: - return vm::BufferSliceBlobView::create(serialization_.clone()); - case BenchBocDeserializerConfig::FileMemoryMap: - return vm::FileMemoryMappingBlobView::create("serialization").move_as_ok(); - default: - UNREACHABLE(); - } - UNREACHABLE(); - }(); - auto boc_deserializer = DeserializerT::create(std::move(blob)).move_as_ok(); - ASSERT_EQ(1u, boc_deserializer->get_root_count().move_as_ok()); - return boc_deserializer->get_root_cell(0).move_as_ok(); - } - - void run(int n) override { - td::Random::Xorshift128plus rnd{123}; - - std::vector threads; - //TODO: use config.k - auto K = config_.k == 0 ? n : config_.k; - td::Stage stage; - vm::Ref root; - for (int t = 0; t < config_.threads_n; t++) { - threads.emplace_back([&, seed = rnd(), thread_i = t] { - for (int round_i = 0; round_i < n / K; round_i++) { - if (thread_i == 0) { - root = load_root(); - } - stage.wait(config_.threads_n * (2 * round_i + 1)); - - vm::CompactArray array(array_size, root); - td::Random::Xorshift128plus rnd{seed}; - td::uint64 start_pos = - config_.mode == BenchBocDeserializerConfig::Range ? array_size / config_.threads_n * thread_i : 0; - for (int k = 0; k < K; k++) { - auto pos = start_pos; - switch (config_.mode) { - case BenchBocDeserializerConfig::Prefix: - case BenchBocDeserializerConfig::Range: - pos = (pos + k) % array_size; - break; - case BenchBocDeserializerConfig::Random: - pos = rnd() % array_size; - break; - } - ASSERT_EQ(fast_array_.get(td::narrow_cast(pos)), array.get(td::narrow_cast(pos))); - } - stage.wait(config_.threads_n * (2 * round_i + 2)); - } - }); - } - for (auto &thread : threads) { - thread.join(); - } - } - - private: - std::string name_; - td::BufferSlice serialization_; - BenchBocDeserializerConfig config_; - static constexpr td::uint32 array_size = 1024 * 1024; - vm::FastCompactArray fast_array_{array_size}; - vm::Ref root_; - vm::TonDb db_; -}; - -TEST(TonDb, BenchBocSerializerImport) { - if (0) { - BenchBocSerializerImport b; - while (true) { - td::bench_n(b, 1000000); - } - } - td::bench(BenchBocSerializerImport()); -} -TEST(TonDb, BenchBocSerializerSerialize) { - td::bench(BenchBocSerializerSerialize()); -} - -template -void bench_deserializer(std::string name, bool full) { - using Config = BenchBocDeserializerConfig; - if (full) { - for (auto k : {1, 10, 100}) { - for (auto with_index : {false, true}) { - for (auto mode : {Config::Prefix, Config::Range, Config::Random}) { - for (auto blob_type : {Config::Memory, Config::File, Config::FileMemoryMap}) { - BenchBocDeserializerConfig config; - config.k = k; - config.with_index = with_index; - config.mode = mode; - config.blob_type = blob_type; - td::bench(BenchBocDeserializer(name, config)); - } - } - } - } - } else { - td::bench(BenchBocDeserializer(name, BenchBocDeserializerConfig())); - } -} -template -void bench_deserializer_threads(std::string name) { - using Config = BenchBocDeserializerConfig; - for (auto threads_n : {1, 4, 16}) { - //for (auto threads_n : {16}) { - //for (auto with_index : {false, true}) { - //for (auto mode : {BenchBocDeserializerConfig::Prefix, BenchBocDeserializerConfig::Range, - //BenchBocDeserializerConfig::Random}) { - //for (auto from_file : {false, true}) { - BenchBocDeserializerConfig config; - config.threads_n = threads_n; - config.k = 0; - config.with_index = true; - config.mode = Config::Random; - config.mode = Config::Range; - config.mode = Config::Prefix; - config.blob_type = Config::Memory; - td::bench(BenchBocDeserializer(name, config)); - //td::bench_n(BenchBocThreadsDeserializer(name, config), 1000000); - //} - //} - //} - } -} - -TEST(TonDb, BenchBocThreadsDeserializerSimple) { - //td::bench_n(BenchBocDeserializer("simple", BenchBocDeserializerConfig()), 1000000); - //std::exit(0); - bench_deserializer_threads("simple"); -} -TEST(TonDb, BenchBocDeserializerSimple) { - //td::bench_n(BenchBocDeserializer("simple", BenchBocDeserializerConfig()), 1000000); - //std::exit(0); - bench_deserializer("simple", false); -} -TEST(TonDb, BenchBocDeserializerBaseline) { - //td::bench_n(BenchBocDeserializer("baseline", BenchBocDeserializerConfig()), 1000000); - //std::exit(0); - bench_deserializer("baseline", false); -} -TEST(TonDb, BenchBocDeserializerRocksDb) { - //td::bench_n(BenchBocDeserializer("baseline", BenchBocDeserializerConfig()), 1000000); - //std::exit(0); - auto config = BenchBocDeserializerConfig(); - config.blob_type = BenchBocDeserializerConfig::RocksDb; - config.threads_n = 4; - config.k = 0; - td::bench(BenchBocDeserializer("rockdb", config)); -} - -TEST(TonDb, CompactArray) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - td::Slice db_path = "compact_array_db"; - td::RocksDb::destroy(db_path).ensure(); - - td::Random::Xorshift128plus rnd(123); - - auto next_array_size = [&rnd]() { - static std::vector array_sizes = {1, 2, 4, 10, 37, 100, 1000, 10000}; - return array_sizes[rnd() % array_sizes.size()]; - }; - - vm::CompactArray array(2); - vm::FastCompactArray fast_array(2); - auto next_pos = [&] { return static_cast(rnd() % array.size()); }; - - auto db = vm::TonDbImpl::open(db_path).move_as_ok(); - auto txn = db->begin_transaction(); - auto smt = txn->begin_smartcontract(); - SCOPE_EXIT { - db->commit_transaction(std::move(txn)); - }; - SCOPE_EXIT { - txn->commit_smartcontract(std::move(smt)); - }; - - auto flush_to_db = [&] { - if (rnd() % 10 != 0) { - return; - } - bool restart_db = rnd() % 20 == 0; - bool reload_array = rnd() % 5 == 0; - smt->set_root(array.root()); - txn->commit_smartcontract(std::move(smt)); - db->commit_transaction(std::move(txn)); - if (restart_db) { - db->clear_cache(); - //db.reset(); - //db = vm::TonDbImpl::open(db_path).move_as_ok(); - } - txn = db->begin_transaction(); - smt = txn->begin_smartcontract(); - smt->validate_meta().ensure(); - ASSERT_EQ(smt->get_root()->get_hash(), array.root()->get_hash()); - if (reload_array) { - auto size = array.size(); - array = vm::CompactArray(size, smt->get_root()); - } - }; - - auto do_validate = [&](size_t pos) { ASSERT_EQ(array.get(pos), fast_array.get(pos)); }; - auto validate = [&] { do_validate(next_pos()); }; - auto validate_full = [&] { - for (size_t pos = 0; pos < array.size(); pos++) { - do_validate(pos); - } - }; - - auto set_value = [&] { - auto pos = static_cast(rnd() % array.size()); - auto value = rnd() % 3; - array.set(pos, value); - fast_array.set(pos, value); - }; - - auto reset_array = [&] { - auto size = next_array_size(); - array = vm::CompactArray(size); - fast_array = vm::FastCompactArray(size); - }; - - td::RandomSteps steps({{reset_array, 1}, {set_value, 1000}, {validate, 10}, {validate_full, 2}, {flush_to_db, 1}}); - for (size_t t = 0; t < 100000; t++) { - if (t % 10000 == 0) { - LOG(ERROR) << t; - } - steps.step(rnd); - } -}; - -TEST(TonDb, CompactArrayOld) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - using namespace vm; - //auto kv = std::make_unique(); - td::RocksDb::destroy("ttt").ensure(); - - auto ton_db = vm::TonDbImpl::open("ttt").move_as_ok(); - - //auto storage = std::make_unique(kv.get()); - - size_t array_size = 1000; - std::string hash; - td::Random::Xorshift128plus rnd(123); - FastCompactArray fast_array(array_size); - { - auto txn = ton_db->begin_transaction(); - SCOPE_EXIT { - ton_db->commit_transaction(std::move(txn)); - }; - auto smart = txn->begin_smartcontract(""); - SCOPE_EXIT { - txn->commit_smartcontract(std::move(smart)); - }; - CompactArray arr(array_size); - arr.set(array_size / 2, 124); - fast_array.set(array_size / 2, 124); - //for (size_t i = 0; i < array_size; i++) { - //int x = rnd() % 2; - //arr.set(i, x); - //fast_array.set(i, x); - //} - smart->set_root(arr.root()); - LOG(ERROR) << smart->get_root()->get_hash().to_hex(); - } - //LOG(ERROR) << "OK"; - - for (int i = 0; i < 100; i++) { - if (i % 10 == 9) { - //LOG(ERROR) << ton_db->stat(); - ton_db.reset(); - ton_db = vm::TonDbImpl::open("ttt").move_as_ok(); - } - auto txn = ton_db->begin_transaction(); - SCOPE_EXIT { - ton_db->commit_transaction(std::move(txn)); - }; - auto smart = txn->begin_smartcontract(""); - //smart->validate_meta(); - SCOPE_EXIT { - txn->commit_smartcontract(std::move(smart)); - }; - if (i % 1000 == 0) { - LOG(ERROR) << "i = " << i; - } - CompactArray arr(array_size, smart->get_root()); - auto key = static_cast(rnd() % array_size); - auto value = rnd() % 2; - arr.set(key, value); - fast_array.set(key, value); - smart->set_root(arr.root()); - //LOG(ERROR) << storage->size(); - } - { - auto txn = ton_db->begin_transaction(); - SCOPE_EXIT { - ton_db->abort_transaction(std::move(txn)); - }; - auto smart = txn->begin_smartcontract(""); - SCOPE_EXIT { - txn->abort_smartcontract(std::move(smart)); - }; - - CompactArray arr(array_size, smart->get_root()); - for (size_t i = 0; i < array_size; i++) { - ASSERT_EQ(fast_array.get(i), arr.get(i)); - } - } -} - -TEST(TonDb, StackOverflow) { - try { - td::Ref cell = vm::CellBuilder().finalize(); - for (int i = 0; i < 10000000; i++) { - vm::CellBuilder cb; - cb.store_ref(std::move(cell)); - cell = cb.finalize(); - } - LOG(ERROR) << "A"; - vm::test_boc_deserializer({cell}, 31); - LOG(ERROR) << "B"; - vm::test_boc_deserializer({cell}, 31); - LOG(ERROR) << "C"; - } catch (...) { - } - - struct A : public td::CntObject { - explicit A(td::Ref next) : next(next) { - } - td::Ref next; - }; - { - td::Ref head; - for (int i = 0; i < 10000000; i++) { - td::Ref new_head = td::Ref(true, std::move(head)); - head = std::move(new_head); - } - } -} - -TEST(TonDb, BocRespectsUsageCell) { - td::Random::Xorshift128plus rnd(123); - auto cell = vm::gen_random_cell(20, rnd, true); - auto usage_tree = std::make_shared(); - auto usage_cell = vm::UsageCell::create(cell, usage_tree->root_ptr()); - auto serialization = serialize_boc(usage_cell); - auto proof = vm::MerkleProof::generate(cell, usage_tree.get()); - auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1); - auto serialization_of_virtualized_cell = serialize_boc(virtualized_proof); - ASSERT_STREQ(serialization, serialization_of_virtualized_cell); -} - -TEST(TonDb, DynamicBocRespectsUsageCell) { - td::Random::Xorshift128plus rnd(123); - auto cell = vm::gen_random_cell(20, rnd, true); - auto usage_tree = std::make_shared(); - auto usage_cell = vm::UsageCell::create(cell, usage_tree->root_ptr()); - - auto kv = std::make_shared(); - auto dboc = vm::DynamicBagOfCellsDb::create(); - dboc->set_loader(std::make_unique(kv)); - dboc->inc(usage_cell); - { - vm::CellStorer cell_storer(*kv); - dboc->commit(cell_storer); - } - - auto proof = vm::MerkleProof::generate(cell, usage_tree.get()); - auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1); - auto serialization_of_virtualized_cell = serialize_boc(virtualized_proof); - auto serialization = serialize_boc(cell); - ASSERT_STREQ(serialization, serialization_of_virtualized_cell); -} - -TEST(TonDb, DoNotMakeListsPrunned) { - auto cell = vm::CellBuilder().store_bytes("abc").finalize(); - auto is_prunned = [&](const td::Ref &cell) { return true; }; - auto proof = vm::MerkleProof::generate(cell, is_prunned); - auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1); - ASSERT_TRUE(virtualized_proof->get_virtualization() == 0); -} - -TEST(TonDb, CellStat) { - td::Random::Xorshift128plus rnd(123); - bool with_prunned_branches = true; - for (int i = 0; i < 1000; i++) { - auto A = vm::gen_random_cell(100, rnd, with_prunned_branches); - td::Ref B, AB, B_proof; - std::shared_ptr usage_tree; - std::tie(B, AB, usage_tree) = gen_merkle_update(A, rnd, with_prunned_branches); - B_proof = vm::CellSlice(vm::NoVm(), AB).prefetch_ref(1); - - vm::CellStorageStat stat; - stat.add_used_storage(B); - - vm::NewCellStorageStat new_stat; - new_stat.add_cell({}); - new_stat.add_cell(B); - ASSERT_EQ(stat.cells, new_stat.get_stat().cells); - ASSERT_EQ(stat.bits, new_stat.get_stat().bits); - - vm::CellStorageStat proof_stat; - proof_stat.add_used_storage(B_proof); - - vm::NewCellStorageStat new_proof_stat; - new_proof_stat.add_proof(B, usage_tree.get()); - CHECK(new_proof_stat.get_stat().cells == 0); - CHECK(new_proof_stat.get_proof_stat().cells <= proof_stat.cells); - //CHECK(new_proof_stat.get_proof_stat().cells + new_proof_stat.get_proof_stat().external_refs >= proof_stat.cells); - - vm::NewCellStorageStat new_all_stat; - new_all_stat.add_cell_and_proof(B, usage_tree.get()); - CHECK(new_proof_stat.get_proof_stat() == new_all_stat.get_proof_stat()); - CHECK(new_stat.get_stat() == new_all_stat.get_stat()); - - stat.add_used_storage(A); - auto AB_stat = new_stat.get_stat() + const_cast(new_stat).tentative_add_cell(A); - new_stat.add_cell(A); - CHECK(AB_stat == new_stat.get_stat()); - ASSERT_EQ(stat.cells, new_stat.get_stat().cells); - ASSERT_EQ(stat.bits, new_stat.get_stat().bits); - - CHECK(usage_tree.unique()); - usage_tree.reset(); - td::Ref C, BC, C_proof; - std::shared_ptr usage_tree_B; - std::tie(C, BC, usage_tree_B) = gen_merkle_update(B, rnd, with_prunned_branches); - C_proof = vm::CellSlice(vm::NoVm(), BC).prefetch_ref(1); - - auto BC_proof_stat = new_proof_stat.get_proof_stat() + new_proof_stat.tentative_add_proof(C, usage_tree_B.get()); - new_proof_stat.add_proof(C, usage_tree_B.get()); - CHECK(BC_proof_stat == new_proof_stat.get_proof_stat()); - } -} - -struct String { - String() { - total_strings.add(1); - } - String(std::string str) : str(std::move(str)) { - total_strings.add(1); - } - ~String() { - total_strings.add(-1); - } - static td::ThreadSafeCounter total_strings; - std::string str; -}; - -td::ThreadSafeCounter String::total_strings; -TEST(Ref, AtomicRef) { - struct Node { - td::AtomicRefLockfree> name_; - char pad[64]; - }; - - int threads_n = 10; - std::vector nodes(threads_n); - std::vector threads(threads_n); - int thread_id = 0; - for (auto &thread : threads) { - thread = td::thread([&] { - for (int i = 0; i < 1000000; i++) { - auto &node = nodes[td::Random::fast(0, threads_n / 3 - 1)]; - auto name = node.name_.load(); - if (name.not_null()) { - CHECK(name->str == "one" || name->str == "twotwo"); - } - if (td::Random::fast(0, 5) == 0) { - auto new_string = td::Ref>{true, td::Random::fast(0, 1) == 0 ? "one" : "twotwo"}; - node.name_.store(std::move(new_string)); - } - } - }); - thread_id++; - } - for (auto &thread : threads) { - thread.join(); - } - nodes.clear(); - LOG(ERROR) << String::total_strings.sum(); -} - -class FileMerkleTree { - public: - FileMerkleTree(size_t chunks_count, td::Ref root = {}) { - log_n_ = 0; - while ((size_t(1) << log_n_) < chunks_count) { - log_n_++; - } - n_ = size_t(1) << log_n_; - mark_.resize(n_ * 2); - proof_.resize(n_ * 2); - - CHECK(n_ == chunks_count); // TODO: support other chunks_count - //auto x = vm::CellBuilder().finalize(); - root_ = std::move(root); - } - - struct Chunk { - td::size_t index{0}; - td::Slice hash; - }; - - void remove_chunk(td::size_t index) { - CHECK(index < n_); - index += n_; - while (proof_[index].not_null()) { - proof_[index] = {}; - index /= 2; - } - } - - bool has_chunk(td::size_t index) const { - CHECK(index < n_); - index += n_; - return proof_[index].not_null(); - } - - void add_chunk(td::size_t index, td::Slice hash) { - CHECK(hash.size() == 32); - CHECK(index < n_); - index += n_; - auto cell = vm::CellBuilder().store_bytes(hash).finalize(); - CHECK(proof_[index].is_null()); - proof_[index] = std::move(cell); - for (index /= 2; index != 0; index /= 2) { - CHECK(proof_[index].is_null()); - auto &left = proof_[index * 2]; - auto &right = proof_[index * 2 + 1]; - if (left.not_null() && right.not_null()) { - proof_[index] = vm::CellBuilder().store_ref(left).store_ref(right).finalize(); - } else { - mark_[index] = mark_id_; - } - } - } - - td::Status validate_proof(td::Ref new_root) { - // TODO: check structure - return td::Status::OK(); - } - - td::Status add_proof(td::Ref new_root) { - TRY_STATUS(validate_proof(new_root)); - auto combined = vm::MerkleProof::combine_fast_raw(root_, new_root); - if (combined.is_null()) { - return td::Status::Error("Can't combine proofs"); - } - root_ = std::move(combined); - return td::Status::OK(); - } - - td::Status try_add_chunks(td::Span chunks) { - for (auto chunk : chunks) { - if (has_chunk(chunk.index)) { - return td::Status::Error("Already has chunk"); - } - } - mark_id_++; - for (auto chunk : chunks) { - add_chunk(chunk.index, chunk.hash); - } - auto r_new_root = merge(root_, 1); - if (r_new_root.is_error()) { - for (auto chunk : chunks) { - remove_chunk(chunk.index); - } - return r_new_root.move_as_error(); - } - root_ = r_new_root.move_as_ok(); - return td::Status::OK(); - } - - td::Result> merge(td::Ref root, size_t index) { - const auto &down = proof_[index]; - if (down.not_null()) { - if (down->get_hash() != root->get_hash(0)) { - return td::Status::Error("Hash mismatch"); - } - return down; - } - - if (mark_[index] != mark_id_) { - return root; - } - - vm::CellSlice cs(vm::NoVm(), root); - if (cs.is_special()) { - return td::Status::Error("Proof is not enough to validate chunks"); - } - - CHECK(cs.size_refs() == 2); - vm::CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - TRY_RESULT(left, merge(cs.fetch_ref(), index * 2)); - TRY_RESULT(right, merge(cs.fetch_ref(), index * 2 + 1)); - cb.store_ref(std::move(left)).store_ref(std::move(right)); - return cb.finalize(); - } - - void init_proof() { - CHECK(proof_[1].not_null()); - root_ = proof_[1]; - } - - td::Result> gen_proof(size_t l, size_t r) { - auto usage_tree = std::make_shared(); - auto usage_cell = vm::UsageCell::create(root_, usage_tree->root_ptr()); - TRY_STATUS(do_gen_proof(std::move(usage_cell), 0, n_ - 1, l, r)); - auto res = vm::MerkleProof::generate_raw(root_, usage_tree.get()); - CHECK(res.not_null()); - return res; - } - - private: - td::size_t n_; // n = 2^log_n - td::size_t log_n_; - td::size_t mark_id_{0}; - std::vector mark_; // n_ * 2 - std::vector> proof_; // n_ * 2 - td::Ref root_; - - td::Status do_gen_proof(td::Ref node, size_t il, size_t ir, size_t l, size_t r) { - if (ir < l || il > r) { - return td::Status::OK(); - } - if (l <= il && ir <= r) { - return td::Status::OK(); - } - vm::CellSlice cs(vm::NoVm(), std::move(node)); - if (cs.is_special()) { - return td::Status::Error("Can't generate a proof"); - } - CHECK(cs.size_refs() == 2); - auto ic = (il + ir) / 2; - TRY_STATUS(do_gen_proof(cs.fetch_ref(), il, ic, l, r)); - TRY_STATUS(do_gen_proof(cs.fetch_ref(), ic + 1, ir, l, r)); - return td::Status::OK(); - } -}; - -TEST(FileMerkleTree, Manual) { - // create big random file - size_t chunk_size = 768; - // for simplicity numer of chunks in a file is a power of two - size_t chunks_count = 1 << 16; - size_t file_size = chunk_size * chunks_count; - td::Timer timer; - LOG(INFO) << "Generate random string"; - const auto file = td::rand_string('a', 'z', td::narrow_cast(file_size)); - LOG(INFO) << timer; - - timer = {}; - LOG(INFO) << "Calculate all hashes"; - std::vector hashes(chunks_count); - for (size_t i = 0; i < chunks_count; i++) { - td::sha256(td::Slice(file).substr(i * chunk_size, chunk_size), hashes[i].as_slice()); - } - LOG(INFO) << timer; - - timer = {}; - LOG(INFO) << "Init merkle tree"; - FileMerkleTree tree(chunks_count); - for (size_t i = 0; i < chunks_count; i++) { - tree.add_chunk(i, hashes[i].as_slice()); - } - tree.init_proof(); - LOG(INFO) << timer; - - auto root_proof = tree.gen_proof(0, chunks_count - 1).move_as_ok(); - - // first download each chunk one by one - - for (size_t stride : {1 << 6, 1}) { - timer = {}; - LOG(INFO) << "Gen all proofs, stride = " << stride; - for (size_t i = 0; i < chunks_count; i += stride) { - tree.gen_proof(i, i + stride - 1).move_as_ok(); - } - LOG(INFO) << timer; - timer = {}; - LOG(INFO) << "Proof size: " << vm::std_boc_serialize(tree.gen_proof(0, stride - 1).move_as_ok()).ok().size(); - LOG(INFO) << "Download file, stride = " << stride; - { - FileMerkleTree new_tree(chunks_count, root_proof); - for (size_t i = 0; i < chunks_count; i += stride) { - new_tree.add_proof(tree.gen_proof(i, i + stride - 1).move_as_ok()).ensure(); - std::vector chunks; - for (size_t j = 0; j < stride; j++) { - chunks.push_back({i + j, hashes[i + j].as_slice()}); - } - new_tree.try_add_chunks(chunks).ensure(); - } - } - LOG(INFO) << timer; - } -} - -//TEST(Tmp, Boc) { -//LOG(ERROR) << "A"; -//auto data = td::read_file("boc"); -//LOG(ERROR) << "B"; -//auto cell = vm::deserialize_boc(data.move_as_ok().as_slice()); -//vm::CellStorageStat stat; -//stat.add_used_storage(cell, false); -//LOG(ERROR) << stat.cells; -////LOG(ERROR) << "C"; -////auto new_data = vm::serialize_boc(cell); -////LOG(ERROR) << "D"; -//vm::test_boc_deserializer({cell}, 31); -//} diff --git a/submodules/ton/tonlib-src/crypto/test/test-ed25519-crypto.cpp b/submodules/ton/tonlib-src/crypto/test/test-ed25519-crypto.cpp deleted file mode 100644 index 3e3dab89..00000000 --- a/submodules/ton/tonlib-src/crypto/test/test-ed25519-crypto.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include - -#include "crypto/ellcurve/Ed25519.h" - -static void my_assert_impl(bool cond, const char* str, const char* file, int line) { - if (!cond) { - std::cerr << "Failed " << str << " in " << file << " at " << line << ".\n"; - } -} -#define my_assert(x) my_assert_impl(x, #x, __FILE__, __LINE__) - -void print_buffer(const unsigned char buffer[32]) { - for (int i = 0; i < 32; i++) { - char buff[4]; - sprintf(buff, "%02x", buffer[i]); - std::cout << buff; - } -} - -std::string buffer_to_hex(const unsigned char* buffer, std::size_t size = 32) { - const char* hex = "0123456789ABCDEF"; - std::string res(2 * size, '\0'); - for (std::size_t i = 0; i < size; i++) { - auto c = buffer[i]; - res[2 * i] = hex[c & 15]; - res[2 * i + 1] = hex[c >> 4]; - } - return res; -} - -// export of (17/12)G on twisted Edwards curve -unsigned char test_vector1[32] = {0xfc, 0xb7, 0x42, 0x1e, 0x26, 0xad, 0x1b, 0x17, 0xf6, 0xb1, 0x52, - 0x0c, 0xdb, 0x8a, 0x64, 0x7d, 0x28, 0xa7, 0x56, 0x69, 0xd4, 0xb6, - 0x0c, 0xec, 0x63, 0x72, 0x5e, 0xe6, 0x32, 0x4d, 0xf7, 0xe6}; - -unsigned char rfc7748_output[32] = { - 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, - 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, -}; - -bool test_ed25519_impl(void) { - std::cout << "************** Testing Curve25519 / Ed25519 operations ************\n"; - auto& E = ellcurve::Curve25519(); - auto& Edw = ellcurve::Ed25519(); - arith::Bignum L = E.get_ell(); - my_assert(arith::is_prime(L)); - my_assert(L == Edw.get_ell()); - arith::ResidueRing Fl(L); - arith::Bignum s = Fl.frac(17, 12).extract(); - arith::Bignum t = Fl.frac(12, 17).extract(); - std::cout << "l = " << L << std::endl; - std::cout << "s = 17/12 mod l = " << s << std::endl; - std::cout << "t = 12/17 mod l = " << t << std::endl; - auto sG = E.power_gen_xz(s); - auto u_sG = sG.get_u(); - std::cout << "Curve25519 u(sG) = " << sG.get_u().extract() << std::endl; - std::cout << "Curve25519 y(sG) = " << sG.get_y().extract() << std::endl; - auto sG1 = Edw.power_gen(s); - std::cout << "Ed25519 u(sG) = " << sG1.get_u().extract() << std::endl; - std::cout << "Ed25519 y(sG) = " << sG1.get_y().extract() << std::endl; - std::cout << "Ed25519 x(sG) = " << sG1.get_x().extract() << std::endl; - my_assert(sG1.get_x().extract() != sG1.get_y().extract()); - my_assert(sG.get_u() == sG1.get_u()); - my_assert(sG.get_y() == sG1.get_y()); - - my_assert( - sG1.get_x().extract() == - arith::Bignum(arith::dec_string{"9227429025021714590777223519505276506601225973596506606120015751301699519597"})); - my_assert(sG1.get_y().extract() == - arith::Bignum( - arith::dec_string{"46572854587220149033453000581008590225032365765275643343836649812808016508924"})); - - auto sG2 = Edw.power_gen(s, true); - my_assert(sG1.get_u() == sG2.get_u()); - my_assert(sG1.get_y() == sG2.get_y()); - unsigned char buff[32]; - std::memset(buff, 0, 32); - my_assert(sG1.export_point(buff)); - std::cout << "sG export = " << buffer_to_hex(buff) << std::endl; - bool ok; - auto sG3 = Edw.import_point(buff, ok); - my_assert(ok); - my_assert(!std::memcmp(buff, test_vector1, 32)); - my_assert(sG3.get_u() == sG1.get_u()); - my_assert(sG2.get_x() == sG2.get_x()); - my_assert(sG2.get_y() == sG2.get_y()); - - auto stG = E.power_xz(u_sG, t); - std::cout << "Curve25519 u(stG) = " << stG.get_u().extract() << std::endl; - my_assert(stG.get_u().extract() == 9); - auto stG1 = Edw.power_point(sG1, t); - std::cout << "Ed25519 u(stG) = " << stG1.get_u().extract() << std::endl; - my_assert(stG1.get_u().extract() == 9); - stG1.normalize(); - my_assert(stG1.XY == Edw.get_base_point().XY); - my_assert(stG1.X == Edw.get_base_point().X); - my_assert(stG1.Y == Edw.get_base_point().Y); - my_assert(stG1.Z == Edw.get_base_point().Z); - auto stG2 = Edw.power_point(sG2, t, true); - my_assert(stG2.get_u().extract() == 9); - stG2.normalize(); - my_assert(stG2.XY == stG1.XY && stG2.X == stG1.X && stG2.Y == stG1.Y); - auto stG3 = Edw.power_point(sG3, t).normalize(); - auto stG4 = Edw.power_point(sG3, t, true).normalize(); - my_assert(stG3.XY == stG1.XY && stG3.X == stG1.X && stG3.Y == stG1.Y); - my_assert(stG4.XY == stG1.XY && stG4.X == stG1.X && stG4.Y == stG1.Y); - - // RFC7748 test vector - auto u = - arith::Bignum(arith::dec_string{"8883857351183929894090759386610649319417338800022198945255395922347792736741"}); - //u[255] = 0; - auto n = - arith::Bignum(arith::dec_string{"35156891815674817266734212754503633747128614016119564763269015315466259359304"}); - //n[255] = 0; n[254] = 1; - //n[0] = n[1] = n[2] = 0; - auto umodp = arith::Residue(u, E.get_base_ring()); - auto nP = E.power_xz(umodp, n); - std::cout << "u(P) = " << u.to_hex() << std::endl; - std::cout << "n = " << n.to_hex() << std::endl; - std::cout << "u(nP) = " << nP.get_u().extract().to_hex() << std::endl; - unsigned char buffer[32]; - std::memset(buffer, 0, 32); - nP.export_point_u(buffer); - std::cout << "u(nP) export = " << buffer_to_hex(buffer) << std::endl; - my_assert(!std::memcmp(buffer, rfc7748_output, 32)); - - std::cout << "********* ok\n\n"; - return true; -} - -unsigned char fixed_privkey[32] = "abacabadabacabaeabacabadabacaba"; -unsigned char fixed_pubkey[32] = {0x6f, 0x9e, 0x5b, 0xde, 0xce, 0x87, 0x21, 0xeb, 0x57, 0x37, 0xfb, - 0xb5, 0x92, 0x28, 0xba, 0x07, 0xf7, 0x88, 0x0f, 0x73, 0xce, 0x5b, - 0xfa, 0xa1, 0xb7, 0x15, 0x73, 0x03, 0xd4, 0x20, 0x1e, 0x74}; - -unsigned char rfc8032_secret_key1[32] = {0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a, - 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32, - 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60}; - -unsigned char rfc8032_public_key1[32] = {0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe, - 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, - 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a}; - -unsigned char rfc8032_signature1[64] = { - 0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a, - 0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55, - 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, - 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b, -}; - -unsigned char rfc8032_secret_key2[32] = { - 0xc5, 0xaa, 0x8d, 0xf4, 0x3f, 0x9f, 0x83, 0x7b, 0xed, 0xb7, 0x44, 0x2f, 0x31, 0xdc, 0xb7, 0xb1, - 0x66, 0xd3, 0x85, 0x35, 0x07, 0x6f, 0x09, 0x4b, 0x85, 0xce, 0x3a, 0x2e, 0x0b, 0x44, 0x58, 0xf7, -}; - -unsigned char rfc8032_public_key2[32] = { - 0xfc, 0x51, 0xcd, 0x8e, 0x62, 0x18, 0xa1, 0xa3, 0x8d, 0xa4, 0x7e, 0xd0, 0x02, 0x30, 0xf0, 0x58, - 0x08, 0x16, 0xed, 0x13, 0xba, 0x33, 0x03, 0xac, 0x5d, 0xeb, 0x91, 0x15, 0x48, 0x90, 0x80, 0x25, -}; - -unsigned char rfc8032_message2[2] = {0xaf, 0x82}; - -unsigned char rfc8032_signature2[64] = { - 0x62, 0x91, 0xd6, 0x57, 0xde, 0xec, 0x24, 0x02, 0x48, 0x27, 0xe6, 0x9c, 0x3a, 0xbe, 0x01, 0xa3, - 0x0c, 0xe5, 0x48, 0xa2, 0x84, 0x74, 0x3a, 0x44, 0x5e, 0x36, 0x80, 0xd7, 0xdb, 0x5a, 0xc3, 0xac, - 0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59, - 0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, 0xc0, 0x27, 0xbe, 0xce, 0xea, 0x1e, 0xc4, 0x0a, -}; - -bool test_ed25519_crypto() { - std::cout << "************** Testing Curve25519 / Ed25519 cryptographic primitives ************\n"; - crypto::Ed25519::PrivateKey PK1, PK2, PK3, PK4, PK5; - PK1.random_private_key(); - PK2.import_private_key(fixed_privkey); - unsigned char priv2_export[32]; - bool ok = PK1.export_private_key(priv2_export); - std::cout << "PK1 = " << ok << " " << buffer_to_hex(priv2_export) << std::endl; - my_assert(ok); - ok = PK2.export_private_key(priv2_export); - std::cout << "PK2 = " << ok << " " << buffer_to_hex(priv2_export) << std::endl; - my_assert(ok); - PK3.import_private_key(priv2_export); - std::cout << "PK3 = " << PK3.ok() << std::endl; - my_assert(PK3.ok()); - - unsigned char pub_export[32]; - ok = PK1.export_public_key(pub_export); - std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - my_assert(ok); - crypto::Ed25519::PublicKey PubK1(pub_export); - ok = PK2.export_public_key(pub_export); - std::cout << "PubK2 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - my_assert(ok); - my_assert(!std::memcmp(pub_export, fixed_pubkey, 32)); - crypto::Ed25519::PublicKey PubK2(pub_export); - ok = PK3.export_public_key(pub_export); - std::cout << "PubK3 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - my_assert(ok); - my_assert(!std::memcmp(pub_export, fixed_pubkey, 32)); - crypto::Ed25519::PublicKey PubK3(pub_export); - ok = PubK1.export_public_key(pub_export); - std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - my_assert(ok); - - unsigned char secret22[32]; - ok = PK2.compute_shared_secret(secret22, PubK3); - std::cout << "secret(PK2,PubK2)=" << ok << " " << buffer_to_hex(secret22) << std::endl; - my_assert(ok); - - unsigned char secret12[32], secret21[32]; - ok = PK1.compute_shared_secret(secret12, PubK3); - std::cout << "secret(PK1,PubK2)=" << ok << " " << buffer_to_hex(secret12) << std::endl; - my_assert(ok); - ok = PK2.compute_shared_secret(secret21, PubK1); - std::cout << "secret(PK2,PubK1)=" << ok << " " << buffer_to_hex(secret21) << std::endl; - my_assert(ok); - my_assert(!std::memcmp(secret12, secret21, 32)); - - // for (int i = 0; i < 1000; i++) { - // ok = PK1.compute_shared_secret(secret12, PubK3); - // my_assert(ok); - // ok = PK2.compute_shared_secret(secret21, PubK1); - // my_assert(ok); - // } - - unsigned char signature[64]; - ok = PK1.sign_message(signature, (const unsigned char*)"abc", 3); - std::cout << "PK1.signature=" << ok << " " << buffer_to_hex(signature, 64) << std::endl; - my_assert(ok); - - // signature[63] ^= 1; - ok = PubK1.check_message_signature(signature, (const unsigned char*)"abc", 3); - std::cout << "PubK1.check_signature=" << ok << std::endl; - my_assert(ok); - - PK4.import_private_key(rfc8032_secret_key1); - PK4.export_public_key(pub_export); - std::cout << "PK4.private_key = " << buffer_to_hex(rfc8032_secret_key1) << std::endl; - std::cout << "PK4.public_key = " << buffer_to_hex(pub_export) << std::endl; - my_assert(!std::memcmp(pub_export, rfc8032_public_key1, 32)); - ok = PK4.sign_message(signature, (const unsigned char*)"", 0); - std::cout << "PK4.signature('') = " << buffer_to_hex(signature, 64) << std::endl; - my_assert(ok); - my_assert(!std::memcmp(signature, rfc8032_signature1, 32)); - - PK5.import_private_key(rfc8032_secret_key2); - PK5.export_public_key(pub_export); - std::cout << "PK5.private_key = " << buffer_to_hex(rfc8032_secret_key2) << std::endl; - std::cout << "PK5.public_key = " << buffer_to_hex(pub_export) << std::endl; - my_assert(!std::memcmp(pub_export, rfc8032_public_key2, 32)); - ok = PK5.sign_message(signature, rfc8032_message2, 2); - std::cout << "PK5.signature('') = " << buffer_to_hex(signature, 64) << std::endl; - my_assert(ok); - my_assert(!std::memcmp(signature, rfc8032_signature2, 32)); - crypto::Ed25519::PublicKey PubK5(pub_export); - - // for (int i = 0; i < 10000; i++) { - // ok = PK5.sign_message (signature, rfc8032_message2, 2); - // my_assert (ok); - // } - // for (int i = 0; i < 10000; i++) { - // ok = PubK5.check_message_signature (signature, rfc8032_message2, 2); - // my_assert (ok); - // } - - unsigned char temp_pubkey[32]; - crypto::Ed25519::TempKeyGenerator TKG; // use one generator a lot of times - - TKG.create_temp_shared_secret(temp_pubkey, secret12, PubK1, (const unsigned char*)"abc", 3); - std::cout << "secret12=" << buffer_to_hex(secret12) << "; temp_pubkey=" << buffer_to_hex(temp_pubkey) << std::endl; - - PK1.compute_temp_shared_secret(secret21, temp_pubkey); - std::cout << "secret21=" << buffer_to_hex(secret21) << std::endl; - my_assert(!std::memcmp(secret12, secret21, 32)); - - std::cout << "********* ok\n\n"; - return true; -} - -int main(void) { - test_ed25519_impl(); - test_ed25519_crypto(); - return 0; -} diff --git a/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp b/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp deleted file mode 100644 index fb82493e..00000000 --- a/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp +++ /dev/null @@ -1,1779 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/dict.h" -#include "common/bigint.hpp" - -#include "Ed25519.h" - -#include "block/block-auto.h" -#include "block/block.h" -#include "block/block-parse.h" - -#include "fift/Fift.h" -#include "fift/words.h" -#include "fift/utils.h" - -#include "smc-envelope/GenericAccount.h" -#include "smc-envelope/ManualDns.h" -#include "smc-envelope/MultisigWallet.h" -#include "smc-envelope/SmartContract.h" -#include "smc-envelope/SmartContractCode.h" -#include "smc-envelope/TestGiver.h" -#include "smc-envelope/TestWallet.h" -#include "smc-envelope/Wallet.h" -#include "smc-envelope/WalletV3.h" -#include "smc-envelope/HighloadWallet.h" -#include "smc-envelope/HighloadWalletV2.h" -#include "smc-envelope/PaymentChannel.h" - -#include "td/utils/base64.h" -#include "td/utils/crypto.h" -#include "td/utils/Random.h" -#include "td/utils/tests.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/StringBuilder.h" -#include "td/utils/Timer.h" -#include "td/utils/PathView.h" -#include "td/utils/filesystem.h" -#include "td/utils/port/path.h" -#include "td/utils/Variant.h" - -#include -#include -#include - -std::string current_dir() { - return td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str(); -} - -std::string load_source(std::string name) { - return td::read_file_str(current_dir() + "../../crypto/" + name).move_as_ok(); -} - -td::Ref get_test_wallet_source() { - std::string code = R"ABCD( -SETCP0 DUP IFNOTRET // return if recv_internal -DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk -}> -INC 32 THROWIF // fail unless recv_external -512 INT LDSLICEX DUP 32 PLDU // sign cs cnt -c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk -s1 s2 XCPU // sign cs cnt pubk cnt' cnt -EQUAL 33 THROWIFNOT // ( seqno mismatch? ) -s2 PUSH HASHSU // sign cs cnt pubk hash -s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk -CHKSIGNU // pubk cs cnt ? -34 THROWIFNOT // signature mismatch -ACCEPT -SWAP 32 LDU NIP -DUP SREFS IF:<{ - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF // pubk cnt mode msg cs - s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent ) -}> -ENDS -INC NEWC 32 STU 256 STU ENDC c4 POPCTR -)ABCD"; - return fift::compile_asm(code).move_as_ok(); -} - -td::Ref get_wallet_source() { - std::string code = R"ABCD( -SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk - }> - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs - c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key - s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno - EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno - s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash - s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key - ACCEPT - s0 s2 XCHG // public_key stored_seqno cs - WHILE:<{ - DUP SREFS // public_key stored_seqno cs _40 - }>DO<{ // public_key stored_seqno cs - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode - SENDRAWMSG // public_key stored_seqno cs - }> - ENDS INC // public_key seqno' - NEWC 32 STU 256 STU ENDC c4 POP -)ABCD"; - return fift::compile_asm(code).move_as_ok(); -} -td::Ref get_wallet_v3_source() { - std::string code = R"ABCD( -SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods - 1 INT AND c4 PUSHCTR CTOS 32 LDU 32 LDU NIP 256 PLDU CONDSEL // cnt or pubk - }> - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs - NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno - c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key - s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet - s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno - s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash - s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key - CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs - ACCEPT - WHILE:<{ - DUP SREFS // public_key stored_seqno stored_subwallet cs _51 - }>DO<{ // public_key stored_seqno stored_subwallet cs - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode - SENDRAWMSG - }> // public_key stored_seqno stored_subwallet cs - ENDS SWAP INC // public_key stored_subwallet seqno' - NEWC 32 STU 32 STU 256 STU ENDC c4 POP -)ABCD"; - return fift::compile_asm(code).move_as_ok(); -} - -TEST(Tonlib, TestWallet) { - LOG(ERROR) << td::base64_encode(std_boc_serialize(get_test_wallet_source()).move_as_ok()); - CHECK(get_test_wallet_source()->get_hash() == ton::TestWallet::get_init_code()->get_hash()); - auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet.fif"), {"aba", "0"}).move_as_ok(); - - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = ton::TestWallet::get_init_state(pub_key); - auto init_message = ton::TestWallet::get_init_message_new(priv_key); - auto address = ton::GenericAccount::get_address(0, init_state); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "-------"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet.fif")).ensure(); - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - fift_output = fift::mem_run_fift(std::move(fift_output.source_lookup), - {"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", - "321", "-C", "TEST"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - ton::TestWallet::Gift gift; - gift.destination = dest; - gift.message = "TEST"; - gift.gramms = 321000000000ll; - ton::TestWallet wallet(priv_key.get_public_key().move_as_ok(), 123); - ASSERT_EQ(123u, wallet.get_seqno().ok()); - CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet.get_public_key().ok().as_octet_string()); - auto gift_message = ton::GenericAccount::create_ext_message( - address, {}, wallet.make_a_gift_message(priv_key, 0, {gift}).move_as_ok()); - LOG(ERROR) << "-------"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -td::Ref get_wallet_source_fc() { - return fift::compile_asm(load_source("smartcont/wallet-code.fif"), "", false).move_as_ok(); -} - -TEST(Tonlib, Wallet) { - LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_source()).move_as_ok()); - CHECK(get_wallet_source()->get_hash() == ton::Wallet::get_init_code()->get_hash()); - - auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v2.fif"), {"aba", "0"}).move_as_ok(); - - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = ton::Wallet::get_init_state(pub_key); - auto init_message = ton::Wallet::get_init_message_new(priv_key); - auto address = ton::GenericAccount::get_address(0, init_state); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "-------"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v2.fif")).ensure(); - class ZeroOsTime : public fift::OsTime { - public: - td::uint32 now() override { - return 0; - } - }; - fift_output.source_lookup.set_os_time(std::make_unique()); - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - fift_output = fift::mem_run_fift(std::move(fift_output.source_lookup), - {"aba", "new-wallet", "-C", "TESTv2", - "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", "321"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - ton::TestWallet::Gift gift; - gift.destination = dest; - gift.message = "TESTv2"; - gift.gramms = 321000000000ll; - ton::Wallet wallet(priv_key.get_public_key().move_as_ok(), 123); - ASSERT_EQ(123u, wallet.get_seqno().ok()); - CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet.get_public_key().ok().as_octet_string()); - auto gift_message = ton::GenericAccount::create_ext_message( - address, {}, wallet.make_a_gift_message(priv_key, 60, {gift}).move_as_ok()); - LOG(ERROR) << "-------"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -TEST(Tonlib, WalletV3) { - LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_v3_source()).move_as_ok()); - CHECK(get_wallet_v3_source()->get_hash() == ton::WalletV3::get_init_code()->get_hash()); - - auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v3.fif"), {"aba", "0", "239"}).move_as_ok(); - - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = ton::WalletV3::get_init_state(pub_key, 239); - auto init_message = - ton::WalletV3(priv_key.get_public_key().move_as_ok(), 239).get_init_message(priv_key).move_as_ok(); - auto address = ton::GenericAccount::get_address(0, init_state); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "-------"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v3.fif")).ensure(); - class ZeroOsTime : public fift::OsTime { - public: - td::uint32 now() override { - return 0; - } - }; - fift_output.source_lookup.set_os_time(std::make_unique()); - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - fift_output = fift::mem_run_fift(std::move(fift_output.source_lookup), - {"aba", "new-wallet", "-C", "TESTv3", - "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "239", "123", "321"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - - ton::WalletV3::Gift gift; - gift.destination = dest; - gift.message = "TESTv3"; - gift.gramms = 321000000000ll; - - ton::WalletV3 wallet(priv_key.get_public_key().move_as_ok(), 239, 123); - ASSERT_EQ(239u, wallet.get_wallet_id().ok()); - ASSERT_EQ(123u, wallet.get_seqno().ok()); - CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet.get_public_key().ok().as_octet_string()); - CHECK(priv_key.get_public_key().ok().as_octet_string() == - ton::GenericAccount::get_public_key(wallet).ok().as_octet_string()); - - auto gift_message = ton::GenericAccount::create_ext_message( - address, {}, wallet.make_a_gift_message(priv_key, 60, {gift}).move_as_ok()); - LOG(ERROR) << "-------"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -TEST(Tonlib, HighloadWallet) { - auto source_lookup = fift::create_mem_source_lookup(load_source("smartcont/new-highload-wallet.fif")).move_as_ok(); - source_lookup.write_file("/auto/highload-wallet-code.fif", load_source("smartcont/auto/highload-wallet-code.fif")) - .ensure(); - auto fift_output = fift::mem_run_fift(std::move(source_lookup), {"aba", "0", "239"}).move_as_ok(); - - LOG(ERROR) << fift_output.output; - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet239-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet239.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = ton::HighloadWallet::get_init_state(pub_key, 239, -1); - auto init_message = ton::HighloadWallet::get_init_message(priv_key, 239); - auto address = ton::GenericAccount::get_address(0, init_state); - - ton::HighloadWallet wallet( - {ton::HighloadWallet::get_init_code(-1), ton::HighloadWallet::get_init_data(pub_key, 239)}); - ASSERT_EQ(239u, wallet.get_wallet_id().ok()); - ASSERT_EQ(0u, wallet.get_seqno().ok()); - CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string()); - CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string()); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "---smc-envelope----"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "---fift scripts----"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/highload-wallet.fif")).ensure(); - std::string order; - std::vector gifts; - auto add_order = [&](td::Slice dest_str, td::int64 gramms) { - auto g = td::to_string(gramms); - if (g.size() < 10) { - g = std::string(10 - g.size(), '0') + g; - } - order += PSTRING() << "SEND " << dest_str << " " << g.substr(0, g.size() - 9) << "." << g.substr(g.size() - 9) - << "\n"; - - ton::HighloadWallet::Gift gift; - gift.destination = block::StdAddress::parse(dest_str).move_as_ok(); - gift.gramms = gramms; - gifts.push_back(gift); - }; - std::string dest_str = "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX"; - add_order(dest_str, 0); - add_order(dest_str, 321000000000ll); - add_order(dest_str, 321ll); - fift_output.source_lookup.write_file("/order", order).ensure(); - class ZeroOsTime : public fift::OsTime { - public: - td::uint32 now() override { - return 0; - } - }; - fift_output.source_lookup.set_os_time(std::make_unique()); - fift_output = fift::mem_run_fift(std::move(fift_output.source_lookup), {"aba", "new-wallet", "239", "123", "order"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - auto gift_message = ton::GenericAccount::create_ext_message( - address, {}, ton::HighloadWallet::make_a_gift_message(priv_key, 239, 123, 60, gifts)); - LOG(ERROR) << "---smc-envelope----"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "---fift scripts----"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -TEST(Tonlib, HighloadWalletV2) { - auto source_lookup = fift::create_mem_source_lookup(load_source("smartcont/new-highload-wallet-v2.fif")).move_as_ok(); - source_lookup - .write_file("/auto/highload-wallet-v2-code.fif", load_source("smartcont/auto/highload-wallet-v2-code.fif")) - .ensure(); - class ZeroOsTime : public fift::OsTime { - public: - td::uint32 now() override { - return 0; - } - }; - source_lookup.set_os_time(std::make_unique()); - auto fift_output = fift::mem_run_fift(std::move(source_lookup), {"aba", "0", "239"}).move_as_ok(); - - LOG(ERROR) << fift_output.output; - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet239-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet239.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = ton::HighloadWalletV2::get_init_state(pub_key, 239, -1); - auto init_message = ton::HighloadWalletV2::get_init_message(priv_key, 239, 65535); - auto address = ton::GenericAccount::get_address(0, init_state); - - ton::HighloadWalletV2 wallet( - {ton::HighloadWalletV2::get_init_code(-1), ton::HighloadWalletV2::get_init_data(pub_key, 239)}); - ASSERT_EQ(239u, wallet.get_wallet_id().ok()); - CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string()); - CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string()); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "---smc-envelope----"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "---fift scripts----"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/highload-wallet-v2.fif")).ensure(); - std::string order; - std::vector gifts; - auto add_order = [&](td::Slice dest_str, td::int64 gramms) { - auto g = td::to_string(gramms); - if (g.size() < 10) { - g = std::string(10 - g.size(), '0') + g; - } - order += PSTRING() << "SEND " << dest_str << " " << g.substr(0, g.size() - 9) << "." << g.substr(g.size() - 9) - << "\n"; - - ton::HighloadWalletV2::Gift gift; - gift.destination = block::StdAddress::parse(dest_str).move_as_ok(); - gift.gramms = gramms; - gifts.push_back(gift); - }; - std::string dest_str = "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX"; - add_order(dest_str, 0); - add_order(dest_str, 321000000000ll); - add_order(dest_str, 321ll); - fift_output.source_lookup.write_file("/order", order).ensure(); - fift_output.source_lookup.set_os_time(std::make_unique()); - fift_output = - fift::mem_run_fift(std::move(fift_output.source_lookup), {"aba", "new-wallet", "239", "order"}).move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - auto gift_message = ton::GenericAccount::create_ext_message( - address, {}, ton::HighloadWalletV2::make_a_gift_message(priv_key, 239, 60, gifts)); - LOG(ERROR) << "---smc-envelope----"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "---fift scripts----"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -TEST(Tonlib, TestGiver) { - auto address = - block::StdAddress::parse("-1:60c04141c6a7b96d68615e7a91d265ad0f3a9a922e9ae9c901d4fa83f5d3c0d0").move_as_ok(); - LOG(ERROR) << address.bounceable; - auto fift_output = fift::mem_run_fift(load_source("smartcont/testgiver.fif"), - {"aba", address.rserialize(), "0", "6.666", "wallet-query"}) - .move_as_ok(); - LOG(ERROR) << fift_output.output; - - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - - ton::TestGiver::Gift gift; - gift.gramms = 1000000000ll * 6666 / 1000; - gift.message = "GIFT"; - gift.destination = address; - td::Ed25519::PrivateKey key{td::SecureString()}; - auto res = ton::GenericAccount::create_ext_message(ton::TestGiver::address(), {}, - ton::TestGiver().make_a_gift_message(key, 0, {gift}).move_as_ok()); - vm::CellSlice(vm::NoVm(), res).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == res->get_hash()); -} - -TEST(Tonlib, RestrictedWallet) { - //auto source_lookup = fift::create_mem_source_lookup(load_source("smartcont/new-restricted-wallet2.fif")).move_as_ok(); - //source_lookup - //.write_file("/auto/restricted-wallet2-code.fif", load_source("smartcont/auto/restricted-wallet2-code.fif")) - //.ensure(); - //class ZeroOsTime : public fift::OsTime { - //public: - //td::uint32 now() override { - //return 0; - //} - //}; - //source_lookup.set_os_time(std::make_unique()); - //auto priv_key = td::Ed25519::generate_private_key().move_as_ok(); - //auto pub_key = priv_key.get_public_key().move_as_ok(); - //auto pub_key_serialized = block::PublicKey::from_bytes(pub_key.as_octet_string()).move_as_ok().serialize(true); - - //std::vector args = {"path", pub_key_serialized, std::string("100")}; - //auto fift_output = fift::mem_run_fift(std::move(source_lookup), args).move_as_ok(); - - //ton::RestrictedWallet::InitData init_data; - //td::uint64 x = 100 * 1000000000ull; - //init_data.key = &pub_key; - //init_data.start_at = 0; - //init_data.limits = {{-32768, x}, {92, x * 3 / 4}, {183, x * 1 / 2}, {366, x * 1 / 4}, {548, 0}}; - //auto wallet = ton::RestrictedWallet::create(init_data, -1); - - //ASSERT_EQ(0u, wallet->get_seqno().move_as_ok()); - //CHECK(pub_key.as_octet_string() == wallet->get_public_key().move_as_ok().as_octet_string()); - ////LOG(ERROR) << wallet->get_balance(x, 60 * 60 * 24 * 400).move_as_ok(); - - //auto new_wallet_query = fift_output.source_lookup.read_file("rwallet-query.boc").move_as_ok().data; - //auto new_wallet_addr = fift_output.source_lookup.read_file("rwallet.addr").move_as_ok().data; - - //auto address = wallet->get_address(-1); - ////CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - //address.bounceable = false; - //auto res = ton::GenericAccount::create_ext_message(address, wallet->get_init_state(), - //wallet->get_init_message(priv_key).move_as_ok()); - //LOG(ERROR) << "-------"; - //vm::load_cell_slice(res).print_rec(std::cerr); - //LOG(ERROR) << "-------"; - //vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - //CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - //auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - //fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v2.fif")).ensure(); - //fift_output.source_lookup.write_file("rwallet.pk", priv_key.as_octet_string().as_slice()).ensure(); - //fift_output = fift::mem_run_fift( - //std::move(fift_output.source_lookup), - //{"aba", "rwallet", "-C", "TESTv2", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "0", "321"}) - //.move_as_ok(); - //auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - //ton::TestWallet::Gift gift; - //gift.destination = dest; - //gift.message = "TESTv2"; - //gift.gramms = 321000000000ll; - ////CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet->get_public_key().ok().as_octet_string()); - //auto gift_message = ton::GenericAccount::create_ext_message( - //address, {}, wallet->make_a_gift_message(priv_key, 60, {gift}).move_as_ok()); - //LOG(ERROR) << "-------"; - //vm::load_cell_slice(gift_message).print_rec(std::cerr); - //LOG(ERROR) << "-------"; - //vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - //CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} -TEST(Tonlib, RestrictedWallet3) { - auto init_priv_key = td::Ed25519::generate_private_key().move_as_ok(); - auto init_pub_key = init_priv_key.get_public_key().move_as_ok(); - auto priv_key = td::Ed25519::generate_private_key().move_as_ok(); - auto pub_key = priv_key.get_public_key().move_as_ok(); - - ton::RestrictedWallet::InitData init_data; - init_data.init_key = init_pub_key.as_octet_string(); - init_data.main_key = pub_key.as_octet_string(); - init_data.wallet_id = 123; - auto wallet = ton::RestrictedWallet::create(init_data, 1); - - auto address = wallet->get_address(); - - td::uint64 x = 100 * 1000000000ull; - ton::RestrictedWallet::Config config; - config.start_at = 1; - config.limits = {{-32768, x}, {92, x * 3 / 4}, {183, x * 1 / 2}, {366, x * 1 / 4}, {548, 0}}; - CHECK(wallet.write().send_external_message(wallet->get_init_message(init_priv_key, 10, config).move_as_ok()).success); - CHECK(wallet->get_seqno().move_as_ok() == 1); - - ton::WalletInterface::Gift gift; - gift.destination = address; - gift.message = "hello"; - CHECK(wallet.write().send_external_message(wallet->make_a_gift_message(priv_key, 10, {gift}).move_as_ok()).success); - CHECK(wallet->get_seqno().move_as_ok() == 2); -} - -class SimpleWallet : public ton::SmartContract { - public: - SimpleWallet(State state) : SmartContract(std::move(state)) { - } - - const State& get_state() const { - return state_; - } - SimpleWallet* make_copy() const override { - return new SimpleWallet{state_}; - } - - static td::Ref create_empty() { - return td::Ref(true, - State{ton::SmartContractCode::get_code(ton::SmartContractCode::WalletV1Ext), {}}); - } - static td::Ref create(td::Ref data) { - return td::Ref( - true, State{ton::SmartContractCode::get_code(ton::SmartContractCode::WalletV1Ext), std::move(data)}); - } - static td::Ref create_fast(td::Ref data) { - return td::Ref( - true, State{ton::SmartContractCode::get_code(ton::SmartContractCode::WalletV1), std::move(data)}); - } - - td::int32 seqno() const { - auto res = run_get_method("seqno"); - return res.stack.write().pop_smallint_range(1000000000); - } - - td::Ref create_init_state(td::Slice public_key) const { - td::RefInt256 pk{true}; - pk.write().import_bytes(public_key.ubegin(), public_key.size(), false); - auto res = run_get_method("create_init_state", {pk}); - return res.stack.write().pop_cell(); - } - - td::Ref prepare_send_message(td::Ref msg, td::int8 mode = 3) const { - auto res = run_get_method("prepare_send_message", {td::make_refint(mode), msg}); - return res.stack.write().pop_cell(); - } - - static td::Ref sign_message(vm::Ref body, const td::Ed25519::PrivateKey& pk) { - auto signature = pk.sign(body->get_hash().as_slice()).move_as_ok(); - return vm::CellBuilder().store_bytes(signature.as_slice()).append_cellslice(vm::load_cell_slice(body)).finalize(); - } -}; - -TEST(Smartcon, Simple) { - auto private_key = td::Ed25519::generate_private_key().move_as_ok(); - auto public_key = private_key.get_public_key().move_as_ok().as_octet_string(); - - auto w_lib = SimpleWallet::create_empty(); - auto init_data = w_lib->create_init_state(public_key); - - auto w = SimpleWallet::create(init_data); - LOG(ERROR) << w->code_size(); - auto fw = SimpleWallet::create_fast(init_data); - LOG(ERROR) << fw->code_size(); - LOG(ERROR) << w->seqno(); - - for (int i = 0; i < 20; i++) { - auto msg = w->sign_message(w->prepare_send_message(vm::CellBuilder().finalize()), private_key); - w.write().send_external_message(msg); - fw.write().send_external_message(msg); - } - ASSERT_EQ(20, w->seqno()); - CHECK(w->get_state().data->get_hash() == fw->get_state().data->get_hash()); -} - -namespace std { // ouch -bool operator<(const ton::MultisigWallet::Mask& a, const ton::MultisigWallet::Mask& b) { - for (size_t i = 0; i < a.size(); i++) { - if (a[i] != b[i]) { - return a[i] < b[i]; - } - } - return false; -} -} // namespace std - -TEST(Smartcon, Multisig) { - auto ms_lib = ton::MultisigWallet::create(); - - int n = 100; - int k = 99; - td::uint32 wallet_id = std::numeric_limits::max() - 3; - std::vector keys; - for (int i = 0; i < n; i++) { - keys.push_back(td::Ed25519::generate_private_key().move_as_ok()); - } - auto init_state = ms_lib->create_init_data( - wallet_id, td::transform(keys, [](auto& key) { return key.get_public_key().ok().as_octet_string(); }), k); - auto ms = ton::MultisigWallet::create(init_state); - - td::uint32 now = 0; - auto args = [&now]() -> ton::SmartContract::Args { return ton::SmartContract::Args().set_now(now); }; - - // first empty query (init) - CHECK(ms.write().send_external_message(vm::CellBuilder().finalize(), args()).code == 0); - // first empty query - CHECK(ms.write().send_external_message(vm::CellBuilder().finalize(), args()).code > 0); - - { - td::uint64 query_id = 123 | ((now + 10 * 60ull) << 32); - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - auto query = qb.create(0, keys[0]); - auto res = ms.write().send_external_message(query, args()); - CHECK(!res.accepted); - CHECK(res.code == 41); - } - { - for (int i = 1; i <= 11; i++) { - td::uint64 query_id = i | ((now + 100 * 60ull) << 32); - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - auto query = qb.create(5, keys[5]); - auto res = ms.write().send_external_message(query, args()); - if (i <= 10) { - CHECK(res.accepted); - } else { - CHECK(!res.accepted); - } - } - - now += 100 * 60 + 100; - { - td::uint64 query_id = 200 | ((now + 100 * 60ull) << 32); - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - auto query = qb.create(6, keys[6]); - auto res = ms.write().send_external_message(query, args()); - CHECK(res.accepted); - } - - { - td::uint64 query_id = 300 | ((now + 100 * 60ull) << 32); - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - auto query = qb.create(5, keys[5]); - auto res = ms.write().send_external_message(query, args()); - CHECK(res.accepted); - } - } - - td::uint64 query_id = 123 | ((now + 100 * 60ull) << 32); - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - for (int i = 0; i < 10; i++) { - auto query = qb.create(i, keys[i]); - auto ans = ms.write().send_external_message(query, args()); - LOG(INFO) << "CODE: " << ans.code; - LOG(INFO) << "GAS: " << ans.gas_used; - } - for (int i = 0; i + 1 < 50; i++) { - qb.sign(i, keys[i]); - } - auto query = qb.create(49, keys[49]); - - CHECK(ms->get_n_k() == std::make_pair(n, k)); - auto ans = ms.write().send_external_message(query, args()); - LOG(INFO) << "CODE: " << ans.code; - LOG(INFO) << "GAS: " << ans.gas_used; - CHECK(ans.success); - ASSERT_EQ(0, ms->processed(query_id)); - CHECK(ms.write().send_external_message(query, args()).code > 0); - ASSERT_EQ(0, ms->processed(query_id)); - - { - ton::MultisigWallet::QueryBuilder qb(wallet_id, query_id, vm::CellBuilder().finalize()); - for (int i = 50; i + 1 < 100; i++) { - qb.sign(i, keys[i]); - } - query = qb.create(99, keys[99]); - } - - ans = ms.write().send_external_message(query, args()); - LOG(INFO) << "CODE: " << ans.code; - LOG(INFO) << "GAS: " << ans.gas_used; - ASSERT_EQ(-1, ms->processed(query_id)); -} - -TEST(Smartcont, MultisigStress) { - int n = 10; - int k = 5; - td::uint32 wallet_id = std::numeric_limits::max() - 3; - - std::vector keys; - for (int i = 0; i < n; i++) { - keys.push_back(td::Ed25519::generate_private_key().move_as_ok()); - } - auto public_keys = td::transform(keys, [](auto& key) { return key.get_public_key().ok().as_octet_string(); }); - auto ms_lib = ton::MultisigWallet::create(); - auto init_state_old = - ms_lib->create_init_data_fast(wallet_id, td::transform(public_keys, [](auto& key) { return key.copy(); }), k); - auto init_state = - ms_lib->create_init_data(wallet_id, td::transform(public_keys, [](auto& key) { return key.copy(); }), k); - CHECK(init_state_old->get_hash() == init_state->get_hash()); - auto ms = ton::MultisigWallet::create(init_state); - CHECK(ms->get_public_keys() == public_keys); - - td::int32 now = 100 * 60; - td::int32 qid = 1; - using Mask = std::bitset<128>; - struct Query { - td::int64 id; - td::Ref message; - Mask signed_mask; - }; - - std::vector queries; - int max_queries = 300; - - td::Random::Xorshift128plus rnd(123); - - auto new_query = [&] { - if (qid > max_queries) { - return; - } - Query query; - query.id = (static_cast(now) << 32) | qid++; - query.message = vm::CellBuilder().store_bytes(td::rand_string('a', 'z', rnd.fast(0, 100))).finalize(); - queries.push_back(std::move(query)); - }; - - auto verify = [&] { - auto messages = ms->get_unsigned_messaged(); - std::set> s; - std::set> t; - - for (auto& m : messages) { - auto x = std::make_tuple(m.query_id, m.signed_by, m.message->get_hash().as_slice().str()); - s.insert(std::move(x)); - } - - for (auto& q : queries) { - if (q.signed_mask.none()) { - continue; - } - t.insert(std::make_tuple(q.id, q.signed_mask, q.message->get_hash().as_slice().str())); - } - ASSERT_EQ(t.size(), s.size()); - CHECK(s == t); - }; - - auto sign_query = [&](Query& query, Mask mask) { - auto qb = ton::MultisigWallet::QueryBuilder(wallet_id, query.id, query.message); - int first_i = -1; - for (int i = 0; i < (int)mask.size(); i++) { - if (mask.test(i)) { - if (first_i == -1) { - first_i = i; - } else { - qb.sign(i, keys[i]); - } - } - } - return qb.create(first_i, keys[first_i]); - }; - - auto send_signature = [&](td::Ref query) { - auto ans = ms.write().send_external_message(query); - LOG(ERROR) << "GAS: " << ans.gas_used; - return ans.code == 0; - }; - - auto is_ready = [&](Query& query) { return ms->processed(query.id) == -1; }; - - auto gen_query = [&](Query& query) { - auto x = rnd.fast(1, n); - Mask mask; - for (int t = 0; t < x; t++) { - mask.set(rnd() % n); - } - - auto signature = sign_query(query, mask); - return std::make_pair(signature, mask); - }; - - auto rand_sign = [&] { - if (queries.empty()) { - return; - } - - size_t query_i = rnd() % queries.size(); - auto& query = queries[query_i]; - - Mask mask; - td::Ref signature; - std::tie(signature, mask) = gen_query(query); - if (false && rnd() % 6 == 0) { - Mask mask2; - td::Ref signature2; - std::tie(signature2, mask2) = gen_query(query); - for (int i = 0; i < (int)keys.size(); i++) { - if (mask[i]) { - signature = ms->merge_queries(std::move(signature), std::move(signature2)); - break; - } - if (mask2[i]) { - signature = ms->merge_queries(std::move(signature2), std::move(signature)); - break; - } - } - //signature = ms->merge_queries(std::move(signature), std::move(signature2)); - mask |= mask2; - } - - int got_cnt; - Mask got_cnt_bits; - std::tie(got_cnt, got_cnt_bits) = ms->check_query_signatures(signature); - CHECK(mask == got_cnt_bits); - - bool expect_ok = true; - { - auto new_mask = mask & ~query.signed_mask; - expect_ok &= new_mask.any(); - for (size_t i = 0; i < mask.size(); i++) { - if (mask[i]) { - expect_ok &= new_mask[i]; - break; - } - } - } - - ASSERT_EQ(expect_ok, send_signature(std::move(signature))); - if (expect_ok) { - query.signed_mask |= mask; - } - auto expect_is_ready = query.signed_mask.count() >= (size_t)k; - auto state = ms->get_query_state(query.id); - ASSERT_EQ(expect_is_ready, (state.state == ton::MultisigWallet::QueryState::Sent)); - CHECK(expect_is_ready || state.mask == query.signed_mask); - ASSERT_EQ(expect_is_ready, is_ready(query)); - if (expect_is_ready) { - queries.erase(queries.begin() + query_i); - } - verify(); - }; - td::RandomSteps steps({{rand_sign, 2}, {new_query, 1}}); - while (!queries.empty() || qid <= max_queries) { - steps.step(rnd); - //LOG(ERROR) << ms->data_size(); - } - LOG(INFO) << "Final code size: " << ms->code_size(); - LOG(INFO) << "Final data size: " << ms->data_size(); -} - -class MapDns { - public: - using ManualDns = ton::ManualDns; - struct Entry { - std::string name; - td::int16 category{0}; - std::string text; - - auto key() const { - return std::tie(name, category); - } - bool operator<(const Entry& other) const { - return key() < other.key(); - } - bool operator==(const ton::DnsInterface::Entry& other) const { - return key() == other.key() && other.data.type == ManualDns::EntryData::Type::Text && - other.data.data.get().text == text; - } - bool operator==(const Entry& other) const { - return key() == other.key() && text == other.text; - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Entry& entry) { - return sb << "[" << entry.name << ":" << entry.category << ":" << entry.text << "]"; - } - }; - struct Action { - std::string name; - td::int16 category{0}; - td::optional text; - - bool does_create_category() const { - CHECK(!name.empty()); - CHECK(category != 0); - return static_cast(text); - } - bool does_change_empty() const { - CHECK(!name.empty()); - CHECK(category != 0); - return static_cast(text) && !text.value().empty(); - } - void make_non_empty() { - CHECK(!name.empty()); - CHECK(category != 0); - if (!text) { - text = ""; - } - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Action& entry) { - return sb << "[" << entry.name << ":" << entry.category << ":" << (entry.text ? entry.text.value() : "") - << "]"; - } - }; - void update(td::Span actions) { - for (auto& action : actions) { - do_update(action); - } - } - using CombinedActions = ton::ManualDns::CombinedActions; - void update_combined(td::Span actions) { - LOG(ERROR) << "BEGIN"; - LOG(ERROR) << td::format::as_array(actions); - auto combined_actions = ton::ManualDns::combine_actions(actions); - for (auto& c : combined_actions) { - LOG(ERROR) << c.name << ":" << c.category; - if (c.actions) { - LOG(ERROR) << td::format::as_array(c.actions.value()); - } - } - LOG(ERROR) << "END"; - for (auto& combined_action : combined_actions) { - do_update(combined_action); - } - } - - std::vector resolve(td::Slice name, td::int16 category) { - std::vector res; - if (name.empty()) { - for (auto& a : entries_) { - for (auto& b : a.second) { - res.push_back({a.first, b.first, b.second}); - } - } - } else { - auto it = entries_.find(name); - while (it == entries_.end()) { - auto sz = name.find('.'); - category = -1; - if (sz != td::Slice::npos) { - name = name.substr(sz + 1); - } else { - break; - } - it = entries_.find(name); - } - if (it != entries_.end()) { - for (auto& b : it->second) { - if (category == 0 || category == b.first) { - res.push_back({name.str(), b.first, b.second}); - } - } - } - } - - std::sort(res.begin(), res.end()); - return res; - } - - private: - std::map, std::less<>> entries_; - void do_update(const Action& action) { - if (action.name.empty()) { - entries_.clear(); - return; - } - if (action.category == 0) { - entries_.erase(action.name); - return; - } - if (action.text) { - if (action.text.value().empty()) { - entries_[action.name].erase(action.category); - } else { - entries_[action.name][action.category] = action.text.value(); - } - } else { - auto it = entries_.find(action.name); - if (it != entries_.end()) { - it->second.erase(action.category); - } - } - } - - void do_update(const CombinedActions& actions) { - if (actions.name.empty()) { - entries_.clear(); - LOG(ERROR) << "CLEAR"; - if (!actions.actions) { - return; - } - for (auto& action : actions.actions.value()) { - CHECK(!action.name.empty()); - CHECK(action.category != 0); - CHECK(action.text); - if (action.text.value().empty()) { - entries_[action.name]; - } else { - entries_[action.name][action.category] = action.text.value(); - } - } - return; - } - if (actions.category == 0) { - entries_.erase(actions.name); - LOG(ERROR) << "CLEAR " << actions.name; - if (!actions.actions) { - return; - } - entries_[actions.name]; - for (auto& action : actions.actions.value()) { - CHECK(action.name == actions.name); - CHECK(action.category != 0); - CHECK(action.text); - if (action.text.value().empty()) { - entries_[action.name]; - } else { - entries_[action.name][action.category] = action.text.value(); - } - } - return; - } - CHECK(actions.actions); - CHECK(actions.actions.value().size() == 1); - for (auto& action : actions.actions.value()) { - CHECK(action.name == actions.name); - CHECK(action.category != 0); - if (action.text) { - if (action.text.value().empty()) { - entries_[action.name].erase(action.category); - } else { - entries_[action.name][action.category] = action.text.value(); - } - } else { - auto it = entries_.find(action.name); - if (it != entries_.end()) { - it->second.erase(action.category); - } - } - } - } -}; - -class CheckedDns { - public: - explicit CheckedDns(bool check_smc = true, bool check_combine = true) { - if (check_smc) { - key_ = td::Ed25519::generate_private_key().move_as_ok(); - dns_ = ManualDns::create(ManualDns::create_init_data_fast(key_.value().get_public_key().move_as_ok(), 123)); - } - if (check_combine) { - combined_map_dns_ = MapDns(); - } - } - using Action = MapDns::Action; - using Entry = MapDns::Entry; - void update(td::Span entries) { - if (dns_.not_null()) { - auto smc_actions = td::transform(entries, [](auto& entry) { - ton::DnsInterface::Action action; - action.name = entry.name; - action.category = entry.category; - if (entry.text) { - if (entry.text.value().empty()) { - action.data = td::Ref(); - } else { - action.data = ManualDns::EntryData::text(entry.text.value()).as_cell().move_as_ok(); - } - } - return action; - }); - auto query = dns_->create_update_query(key_.value(), smc_actions).move_as_ok(); - CHECK(dns_.write().send_external_message(std::move(query)).code == 0); - } - map_dns_.update(entries); - if (combined_map_dns_) { - combined_map_dns_.value().update_combined(entries); - } - } - void update(const Action& action) { - return update(td::Span(&action, 1)); - } - - std::vector resolve(td::Slice name, td::int16 category) { - LOG(ERROR) << "RESOLVE: " << name << " " << category; - auto res = map_dns_.resolve(name, category); - LOG(ERROR) << td::format::as_array(res); - - if (dns_.not_null()) { - auto other_res = dns_->resolve(name, category).move_as_ok(); - - std::sort(other_res.begin(), other_res.end()); - if (res.size() != other_res.size()) { - LOG(ERROR) << td::format::as_array(res); - LOG(FATAL) << td::format::as_array(other_res); - } - for (size_t i = 0; i < res.size(); i++) { - if (!(res[i] == other_res[i])) { - LOG(ERROR) << td::format::as_array(res); - LOG(FATAL) << td::format::as_array(other_res); - } - } - } - if (combined_map_dns_) { - auto other_res = combined_map_dns_.value().resolve(name, category); - - std::sort(other_res.begin(), other_res.end()); - if (res.size() != other_res.size()) { - LOG(ERROR) << td::format::as_array(res); - LOG(FATAL) << td::format::as_array(other_res); - } - for (size_t i = 0; i < res.size(); i++) { - if (!(res[i] == other_res[i])) { - LOG(ERROR) << td::format::as_array(res); - LOG(FATAL) << td::format::as_array(other_res); - } - } - } - - return res; - } - - private: - using ManualDns = ton::ManualDns; - td::optional key_; - td::Ref dns_; - - MapDns map_dns_; - td::optional combined_map_dns_; - - void do_update_smc(const Action& entry) { - LOG(ERROR) << td::format::escaped(ManualDns::encode_name(entry.name)); - ton::DnsInterface::Action action; - action.name = entry.name; - action.category = entry.category; - action.data = ManualDns::EntryData::text(entry.text.value()).as_cell().move_as_ok(); - } -}; - -void do_dns_test(CheckedDns&& dns) { - using Action = CheckedDns::Action; - std::vector actions; - - td::Random::Xorshift128plus rnd(123); - - auto gen_name = [&] { - auto cnt = rnd.fast(1, 2); - std::string res; - for (int i = 0; i < cnt; i++) { - if (i != 0) { - res += '.'; - } - auto len = rnd.fast(1, 1); - for (int j = 0; j < len; j++) { - res += static_cast(rnd.fast('a', 'b')); - } - } - return res; - }; - auto gen_text = [&] { - std::string res; - int len = 5; - for (int j = 0; j < len; j++) { - res += static_cast(rnd.fast('a', 'b')); - } - return res; - }; - - auto gen_action = [&] { - Action action; - if (rnd.fast(0, 1000) == 0) { - return action; - } - action.name = gen_name(); - if (rnd.fast(0, 20) == 0) { - return action; - } - action.category = td::narrow_cast(rnd.fast(1, 5)); - if (rnd.fast(0, 4) == 0) { - return action; - } - if (rnd.fast(0, 4) == 0) { - action.text = ""; - return action; - } - action.text = gen_text(); - return action; - }; - - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - for (int i = 0; i < 100000; i++) { - actions.push_back(gen_action()); - if (rnd.fast(0, 10) == 0) { - dns.update(actions); - actions.clear(); - } - auto name = gen_name(); - dns.resolve(name, td::narrow_cast(rnd.fast(0, 5))); - } -}; - -TEST(Smartcont, DnsManual) { - using ManualDns = ton::ManualDns; - auto test_entry_data = [](auto&& entry_data) { - auto cell = entry_data.as_cell().move_as_ok(); - auto cs = vm::load_cell_slice(cell); - auto new_entry_data = ManualDns::EntryData::from_cellslice(cs).move_as_ok(); - ASSERT_EQ(entry_data, new_entry_data); - }; - test_entry_data(ManualDns::EntryData::text("abcd")); - test_entry_data(ManualDns::EntryData::adnl_address(ton::Bits256{})); - - CHECK(td::Slice("a\0b\0") == ManualDns::encode_name("b.a")); - CHECK(td::Slice("a\0b\0") == ManualDns::encode_name(".b.a")); - ASSERT_EQ("b.a", ManualDns::decode_name("a\0b\0")); - ASSERT_EQ("b.a", ManualDns::decode_name("a\0b")); - ASSERT_EQ("", ManualDns::decode_name("")); - - auto key = td::Ed25519::generate_private_key().move_as_ok(); - - auto manual = ManualDns::create(ManualDns::create_init_data_fast(key.get_public_key().move_as_ok(), 123)); - CHECK(manual->get_wallet_id().move_as_ok() == 123); - auto init_query = manual->create_init_query(key).move_as_ok(); - LOG(ERROR) << "A"; - CHECK(manual.write().send_external_message(init_query).code == 0); - LOG(ERROR) << "B"; - CHECK(manual.write().send_external_message(init_query).code != 0); - - auto value = vm::CellBuilder().store_bytes("hello world").finalize(); - auto set_query = - manual - ->sign(key, - manual->prepare(manual->create_set_value_unsigned(1, "a\0b\0", value).move_as_ok(), 1).move_as_ok()) - .move_as_ok(); - CHECK(manual.write().send_external_message(set_query).code == 0); - - auto res = manual->run_get_method( - "dnsresolve", {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes("a\0b\0").finalize()), td::make_refint(1)}); - CHECK(res.code == 0); - CHECK(res.stack.write().pop_cell()->get_hash() == value->get_hash()); - - CheckedDns dns; - dns.update(CheckedDns::Action{"a.b.c", 1, "hello"}); - CHECK(dns.resolve("a.b.c", 1).at(0).text == "hello"); - dns.resolve("a", 1); - dns.resolve("a.b", 1); - CHECK(dns.resolve("a.b.c", 2).empty()); - dns.update(CheckedDns::Action{"a.b.c", 2, "test"}); - CHECK(dns.resolve("a.b.c", 2).at(0).text == "test"); - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - LOG(ERROR) << "Test zero category"; - dns.resolve("a.b.c", 0); - dns.update(CheckedDns::Action{"", 0, ""}); - CHECK(dns.resolve("a.b.c", 2).empty()); - - LOG(ERROR) << "Test multipe update"; - { - CheckedDns::Action e[4] = {CheckedDns::Action{"", 0, ""}, CheckedDns::Action{"a.b.c", 1, "hello"}, - CheckedDns::Action{"a.b.c", 2, "world"}, CheckedDns::Action{"x.y.z", 3, "abc"}}; - dns.update(td::Span(e, 4)); - } - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 3); - - { - CheckedDns::Action e[1] = {CheckedDns::Action{"x.y.z", 0, ""}}; - dns.update(td::Span(e, 1)); - } - - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 3); - - { - CheckedDns::Action e[3] = {CheckedDns::Action{"x.y.z", 0, ""}, CheckedDns::Action{"x.y.z", 1, "xxx"}, - CheckedDns::Action{"x.y.z", 2, "yyy"}}; - dns.update(td::Span(e, 3)); - } - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 1); - dns.resolve("x.y.z", 2); - dns.resolve("x.y.z", 3); - - { - auto actions_ext = - ton::ManualDns::parse("delete.name one\nset one 1 TEXT:one\ndelete.name two\nset two 2 TEXT:two").move_as_ok(); - - auto actions = td::transform(actions_ext, [](auto& action) { - td::optional data; - if (action.data) { - data = action.data.value().data.template get().text; - } - return CheckedDns::Action{action.name, action.category, std::move(data)}; - }); - - dns.update(actions); - } - dns.resolve("one", 1); - dns.resolve("two", 2); - - // TODO: rethink semantic of creating an empty dictionary - do_dns_test(CheckedDns(true, true)); -} - -using namespace ton::pchan; - -template -struct ValidateState { - T& self() { - return static_cast(*this); - } - - void init(td::Ref state) { - state_ = state; - block::gen::ChanData::Record data_rec; - if (!tlb::unpack_cell(state, data_rec)) { - on_fatal_error(td::Status::Error("Expected Data")); - return; - } - if (!tlb::unpack_cell(data_rec.state, self().rec)) { - on_fatal_error(td::Status::Error("Expected StatePayout")); - return; - } - CHECK(self().rec.A.not_null()); - } - - T& expect_grams(td::Ref cs, td::uint64 expected, td::Slice name) { - if (has_fatal_error_) { - return self(); - } - td::RefInt256 got; - CHECK(cs.not_null()); - CHECK(block::tlb::t_Grams.as_integer_to(cs, got)); - if (got->cmp(expected) != 0) { - on_error(td::Status::Error(PSLICE() << name << ": expected " << expected << ", got " << got->to_dec_string())); - } - return self(); - } - template - T& expect_eq(S a, S expected, td::Slice name) { - if (has_fatal_error_) { - return self(); - } - if (!(a == expected)) { - on_error(td::Status::Error(PSLICE() << name << ": expected " << expected << ", got " << a)); - } - return self(); - } - - td::Status finish() { - if (errors_.empty()) { - return td::Status::OK(); - } - std::stringstream ss; - block::gen::t_ChanData.print_ref(ss, state_); - td::StringBuilder sb; - for (auto& error : errors_) { - sb << error << "\n"; - } - sb << ss.str(); - return td::Status::Error(sb.as_cslice()); - } - - void on_fatal_error(td::Status error) { - CHECK(!has_fatal_error_); - has_fatal_error_ = true; - on_error(std::move(error)); - } - void on_error(td::Status error) { - CHECK(error.is_error()); - errors_.push_back(std::move(error)); - } - - public: - td::Ref state_; - bool has_fatal_error_{false}; - std::vector errors_; -}; - -struct ValidateStatePayout : public ValidateState { - ValidateStatePayout& expect_A(td::uint64 a) { - expect_grams(rec.A, a, "A"); - return *this; - } - ValidateStatePayout& expect_B(td::uint64 b) { - expect_grams(rec.B, b, "B"); - return *this; - } - - ValidateStatePayout(td::Ref state) { - init(std::move(state)); - } - - block::gen::ChanState::Record_chan_state_payout rec; -}; - -struct ValidateStateInit : public ValidateState { - ValidateStateInit& expect_A(td::uint64 a) { - expect_grams(rec.A, a, "A"); - return *this; - } - ValidateStateInit& expect_B(td::uint64 b) { - expect_grams(rec.B, b, "B"); - return *this; - } - ValidateStateInit& expect_min_A(td::uint64 a) { - expect_grams(rec.min_A, a, "min_A"); - return *this; - } - ValidateStateInit& expect_min_B(td::uint64 b) { - expect_grams(rec.min_B, b, "min_B"); - return *this; - } - ValidateStateInit& expect_expire_at(td::uint32 b) { - expect_eq(rec.expire_at, b, "expire_at"); - return *this; - } - ValidateStateInit& expect_signed_A(bool x) { - expect_eq(rec.signed_A, x, "signed_A"); - return *this; - } - ValidateStateInit& expect_signed_B(bool x) { - expect_eq(rec.signed_B, x, "signed_B"); - return *this; - } - - ValidateStateInit(td::Ref state) { - init(std::move(state)); - } - - block::gen::ChanState::Record_chan_state_init rec; -}; - -struct ValidateStateClose : public ValidateState { - ValidateStateClose& expect_A(td::uint64 a) { - expect_grams(rec.A, a, "A"); - return *this; - } - ValidateStateClose& expect_B(td::uint64 b) { - expect_grams(rec.B, b, "B"); - return *this; - } - ValidateStateClose& expect_promise_A(td::uint64 a) { - expect_grams(rec.promise_A, a, "promise_A"); - return *this; - } - ValidateStateClose& expect_promise_B(td::uint64 b) { - expect_grams(rec.promise_B, b, "promise_B"); - return *this; - } - ValidateStateClose& expect_expire_at(td::uint32 b) { - expect_eq(rec.expire_at, b, "expire_at"); - return *this; - } - ValidateStateClose& expect_signed_A(bool x) { - expect_eq(rec.signed_A, x, "signed_A"); - return *this; - } - ValidateStateClose& expect_signed_B(bool x) { - expect_eq(rec.signed_B, x, "signed_B"); - return *this; - } - - ValidateStateClose(td::Ref state) { - init(std::move(state)); - } - - block::gen::ChanState::Record_chan_state_close rec; -}; - -// config$_ initTimeout:int exitTimeout:int a_key:int256 b_key:int256 a_addr b_addr channel_id:int256 = Config; -TEST(Smarcont, Channel) { - auto code = ton::SmartContractCode::get_code(ton::SmartContractCode::PaymentChannel); - Config config; - auto a_pkey = td::Ed25519::generate_private_key().move_as_ok(); - auto b_pkey = td::Ed25519::generate_private_key().move_as_ok(); - config.init_timeout = 20; - config.close_timeout = 40; - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - config.a_addr = dest; - config.b_addr = dest; - config.a_key = a_pkey.get_public_key().ok().as_octet_string(); - config.b_key = b_pkey.get_public_key().ok().as_octet_string(); - config.channel_id = 123; - - Data data; - data.config = config.serialize(); - data.state = data.init_state(); - auto data_cell = data.serialize(); - - auto channel = ton::SmartContract::create(ton::SmartContract::State{code, data_cell}); - ValidateStateInit(channel->get_state().data) - .expect_A(0) - .expect_B(0) - .expect_min_A(0) - .expect_min_B(0) - .expect_signed_A(false) - .expect_signed_B(false) - .expect_expire_at(0) - .finish() - .ensure(); - - enum err { - ok = 0, - wrong_a_signature = 31, - wrong_b_signature, - msg_value_too_small, - replay_protection, - no_timeout, - expected_init, - expected_close, - no_promise_signature, - wrong_channel_id - }; - -#define expect_code(description, expected_code, e) \ - { \ - auto res = e; \ - LOG_IF(FATAL, expected_code != res.code) << " res.code=" << res.code << " " << description << "\n" << #e; \ - } -#define expect_ok(description, e) expect_code(description, 0, e) - - expect_code("Trying to invoke a timeout while channel is empty", no_timeout, - channel.write().send_external_message(MsgTimeoutBuilder().finalize(), - ton::SmartContract::Args().set_now(1000000))); - - expect_code("External init message with no signatures", replay_protection, - channel.write().send_external_message(MsgInitBuilder().channel_id(config.channel_id).finalize())); - expect_code("Internal init message with not enough value", msg_value_too_small, - channel.write().send_internal_message( - MsgInitBuilder().channel_id(config.channel_id).inc_A(1000).min_B(2000).with_a_key(&a_pkey).finalize(), - ton::SmartContract::Args().set_amount(100))); - expect_code( - "Internal init message with wrong channel_id", wrong_channel_id, - channel.write().send_internal_message(MsgInitBuilder().inc_A(1000).min_B(2000).with_a_key(&a_pkey).finalize(), - ton::SmartContract::Args().set_amount(1000))); - expect_ok("A init with (inc_A = 1000, min_A = 1, min_B = 2000)", - channel.write().send_internal_message(MsgInitBuilder() - .channel_id(config.channel_id) - .inc_A(1000) - .min_A(1) - .min_B(2000) - .with_a_key(&a_pkey) - .finalize(), - ton::SmartContract::Args().set_amount(1000))); - ValidateStateInit(channel->get_state().data) - .expect_A(1000) - .expect_B(0) - .expect_min_A(1) - .expect_min_B(2000) - .expect_signed_A(true) - .expect_signed_B(false) - .expect_expire_at(config.init_timeout) - .finish() - .ensure(); - - expect_code("Repeated init of A init with (inc_A = 100, min_B = 5000). Must be ignored", replay_protection, - channel.write().send_internal_message( - MsgInitBuilder().channel_id(config.channel_id).inc_A(100).min_B(5000).with_a_key(&a_pkey).finalize(), - ton::SmartContract::Args().set_amount(1000))); - expect_code( - "Trying to invoke a timeout too early", no_timeout, - channel.write().send_external_message(MsgTimeoutBuilder().finalize(), ton::SmartContract::Args().set_now(0))); - - { - auto channel_copy = channel; - expect_ok("Invoke a timeout", channel_copy.write().send_external_message(MsgTimeoutBuilder().finalize(), - ton::SmartContract::Args().set_now(21))); - ValidateStatePayout(channel_copy->get_state().data).expect_A(1000).expect_B(0).finish().ensure(); - } - { - auto channel_copy = channel; - expect_ok("B init with inc_B < min_B. Leads to immediate payout", - channel_copy.write().send_internal_message( - MsgInitBuilder().channel_id(config.channel_id).inc_B(1500).with_b_key(&b_pkey).finalize(), - ton::SmartContract::Args().set_amount(1500))); - ValidateStatePayout(channel_copy->get_state().data).expect_A(1000).expect_B(1500).finish().ensure(); - } - - expect_ok("B init with (inc_B = 2000, min_A = 1, min_A = 1000)", - channel.write().send_internal_message( - MsgInitBuilder().channel_id(config.channel_id).inc_B(2000).min_A(1000).with_b_key(&b_pkey).finalize(), - ton::SmartContract::Args().set_amount(2000))); - ValidateStateClose(channel->get_state().data) - .expect_A(1000) - .expect_B(2000) - .expect_promise_A(0) - .expect_promise_B(0) - .expect_signed_A(false) - .expect_signed_B(false) - .expect_expire_at(0) - .finish() - .ensure(); - - { - auto channel_copy = channel; - expect_ok("A&B send Promise(1000000, 1000000 + 10) signed by nobody", - channel_copy.write().send_external_message(MsgCloseBuilder() - .signed_promise(SignedPromiseBuilder() - .promise_A(1000000) - .promise_B(1000000 + 10) - .channel_id(config.channel_id) - .finalize()) - .with_a_key(&a_pkey) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - ValidateStatePayout(channel_copy->get_state().data).expect_A(1000 + 10).expect_B(2000 - 10).finish().ensure(); - } - { - auto channel_copy = channel; - expect_ok("A&B send Promise(1000000, 1000000 + 10) signed by A", - channel_copy.write().send_external_message(MsgCloseBuilder() - .signed_promise(SignedPromiseBuilder() - .promise_A(1000000) - .promise_B(1000000 + 10) - .with_key(&a_pkey) - .channel_id(config.channel_id) - .finalize()) - .with_a_key(&a_pkey) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - ValidateStatePayout(channel_copy->get_state().data).expect_A(1000 + 10).expect_B(2000 - 10).finish().ensure(); - } - - expect_code( - "A sends Promise(1000000, 0) signed by A", wrong_b_signature, - channel.write().send_external_message( - MsgCloseBuilder() - .signed_promise( - SignedPromiseBuilder().promise_A(1000000).with_key(&a_pkey).channel_id(config.channel_id).finalize()) - .with_a_key(&a_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - expect_code( - "B sends Promise(1000000, 0) signed by B", wrong_a_signature, - channel.write().send_external_message( - MsgCloseBuilder() - .signed_promise( - SignedPromiseBuilder().promise_A(1000000).with_key(&b_pkey).channel_id(config.channel_id).finalize()) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - expect_code("B sends Promise(1000000, 0) signed by A with wrong channel_id", wrong_channel_id, - channel.write().send_external_message(MsgCloseBuilder() - .signed_promise(SignedPromiseBuilder() - .promise_A(1000000) - .with_key(&a_pkey) - .channel_id(config.channel_id + 1) - .finalize()) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - expect_code( - "B sends unsigned Promise(1000000, 0)", no_promise_signature, - channel.write().send_external_message( - MsgCloseBuilder() - .signed_promise(SignedPromiseBuilder().promise_A(1000000).channel_id(config.channel_id).finalize()) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - - expect_ok( - "B sends Promise(1000000, 0) signed by A", - channel.write().send_external_message( - MsgCloseBuilder() - .signed_promise( - SignedPromiseBuilder().promise_A(1000000).with_key(&a_pkey).channel_id(config.channel_id).finalize()) - .with_b_key(&b_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - ValidateStateClose(channel->get_state().data) - .expect_A(1000) - .expect_B(2000) - .expect_promise_A(1000000) - .expect_promise_B(0) - .expect_signed_A(false) - .expect_signed_B(true) - .expect_expire_at(21 + config.close_timeout) - .finish() - .ensure(); - - expect_ok("B sends Promise(0, 1000000 + 10) signed by A", - channel.write().send_external_message(MsgCloseBuilder() - .signed_promise(SignedPromiseBuilder() - .promise_B(1000000 + 10) - .with_key(&b_pkey) - .channel_id(config.channel_id) - .finalize()) - .with_a_key(&a_pkey) - .finalize(), - ton::SmartContract::Args().set_now(21))); - ValidateStatePayout(channel->get_state().data).expect_A(1000 + 10).expect_B(2000 - 10).finish().ensure(); -#undef expect_ok -#undef expect_code -} diff --git a/submodules/ton/tonlib-src/crypto/test/vm.cpp b/submodules/ton/tonlib-src/crypto/test/vm.cpp deleted file mode 100644 index 3227f8fa..00000000 --- a/submodules/ton/tonlib-src/crypto/test/vm.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/vm.h" -#include "vm/cp0.h" -#include "vm/dict.h" -#include "fift/utils.h" -#include "common/bigint.hpp" - -#include "td/utils/base64.h" -#include "td/utils/tests.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/StringBuilder.h" - -std::string run_vm(td::Ref cell) { - vm::init_op_cp0(); - vm::DictionaryBase::get_empty_dictionary(); - - class Logger : public td::LogInterface { - public: - void append(td::CSlice slice) override { - res.append(slice.data(), slice.size()); - } - std::string res; - }; - static Logger logger; - logger.res = ""; - td::set_log_fatal_error_callback([](td::CSlice message) { td::default_log_interface->append(logger.res); }); - vm::VmLog log{&logger, td::LogOptions::plain()}; - log.log_options.level = 4; - log.log_options.fix_newlines = true; - log.log_mask |= vm::VmLog::DumpStack; - - auto total_data_cells_before = vm::DataCell::get_total_data_cells(); - SCOPE_EXIT { - auto total_data_cells_after = vm::DataCell::get_total_data_cells(); - ASSERT_EQ(total_data_cells_before, total_data_cells_after); - }; - - vm::Stack stack; - try { - vm::GasLimits gas_limit(1000, 1000); - - vm::run_vm_code(vm::load_cell_slice_ref(cell), stack, 0 /*flags*/, nullptr /*data*/, std::move(log) /*VmLog*/, - nullptr, &gas_limit); - } catch (...) { - LOG(FATAL) << "catch unhandled exception"; - } - return logger.res; // must be a copy -} - -td::Ref to_cell(const unsigned char *buff, int bits) { - return vm::CellBuilder().store_bits(buff, bits, 0).finalize(); -} -void test_run_vm(td::Ref code) { - auto a = run_vm(code); - auto b = run_vm(code); - ASSERT_EQ(a, b); - REGRESSION_VERIFY(a); -} - -void test_run_vm(td::Slice code_hex) { - unsigned char buff[128]; - int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), code_hex.begin(), code_hex.end()); - CHECK(bits >= 0); - test_run_vm(to_cell(buff, bits)); -} - -void test_run_vm_raw(td::Slice code64) { - auto code = td::base64_decode(code64).move_as_ok(); - if (code.size() > 127) { - code.resize(127); - } - test_run_vm(vm::CellBuilder().store_bytes(code).finalize()); -} - -TEST(VM, simple) { - test_run_vm("ABCBABABABA"); -} - -TEST(VM, memory_leak_old) { - test_run_vm("90787FDB3B"); -} - -TEST(VM, memory_leak) { - test_run_vm("90707FDB3B"); -} - -TEST(VM, bug_div_short_any) { - test_run_vm("6883FF73A98D"); -} -TEST(VM, assert_pfx_dict_lookup) { - test_run_vm("778B04216D73F43E018B04591277F473"); -} - -TEST(VM, assert_lookup_prefix) { - test_run_vm("78E58B008B028B04010000016D90ED5272F43A755D77F4A8"); -} - -TEST(VM, assert_code_not_null) { - test_run_vm("76ED40DE"); -} - -TEST(VM, bug_exec_dict_getnear) { - test_run_vm("8B048B00006D72F47573655F6D656D6D656D8B007F"); -} - -TEST(VM, bug_stack_overflow) { - test_run_vm("72A93AF8"); -} - -TEST(VM, assert_extract_minmax_key) { - test_run_vm("6D6DEB21807AF49C2180EB21807AF41C"); -} - -TEST(VM, memory_leak_new) { - test_run_vm("72E5ED40DB3603"); -} - -TEST(VM, unhandled_exception_1) { - test_run_vm("70EDA2ED00"); -} - -TEST(VM, unhandled_exception_2) { - // infinite loop now - test_run_vm("EBEDB4"); -} - -TEST(VM, unhandled_exception_3) { - // infinite loop now - test_run_vm("EBEDC0"); -} - -TEST(VM, unhandled_exception_4) { - test_run_vm("7F853EA1C8CB3E"); -} - -TEST(VM, unhandled_exception_5) { - test_run_vm("738B04016D21F41476A721F49F"); -} - -TEST(VM, infinity_loop_1) { - test_run_vm_raw("f3r4AJGQ6rDraIQ="); -} -TEST(VM, infinity_loop_2) { - test_run_vm_raw("kpTt7ZLrig=="); -} - -TEST(VM, oom_1) { - test_run_vm_raw("bXflX/BvDw=="); -} - -TEST(VM, bigint) { - td::StringBuilder sb({}, true); - - using word_t = td::BigIntInfo::word_t; - std::vector numbers{1, - -1, - 2, - -2, - 100, - -100, - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::max() - 1, - std::numeric_limits::min() + 1}; - for (auto x : numbers) { - for (auto y : numbers) { - word_t a; - word_t b; - td::BigIntInfo::set_mul(&a, &b, x, y); - sb << "set_mul " << x << " * " << y << " = " << a << " " << b << "\n"; - td::BigIntInfo::add_mul(&a, &b, x, y); - sb << "add_mul " << x << " " << y << " = " << a << " " << b << "\n"; - td::BigIntInfo::sub_mul(&a, &b, x, y); - sb << "sub_mul " << x << " " << y << " = " << a << " " << b << "\n"; - } - } - auto base = td::BigIntInfo::Base; - std::vector lo_numbers{1, -1, 2, -2, 100, -100, base - 1, base - 2, -base + 1, -base + 2}; - for (auto x : numbers) { - for (auto y : lo_numbers) { - for (auto z : numbers) { - word_t a; - word_t b; - td::BigIntInfo::dbl_divmod(&a, &b, x, y, z); - sb << "dbl_divmod " << x << " " << y << " / " << z << " = " << a << " " << b << "\n"; - } - } - } - - REGRESSION_VERIFY(sb.as_cslice()); -} - -TEST(VM, report3_1) { - //WA: expect (1, 2, 6, 3) - td::Slice test1 = - R"A( -CONT:<{ -DEPTH -}> -3 SETNUMARGS -c0 POPCTR -1 INT -2 INT -3 INT -4 INT -5 INT -6 INT -4 RETURNARGS -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_2) { - td::Slice test1 = - R"A( -CONT:<{ -DEPTH -}> -2 SETNUMARGS -c0 POPCTR -1 INT -2 INT -3 INT -4 INT -2 RETARGS -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_3) { - // WA: expect (9) - td::Slice test1 = - R"A( -CONT:<{ - 8 INT -}> -c0 POPCTR -CONT:<{ - 9 INT -}> -c1 POPCTR -0 INT -BRANCH -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_4) { - td::Slice test1 = - R"A( -CONT:<{ -1 INT -2 INT -3 INT -2 RETARGS -}> -CALLX -ADD -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_6) { - // WA: expect StackOverflow - td::Slice test1 = - R"A( -10 INT -20 INT -30 INT -CONT:<{ - DEPTH - 40 INT - SWAP -}> -2 SETNUMARGS -3 1 CALLXARGS -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -//TEST(VM, report3_ce) { -//td::Slice test1 = -//R"A( -//s16 POP -//s16 PUSH -//s0 s16 XCHG -//)A"; -//test_run_vm(fift::compile_asm(test1).move_as_ok()); -//} - -TEST(VM, report3_int_overflow_1) { - td::Slice test1 = - R"A( -4 INT -16 INT --115792089237316195423570985008687907853269984665640564039457584007913129639936 INT -MULDIVMOD -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} -TEST(VM, report3_int_overflow_2) { - td::Slice test1 = - R"A( -4 INT -16 INT --115792089237316195423570985008687907853269984665640564039457584007913129639936 INT -MULDIVR -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_qnot) { - td::Slice test1 = - R"A( -PUSHNAN -QNOT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_loop_1) { - //WA - td::Slice test1 = - R"A( -CONT:<{ - 2 INT -}> -ATEXITALT -CONT:<{ - 1 INT - RETALT - -1 INT -}> -AGAIN -3 INT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_loop_2) { - //WA - td::Slice test1 = - R"A( -CONT:<{ - 2 INT -}> -ATEXITALT -CONT:<{ - 1 INT - RETALT - -1 INT -}> -UNTIL -3 INT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_loop_3) { - //WA - td::Slice test1 = - R"A( -1 INT -CONT:<{ - UNTILEND - RET - -1 INT -}> -CALLX -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_loop_4) { - //WA - td::Slice test1 = - R"A( -CONT:<{ - 2 INT -}> -ATEXITALT -CONT:<{ - 1 INT - RETALT - -1 PUSHINT -}> -CONT:<{ - -1 INT -}> -WHILE -3 INT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} -TEST(VM, report3_loop_5) { - //WA - td::Slice test1 = - R"A( -CONT:<{ - 1 INT - 2 INT -}> -ATEXITALT -3 INT -AGAINEND -DEC -DUP -IFRET -DROP -RETALT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} - -TEST(VM, report3_loop_6) { - //WA - td::Slice test1 = - R"A( -CONT:<{ - 1 INT - 2 INT -}> -3 INT -AGAINEND -DEC -DUP -IFRET -DROP -ATEXITALT -RETALT -)A"; - test_run_vm(fift::compile_asm(test1).move_as_ok()); -} diff --git a/submodules/ton/tonlib-src/crypto/test/wycheproof.h b/submodules/ton/tonlib-src/crypto/test/wycheproof.h deleted file mode 100644 index 182760ac..00000000 --- a/submodules/ton/tonlib-src/crypto/test/wycheproof.h +++ /dev/null @@ -1,1160 +0,0 @@ -#pragma once - -#include - -std::string wycheproof_ed25519() { - return - R"abcd({ - "algorithm" : "EDDSA", - "generatorVersion" : "0.4.12", - "notes" : { - "SignatureMalleability" : "EdDSA signatures are non-malleable, if implemented accordingly. Failing to check the range of S allows to modify signatures. See RFC 8032, Section 5.2.7 and Section 8.4." - }, - "numberOfTests" : 111, - "header" : [], - "testGroups" : [ - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", - "sk" : "add4bb8103785baf9ac534258e8aaf65f5f1adb5ef5f3df19bb80ab989c4d64b", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321007d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 1, - "comment" : "", - "msg" : "", - "sig" : "d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 2, - "comment" : "", - "msg" : "78", - "sig" : "d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 3, - "comment" : "", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 4, - "comment" : "", - "msg" : "48656c6c6f", - "sig" : "1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 5, - "comment" : "", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 6, - "comment" : "", - "msg" : "000000000000000000000000", - "sig" : "d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 7, - "comment" : "", - "msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", - "sig" : "879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 8, - "comment" : "", - "msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", - "sig" : "7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 9, - "comment" : "", - "msg" : "ffffffffffffffffffffffffffffffff", - "sig" : "5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 10, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 11, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 12, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 13, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 14, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 15, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 16, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 17, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 18, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 19, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 20, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 21, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 22, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 23, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 24, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 25, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 26, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 27, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 28, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 29, - "comment" : "special values for r and s", - "msg" : "3f", - "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 30, - "comment" : "empty signature", - "msg" : "54657374", - "sig" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 31, - "comment" : "s missing", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 32, - "comment" : "signature too short", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 33, - "comment" : "signature too long", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020", - "result" : "invalid", - "flags" : [] - },)abcd" R"abcd( - { - "tcId" : 34, - "comment" : "include pk in signature", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 35, - "comment" : "prepending 0 byte to signature", - "msg" : "54657374", - "sig" : "007c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 36, - "comment" : "prepending 0 byte to s", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0007a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 37, - "comment" : "appending 0 byte to signature", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d00", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 38, - "comment" : "removing 0 byte from signature", - "msg" : "546573743137", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b3", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 39, - "comment" : "removing 0 byte from signature", - "msg" : "54657374313236", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab09155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 40, - "comment" : "removing leading 0 byte from signature", - "msg" : "546573743530", - "sig" : "38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 41, - "comment" : "dropping byte from signature", - "msg" : "54657374333437", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab09155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 42, - "comment" : "modified bit 0 in R", - "msg" : "313233343030", - "sig" : "647c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b1d125e5538f38afbcc1c84e489521083041d24bc6240767029da063271a1ff0c", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 43, - "comment" : "modified bit 1 in R", - "msg" : "313233343030", - "sig" : "677c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bc108ca4b87a49c9ed2cf383aecad8f54a962b2899da891e12004d7993a627e01", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 44, - "comment" : "modified bit 2 in R", - "msg" : "313233343030", - "sig" : "617c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b9ce23fc6213ed5b87912e9bbf92f5e2c780eae26d15c50a112d1e97d2ea33c06", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 45, - "comment" : "modified bit 7 in R", - "msg" : "313233343030", - "sig" : "e57c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bbb3eb51cd98dddb235a5f46f2bded6af184a58d09cce928bda43f41d69118a03", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 46, - "comment" : "modified bit 8 in R", - "msg" : "313233343030", - "sig" : "657d1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcd237dda9a116501f67a5705a854b9adc304f34720803a91b324f2c13e0f5a09", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 47, - "comment" : "modified bit 16 in R", - "msg" : "313233343030", - "sig" : "657c1592402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b6b167bbdc0d881cc04d28905552c1876f3709851abc5007376940cc8a435c300", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 48, - "comment" : "modified bit 31 in R", - "msg" : "313233343030", - "sig" : "657c1412402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7fd2ac7da14afffcceeb13f2a0d6b887941cb1a5eb57a52f3cb131a16cce7b0e", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 49, - "comment" : "modified bit 32 in R", - "msg" : "313233343030", - "sig" : "657c1492412ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7373ba13ebbef99cd2a8ead55ce735c987d85a35320925a8e871702dc7c5c40d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 50, - "comment" : "modified bit 63 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab54e03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bd35bd331c03f0855504ca1cab87b83c36a028425a3cf007ede4f4254c261cb00", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 51, - "comment" : "modified bit 64 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce02e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcb35101f73cf467deac8c1a03b6c3dc35af544132734b7e57ab20c89b2e4750d", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 52, - "comment" : "modified bit 97 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f2384d051b9cf3570f1207fc78c1bcc98c281c2bb58d2e8878290bff8d3355fdd4ea381924ee578752354eb6dee678ab4011c301", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 53, - "comment" : "modified bit 127 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d851b9cf3570f1207fc78c1bcc98c281c2bb978c866187ffb1cc7b29a0b4045aefc08768df65717194ff0c6e63f4dea0d02", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 54, - "comment" : "modified bit 240 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281d2b0576ecf8eaf675f00f3dfbe19f75b83b7607a6c96414f6821af920a2498d0305", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 55, - "comment" : "modified bit 247 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c289c2be5241a345c7b5428054c74b7c382fa10d4a5f1e8f8b79a71d3fdea2254f1ff0e", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 56, - "comment" : "modified bit 248 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2a63950c85cd6dc96364e768de50ff7732b538f8a0b1615d799190ab600849230e", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 57, - "comment" : "modified bit 253 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c0b543bd3da0a56a8c9c152f59c9fec12f31fa66434d48b817b30d90cb4efa8b501", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 58, - "comment" : "modified bit 254 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c6b8da07efd07a6dafb015ed6a32fe136319a972ffbc341f3a0beae97ccf8136505", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 59, - "comment" : "modified bit 255 in R", - "msg" : "313233343030", - "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281cab227aedf259f910f0f3a759a335062665217925d019173b88917eae294f75d40f", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 60, - "comment" : "R==0", - "msg" : "313233343030", - "sig" : "0000000000000000000000000000000000000000000000000000000000000000e0b8e7770d51c7a36375d006c5bffd6af43ff54aaf47e4330dc118c71d61ec02", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 61, - "comment" : "invalid R", - "msg" : "313233343030", - "sig" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff463a1908382e7eb7693acef9884f7cf931a215e0791876be22c631a59881fd0e", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 62, - "comment" : "all bits flipped in R", - "msg" : "313233343030", - "sig" : "9a83eb6dbfd54a31fc1d3c580fc7b2fae4630ca8f0edf803873e433673d7e3d40e94254586cb6188c5386c3febed477cb9a6cb29e3979adc4cb27cf5278fb70a", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 63, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 64, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab05439412b5395d42f462c67008eba6ca839d4eef676573336a5c51eb6f946b32d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 65, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab02ee12ce5875bf9dff26556464bae2ad239d4eef676573336a5c51eb6f946b34d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 66, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0e2300459f1e742404cd934d2c595a6253ad4eef676573336a5c51eb6f946b38d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 67, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b32d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - },)abcd" R"abcd( - { - "tcId" : 68, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b34d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 69, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - }, - { - "tcId" : 70, - "comment" : "checking malleability ", - "msg" : "54657374", - "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0679155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d", - "result" : "invalid", - "flags" : [ - "SignatureMalleability" - ] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c", - "sk" : "0a23a20072891237aa0864b5765139514908787878cd77135a0059881d313f00", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAoSwr63cmXyqslTtQCTSdlBVaA62kFqrUUTGUgOmDykw=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 71, - "comment" : "", - "msg" : "", - "sig" : "5056325d2ab440bf30bbf0f7173199aa8b4e6fbc091cf3eb6bc6cf87cd73d992ffc216c85e4ab5b8a0bbc7e9a6e9f8d33b7f6e5ac0ffdc22d9fcaf784af84302", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 72, - "comment" : "", - "msg" : "78", - "sig" : "481fafbf4364d7b682475282f517a3ac0538c9a6b6a562e99a3d8e5afb4f90a559b056b9f07af023905753b02d95eb329a35c77f154b79abbcd291615ce42f02", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 73, - "comment" : "", - "msg" : "54657374", - "sig" : "8a9bb4c465a3863abc9fd0dd35d80bb28f7d33d37d74679802d63f82b20da114b8d765a1206b3e9ad7cf2b2d8d778bb8651f1fa992db293c0039eacb6161480f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 74, - "comment" : "", - "msg" : "48656c6c6f", - "sig" : "d839c20abfda1fd429531831c64f813f84b913e9928540310cf060b44c3dbf9457d44a7721fdc0d67724ff81cb450dd39b10cfb65db15dda4b8bf09d26bd3801", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 75, - "comment" : "", - "msg" : "313233343030", - "sig" : "9bbb1052dcfa8ad2715c2eb716ae4f1902dea353d42ee09fd4c0b4fcb8b52b5219e2200016e1199d0061891c263e31b0bc3b55673c19610c4e0fa5408004160b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 76, - "comment" : "", - "msg" : "000000000000000000000000", - "sig" : "f63b5c0667c7897fc283296416f7f60e84bbde9cbd832e56be463ed9f568069702b17a2f7c341ebf590706a6388ac76ac613c1675ec0f2c7118f2573422a500b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 77, - "comment" : "", - "msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", - "sig" : "1bc44d7001e6b5b9090fef34b2ca480f9786bbefa7d279353e5881e8dfb91b803ccd46500e270ef0109bfd741037558832120bc2a4f20fbe7b5fb3c3aaf23e08", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 78, - "comment" : "", - "msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", - "sig" : "ea8e22143b02372e76e99aece3ed36aec529768a27e2bb49bdc135d44378061e1f62d1ac518f33ebf37b2ee8cc6dde68a4bd7d4a2f4d6cb77f015f71ca9fc30d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 79, - "comment" : "", - "msg" : "ffffffffffffffffffffffffffffffff", - "sig" : "8acd679e1a914fc45d5fa83d3021f0509c805c8d271df54e52f43cfbd00cb6222bf81d58fe1de2de378df67ee9f453786626961fe50a9b05f12b6f0899ebdd0a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", - "sk" : "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 80, - "comment" : "draft-josefsson-eddsa-ed25519-02: Test 1", - "msg" : "", - "sig" : "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", - "sk" : "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321003d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 81, - "comment" : "draft-josefsson-eddsa-ed25519-02: Test 2", - "msg" : "72", - "sig" : "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", - "sk" : "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/FHNjmIYoaONpH7QAjDwWAgW7RO6MwOsXeuRFUiQgCU=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 82, - "comment" : "draft-josefsson-eddsa-ed25519-02: Test 3", - "msg" : "af82", - "sig" : "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", - "sk" : "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAJ4EX/BRMcjQPZ9DyMW6Dhs7/vyskKMnFH+98WX8dQm4=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 83, - "comment" : "draft-josefsson-eddsa-ed25519-02: Test 1024", - "msg" : "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", - "sig" : "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "8fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a", - "sk" : "d7ad3f1f6bbe0477c3c357a806a19eb41ae3f94025035bc87f281f8ee9fc0e34", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321008fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAj9ZZt3tVjtk4gsEVdDhFCshuxi1CHVaOmO4jbzgQKVo=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 84, - "comment" : "Random test failure 1", - "msg" : "b0729a713593a92e46b56eaa66b9e435f7a09a8e7de03b078f6f282285276635f301e7aaafe42187c45d6f5b13f9f16b11195cc125c05b90d24dfe4c", - "sig" : "7db17557ac470c0eda4eedaabce99197ab62565653cf911f632ee8be0e5ffcfc88fb94276b42e0798fd3aa2f0318be7fc6a29fae75f70c3dcdc414a0ad866601", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082", - "sk" : "ad9b22793336fcdac10e136c4deea599be187a38eef91c1cf7c7a4ec884dda08", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321002a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAKmBr9nrHcMYHA4sAQQGzJe21ae/TQT0tHyw+a05uMII=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 85, - "comment" : "Random test failure 2", - "msg" : "a8546e50ba31cae3234310d32672447be213fad91a227a19669c53d309b959782b0e6b71f8791fdb470043b58122003157d2d96a43a6cbd7d3a8d86bf4c97391883e268d50af80e1e6e12939c2bd50ca746cdadfad4edf1bda875299740724148efb1ebe73fb60088cda890317658627a5f7ab5a0c075d9d8f3f97b6492b35519e50ff6b38377432a7081f9176bb1c29a862deac1336ca20b097a47829cec10a6a7cec178eda2d12f6dc6c87f910454af0123555ba184e68804d9cced60fd5c8c90943e56599c8f0ba59a38491ba5e5a53460682474c07e40ca142983314fd762856bb1093f359da6eb0a756bd93a3160c10dd8feea6b97e7c6a17cb54bd5d7649c05c66d7bdee056671dfdaf689fa3945bb8e29a429f4bd5d355dce9687b06f01d5e33e3999f0e8", - "sig" : "67d84d4c3945aaf06e06d524be63acbfb5dbb1988c4aea96a5ee9f7a9b9eecc29df4f66b8aa1d9e8607a58fb1ef0c2ad69aac005b4f58e34103344a9c8871a09", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 86, - "comment" : "Random test failure 24", - "msg" : "b477b0480bb84642608b908d29a51cf2fce63f24ee95", - "sig" : "28fafbb62b4d688fa79e1ac92851f46e319b161f801d4dc09acc21fdd6780a2c4292b8c1003c61c2bcebe7f3f88ccc4bb26d407387c5f27cb8c94cf6ce810405", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051", - "sk" : "04a6553d68a9baef78a2175af375458eaa01cdb77350c61e282ef5f0c7116599", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyclGy8VUSsdO70kfB8WIHBb69+wxzkqpG7YK57RTkFE=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 87, - "comment" : "Random test failure 3", - "msg" : "cd2212eddb0706f62c995cef958634f0cb7793444cbf4d30e81c27c41ebea6cb02607510131f9c015692dfd521b148841e9a2d3564d20ac401f6cb8e40f520fe0cafbeaa88840b83013369d879f013463fe52a13267aa0c8c59c45cde9399cd1e6be8cc64cf48315ac2eb31a1c567a4fb7d601746d1f63b5ac020712adbbe07519bded6f", - "sig" : "24087d47f3e20af51b9668ae0a88ce76586802d0ec75d8c0f28fc30962b5e1d1a1d509571a1624ed125a8df92a6e963728d6b5de99200b8e285f70feb6f05207", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 88, - "comment" : "Random test failure 20", - "msg" : "27d465bc632743522aefa23c", - "sig" : "c2656951e2a0285585a51ff0eda7e9a23c2dfd2ffa273aee7808f4604e8f9a8c8ea49e9fce4eb2d8d75d36b7238fe6fc13b6c5d9427dd58f8c6615d033c0bd0f", - "result" : "valid", - "flags" : [] - } - ] - },)abcd" R"abcd( - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e", - "sk" : "c367c8d2ebeeecd70c1e8985b70c3808b75657f243b21ba4f322792540e92257", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b657003210032ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAMq0Cb2k9DSr+f0OI2RxMlkQm/LnjZlw+vYZQAJuBXI4=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 89, - "comment" : "Random test failure 4", - "msg" : "ec5c7cb078", - "sig" : "d920d421a5956b69bfe1ba834c025e2babb6c7a6d78c97de1d9bb1116dfdd1185147b2887e34e15578172e150774275ea2aad9e02106f7e8ca1caa669a066f0c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 90, - "comment" : "Random test failure 5", - "msg" : "4668c6a76f0e482190a7175b9f3806a5fe4314a004fa69f988373f7a", - "sig" : "4f62daf7f7c162038552ad7d306e195baa37ecf6ca7604142679d7d1128e1f8af52e4cb3545748c44ef1ff1c64e877e4f4d248259b7f6eb56e3ef72097dc8e0c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 91, - "comment" : "Random test failure 8", - "msg" : "5dc9bb87eb11621a93f92abe53515697d2611b2eef73", - "sig" : "deecafb6f2ede73fec91a6f10e45b9c1c61c4b9bfbe6b6147e2de0b1df6938971f7896c3ab83851fb5d9e537037bff0fca0ccb4a3cc38f056f91f7d7a0557e08", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 92, - "comment" : "Random test failure 10", - "msg" : "7dcfe60f881e1285676f35b68a1b2dbcdd7be6f719a288ababc28d36e3a42ac3010a1ca54b32760e74", - "sig" : "7f8663cf98cbd39d5ff553f00bcf3d0d520605794f8866ce75714d77cc51e66c91818b657d7b0dae430a68353506edc4a714c345f5ddb5c8b958ba3d035f7a01", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 93, - "comment" : "Random test failure 12", - "msg" : "58e456064dff471109def4ca27fa8310a1df32739655b624f27e6418d34b7f007173f3faa5", - "sig" : "6aab49e5c0bc309b783378ee03ffda282f0185cdf94c847701ff307a6ee8d0865411c44e0a8206f6a5f606107451940c2593af790ce1860f4c14ab25b2deae08", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 94, - "comment" : "Random test failure 15", - "msg" : "a1", - "sig" : "1a74ed2cbdc7d8f3827014e8e6ecf8fd2698ac8f86833acccdd400df710fe0d6b0543c9cfa00d52bf024ab7ce0d91981944097233ec134d5c7abbd44bfd32d0d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 95, - "comment" : "Random test failure 19", - "msg" : "11cb1eafa4c42a8402c4193c4696f7b2e6d4585e4b42dcf1a8b67a80b2da80bc9d4b649fb2f35eaf1f56c426fd0b", - "sig" : "14ceb2eaf4688d995d482f44852d71ad878cd7c77b41e60b0065fd01a59b054ee74759224187dbde9e59a763a70277c960892ef89fba997aba2576b2c54ba608", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 96, - "comment" : "Random test failure 25", - "msg" : "aa365b442d12b7f3c925", - "sig" : "83c40ce13d483cc58ff65844875862d93df4bd367af77efa469ec06a8ed9e6d7905a04879535708ddf225567a815c9b941d405c98e918fd0c151165cea7fb101", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 97, - "comment" : "Random test failure 28", - "msg" : "475f", - "sig" : "71a4a06a34075f2fd47bc3abf4714d46db7e97b08cb6180d3f1539ac50b18ce51f8af8ae95ed21d4fa0daab7235925631ecea1fd9d0d8a2ba7a7583fd04b900c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a", - "sk" : "56c1e22d616cbb6dea869288b4b1c02bb98696583c2f6e650013a03e17049c62", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwp7BiU4G0ntOQEhrT6UGPWanRsf5wyOxIgPAO3K4t4o=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 98, - "comment" : "Random test failure 6", - "msg" : "0f325ffd87e58131ffa23c05ea4579513b287fdba87b44", - "sig" : "6669acf94667c5b541afe5307bde9476b13ae7e0e6058a772101ac8eb0a94331428eb4db0a2c68a9b6c1763b8624dab259b0876cdcfaeacc17b21a18e3fc010a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 99, - "comment" : "Random test failure 21", - "msg" : "5ffa", - "sig" : "931e5152fcef078c22cc5d6a3a65f06e396289f6f5f2d1efa6340254a53526ef5dc6874eeddf35c3f50991c53cd02bf06313e37d93ee1f7022128ffa3b8f300b", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10", - "sk" : "b7d2f64276df417fed27d8e15b4e90f6fd93dace707294c338bd32bc4bbd8fdb", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAz9pbiZ41dkxSKeWSlf4SIrfdzhdmQ2l8KeRuy7oQzxA=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 100, - "comment" : "Random test failure 7", - "msg" : "ec5c7cb078", - "sig" : "30490c28f806298225df62103521dcee047153912c33ab8ab8bbdd1ffabd70fd4fdb360f05be535b067d1cf4e78c2cb432206bf280aab3bd21aaa1cb894c5b06", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 101, - "comment" : "Random test failure 9", - "msg" : "67484059b2490b1a0a4f8dee77979e26", - "sig" : "4cd4f77ed473a6647387f3163541c67a1708a3c3bd1673247cb87f0cb68b3c56f04bfa72970c8a483efe659c87009ab4020b590b6641316b3deddb5450544e02", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 102, - "comment" : "Random test failure 11", - "msg" : "a020a4381dc9141f47ee508871ab7a8b5a3648727c4281ae9932376f23a8e1bcda0626b7129197d864178631ec89c4332dbb18", - "sig" : "1e41a24fe732bd7cab14c2a2f5134ee8c87fcbd2e987e60957ed9239e5c32404d56977e1b4282871896cb10625a1937468e4dc266e16a9c1b8e9891177eca802", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 103, - "comment" : "Random test failure 14", - "msg" : "a25176b3afea318b2ec11ddacb10caf7179c0b3f8eabbfa2895581138d3c1e0e", - "sig" : "2a833aadecd9f28235cb5896bf3781521dc71f28af2e91dbe1735a61dce3e31ac15ca24b3fc47817a59d386bbbb2ce60a6adc0a2703bb2bdea8f70f91051f706", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 104, - "comment" : "Random test failure 18", - "msg" : "a9e6d94870a67a9fe1cf13b1e6f9150cdd407bf6480ec841ea586ae3935e9787163cf419c1", - "sig" : "c97e3190f83bae7729ba473ad46b420b8aad735f0808ea42c0f898ccfe6addd4fd9d9fa3355d5e67ee21ab7e1f805cd07f1fce980e307f4d7ad36cc924eef00c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56", - "sk" : "7d597c3b7283929d07ed8f01f31d2596823e5e46ab226c7be4234d1a9dcaef37", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAUpkZyceAmFqEHEK6bBgP8tZ6J2zPvigQgOR6txp1j1Y=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 105, - "comment" : "Random test failure 13", - "msg" : "e1cbf2d86827825613fb7a85811d", - "sig" : "01abfa4d6bbc726b196928ec84fd03f0c953a4fa2b228249562ff1442a4f63a7150b064f3712b51c2af768d2c2711a71aabf8d186833e941a0301b82f0502905", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 106, - "comment" : "Random test failure 22", - "msg" : "25", - "sig" : "e4ae21f7a8f4b3b325c161a8c6e53e2edd7005b9c2f8a2e3b0ac4ba94aa80be6f2ee22ac8d4a96b9a3eb73a825e7bb5aff4a3393bf5b4a38119e9c9b1b041106", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1", - "sk" : "f401cee4bfb1732f0e9b8d8ba79469565c3115296141dbdf7e9c311a0ac1823b", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321002252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAIlKz1Xx0y/i8Rg3C4IKEeSa8Ai8Jq2rpV1Y2K/0RZ8E=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 107, - "comment" : "Random test failure 16", - "msg" : "975ef941710071a9e1e6325a0c860becd7c695b5117c3107b686e330e5", - "sig" : "af0fd9dda7e03e12313410d8d8844ebb6fe6b7f65141f22d7bcba5695a25414a9e54326fb44d59fb14707899a8aae70857b23d4080d7ab2c396ef3a36d45ce02", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 108, - "comment" : "Random test failure 23", - "msg" : "80fdd6218f29c8c8f6bd820945f9b0854e3a8824", - "sig" : "e097e0bd0370bff5bde359175a11b728ee9639095d5df8eda496395565616edfe079977f7d4dc8c75d6113a83d6a55e6e1676408c0967a2906339b43337dcb01", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a", - "sk" : "3d658956410377d0644676d2599542412a4f3b0e4eadfb7f3f836615f42b18bc", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b6570032100c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwKdzEQ+XXeNzI1W7fsfwxBwJHAJSlmBwIFUWaTuZKko=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 109, - "comment" : "Random test failure 17", - "msg" : "", - "sig" : "0280427e713378f49d478df6373c6cac847b622b567daa2376c839e7ac10e22c380ab0fa8617c9dcfe76c4d9db5459b21dc1413726e46cc8f387d359e344f407", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "54cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311", - "sk" : "bccb61323840c2a96fc36f7e54ea6c8e55f9d221f7f05791ed60025e06064439", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b657003210054cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAVM2mIyRXWa1tQ+YgpgaQi+/GM9YHkrx3mER6DvOOcxE=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 110, - "comment" : "Random test failure 26", - "msg" : "27e792b28b2f1702", - "sig" : "14d9b497c19b91d43481c55bb6f5056de252d9ecb637575c807e58e9b4c5eac8b284089d97e2192dc242014363208e2c9a3435edf8928fb1d893553e9be4c703", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "edwards25519", - "keySize" : 255, - "pk" : "2362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe", - "sk" : "f2d3023b9c19e241748bc4039a7a43c595701f23675505015213a8a2a0274c1b", - "type" : "EDDSAKeyPair" - }, - "keyDer" : "302a300506032b65700321002362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI2K6xRTV+tM4AmQul5oegt5utvG8v2pbME8rsCueV/4=\n-----END PUBLIC KEY-----\n", - "type" : "EDDSAVer", - "tests" : [ - { - "tcId" : 111, - "comment" : "Random test failure 27", - "msg" : "eef3bb0f617c17d0420c115c21c28e3762edc7b7fb048529b84a9c2bc6", - "sig" : "242ddb3a5d938d07af690b1b0ef0fa75842c5f9549bf39c8750f75614c712e7cbaf2e37cc0799db38b858d41aec5b9dd2fca6a3c8e082c10408e2cf3932b9d08", - "result" : "valid", - "flags" : [] - } - ] - } - ] -})abcd"; -} diff --git a/submodules/ton/tonlib-src/crypto/tl/boc.tlb b/submodules/ton/tonlib-src/crypto/tl/boc.tlb deleted file mode 100644 index d283c78c..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/boc.tlb +++ /dev/null @@ -1,46 +0,0 @@ -// -// Bag-of-Cells (BoC) serialization formats -// - -serialized_boc_idx#68ff65f3 size:(## 8) { size <= 4 } - off_bytes:(## 8) { off_bytes <= 8 } - cells:(##(size * 8)) - roots:(##(size * 8)) { roots = 1 } - absent:(##(size * 8)) { roots + absent <= cells } - tot_cells_size:(##(off_bytes * 8)) - index:(cells * ##(off_bytes * 8)) - cell_data:(tot_cells_size * [ uint8 ]) - = BagOfCells; - -serialized_boc_idx_crc32c#acc3a728 size:(## 8) { size <= 4 } - off_bytes:(## 8) { off_bytes <= 8 } - cells:(##(size * 8)) - roots:(##(size * 8)) { roots = 1 } - absent:(##(size * 8)) { roots + absent <= cells } - tot_cells_size:(##(off_bytes * 8)) - index:(cells * ##(off_bytes * 8)) - cell_data:(tot_cells_size * [ uint8 ]) - crc32c:uint32 = BagOfCells; - -serialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1) - has_cache_bits:(## 1) flags:(## 2) { flags = 0 } - size:(## 3) { size <= 4 } - off_bytes:(## 8) { off_bytes <= 8 } - cells:(##(size * 8)) - roots:(##(size * 8)) { roots >= 1 } - absent:(##(size * 8)) { roots + absent <= cells } - tot_cells_size:(##(off_bytes * 8)) - root_list:(roots * ##(size * 8)) - index:has_idx?(cells * ##(off_bytes * 8)) - cell_data:(tot_cells_size * [ uint8 ]) - crc32c:has_crc32c?uint32 - = BagOfCells; - -compiled_smart_contract - compiled_at:uint32 code:^Cell data:^Cell - description:(Maybe ^TinyString) - ^[ source_file:(Maybe ^TinyString) - compiler_version:(Maybe ^TinyString) ] - = CompiledSmartContract; - -tiny_string#_ len:(#<= 126) str:(len * [ uint8 ]) = TinyString; diff --git a/submodules/ton/tonlib-src/crypto/tl/hashmap.tlb b/submodules/ton/tonlib-src/crypto/tl/hashmap.tlb deleted file mode 100644 index 0ec55a65..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/hashmap.tlb +++ /dev/null @@ -1,60 +0,0 @@ -bit#_ _:(## 1) = Bit; - -// ordinary Hashmap / HashmapE, with fixed length keys -// -hm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X; - -hmn_leaf#_ {X:Type} value:X = HashmapNode 0 X; -hmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X) - right:^(Hashmap n X) = HashmapNode (n + 1) X; - -hml_short$0 {m:#} {n:#} len:(Unary ~n) s:(n * Bit) = HmLabel ~n m; -hml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m; -hml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m; - -unary_zero$0 = Unary ~0; -unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1); - -hme_empty$0 {n:#} {X:Type} = HashmapE n X; -hme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X; - -true#_ = True; -_ {n:#} _:(Hashmap n True) = BitstringSet n; - - -// VarHashmap / VarHashmapE, with variable-length keys -// -vhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(VarHashmapNode m X) - = VarHashmap n X; -vhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X; -vhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X) - right:^(VarHashmap n X) value:(Maybe X) - = VarHashmapNode (n + 1) X; -vhmn_cont$1 {n:#} {X:Type} branch:Bit child:^(VarHashmap n X) - value:X = VarHashmapNode (n + 1) X; - -nothing$0 {X:Type} = Maybe X; -just$1 {X:Type} value:X = Maybe X; - -vhme_empty$0 {n:#} {X:Type} = VarHashmapE n X; -vhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X) - = VarHashmapE n X; - -// -// PfxHashmap / PfxHashmapE, with variable-length keys -// constituting a prefix code -// - -phm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) - {n = (~m) + l} node:(PfxHashmapNode m X) - = PfxHashmap n X; - -phmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X; -phmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X) - right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X; - -phme_empty$0 {n:#} {X:Type} = PfxHashmapE n X; -phme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X) - = PfxHashmapE n X; diff --git a/submodules/ton/tonlib-src/crypto/tl/tlbc-aux.h b/submodules/ton/tonlib-src/crypto/tl/tlbc-aux.h deleted file mode 100644 index 97e5082e..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlbc-aux.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include -#include - -namespace tlbc { - -static constexpr unsigned long long All = 1ULL << 63; - -struct BitPfxCollection { - std::vector pfx; - void clear() { - pfx.clear(); - } - void all() { - pfx.clear(); - pfx.push_back(All); - } - BitPfxCollection() = default; - BitPfxCollection(unsigned long long one_pfx) { - if (one_pfx) { - pfx.push_back(one_pfx); - } - } - bool empty() const { - return pfx.empty(); - } - unsigned long long min() const { - return pfx.empty() ? 0 : pfx[0]; - } - bool is_all() const { - return pfx.size() == 1 && pfx[0] == All; - } - BitPfxCollection& operator*=(unsigned long long prepend); - BitPfxCollection operator*(unsigned long long prepend) const; - BitPfxCollection operator+(const BitPfxCollection& other) const; - bool operator+=(const BitPfxCollection& other); - bool operator==(const BitPfxCollection& other) const { - return pfx == other.pfx; - } - bool operator!=(const BitPfxCollection& other) const { - return pfx != other.pfx; - } - void merge_back(unsigned long long z); - void show(std::ostream& os) const; -}; - -std::ostream& operator<<(std::ostream& os, const BitPfxCollection& p); - -struct AdmissibilityInfo { - enum { side = 4 }; - std::vector info; - int dim; - AdmissibilityInfo() : info(1, false), dim(0) { - } - void extend(int dim1); - bool operator[](std::size_t i) { - return info[i & (info.size() - 1)]; - } - void operator|=(const AdmissibilityInfo& other); - void set_all(bool val = true); - void clear_all() { - set_all(false); - } - void set_by_pattern(int pdim, int pattern[]); - void show(std::ostream& os) const; - bool is_set_all() const { - return !dim && info[0]; - } - bool extract1(char A[side], char tag, int p1) const; - bool extract2(char A[side][side], char tag, int p1, int p2) const; - bool extract3(char A[side][side][side], char tag, int p1, int p2, int p3) const; - int conflicts_at(const AdmissibilityInfo& other) const; - bool conflicts_with(const AdmissibilityInfo& other) const { - return conflicts_at(other) >= 0; - } -}; - -std::ostream& operator<<(std::ostream& os, const AdmissibilityInfo& p); - -struct ConflictSet { - unsigned long long x; - explicit ConflictSet(unsigned long long _x = 0) : x(_x) { - } - bool operator[](int i) const { - return (x >> i) & 1; - } - ConflictSet& operator|=(ConflictSet other) { - x |= other.x; - return *this; - } - int size() const { - return td::count_bits64(x); - } - int min() const { - return x ? td::count_trailing_zeroes_non_zero64(x) : 0x7fffffff; - } - int max() const { - return x ? 63 - td::count_leading_zeroes_non_zero64(x) : -1; - } - void remove(int i) { - x &= ~(1ULL << i); - } - void insert(int i) { - x |= (1ULL << i); - } -}; - -struct ConflictGraph { - std::array g; - ConflictSet& operator[](int i) { - return g[i]; - } - const ConflictSet& operator[](int i) const { - return g[i]; - } - void set_clique(ConflictSet set); -}; - -struct BinTrie { - std::unique_ptr left, right; - unsigned long long tag, down_tag; - int useful_depth; - BinTrie(unsigned long long _tag = 0, std::unique_ptr _left = {}, std::unique_ptr _right = {}) - : left(std::move(_left)), right(std::move(_right)), tag(_tag), down_tag(0), useful_depth(0) { - } - void ins_path(unsigned long long path, unsigned long long new_tag); - unsigned long long lookup_tag(unsigned long long path) const; - const BinTrie* lookup_node_const(unsigned long long path) const; - BinTrie* lookup_node(unsigned long long path); - bool is_unique() const { - return !(down_tag & (down_tag - 1)); - } - int unique_value() const { - return down_tag ? td::count_trailing_zeroes_non_zero64(down_tag) : -1; - } - static std::unique_ptr insert_path(std::unique_ptr root, unsigned long long path, - unsigned long long tag); - static std::unique_ptr insert_paths(std::unique_ptr root, const BitPfxCollection& paths, - unsigned long long tag); - void set_conflict_graph(ConflictGraph& gr, unsigned long long colors = 0) const; - int compute_useful_depth(unsigned long long colors = 0); - unsigned long long find_conflict_path(unsigned long long colors = 0, unsigned long long mask = ~0ULL) const; - unsigned long long build_submap_at(int depth, unsigned long long A[], unsigned long long pfx) const; - unsigned long long build_submap(int depth, unsigned long long A[]) const; - void show(std::ostream& os, unsigned long long pfx = 1ULL << 63) const; -}; - -std::ostream& operator<<(std::ostream& os, const BinTrie& bt); - -struct MinMaxSize { - enum : unsigned long long { Any = 0x7ff07, OneRef = 0x100000001ULL, Impossible = (0x7ff07ULL << 32) }; - unsigned long long minmax_size; - unsigned min_size() const { - return (unsigned)(minmax_size >> 32); - } - unsigned max_size() const { - return (unsigned)(minmax_size & 0xffffffff); - } - unsigned long long get() const { - return minmax_size; - } - bool is_fixed() const { - return min_size() == max_size(); - } - int fixed_bit_size() const { - return is_fixed() && !(min_size() & 0xff) ? (min_size() >> 8) : -1; - } - bool fits_into_cell() const { - return !((0x3ff04 - min_size()) & 0x80000080U); - } - bool is_possible() const { - return !((max_size() - min_size()) & 0x80000080U); - } - void normalize(); - MinMaxSize& clear() { - minmax_size = 0; - return *this; - } - MinMaxSize& clear_min() { - minmax_size &= (1ULL << 32) - 1; - return *this; - } - MinMaxSize& infinite_max() { - minmax_size |= 0x3ff07; - return *this; - } - MinMaxSize(unsigned long long _size = Impossible, bool _normalize = false) : minmax_size(_size) { - if (_normalize) { - normalize(); - } - } - static unsigned convert_size(unsigned z) { - return ((z & 0xff) << 16) | (z >> 8); - } - unsigned convert_min_size() const { - return convert_size(min_size()); - } - unsigned convert_max_size() const { - return convert_size(max_size()); - } - MinMaxSize operator+(MinMaxSize y) { - return MinMaxSize(get() + y.get(), true); - } - MinMaxSize& operator+=(MinMaxSize y) { - minmax_size += y.get(); - normalize(); - return *this; - } - MinMaxSize& operator|=(MinMaxSize y); - bool operator==(MinMaxSize y) { - return get() == y.get(); - } - bool operator!=(MinMaxSize y) { - return get() != y.get(); - } - MinMaxSize& repeat(int count); - MinMaxSize& repeat_at_least(int count); - static MinMaxSize fixed_size(unsigned sz) { - return MinMaxSize(sz * 0x10000000100ULL); - } - static MinMaxSize size_range(unsigned min_sz, unsigned max_sz) { - return MinMaxSize((((unsigned long long)min_sz << 32) + max_sz) << 8); - } - void show(std::ostream& os) const; - struct unpacked { - unsigned min_bits, min_refs, max_bits, max_refs; - unpacked(MinMaxSize val); - MinMaxSize pack() const; - void show(std::ostream& os) const; - }; - - private: - void nrm(unsigned long long a, unsigned long long b) { - if (minmax_size & a) { - minmax_size = (minmax_size | (a | b)) - a; - } - } -}; - -std::ostream& operator<<(std::ostream& os, MinMaxSize t); - -} // namespace tlbc diff --git a/submodules/ton/tonlib-src/crypto/tl/tlbc-data.h b/submodules/ton/tonlib-src/crypto/tl/tlbc-data.h deleted file mode 100644 index 8b6f2392..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlbc-data.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include "common/linalloc.hpp" - -namespace tlbc { - -using src::Lexem; -using src::Lexer; -using sym::sym_idx_t; - -extern td::LinearAllocator AR; - -struct Type; -struct Constructor; - -struct TypeExpr { - enum { - te_Unknown, - te_Type, - te_Param, - te_Apply, - te_Add, - te_GetBit, - te_MulConst, - te_IntConst, - te_Tuple, - te_Ref, - te_CondType - }; - enum { max_const_expr = 100000, const_htable_size = 170239 }; - int tp; - int value; - Type* type_applied; - bool is_nat; // we keep integer expressions in 'TypeExpr' as well - bool is_nat_subtype; // this is # or a subtype of # - bool negated; // is it linearly negative - bool tchk_only; // type to be used as RHS of : only - int is_constexpr; // if non-zero, it is an index in `const_type_expr`, the table of all constant type expressions - src::SrcLocation where; - std::vector args; - TypeExpr(const src::SrcLocation& loc, int _tp, int _value = 0, bool _pol = false) - : tp(_tp) - , value(_value) - , type_applied(nullptr) - , is_nat_subtype(false) - , negated(_pol) - , tchk_only(false) - , is_constexpr(0) - , where(loc) { - init_is_nat(); - } - TypeExpr(const src::SrcLocation& loc, int _tp, int _value, std::initializer_list _arglist, - bool _pol = false) - : tp(_tp) - , value(_value) - , type_applied(nullptr) - , is_nat_subtype(false) - , negated(_pol) - , tchk_only(false) - , is_constexpr(0) - , where(loc) - , args(std::move(_arglist)) { - init_is_nat(); - } - TypeExpr(const src::SrcLocation& loc, int _tp, int _value, std::vector _arglist, bool _pol = false) - : tp(_tp) - , value(_value) - , type_applied(nullptr) - , is_nat_subtype(false) - , negated(_pol) - , tchk_only(false) - , is_constexpr(0) - , where(loc) - , args(std::move(_arglist)) { - init_is_nat(); - } - void check_mode(const src::SrcLocation& loc, int mode); - bool no_tchk() const; - bool close(const src::SrcLocation& loc); - bool bind_value(bool value_negated, Constructor& cs, bool checking_type = false); - int abstract_interpret_nat() const; - MinMaxSize compute_size() const; - bool compute_any_bits() const; - bool detect_constexpr(); - int is_integer() const; - bool is_anon() const; - bool is_ref_to_anon() const; - bool equal(const TypeExpr& other) const; - void const_type_name(std::ostream& os) const; - static TypeExpr* mk_intconst(const src::SrcLocation& loc, std::string int_const); - static TypeExpr* mk_intconst(const src::SrcLocation& loc, unsigned int_const); - static TypeExpr* mk_apply_gen(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2); - static TypeExpr* mk_mulint(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2); - static TypeExpr* mk_cellref(const src::SrcLocation& loc, TypeExpr* expr1); - static TypeExpr* mk_apply(const src::SrcLocation& loc, int tp, TypeExpr* expr1, TypeExpr* expr2); - static TypeExpr* mk_apply_empty(const src::SrcLocation& loc, sym_idx_t name, Type* type_applied); - void show(std::ostream& os, const Constructor* cs = nullptr, int prio = 0, int mode = 0) const; - - private: - void init_is_nat() { - is_nat = (tp >= te_Add && tp <= te_IntConst); - } - unsigned long long compute_hash() const; - static TypeExpr* const_htable[const_htable_size]; -}; - -// extern TypeExpr* TypeExpr::const_htable[TypeExpr::const_htable_size]; -extern TypeExpr* const_type_expr[TypeExpr::max_const_expr]; -extern int const_type_expr_num; - -std::ostream& operator<<(std::ostream& os, const TypeExpr* te); - -struct Field { - int field_idx; - bool implicit; - bool known; - bool constraint; - bool used; - bool subrec; - sym_idx_t name; - TypeExpr* type; - const src::SrcLocation loc; - Field(const src::SrcLocation& where, bool impl, int idx, sym_idx_t fname = 0, TypeExpr* ftype = nullptr) - : field_idx(idx) - , implicit(impl) - , known(false) - , constraint(false) - , used(false) - , subrec(false) - , name(fname) - , type(ftype) - , loc(where) { - } - void register_sym() const; - std::string get_name() const; - bool isomorphic_to(const Field& f, bool allow_other_names = true) const; -}; - -struct Constructor { - sym_idx_t constr_name; - sym_idx_t type_name; - Type* type_defined; - src::SrcLocation where; - unsigned long long tag; - int tag_bits; - int fields_num; - int type_arity; - bool is_fwd; - bool is_enum; - bool is_simple_enum; - bool is_special; - bool has_fixed_size; - bool any_bits; - MinMaxSize size; - BitPfxCollection begins_with; - std::vector fields; - std::vector params; - std::vector param_negated; - std::vector param_const_val; // -1 -- not integer or not constant - AdmissibilityInfo admissible_params; - void set_tag(unsigned long long new_tag) { - tag = new_tag; - tag_bits = (tag ? 63 - td::count_trailing_zeroes_non_zero64(tag) : -1); - } - Constructor(const src::SrcLocation& _loc = {}, sym_idx_t cname = 0, sym_idx_t tname = 0, unsigned long long _tag = 0, - Type* type = nullptr) - : constr_name(cname) - , type_name(tname) - , type_defined(type) - , where(_loc) - , fields_num(0) - , type_arity(0) - , is_fwd(false) - , is_enum(false) - , is_simple_enum(false) - , is_special(false) - , has_fixed_size(false) - , any_bits(false) { - set_tag(_tag); - } - Field& new_field(const src::SrcLocation& where, bool implicit, sym_idx_t name); - void show(std::ostream& os, int mode = 0) const; - std::string get_name() const; - std::string get_qualified_name() const; - bool isomorphic_to(const Constructor& cs, bool allow_other_names) const; - unsigned long long compute_tag() const; - void check_assign_tag(); - bool compute_is_fwd(); - bool recompute_begins_with(); - bool recompute_minmax_size(); - bool recompute_any_bits(); - bool compute_admissible_params(); - int get_const_param(unsigned idx) const { - return idx < param_const_val.size() ? param_const_val[idx] : -1; - } -}; - -std::ostream& operator<<(std::ostream& os, const Constructor& cs); - -struct Type { - enum { _IsType = 1, _IsNat = 2, _IsPos = 4, _IsNeg = 8, _NonConst = 16 }; - sym_idx_t type_name; - int type_idx; - int parent_type_idx; - int constr_num; - int arity; - int used; - int last_declared; - static int last_declared_counter; - bool produces_nat; - bool is_final; - bool is_builtin; - bool is_enum; - bool is_simple_enum; - bool is_special; - bool is_pfx_determ; - bool is_param_determ; - bool is_const_param_determ; - bool is_const_param_pfx_determ; - bool is_param_pfx_determ; - bool is_determ; - bool has_fixed_size; - bool any_bits; - bool is_auto; - bool is_anon; - bool is_unit; - bool is_bool; - signed char is_integer; - int useful_depth; - int const_param_idx; - int conflict1, conflict2; - MinMaxSize size; - std::vector constructors; - std::vector args; - BitPfxCollection begins_with; - AdmissibilityInfo admissible_params; - std::unique_ptr cs_trie; - - Type(int idx, sym_idx_t _tname = 0, bool pnat = false, int _arity = -1, bool _final = false, bool _nonempty = false) - : type_name(_tname) - , type_idx(idx) - , parent_type_idx(-1) - , constr_num(0) - , arity(_arity) - , used(0) - , last_declared(0) - , produces_nat(pnat) - , is_final(_final) - , is_builtin(_final) - , is_enum(!_final) - , is_simple_enum(!_final) - , is_special(false) - , is_pfx_determ(false) - , is_param_determ(false) - , is_const_param_determ(false) - , is_const_param_pfx_determ(false) - , is_param_pfx_determ(false) - , is_determ(false) - , has_fixed_size(false) - , any_bits(false) - , is_auto(false) - , is_anon(false) - , is_unit(false) - , is_bool(false) - , is_integer(pnat) - , useful_depth(-1) - , const_param_idx(-1) - , conflict1(-1) - , conflict2(-1) { - if (arity > 0) { - args.resize(arity, 0); - } - if (_nonempty) { - begins_with.all(); - } - } - void bind_constructor(const src::SrcLocation& loc, Constructor* cs); - bool unique_constructor_equals(const Constructor& cs, bool allow_other_names = false) const; - void print_name(std::ostream& os) const; - std::string get_name() const; - bool recompute_begins_with(); - bool recompute_minmax_size(); - bool recompute_any_bits(); - bool compute_admissible_params(); - void compute_constructor_trie(); - int detect_const_params(); - bool check_conflicts(); - void show_constructor_conflict(); - void detect_basic_types(); - bool cons_all_exact() const; - int cons_common_len() const; - bool is_const_arg(int p) const; - std::vector get_all_param_values(int p) const; - std::vector get_constr_by_param_value(int p, int pv) const; - void renew_last_declared() { - last_declared = ++last_declared_counter; - } -}; - -extern TypeExpr type_Type; - -struct SymVal : sym::SymValBase { - TypeExpr* sym_type; - SymVal(int _type, int _idx, TypeExpr* _stype = nullptr) : sym::SymValBase(_type, _idx), sym_type(_stype) { - } - TypeExpr* get_type() const { - return sym_type; - } -}; - -struct SymValType : SymVal { - Type* type_ref; - explicit SymValType(Type* _type = nullptr) : SymVal(sym::SymValBase::_Typename, 0, &type_Type), type_ref(_type) { - } -}; - -extern sym_idx_t Nat_name, Eq_name, Less_name, Leq_name; -extern Type *Nat_type, *Eq_type; -extern Type *NatWidth_type, *NatLess_type, *NatLeq_type, *Int_type, *UInt_type; - -extern int types_num, builtin_types_num; -extern std::vector types; - -} // namespace tlbc diff --git a/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.cpp b/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.cpp deleted file mode 100644 index dedec15d..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.cpp +++ /dev/null @@ -1,3465 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tlbc-gen-cpp.h" -#include "td/utils/bits.h" -#include "td/utils/filesystem.h" - -namespace tlbc { - -/* - * - * C++ CODE GENERATION - * - */ - -CppIdentSet global_cpp_ids; - -std::vector> cpp_type; - -bool add_type_members; - -std::set forbidden_cpp_idents, local_forbidden_cpp_idents; -std::vector const_type_expr_cpp_idents; -std::vector const_type_expr_simple; - -void init_forbidden_cpp_idents() { - std::set& f = forbidden_cpp_idents; - f.insert("true"); - f.insert("false"); - f.insert("int"); - f.insert("bool"); - f.insert("unsigned"); - f.insert("long"); - f.insert("short"); - f.insert("char"); - f.insert("void"); - f.insert("class"); - f.insert("struct"); - f.insert("enum"); - f.insert("union"); - f.insert("public"); - f.insert("private"); - f.insert("protected"); - f.insert("extern"); - f.insert("static"); - f.insert("final"); - f.insert("if"); - f.insert("else"); - f.insert("while"); - f.insert("do"); - f.insert("for"); - f.insert("break"); - f.insert("continue"); - f.insert("return"); - f.insert("virtual"); - f.insert("explicit"); - f.insert("override"); - f.insert("new"); - f.insert("delete"); - f.insert("operator"); - f.insert("Ref"); - f.insert("Cell"); - f.insert("CellSlice"); - f.insert("Anything"); - f.insert("RefAnything"); - f.insert("Nat"); - f.insert("t_Nat"); - f.insert("t_RefCell"); - f.insert("t_Anything"); - f.insert("TLB"); - f.insert("TLB_Complex"); - f.insert("PrettyPrinter"); - std::set& l = local_forbidden_cpp_idents; - l.insert("cons_len"); - l.insert("cons_len_exact"); - l.insert("cons_tag"); - l.insert("skip"); - l.insert("validate_skip"); - l.insert("get_size"); - l.insert("pack"); - l.insert("unpack"); - l.insert("ops"); - l.insert("cs"); - l.insert("cb"); - l.insert("cell_ref"); - l.insert("type_class"); - l.insert("pp"); - l.insert("weak"); -} - -std::string CppIdentSet::compute_cpp_ident(std::string orig_ident, int count) { - std::ostringstream os; - int a, r = 0, cnt = 0; - bool prev_skip = false; - for (int c : orig_ident) { - bool pp = prev_skip; - prev_skip = true; - if (c & 0x80) { - if ((c & 0xe0) == 0xc0) { - a = (c & 0x1f); - r = 1; - continue; - } else if ((c & 0xf0) == 0xe0) { - a = (c & 0x0f); - r = 2; - continue; - } - if ((c & 0xc0) != 0x80) { - continue; - } - if (!r) { - continue; - } - a = (a << 6) | (c & 0x3f); - if (--r) { - continue; - } - c = a; - } - prev_skip = false; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') { - os << (char)c; - cnt++; - continue; - } - if (c >= '0' && c <= '9') { - if (!cnt) { - os << '_'; - cnt++; - } - os << (char)c; - cnt++; - continue; - } - if (c >= 0x410 && c < 0x450) { - os << (char)(0xc0 + (c >> 6)) << (char)(0x80 + (c & 0x3f)); - cnt++; - continue; - } - prev_skip = true; - if (!pp) { - os << '_'; - } - } - if (!cnt) { - os << '_'; - prev_skip = true; - } - if (count) { - os << count; - } - return os.str(); -} - -bool CppIdentSet::is_good_ident(std::string ident) { - return !defined(ident) && !forbidden_cpp_idents.count(ident) && - !(extra_forbidden_idents && extra_forbidden_idents->count(ident)); -} - -std::string CppIdentSet::new_ident(std::string orig_ident, int count, std::string suffix) { - while (true) { - std::string ident = compute_cpp_ident(orig_ident, count) + suffix; - if (is_good_ident(ident)) { - cpp_idents.insert(ident); - return ident; - } - ++count; - } -} - -struct SizeWriter { - int sz; - explicit SizeWriter(int _sz) : sz(_sz) { - } - void write(std::ostream& os) const; -}; - -void SizeWriter::write(std::ostream& os) const { - if (sz < 0x10000) { - os << sz; - } else { - os << "0x" << std::hex << sz << std::dec; - } -} - -std::ostream& operator<<(std::ostream& os, SizeWriter w) { - w.write(os); - return os; -} - -unsigned long long CppTypeCode::compute_selector_mask() const { - unsigned long long z = 0, w = 1; - int c = 0; - for (int v : cons_tag_map) { - if (v > c) { - c = v; - z |= w; - } - w <<= 1; - } - return z; -} - -struct HexConstWriter { - unsigned long long mask; - explicit HexConstWriter(unsigned long long _mask) : mask(_mask){}; - void write(std::ostream& os) const; -}; - -void HexConstWriter::write(std::ostream& os) const { - if (mask < 32) { - os << mask; - } else { - os << "0x" << std::hex << mask << std::dec; - } - if (mask >= (1ULL << 31)) { - os << (mask >= (1ULL << 32) ? "ULL" : "U"); - } -} - -std::ostream& operator<<(std::ostream& os, HexConstWriter w) { - w.write(os); - return os; -} - -cpp_val_type detect_cpp_type(const TypeExpr* expr) { - if (expr->tp == TypeExpr::te_Ref) { - return ct_cell; - } - if (expr->is_nat) { - return ct_int32; - } - MinMaxSize sz = expr->compute_size(); - int l = sz.fixed_bit_size(); - if (expr->is_nat_subtype) { - return l == 1 ? ct_bool : ct_int32; - } - if (expr->tp == TypeExpr::te_CondType) { - cpp_val_type subtype = detect_cpp_type(expr->args.at(1)); - if (subtype == ct_slice || subtype == ct_cell || subtype == ct_integer || subtype == ct_bitstring || - subtype == ct_enum) { - return subtype; - } - if ((subtype == ct_int32 || subtype == ct_int64) && expr->args[1]->is_integer() > 0) { - return subtype; - } - return ct_slice; - } - int x = expr->is_integer(); - if (sz.max_size() & 0xff) { - return ct_slice; - } - if (!x) { - const Type* ta = expr->type_applied; - if (expr->tp == TypeExpr::te_Apply && ta && ta->is_simple_enum) { - return ct_enum; - } - if (expr->tp == TypeExpr::te_Apply && ta && ta->type_idx < builtin_types_num && - (ta == Bits_type || ta->get_name().at(0) == 'b')) { - return (l >= 0 && l <= 256) ? ct_bits : ct_bitstring; - } - if (expr->tp == TypeExpr::te_Tuple && expr->args[1]->tp == TypeExpr::te_Apply && - expr->args[1]->type_applied->is_bool) { - return (l >= 0 && l <= 256) ? ct_bits : ct_bitstring; - } - return ct_slice; - } - l = (sz.max_size() >> 8); - if (x > 0 && l == 1) { - return ct_bool; - } - if (l < 32) { - return ct_int32; - } - if (l == 32) { - return (x < 0 ? ct_int32 : ct_uint32); - } - if (l < 64) { - return ct_int64; - } - if (l == 64) { - return (x < 0 ? ct_int64 : ct_uint64); - } - return ct_integer; -} - -cpp_val_type detect_field_cpp_type(const Field& field) { - return field.subrec ? ct_subrecord : detect_cpp_type(field.type); -} - -void show_valtype(std::ostream& os, cpp_val_type x, int size = -1, bool pass_value = false) { - switch (x) { - case ct_void: - os << "void"; - break; - case ct_slice: - os << "Ref"; - break; - case ct_cell: - os << "Ref"; - break; - case ct_typeptr: - os << "const TLB*"; - break; - case ct_typeref: - os << "const TLB&"; - break; - case ct_bitstring: - os << "Ref"; - break; - case ct_bits: - if (pass_value) { - os << "const "; - } - os << "td::BitArray<" << size << ">"; - if (pass_value) { - os << "&"; - } - break; - case ct_integer: - os << "RefInt256"; - break; - case ct_bool: - os << "bool"; - break; - case ct_enum: - os << "char"; - break; - case ct_int32: - os << "int"; - break; - case ct_uint32: - os << "unsigned"; - break; - case ct_int64: - os << "long long"; - break; - case ct_uint64: - os << "unsigned long long"; - break; - case ct_subrecord: - if (pass_value) { - os << "const "; - } - os << "::Record"; - if (pass_value) { - os << "&"; - } - break; - default: - os << ""; - } -} - -bool CppValType::needs_move() const { - return (vt == ct_cell || vt == ct_slice || vt == ct_bitstring || vt == ct_integer); -} - -void CppValType::show(std::ostream& os, bool pass_value) const { - show_valtype(os, vt, size, pass_value); -} - -std::ostream& operator<<(std::ostream& os, CppValType cvt) { - cvt.show(os); - return os; -} - -void CppTypeCode::ConsField::print_type(std::ostream& os, bool pass_value) const { - if (ctype != ct_subrecord) { - get_cvt().show(os, pass_value); - } else { - assert(subrec); - if (pass_value) { - os << "const "; - } - subrec->print_full_name(os); - if (pass_value) { - os << "&"; - } - } -} - -void CppTypeCode::ConsRecord::print_full_name(std::ostream& os) const { - os << cpp_type.cpp_type_class_name << "::" << cpp_name; -} - -void CppTypeCode::assign_class_name() { - std::string type_name = type.get_name(); - sym_idx_t name = type.type_name; - if (!name && type.parent_type_idx >= 0) { - int i = type.parent_type_idx; - while (true) { - name = types.at(i).type_name; - if (name || types.at(i).parent_type_idx < 0) { - break; - } - i = types.at(i).parent_type_idx; - } - if (name) { - type_name = sym::symbols.get_name(name) + "_aux"; - } - } - cpp_type_class_name = global_cpp_ids.new_ident(type_name); - if (params) { - cpp_type_template_name = global_cpp_ids.new_ident(cpp_type_class_name + "T"); - } else { - cpp_type_var_name = global_cpp_ids.new_ident(std::string{"t_"} + cpp_type_class_name); - } -} - -void CppTypeCode::assign_cons_names() { - cons_enum_name.resize(cons_num); - for (int i = 0; i < cons_num; i++) { - sym_idx_t cons = type.constructors.at(i)->constr_name; - if (cons) { - cons_enum_name[i] = local_cpp_ids.new_ident(sym::symbols.get_name(cons)); - } else if (type.const_param_idx >= 0) { - int pv = type.constructors[i]->get_const_param(type.const_param_idx); - cons_enum_name[i] = local_cpp_ids.new_ident(pv ? "cons" : "cons0", pv); - } else { - cons_enum_name[i] = local_cpp_ids.new_ident("cons", i + 1); - } - } -} - -void CppTypeCode::assign_cons_values() { - std::vector> a; - a.reserve(cons_num); - for (int i = 0; i < cons_num; i++) { - a.emplace_back(type.constructors[i]->begins_with.min(), i); - } - std::sort(a.begin(), a.end()); - cons_enum_value.resize(cons_num); - cons_idx_by_enum.resize(cons_num); - int i = 0; - for (auto z : a) { - cons_enum_value[z.second] = i; - cons_idx_by_enum[i++] = z.second; - } -} - -std::vector std_field_names = {"x", "y", "z", "t", "u", "v", "w"}; - -void CppTypeCode::assign_record_cons_names() { - for (int i = 0; i < cons_num; i++) { - const Constructor& ctor = *type.constructors.at(i); - records.emplace_back(*this, ctor, i); - ConsRecord& record = records.back(); - record.has_trivial_name = (cons_num <= 1 || !ctor.constr_name); - record.declared = false; - record.cpp_name = local_cpp_ids.new_ident(cons_num <= 1 ? "Record" : std::string{"Record_"} + cons_enum_name[i]); - CppIdentSet rec_cpp_ids; - rec_cpp_ids.insert("type_class"); - rec_cpp_ids.insert(record.cpp_name); - // maybe : add field identifiers from type class context (?) - for (int j = 0; j < ctor.fields_num; j++) { - const Field& field = ctor.fields.at(j); - if (field.constraint) { - } else if (!field.implicit) { - MinMaxSize sz = field.type->compute_size(); - if (!sz.max_size()) { - continue; - } - std::string field_name; - const ConsRecord* subrec = nullptr; - if (field.name) { - field_name = rec_cpp_ids.new_ident(field.get_name()); - } else if (field.subrec) { - field_name = rec_cpp_ids.new_ident("r", 1); - subrec = &cpp_type.at(field.type->args.at(0)->type_applied->type_idx)->records.at(0); - } else if (field.type->tp == TypeExpr::te_Ref) { - field_name = rec_cpp_ids.new_ident("ref", 1); - } - record.cpp_fields.emplace_back(field, field_name, detect_field_cpp_type(field), sz.fixed_bit_size(), j, subrec); - } else if (field.used && (add_type_members || field.type->is_nat_subtype)) { - std::string field_name = rec_cpp_ids.new_ident(field.get_name()); - record.cpp_fields.emplace_back(field, field_name, field.type->is_nat_subtype ? ct_int32 : ct_typeptr, -1, j, - nullptr, true); - } - } - auto q = std_field_names.cbegin(); - for (auto& fi : record.cpp_fields) { - if (fi.name.empty()) { - bool is_ok = false; - while (q < std_field_names.cend()) { - if (!rec_cpp_ids.defined(*q)) { - fi.name = rec_cpp_ids.new_ident(*q++); - is_ok = true; - break; - } - } - if (!is_ok) { - fi.name = rec_cpp_ids.new_ident("f", 1); - } - } - } - record.is_trivial = (record.cpp_fields.size() <= 1); - record.is_small = (record.cpp_fields.size() <= 3); - record.inline_record = (record.cpp_fields.size() <= 2); - cpp_val_type t = ct_unknown; - if (record.is_trivial) { - t = (record.cpp_fields.size() == 1) ? record.cpp_fields.at(0).ctype : ct_void; - } - std::vector tv; - for (const auto& f : record.cpp_fields) { - if (f.ctype == ct_subrecord) { - record.is_trivial = record.is_small = false; - } else if (!f.implicit) { - tv.push_back(f.ctype); - } - } - record.equiv_cpp_type = t; - record.equiv_cpp_types = tv; - record.triv_conflict = false; - for (int j = 0; j < i; j++) { - if (records[j].equiv_cpp_types == tv) { - record.triv_conflict = records[j].triv_conflict = true; - break; - } - } - } -} - -bool CppTypeCode::ConsRecord::recover_idents(CppIdentSet& idents) const { - bool is_ok = idents.insert(cpp_name) && idents.insert("type_class"); - for (const auto& f : cpp_fields) { - is_ok &= idents.insert(f.name); - } - return is_ok; -} - -void CppTypeCode::assign_class_field_names() { - char cn = 'm', ct = 'X'; - int c = 0; - for (int z : type.args) { - bool f = z & Type::_IsNat; - bool neg = (z & Type::_IsNeg); - type_param_is_nat.push_back(f); - type_param_is_neg.push_back(neg); - std::string id; - if (!neg && !c++) { - template_args += ", "; - constructor_args += ", "; - } - if (f) { - id = local_cpp_ids.new_ident(std::string{cn}, 0, "_"); - if (cn != 't') { - ++cn; - } - if (!neg) { - template_args += "int "; - constructor_args += "int "; - } else { - skip_extra_args += ", int& "; - skip_extra_args_pass += ", "; - } - } else { - id = local_cpp_ids.new_ident(std::string{ct}, 0, "_"); - if (ct != 'Z') { - ++ct; - } else { - ct = 'T'; - } - assert(!neg); - template_args += "typename "; - constructor_args += "const TLB& "; - } - type_param_name.push_back(id); - if (!neg) { - template_args += id; - constructor_args += id; - } else { - skip_extra_args += id; - skip_extra_args_pass += id; - } - } -} - -bool CppTypeCode::compute_simple_cons_tags() { - if (!type.is_pfx_determ || type.useful_depth > 8) { - return false; - } - int d = type.useful_depth; - int n = (1 << d); - cons_tag_map.resize(n, 0); - //std::cerr << "compute_simple_cons_tags() for `" << type.get_name() << "` (d=" << d << ")\n"; - for (int i = 0; i < cons_num; i++) { - int t = cons_enum_value.at(i) + 1; - for (unsigned long long z : type.constructors[i]->begins_with.pfx) { - int l = std::min(63 - td::count_trailing_zeroes_non_zero64(z), d); - assert(l <= d); - int a = d ? (int)((z & (z - 1)) >> (64 - d)) : 0; - int b = (1 << (d - l)); - while (b-- > 0) { - assert(!cons_tag_map.at(a) || cons_tag_map[a] == t); - cons_tag_map[a++] = t; - } - } - } - int c = 0; - for (int v : cons_tag_map) { - if (v && v != c && v != ++c) { - return false; - } - } - return true; -} - -bool CppTypeCode::check_incremental_cons_tags() const { - if (!cons_num || common_cons_len < 0) { - return false; - } - int l = common_cons_len; - if (!l || l > 32) { - return true; - } - for (int i = 0; i < cons_num; i++) { - unsigned long long tag = (type.constructors.at(i)->tag >> (64 - l)); - if (tag != (unsigned)cons_enum_value.at(i)) { - return false; - } - } - return true; -} - -bool CppTypeCode::init() { - builtin = type.is_builtin; - cons_num = type.constr_num; - params = ret_params = tot_params = 0; - for (int z : type.args) { - if ((z & Type::_IsNeg)) { - ++ret_params; - } else { - ++params; - } - ++tot_params; - } - assign_class_name(); - assign_cons_names(); - assign_class_field_names(); - assign_cons_values(); - assign_record_cons_names(); - simple_get_size = type.has_fixed_size; - inline_skip = simple_get_size; - inline_validate_skip = (inline_skip && type.any_bits && !(type.size.min_size() & 0xff)); - inline_get_tag = (type.is_pfx_determ && type.useful_depth <= 6); - simple_cons_tags = compute_simple_cons_tags(); - common_cons_len = type.cons_common_len(); - incremental_cons_tags = check_incremental_cons_tags(); - return true; -} - -void CppTypeCode::generate_cons_enum(std::ostream& os) { - os << " enum { "; - for (int i = 0; i < cons_num; i++) { - if (i) { - os << ", "; - } - int k = cons_idx_by_enum.at(i); - os << cons_enum_name.at(k); - assert(cons_enum_value.at(k) == i); - } - os << " };\n"; -} - -void CppTypeCode::generate_cons_len_array(std::ostream& os, std::string nl, int options) { - bool f = (options & 2); - os << nl << (f ? "" : "static ") << ((options & 3) ? "constexpr " : "") << "char "; - if (f) { - os << cpp_type_class_name << "::"; - } - os << "cons_len[" << cons_num << "]"; - if (f) { - os << ";\n"; - return; - } - os << " = { "; - for (int i = 0; i < cons_num; i++) { - int k = cons_idx_by_enum.at(i); - const Constructor& constr = *type.constructors.at(k); - if (i > 0) { - os << ", "; - } - os << constr.tag_bits; - } - os << " };\n"; -} - -void CppTypeCode::generate_cons_tag_array(std::ostream& os, std::string nl, int options) { - int m = -1; - for (int i = 0; i < cons_num; i++) { - int k = cons_idx_by_enum.at(i); - const Constructor& constr = *type.constructors.at(k); - if (constr.tag_bits > m) { - m = constr.tag_bits; - } - } - bool f = (options & 2); - os << nl << (f ? "" : "static ") << ((options & 3) ? "constexpr " : ""); - if (m <= 8) { - os << "unsigned char "; - } else if (m <= 16) { - os << "unsigned short "; - } else if (m <= 32) { - os << "unsigned "; - } else { - os << "unsigned long long "; - } - if (f) { - os << cpp_type_class_name << "::"; - } - os << "cons_tag[" << cons_num << "]"; - if (f) { - os << ";\n"; - return; - } - os << " = { "; - for (int i = 0; i < cons_num; i++) { - int k = cons_idx_by_enum.at(i); - const Constructor& constr = *type.constructors.at(k); - if (i > 0) { - os << ", "; - } - os << HexConstWriter{constr.tag_bits ? (constr.tag >> (64 - constr.tag_bits)) : 0}; - } - os << " };\n"; -} - -void CppTypeCode::generate_cons_tag_info(std::ostream& os, std::string nl, int options) { - if (cons_num) { - if (common_cons_len == -1) { - generate_cons_len_array(os, nl, options); - } else if (options & 1) { - os << " static constexpr int cons_len_exact = " << common_cons_len << ";\n"; - } - if (common_cons_len != 0 && !incremental_cons_tags) { - generate_cons_tag_array(os, nl, options); - } - } -} - -void CppTypeCode::generate_get_tag_subcase(std::ostream& os, std::string nl, const BinTrie* trie, int depth) const { - if (!trie || !trie->down_tag) { - os << nl << "return -1; // ???"; - return; - } - if (trie->is_unique()) { - os << nl << "return " << cons_enum_name.at(trie->unique_value()) << ";"; - return; - } - if (!trie->useful_depth) { - generate_get_tag_param(os, nl, trie->down_tag); - return; - } - assert(trie->left || trie->right); - if (!trie->right) { - generate_get_tag_subcase(os, nl, trie->left.get(), depth + 1); - return; - } - if (!trie->left) { - generate_get_tag_subcase(os, nl, trie->right.get(), depth + 1); - return; - } - if (trie->left->is_unique() && trie->right->is_unique()) { - os << nl << "return cs.bit_at(" << depth << ") ? "; - int a = trie->right->unique_value(), b = trie->left->unique_value(); - os << (a >= 0 ? cons_enum_name.at(a) : "-1") << " : "; - os << (b >= 0 ? cons_enum_name.at(b) : "-1") << ";"; - return; - } - os << nl << "if (cs.bit_at(" << depth << ")) {"; - generate_get_tag_subcase(os, nl + " ", trie->right.get(), depth + 1); - os << nl << "} else {"; - generate_get_tag_subcase(os, nl + " ", trie->left.get(), depth + 1); - os << nl << "}"; -} - -void CppTypeCode::generate_get_tag_param(std::ostream& os, std::string nl, unsigned long long tag, - unsigned long long tag_params) const { - if (!tag) { - os << nl << "return -1; // ???"; - return; - } - if (!(tag & (tag - 1))) { - os << nl << "return " << cons_enum_name.at(td::count_trailing_zeroes64(tag)) << ";"; - return; - } - int cnt = td::count_bits64(tag); - DCHECK(cnt >= 2); - int mdim = 0, mmdim = 0; - for (int c = 0; c < 64; c++) { - if ((tag >> c) & 1) { - int dim = type.constructors.at(c)->admissible_params.dim; - if (dim > mdim) { - mmdim = mdim; - mdim = dim; - } else if (dim > mmdim) { - mmdim = dim; - } - } - } - assert(mmdim > 0); - for (int p1 = 0; p1 < mmdim; p1++) { - char A[4]; - std::memset(A, 0, sizeof(A)); - int c; - for (c = 0; c < 64; c++) { - if ((tag >> c) & 1) { - if (!type.constructors[c]->admissible_params.extract1(A, (char)(c + 1), p1)) { - break; - } - } - } - if (c == 64) { - std::string param_name = get_nat_param_name(p1); - generate_get_tag_param1(os, nl, A, ¶m_name); - return; - } - } - for (int p2 = 0; p2 < mmdim; p2++) { - for (int p1 = 0; p1 < p2; p1++) { - char A[4][4]; - std::memset(A, 0, sizeof(A)); - int c; - for (c = 0; c < 64; c++) { - if ((tag >> c) & 1) { - if (!type.constructors[c]->admissible_params.extract2(A, (char)(c + 1), p1, p2)) { - break; - } - } - } - if (c == 64) { - std::string param_names[2]; - param_names[0] = get_nat_param_name(p1); - param_names[1] = get_nat_param_name(p2); - generate_get_tag_param2(os, nl, A, param_names); - return; - } - } - } - for (int p3 = 0; p3 < mmdim; p3++) { - for (int p2 = 0; p2 < p3; p2++) { - for (int p1 = 0; p1 < p2; p1++) { - char A[4][4][4]; - std::memset(A, 0, sizeof(A)); - int c; - for (c = 0; c < 64; c++) { - if ((tag >> c) & 1) { - if (!type.constructors[c]->admissible_params.extract3(A, (char)(c + 1), p1, p2, p3)) { - break; - } - } - } - if (c == 64) { - std::string param_names[3]; - param_names[0] = get_nat_param_name(p1); - param_names[1] = get_nat_param_name(p2); - param_names[2] = get_nat_param_name(p3); - generate_get_tag_param3(os, nl, A, param_names); - return; - } - } - } - } - os << nl << "// ??? cannot distinguish constructors for this type using up to three parameters\n"; - throw src::Fatal{std::string{"cannot generate `"} + cpp_type_class_name + "::get_tag()` method for type `" + - type.get_name() + "`"}; -} - -bool CppTypeCode::match_param_pattern(std::ostream& os, std::string nl, const char A[4], int mask, std::string pattern, - std::string param_name) const { - int v = 0, w = 0; - for (int i = 0; i < 4; i++) { - if (A[i]) { - if ((mask >> i) & 1) { - v = (v && v != A[i] ? -1 : A[i]); - } else { - w = (w && w != A[i] ? -1 : A[i]); - } - } - } - if (v <= 0 || w <= 0) { - return false; - } - os << nl << "return "; - for (char c : pattern) { - if (c != '#') { - os << c; - } else { - os << param_name; - } - } - os << " ? " << cons_enum_name.at(v - 1) << " : " << cons_enum_name.at(w - 1) << ";"; - return true; -} - -void CppTypeCode::generate_get_tag_param1(std::ostream& os, std::string nl, const char A[4], - const std::string param_names[1]) const { - os << nl << "// distinguish by parameter `" << param_names[0] << "` using"; - for (int i = 0; i < 4; i++) { - os << ' ' << (int)A[i]; - } - if (match_param_pattern(os, nl, A, 14, "#", param_names[0]) || - match_param_pattern(os, nl, A, 2, "# == 1", param_names[0]) || - match_param_pattern(os, nl, A, 3, "# <= 1", param_names[0]) || - match_param_pattern(os, nl, A, 10, "(# & 1)", param_names[0]) || - match_param_pattern(os, nl, A, 4, "# && !(# & 1)", param_names[0]) || - match_param_pattern(os, nl, A, 8, "# > 1 && (# & 1)", param_names[0])) { - return; - } - os << nl << "// static inline size_t nat_abs(int x) { return (x > 1) * 2 + (x & 1); }"; - os << nl << "static signed char ctab[4] = { "; - for (int i = 0; i < 4; i++) { - if (i > 0) { - os << ", "; - } - os << (A[i] ? cons_enum_name.at(A[i] - 1) : "-1"); - } - os << " };" << nl << "return ctab[nat_abs(" << param_names[0] << ")];"; -} - -void CppTypeCode::generate_get_tag_param2(std::ostream& os, std::string nl, const char A[4][4], - const std::string param_names[2]) const { - os << nl << "// distinguish by parameters `" << param_names[0] << "`, `" << param_names[1] << "` using"; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - os << ' ' << (int)A[i][j]; - } - } - os << nl << "// static inline size_t nat_abs(int x) { return (x > 1) * 2 + (x & 1); }"; - os << nl << "static signed char ctab[4][4] = { "; - for (int i = 0; i < 16; i++) { - if (i > 0) { - os << ", "; - } - int v = A[i >> 2][i & 3]; - os << (v ? cons_enum_name.at(v - 1) : "-1"); - } - os << " };" << nl << "return ctab[nat_abs(" << param_names[0] << ")][nat_abs(" << param_names[1] << ")];"; -} - -void CppTypeCode::generate_get_tag_param3(std::ostream& os, std::string nl, const char A[4][4][4], - const std::string param_names[3]) const { - os << nl << "// distinguish by parameters `" << param_names[0] << "`, `" << param_names[1] << "`, `" << param_names[2] - << "` using"; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - for (int k = 0; k < 4; k++) { - os << ' ' << (int)A[i][j][k]; - } - } - } - os << nl << "// static inline size_t nat_abs(int x) { return (x > 1) * 2 + (x & 1); }"; - os << nl << "static signed char ctab[4][4][4] = { "; - for (int i = 0; i < 64; i++) { - if (i > 0) { - os << ", "; - } - int v = A[i >> 4][(i >> 2) & 3][i & 3]; - os << (v ? cons_enum_name.at(v - 1) : "-1"); - } - os << " };" << nl << "return ctab[nat_abs(" << param_names[0] << ")][nat_abs(" << param_names[1] << ")][nat_abs(" - << param_names[2] << ")];"; -} - -std::string CppTypeCode::get_nat_param_name(int idx) const { - for (int i = 0; i < tot_params; i++) { - if (!type_param_is_neg.at(i) && type_param_is_nat.at(i) && !idx--) { - return type_param_name.at(i); - } - } - return "???"; -} - -void CppTypeCode::generate_tag_pfx_selector(std::ostream& os, std::string nl, const BinTrie& trie, int d, - int min_size) const { - assert(d >= 0 && d <= 6); - int n = (1 << d); - unsigned long long A[64]; - int c[65]; - unsigned long long mask = trie.build_submap(d, A); - int l = 1; - c[0] = -1; - for (int i = 0; i < n; i++) { - assert(!(A[i] & (A[i] - 1))); - if ((mask >> l) & 1) { - c[l++] = A[i] ? td::count_trailing_zeroes_non_zero64(A[i]) : -1; - } - } - bool simple = (l > n / 2); - if (simple) { - l = n + 1; - for (int i = 0; i < n; i++) { - c[i + 1] = A[i] ? td::count_trailing_zeroes_non_zero64(A[i]) : -1; - } - } - os << nl << "static signed char ctab[" << l << "] = {"; - for (int i = 0; i < l; i++) { - if (i > 0) { - os << ", "; - } - if (c[i] < 0) { - os << c[i]; - } else { - os << cons_enum_name.at(c[i]); - } - } - os << "};" << nl << "return ctab[1 + "; - if (simple) { - os << "(long long)cs.prefetch_ulong(" << d << ")];"; - } else { - os << "(long long)cs.bselect" << (d >= min_size ? "(" : "_ext(") << d << ", " << HexConstWriter{mask} << ")];"; - } -} - -bool CppTypeCode::generate_get_tag_pfx_distinguisher(std::ostream& os, std::string nl, - const std::vector& constr_list, bool in_block) const { - if (constr_list.empty()) { - os << nl << " return -1;"; - return false; - } - if (constr_list.size() == 1) { - os << nl << " return " << cons_enum_name.at(constr_list[0]) << ";"; - return false; - } - std::unique_ptr trie; - for (int i : constr_list) { - trie = BinTrie::insert_paths(std::move(trie), type.constructors.at(i)->begins_with, 1ULL << i); - } - if (!trie) { - os << nl << " return -1;"; - return false; - } - int d = trie->compute_useful_depth(); - bool is_pfx_determ = !trie->find_conflict_path(); - assert(is_pfx_determ); - if (!in_block) { - os << " {"; - } - generate_tag_pfx_selector(os, nl, *trie, d, (int)(type.size.min_size() >> 8)); - return !in_block; -} - -void CppTypeCode::generate_get_tag_body(std::ostream& os, std::string nl) { - int d = type.useful_depth; - cons_tag_exact.resize(cons_num, false); - if (type.is_pfx_determ) { - if (!cons_num) { - os << nl << "return -1;"; - return; - } - if (!d) { - assert(simple_cons_tags && cons_num == 1); - cons_tag_exact[0] = !(type.constructors.at(0)->tag_bits); - os << nl << "return 0;"; - return; - } - int min_size = (int)(type.size.min_size() >> 8); - bool always_has = (d <= min_size); - if (d <= 6 && simple_cons_tags) { - unsigned long long sm = compute_selector_mask(); - if (always_has && sm + 1 == (2ULL << ((1 << d) - 1))) { - for (int i = 0; i < cons_num; i++) { - cons_tag_exact[i] = (type.constructors.at(i)->tag_bits <= d); - } - os << nl << "return (int)cs.prefetch_ulong(" << d << ");"; - return; - } - for (int i = 0; i < cons_num; i++) { - unsigned long long tag = type.constructors.at(i)->tag; - int l = 63 - td::count_trailing_zeroes_non_zero64(tag); - if (l <= d) { - int a = (int)((tag & (tag - 1)) >> (64 - d)); - int b = a + (1 << (d - l)); - cons_tag_exact[i] = ((sm >> a) & 1) && (b == (1 << d) || ((sm >> b) & 1)); - } - } - os << nl << "return cs.bselect" << (always_has ? "(" : "_ext(") << d << ", " << HexConstWriter{sm} << ");"; - return; - } - if (d <= 6) { - generate_tag_pfx_selector(os, nl, *(type.cs_trie), d, min_size); - return; - } - } - if (type.is_const_param_determ || type.is_const_param_pfx_determ) { - int p = type.const_param_idx; - assert(p >= 0); - std::vector param_values = type.get_all_param_values(p); - assert(param_values.size() > 1 && param_values.at(0) >= 0); - os << nl << "switch (" << type_param_name.at(p) << ") {"; - for (int pv : param_values) { - assert(pv >= 0); - os << nl << "case " << pv << ":"; - std::vector constr_list = type.get_constr_by_param_value(p, pv); - assert(!constr_list.empty()); - if (constr_list.size() == 1) { - os << nl << " return " << cons_enum_name.at(constr_list[0]) << ";"; - continue; - } - bool opbr = generate_get_tag_pfx_distinguisher(os, nl + " ", constr_list, false); - if (opbr) { - os << nl << "}"; - } - } - os << nl << "default:" << nl << " return -1;" << nl << "}"; - return; - } - if (d) { - int d1 = std::min(6, d); - int n = (1 << d1); - bool always_has = (d1 <= (int)(type.size.min_size() >> 8)); - unsigned long long A[64], B[64]; - unsigned long long mask = type.cs_trie->build_submap(d1, A); - int l = td::count_bits64(mask); - bool simple = (l > n / 2 || n <= 8); - if (!simple) { - int j = 0; - for (int i = 0; i < n; i++) { - if ((mask >> i) & 1) { - //std::cerr << i << ',' << std::hex << A[i] << std::dec << std::endl; - B[j] = (2 * i + 1ULL) << (63 - d1); - A[j++] = A[i]; - } - } - assert(j == l); - } else { - for (int i = 0; i < n; i++) { - B[i] = (2 * i + 1ULL) << (63 - d1); - } - l = n; - } - os << nl << "switch ("; - if (simple) { - os << "(int)cs.prefetch_ulong(" << d1; - } else { - os << "cs.bselect" << (always_has ? "(" : "_ext(") << d1 << ", " << HexConstWriter{mask}; - } - os << ")) {"; - for (int i = 0; i < l; i++) { - if (A[i] != 0) { - if ((long long)A[i] > 0) { - int j; - for (j = 0; j < i; j++) { - if (A[j] == A[i]) { - break; - } - } - if (j < i) { - continue; - } - } - os << nl << "case " << i << ":"; - if ((long long)A[i] > 0) { - int j; - for (j = i + 1; j < l; j++) { - if (A[j] == A[i]) { - os << " case " << j << ":"; - } - } - if (!(A[i] & (A[i] - 1))) { - os << nl << " return " << cons_enum_name.at(td::count_trailing_zeroes_non_zero64(A[i])) << ";"; - } - } else { - generate_get_tag_subcase(os, nl + " ", type.cs_trie->lookup_node_const(B[i]), d1); - } - } - } - os << nl << "default:" << nl << " return -1;" << nl << "}"; - } else { - generate_get_tag_subcase(os, nl, type.cs_trie.get(), 0); - } -} - -void CppTypeCode::generate_type_fields(std::ostream& os, int options) { - int st = -1; - for (int i = 0; i < tot_params; i++) { - if (type_param_is_neg[i]) { - continue; - } - int nst = type_param_is_nat[i]; - if (st != nst) { - if (st >= 0) { - os << ";\n"; - } - os << (nst ? " int " : " const TLB "); - st = nst; - } else { - os << ", "; - } - if (!nst) { - os << '&'; - } - os << type_param_name[i]; - } - if (st >= 0) { - os << ";\n"; - } -} - -static std::string constr_arg_name(std::string type_field_name) { - if (type_field_name.size() <= 1 || type_field_name.back() != '_') { - return std::string{"_"} + type_field_name; - } else { - return {type_field_name, 0, type_field_name.size() - 1}; - } -} - -void CppTypeCode::generate_type_constructor(std::ostream& os, int options) { - os << " " << cpp_type_class_name << "("; - for (int i = 0, j = 0; i < tot_params; i++) { - if (type_param_is_neg[i]) { - continue; - } - if (j++ > 0) { - os << ", "; - } - os << (type_param_is_nat[i] ? "int " : "const TLB& "); - os << constr_arg_name(type_param_name[i]); - } - os << ")"; - for (int i = 0, j = 0; i < tot_params; i++) { - if (type_param_is_neg[i]) { - continue; - } - if (j++ > 0) { - os << ", "; - } else { - os << " : "; - } - os << type_param_name[i] << "(" << constr_arg_name(type_param_name[i]) << ")"; - } - os << " {}\n"; -} - -void Action::show(std::ostream& os) const { - if (fixed_size >= 0) { - if (!fixed_size) { - os << "true"; - } else if (fixed_size < 0x10000) { - os << "cs.advance(" << fixed_size << ")"; - } else if (!(fixed_size & 0xffff)) { - os << "cs.advance_refs(" << (fixed_size >> 16) << ")"; - } else { - os << "cs.advance_ext(0x" << std::hex << fixed_size << std::dec << ")"; - } - } else { - os << action; - } -} - -bool Action::may_combine(const Action& next) const { - return !fixed_size || !next.fixed_size || (fixed_size >= 0 && next.fixed_size >= 0); -} - -bool Action::operator+=(const Action& next) { - if (!next.fixed_size) { - return true; - } - if (!fixed_size) { - fixed_size = next.fixed_size; - action = next.action; - return true; - } - if (fixed_size >= 0 && next.fixed_size >= 0) { - fixed_size += next.fixed_size; - return true; - } - return false; -} - -void operator+=(std::vector& av, const Action& next) { - if (av.empty() || !(av.back() += next)) { - if (next.is_constraint && !av.empty() && av.back().fixed_size >= 0) { - Action last = av.back(); - av.pop_back(); - av.push_back(next); - av.push_back(last); - } else { - av.push_back(next); - } - } -} - -void CppTypeCode::clear_context() { - actions.clear(); - incomplete = 0; - tmp_ints = 0; - needs_tmp_cell = false; - tmp_vars.clear(); - field_vars.clear(); - field_var_set.clear(); - param_var_set.clear(); - param_constraint_used.clear(); - tmp_cpp_ids.clear(); - tmp_cpp_ids.new_ident("cs"); - tmp_cpp_ids.new_ident("cb"); - tmp_cpp_ids.new_ident("cell_ref"); - tmp_cpp_ids.new_ident("t"); -} - -std::string CppTypeCode::new_tmp_var() { - char buffer[16]; - while (true) { - sprintf(buffer, "t%d", ++tmp_ints); - if (tmp_cpp_ids.is_good_ident(buffer) && local_cpp_ids.is_good_ident(buffer)) { - break; - } - } - std::string s{buffer}; - s = tmp_cpp_ids.new_ident(s); - tmp_vars.push_back(s); - return s; -} - -std::string CppTypeCode::new_tmp_var(std::string hint) { - if (hint.empty() || hint == "_") { - return new_tmp_var(); - } - int count = 0; - while (true) { - std::string s = local_cpp_ids.compute_cpp_ident(hint, count++); - if (tmp_cpp_ids.is_good_ident(s) && local_cpp_ids.is_good_ident(s)) { - s = tmp_cpp_ids.new_ident(s); - tmp_vars.push_back(s); - return s; - } - } -} - -std::string compute_type_class_name(const Type* typ, int& fake_arg) { - fake_arg = -1; - int idx = typ->type_idx; - if (idx >= builtin_types_num) { - return cpp_type[idx]->cpp_type_class_name; - } else if (typ->produces_nat) { - if (typ == Nat_type) { - return "Nat"; - } else if (typ == NatWidth_type) { - return "NatWidth"; - } else if (typ == NatLeq_type) { - return "NatLeq"; - } else if (typ == NatLess_type) { - return "NatLess"; - } - // ... - } else if (typ == Any_type) { - return "Anything"; - } else if (typ->has_fixed_size) { - fake_arg = (typ->size.min_size() >> 8); - int c = typ->get_name()[0]; - return (c == 'b') ? "Bits" : ((c == 'u') ? "UInt" : "Int"); - } else if (typ == Int_type) { - return "Int"; - } else if (typ == UInt_type) { - return "UInt"; - } else if (typ == Bits_type) { - return "Bits"; - } - return ""; -} - -std::string compute_type_expr_class_name(const TypeExpr* expr, int& fake_arg) { - switch (expr->tp) { - case TypeExpr::te_Apply: - return compute_type_class_name(expr->type_applied, fake_arg); - case TypeExpr::te_Ref: - return "RefT"; - case TypeExpr::te_Tuple: - return "TupleT"; - case TypeExpr::te_CondType: - return "CondT"; - } - return ""; -} - -void CppTypeCode::output_cpp_expr(std::ostream& os, const TypeExpr* expr, int prio, bool allow_type_neg) const { - if (expr->negated) { - if (!allow_type_neg || expr->tp != TypeExpr::te_Apply) { - throw src::Fatal{static_cast(std::ostringstream{} << "cannot convert negated expression `" - << expr << "` into C++ code") - .str()}; - } - } - int pos_args = 0; - for (const TypeExpr* arg : expr->args) { - pos_args += !arg->negated; - } - switch (expr->tp) { - case TypeExpr::te_Param: { - int i = expr->value; - assert(field_var_set.at(i)); - std::string fv = field_vars.at(i); - assert(!fv.empty()); - os << fv; - return; - } - case TypeExpr::te_Apply: - if (!pos_args && expr->type_applied->type_idx >= builtin_types_num) { - int type_idx = expr->type_applied->type_idx; - const CppTypeCode& cc = *cpp_type.at(type_idx); - assert(!cc.cpp_type_var_name.empty()); - os << cc.cpp_type_var_name; - return; - } - // fall through - case TypeExpr::te_Ref: - case TypeExpr::te_CondType: - case TypeExpr::te_Tuple: - if (expr->is_constexpr > 0) { - os << const_type_expr_cpp_idents.at(expr->is_constexpr); - return; - } else { - int fake_arg = -1; - os << compute_type_expr_class_name(expr, fake_arg); - os << "{"; - int c = 0; - if (fake_arg >= 0) { - os << fake_arg; - c = 1; - } - for (const TypeExpr* arg : expr->args) { - if (!arg->negated) { - os << (c++ ? ", " : ""); - output_cpp_expr(os, arg); - } - } - os << '}'; - return; - } - case TypeExpr::te_Add: - if (prio > 10) { - os << "("; - } - output_cpp_expr(os, expr->args[0], 10); - os << " + "; - output_cpp_expr(os, expr->args[1], 10); - if (prio > 10) { - os << ")"; - } - return; - case TypeExpr::te_MulConst: - if (prio > 20) { - os << "("; - } - os << expr->value; - os << " * "; - output_cpp_expr(os, expr->args[0], 20); - if (prio > 20) { - os << ")"; - } - return; - case TypeExpr::te_GetBit: - if (prio > 0) { - os << "("; - } - output_cpp_expr(os, expr->args[0], 5); - os << " & "; - if (expr->args[1]->tp == TypeExpr::te_IntConst && (unsigned)expr->args[1]->value <= 31) { - int v = expr->args[1]->value; - if (v > 1024) { - os << "0x" << std::hex << (1 << v) << std::dec; - } else { - os << (1 << v); - } - } else { - os << "(1 << "; - output_cpp_expr(os, expr->args[1], 5); - os << ")"; - } - if (prio > 0) { - os << ")"; - } - return; - case TypeExpr::te_IntConst: - os << expr->value; - return; - } - os << ""; -} - -bool CppTypeCode::can_compute_sizeof(const TypeExpr* expr) const { - if (expr->negated || expr->is_nat) { - return false; - } - MinMaxSize sz = expr->compute_size(); - if (sz.is_fixed()) { - return !(sz.min_size() & 0xff); - } - if (expr->tp == TypeExpr::te_Apply && (expr->type_applied == Int_type || expr->type_applied == UInt_type || - expr->type_applied == NatWidth_type || expr->type_applied == Bits_type)) { - return true; - } - if (expr->tp != TypeExpr::te_CondType && expr->tp != TypeExpr::te_Tuple) { - return false; - } - return can_compute_sizeof(expr->args[1]); -} - -void CppTypeCode::output_cpp_sizeof_expr(std::ostream& os, const TypeExpr* expr, int prio) const { - if (expr->negated) { - throw src::Fatal{static_cast(std::ostringstream{} - << "cannot compute size of negated type expression `" << expr - << "` in C++ code") - .str()}; - } - if (expr->is_nat) { - throw src::Fatal{static_cast(std::ostringstream{} - << "cannot compute size of non-type expression `" << expr - << "` in C++ code") - .str()}; - } - MinMaxSize sz = expr->compute_size(); - if (sz.is_fixed()) { - os << SizeWriter{(int)sz.convert_min_size()}; - return; - } - switch (expr->tp) { - case TypeExpr::te_CondType: - if (prio > 5) { - os << '('; - } - output_cpp_expr(os, expr->args[0], 5); - os << " ? "; - output_cpp_sizeof_expr(os, expr->args[1], 6); - os << " : 0"; - if (prio > 5) { - os << ')'; - } - return; - case TypeExpr::te_Tuple: - if (expr->args[0]->tp == TypeExpr::te_IntConst && expr->args[0]->value == 1) { - output_cpp_sizeof_expr(os, expr->args[1], prio); - return; - } - sz = expr->args[1]->compute_size(); - if (sz.is_fixed() && sz.convert_min_size() == 1) { - output_cpp_expr(os, expr->args[0], prio); - return; - } - if (prio > 20) { - os << '('; - } - output_cpp_expr(os, expr->args[0], 20); - os << " * "; - output_cpp_sizeof_expr(os, expr->args[1], 20); - if (prio > 20) { - os << ')'; - } - return; - case TypeExpr::te_Apply: - if (expr->type_applied == Int_type || expr->type_applied == UInt_type || expr->type_applied == NatWidth_type || - expr->type_applied == Bits_type) { - output_cpp_expr(os, expr->args[0], prio); - return; - } - // no break - } - os << ""; -} - -bool CppTypeCode::can_compute(const TypeExpr* expr) const { - if (expr->negated) { - return false; - } - if (expr->tp == TypeExpr::te_Param) { - return field_var_set.at(expr->value); - } - for (const TypeExpr* arg : expr->args) { - if (!can_compute(arg)) { - return false; - } - } - return true; -} - -bool CppTypeCode::can_use_to_compute(const TypeExpr* expr, int i) const { - if (!expr->negated || !expr->is_nat) { - return false; - } - if (expr->tp == TypeExpr::te_Param) { - return expr->value == i; - } - for (const TypeExpr* arg : expr->args) { - if (!(arg->negated ? can_use_to_compute(arg, i) : can_compute(arg))) { - return false; - } - } - return true; -} - -void CppTypeCode::add_compute_actions(const TypeExpr* expr, int i, std::string bind_to) { - assert(expr->negated && expr->is_nat); - switch (expr->tp) { - case TypeExpr::te_MulConst: { - assert(expr->args.size() == 1 && expr->value > 0); - const TypeExpr* x = expr->args[0]; - assert(x->negated); - std::string tmp; - if (x->tp != TypeExpr::te_Param || (x->value != i && i >= 0)) { - tmp = new_tmp_var(); - } else { - i = x->value; - tmp = field_vars.at(i); - assert(!tmp.empty()); - assert(!field_var_set[i]); - field_var_set[i] = true; - x = nullptr; - } - std::ostringstream ss; - ss << "mul_r1(" << tmp << ", " << expr->value << ", " << bind_to << ")"; - actions += Action{std::move(ss), true}; - if (x) { - add_compute_actions(x, i, tmp); - } - return; - } - case TypeExpr::te_Add: { - assert(expr->args.size() == 2); - const TypeExpr *x = expr->args[0], *y = expr->args[1]; - assert(x->negated ^ y->negated); - if (!x->negated) { - std::swap(x, y); - } - std::string tmp; - if (x->tp != TypeExpr::te_Param || (x->value != i && i >= 0)) { - tmp = new_tmp_var(); - } else { - i = x->value; - tmp = field_vars.at(i); - assert(!tmp.empty()); - assert(!field_var_set[i]); - field_var_set[i] = true; - x = nullptr; - } - std::ostringstream ss; - ss << "add_r1(" << tmp << ", "; - output_cpp_expr(ss, y); - ss << ", " << bind_to << ")"; - actions += Action{std::move(ss), true}; - if (x) { - add_compute_actions(x, i, tmp); - } - return; - } - case TypeExpr::te_Param: - assert(expr->value == i || i < 0); - i = expr->value; - assert(!field_vars.at(i).empty()); - if (!field_var_set.at(i)) { - actions += Action{std::string{"("} + field_vars.at(i) + " = " + bind_to + ") >= 0"}; - field_var_set[i] = true; - } else { - actions += Action{field_vars.at(i) + " == " + bind_to}; - } - return; - } - throw src::Fatal{static_cast(std::ostringstream{} << "cannot use expression `" << expr << "` = " - << bind_to << " to set field variable " - << (i >= 0 ? field_vars.at(i) : "")) - .str()}; -} - -bool CppTypeCode::is_self(const TypeExpr* expr, const Constructor& constr) const { - if (expr->tp != TypeExpr::te_Apply || expr->type_applied != &type || (int)expr->args.size() != tot_params) { - return false; - } - assert(constr.params.size() == expr->args.size()); - for (int i = 0; i < tot_params; i++) { - assert(type_param_is_neg[i] == expr->args[i]->negated); - assert(type_param_is_neg[i] == constr.param_negated[i]); - if (!type_param_is_neg[i] && !expr->args[i]->equal(*constr.params[i])) { - return false; - } - } - return true; -} - -void CppTypeCode::init_cons_context(const Constructor& constr) { - clear_context(); - field_vars.resize(constr.fields.size()); - field_var_set.resize(constr.fields.size(), false); - param_var_set.resize(params + ret_params, false); - param_constraint_used.resize(params + ret_params, false); -} - -void CppTypeCode::identify_cons_params(const Constructor& constr, int options) { - int j = 0; - for (const TypeExpr* pexpr : constr.params) { - if (pexpr->tp == TypeExpr::te_Param) { - if (!type_param_is_neg.at(j)) { - int i = pexpr->value; - if (field_var_set.at(i)) { - // field i and parameter j must be equal - actions += Action{type_param_name.at(j) + " == " + field_vars.at(i)}; - param_constraint_used[j] = true; - } else if (field_vars.at(i).empty()) { - // identify field i with parameter j - field_vars[i] = type_param_name.at(j); - field_var_set[i] = true; - param_constraint_used[j] = true; - } - } else if (!(options & 2)) { - tmp_vars.push_back(type_param_name.at(j)); - } - } - j++; - } -} - -void CppTypeCode::identify_cons_neg_params(const Constructor& constr, int options) { - int j = 0; - for (const TypeExpr* pexpr : constr.params) { - if (pexpr->tp == TypeExpr::te_Param && type_param_is_neg.at(j)) { - int i = pexpr->value; - if (!field_var_set.at(i) && field_vars.at(i).empty()) { - // identify field i with parameter j - field_vars[i] = type_param_name.at(j); - param_constraint_used[j] = true; - } - } - j++; - } -} - -void CppTypeCode::add_cons_tag_check(const Constructor& constr, int cidx, int options) { - if (constr.tag_bits) { - if ((options & 1) && ((options & 8) || cons_num == 1 || !cons_tag_exact.at(cidx))) { - std::ostringstream ss; - int l = constr.tag_bits; - unsigned long long tag = (constr.tag >> (64 - l)); - if (l < 64) { - ss << "cs.fetch_ulong(" << l << ") == " << HexConstWriter{tag}; - } else { - ss << "cs.begins_with_skip(" << l << ", " << HexConstWriter{tag} << ")"; - } - actions.emplace_back(std::move(ss)); - } else { - actions.emplace_back(constr.tag_bits); - } - } -} - -void CppTypeCode::add_cons_tag_store(const Constructor& constr, int cidx) { - if (constr.tag_bits) { - std::ostringstream ss; - int l = constr.tag_bits; - unsigned long long tag = (constr.tag >> (64 - l)); - ss << "cb.store_long_bool(" << HexConstWriter{tag} << ", " << l << ")"; - actions.emplace_back(std::move(ss)); - } -} - -void CppTypeCode::add_remaining_param_constraints_check(const Constructor& constr, int options) { - int j = 0; - for (const TypeExpr* pexpr : constr.params) { - if (!param_constraint_used.at(j)) { - std::ostringstream ss; - if (!type_param_is_neg.at(j)) { - ss << type_param_name.at(j) << " == "; - output_cpp_expr(ss, pexpr); - actions += Action{std::move(ss)}; - } else if (options & 2) { - ss << "(" << type_param_name.at(j) << " = "; - output_cpp_expr(ss, pexpr); - ss << ") >= 0"; - actions += Action{std::move(ss), true}; - } - } - ++j; - } -} - -void CppTypeCode::output_actions(std::ostream& os, std::string nl, int options) { - bool opbr = false; - if (tmp_vars.size() || needs_tmp_cell) { - if (!(options & 4)) { - opbr = true; - os << " {"; - } - if (tmp_vars.size()) { - os << nl << "int"; - int c = 0; - for (auto t : tmp_vars) { - if (c++) { - os << ","; - } - os << " " << t; - } - os << ";"; - } - if (needs_tmp_cell) { - os << nl << "Ref tmp_cell;"; - } - } - if (!actions.size()) { - os << nl << "return true;"; - } else { - for (std::size_t i = 0; i < actions.size(); i++) { - os << nl << (i ? " && " : "return "); - actions[i].show(os); - } - os << ";"; - } - if (incomplete) { - os << nl << "// ???"; - } - if (opbr) { - os << nl << "}"; - } -} - -void CppTypeCode::compute_implicit_field(const Constructor& constr, const Field& field, int options) { - int i = field.field_idx; - if (field_vars.at(i).empty()) { - assert(!field_var_set.at(i)); - assert(field.type->is_nat_subtype); - std::string id = new_tmp_var(field.get_name()); - field_vars[i] = id; - } - int j = -1; - for (const TypeExpr* pexpr : constr.params) { - ++j; - if (!param_constraint_used.at(j) && !type_param_is_neg.at(j)) { - // std::cerr << "can_use_to_compute(" << pexpr << ", " << i << ") = " << can_use_to_compute(pexpr, i) << std::endl; - if (!field_var_set.at(i) && pexpr->tp == TypeExpr::te_Param && pexpr->value == i) { - std::ostringstream ss; - if (field.type->is_nat_subtype) { - ss << "(" << field_vars[i] << " = " << type_param_name.at(j) << ") >= 0"; - } else { - ss << "(" << field_vars[i] << " = &" << type_param_name.at(j) << ")"; - } - actions += Action{std::move(ss)}; - field_vars[i] = type_param_name[j]; - field_var_set[i] = true; - param_constraint_used[j] = true; - } else if (can_compute(pexpr)) { - std::ostringstream ss; - ss << type_param_name.at(j) << " == "; - output_cpp_expr(ss, pexpr); - actions += Action{std::move(ss), true}; - param_constraint_used[j] = true; - } else if (!field_var_set.at(i) && can_use_to_compute(pexpr, i)) { - add_compute_actions(pexpr, i, type_param_name.at(j)); - param_constraint_used[j] = true; - } - } - } -} - -bool CppTypeCode::add_constraint_check(const Constructor& constr, const Field& field, int options) { - const TypeExpr* expr = field.type; - if (expr->tp == TypeExpr::te_Apply && - (expr->type_applied == Eq_type || expr->type_applied == Less_type || expr->type_applied == Leq_type)) { - assert(expr->args.size() == 2); - const TypeExpr *x = expr->args[0], *y = expr->args[1]; - if (x->negated || y->negated) { - assert(expr->type_applied == Eq_type); - assert(x->negated ^ y->negated); - if (!x->negated) { - std::swap(x, y); - } - std::ostringstream ss; - output_cpp_expr(ss, y); - add_compute_actions(x, -1, ss.str()); - } else { - std::ostringstream ss; - output_cpp_expr(ss, x); - ss << (expr->type_applied == Eq_type ? " == " : (expr->type_applied == Less_type ? " < " : " <= ")); - output_cpp_expr(ss, y); - actions += Action{std::move(ss), true}; - } - return true; - } else { - // ... - ++incomplete; - actions += Action{"check_constraint_incomplete"}; - return false; - } -} - -void CppTypeCode::output_negative_type_arguments(std::ostream& os, const TypeExpr* expr) { - assert(expr->tp == TypeExpr::te_Apply); - for (const TypeExpr* arg : expr->args) { - if (arg->negated) { - int j = arg->value; - if (arg->tp == TypeExpr::te_Param && !field_var_set.at(j)) { - assert(!field_vars.at(j).empty()); - os << ", " << field_vars.at(j); - field_var_set[j] = true; - } else { - std::string tmp = new_tmp_var(); - os << ", " << tmp; - postponed_equate.emplace_back(tmp, arg); - } - } - } -} - -void CppTypeCode::add_postponed_equate_actions() { - for (const auto& p : postponed_equate) { - add_compute_actions(p.second, -1, p.first); - } - postponed_equate.clear(); -} - -std::string CppTypeCode::add_fetch_nat_field(const Constructor& constr, const Field& field, int options) { - const TypeExpr* expr = field.type; - int i = field.field_idx; - std::string id = field_vars.at(i); - if (id.empty()) { - field_vars[i] = id = new_tmp_var(field.get_name()); - } - const Type* ta = expr->type_applied; - assert(expr->tp == TypeExpr::te_Apply && - (ta == Nat_type || ta == NatWidth_type || ta == NatLeq_type || ta == NatLess_type)); - std::ostringstream ss; - ss << "cs."; - if (ta == Nat_type) { - ss << "fetch_uint_to(32, " << id << ")"; - } else if (ta == NatWidth_type && expr->args.at(0)->tp == TypeExpr::te_IntConst && expr->args[0]->value == 1) { - ss << "fetch_bool_to(" << id << ")"; - } else { - if (ta == NatWidth_type) { - ss << "fetch_uint_to("; - } else if (ta == NatLeq_type) { - ss << "fetch_uint_leq("; - } else if (ta == NatLess_type) { - ss << "fetch_uint_less("; - } - output_cpp_expr(ss, expr->args[0]); - ss << ", " << id << ")"; - } - actions += Action{std::move(ss)}; - field_var_set[i] = true; - return id; -} - -void CppTypeCode::add_store_nat_field(const Constructor& constr, const Field& field, int options) { - const TypeExpr* expr = field.type; - int i = field.field_idx; - std::string id = field_vars.at(i); - assert(!id.empty()); - const Type* ta = expr->type_applied; - assert(expr->tp == TypeExpr::te_Apply && - (ta == Nat_type || ta == NatWidth_type || ta == NatLeq_type || ta == NatLess_type)); - std::ostringstream ss; - ss << "cb."; - if (ta == Nat_type) { - ss << "store_ulong_rchk_bool(" << id << ", 32)"; - } else if (ta == NatWidth_type) { - if (expr->args.at(0)->tp == TypeExpr::te_IntConst && expr->args[0]->value == 1) { - ss << "store_ulong_rchk_bool(" << id << ", 1)"; - } else { - ss << "store_ulong_rchk_bool(" << id << ", "; - output_cpp_expr(ss, expr->args[0]); - ss << ")"; - } - } else if (ta == NatLeq_type) { - ss << "store_uint_leq("; - output_cpp_expr(ss, expr->args[0]); - ss << ", " << id << ")"; - } else if (ta == NatLess_type) { - ss << "store_uint_less("; - output_cpp_expr(ss, expr->args[0]); - ss << ", " << id << ")"; - } else { - ss << "(" << id << ")"; - } - actions += Action{std::move(ss)}; - field_var_set[i] = true; -} - -void CppTypeCode::generate_skip_field(const Constructor& constr, const Field& field, int options) { - const TypeExpr* expr = field.type; - MinMaxSize sz = expr->compute_size(); - bool any_bits = expr->compute_any_bits(); - bool validating = (options & 1); - // std::cerr << "field `" << field.get_name() << "` size is " << sz << "; fixed=" << sz.is_fixed() << "; any=" << any_bits << std::endl; - if (field.used || (validating && expr->is_nat_subtype && !any_bits)) { - // an explicit field of type # or ## which is used later or its value is not arbitrary - // (must load the value into an integer variable and check) - assert(expr->is_nat_subtype && "cannot use fields of non-`#` type"); - add_fetch_nat_field(constr, field, options); - return; - } - if (sz.is_fixed() && (!validating || (!(sz.min_size() & 0xff) && any_bits))) { - // field has fixed size, and either its bits can have arbitrary values (and it has no references) - // ... or we are not validating - // simply skip the necessary amount of bits - // NB: if the field is a reference, and we are not validating, we arrive here - actions += Action{(int)sz.convert_min_size()}; - return; - } - if (expr->negated) { - // the field type has some "negative" parameters, which will be computed while checking this field - // must invoke the correct validate_skip or skip method for the type in question - std::ostringstream ss; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100, true); - ss << '.'; - } - ss << (validating ? "validate_skip(ops, cs, weak" : "skip(cs"); - output_negative_type_arguments(ss, expr); - ss << ")"; - actions += Action{std::move(ss)}; - add_postponed_equate_actions(); - return; - } - // at this point, if the field type is a reference, we must be validating - if (expr->tp == TypeExpr::te_Ref && expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type)) { - // field type is a reference to a cell with arbitrary contents - actions += Action{0x10000}; - return; - } - // remaining case: general positive type expression - std::ostringstream ss; - std::string tail; - while (expr->tp == TypeExpr::te_CondType) { - // optimization for (chains of) conditional types ( x?type ) - assert(expr->args.size() == 2); - ss << "(!"; - output_cpp_expr(ss, expr->args[0], 30); - ss << " || "; - expr = expr->args[1]; - tail = std::string{")"} + tail; - } - if ((!validating || any_bits) && can_compute_sizeof(expr)) { - // field size can be computed at run-time, and either the contents is arbitrary, or we are not validating - ss << "cs.advance("; - output_cpp_sizeof_expr(ss, expr, 0); - ss << ")" << tail; - actions += Action{std::move(ss)}; - return; - } - if (expr->tp != TypeExpr::te_Ref) { - // field type is not a reference, generate a type expression and invoke skip/validate_skip method - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << (validating ? "validate_skip(ops, cs, weak)" : "skip(cs)") << tail; - actions += Action{std::move(ss)}; - return; - } - // the (remaining) field type is a reference - if (!validating || (expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type))) { - // the subcase when the field type is either a reference to a cell with arbitrary contents - // or it is a reference, and we are not validating, so we simply skip the reference - ss << "cs.advance_refs(1)" << tail; - actions += Action{std::move(ss)}; - return; - } - // general reference type, invoke validate_skip_ref() - // (notice that we are necessarily validating at this point) - expr = expr->args[0]; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << "validate_skip_ref(ops, cs, weak)" << tail; - actions += Action{ss.str()}; -} - -void CppTypeCode::generate_skip_cons_method(std::ostream& os, std::string nl, int cidx, int options) { - const Constructor& constr = *(type.constructors.at(cidx)); - init_cons_context(constr); - identify_cons_params(constr, options); - identify_cons_neg_params(constr, options); - add_cons_tag_check(constr, cidx, options); - for (const Field& field : constr.fields) { - if (!field.implicit) { - generate_skip_field(constr, field, options); - } else if (!field.constraint) { - compute_implicit_field(constr, field, options); - } else { - add_constraint_check(constr, field, options); - } - } - add_remaining_param_constraints_check(constr, options); - output_actions(os, nl, options); - clear_context(); -} - -void CppTypeCode::generate_skip_method(std::ostream& os, int options) { - bool validate = options & 1; - bool ret_ext = options & 2; - os << "\nbool " << cpp_type_class_name - << "::" << (validate ? "validate_skip(int* ops, vm::CellSlice& cs, bool weak" : "skip(vm::CellSlice& cs"); - if (ret_ext) { - os << skip_extra_args; - } - os << ") const {"; - if (cons_num > 1) { - os << "\n switch (get_tag(cs)) {\n"; - for (int i = 0; i < cons_num; i++) { - os << " case " << cons_enum_name[i] << ":"; - generate_skip_cons_method(os, "\n ", i, options & ~4); - os << "\n"; - } - os << " }\n return false;\n"; - } else if (cons_num == 1) { - generate_skip_cons_method(os, "\n ", 0, options | 4); - os << "\n"; - } else { - os << "\n return false;\n"; - } - os << "}\n"; -} - -void CppTypeCode::generate_cons_tag_check(std::ostream& os, std::string nl, int cidx, bool force) { - const Constructor& constr = *(type.constructors.at(cidx)); - if (!constr.tag_bits) { - os << nl << "return " << cons_enum_name[cidx] << ";"; - } else if (force || cons_num == 1 || !cons_tag_exact.at(cidx)) { - os << nl << "return "; - int l = constr.tag_bits; - unsigned long long tag = (constr.tag >> (64 - l)); - if (l < 64 || tag != ~0ULL) { - os << "cs.prefetch_ulong(" << l << ") == " << HexConstWriter{tag}; - } else { - os << "cs.begins_with(" << l << ", " << HexConstWriter{tag} << ")"; - } - os << " ? " << cons_enum_name[cidx] << " : -1;"; - } else { - os << nl << "return cs.have(" << constr.tag_bits << ") ? " << cons_enum_name[cidx] << " : -1;"; - } -} - -void CppTypeCode::generate_check_tag_method(std::ostream& os) { - os << "\nint " << cpp_type_class_name << "::check_tag(const vm::CellSlice& cs) const {"; - if (cons_num > 1) { - os << "\n switch (get_tag(cs)) {\n"; - for (int i = 0; i < cons_num; i++) { - os << " case " << cons_enum_name[i] << ":"; - generate_cons_tag_check(os, "\n ", i); - os << "\n"; - } - os << " }\n return -1;\n"; - } else if (cons_num == 1) { - generate_cons_tag_check(os, "\n ", 0); - os << "\n"; - } else { - os << "\n return -1;\n"; - } - os << "}\n"; -} - -bool CppTypeCode::output_print_simple_field(std::ostream& os, const Field& field, std::string field_name, - const TypeExpr* expr) { - cpp_val_type cvt = detect_cpp_type(expr); - MinMaxSize sz = expr->compute_size(); - int i = expr->is_integer(); - int l = (sz.is_fixed() ? sz.convert_min_size() : -1); - switch (cvt) { - case ct_bitstring: - case ct_bits: - assert(!(sz.max_size() & 0xff)); - os << "pp.fetch_bits_field(cs, "; - output_cpp_sizeof_expr(os, expr, 0); - if (!field_name.empty()) { - os << ", \"" << field_name << '"'; - } - os << ")"; - return true; - case ct_bool: - case ct_int32: - case ct_uint32: - case ct_int64: - case ct_uint64: - assert(i && l <= 64); - os << "pp.fetch_" << (i > 0 ? "u" : "") << "int_field(cs, "; - output_cpp_sizeof_expr(os, expr, 0); - if (!field_name.empty()) { - os << ", \"" << field_name << '"'; - } - os << ")"; - return true; - case ct_integer: - assert(i); - os << "pp.fetch_" << (i > 0 ? "u" : "") << "int256_field(cs, "; - output_cpp_sizeof_expr(os, expr, 0); - if (!field_name.empty()) { - os << ", \"" << field_name << '"'; - } - os << ")"; - return true; - default: - break; - } - return false; -} - -void CppTypeCode::generate_print_field(const Constructor& constr, const Field& field, int options) { - const TypeExpr* expr = field.type; - MinMaxSize sz = expr->compute_size(); - cpp_val_type cvt = detect_cpp_type(expr); - bool any_bits = expr->compute_any_bits(); - bool is_simple = (cvt >= ct_bits && cvt <= ct_uint64 && cvt != ct_enum); - // std::cerr << "field `" << field.get_name() << "` size is " << sz << "; fixed=" << sz.is_fixed() << "; any=" << any_bits << std::endl; - std::string field_name = field.name ? field.get_name() : ""; - if (field.used || expr->is_nat_subtype) { - // an explicit field of type # or ## - assert(expr->is_nat_subtype && "cannot use fields of non-`#` type"); - std::ostringstream ss; - ss << "pp.field_int(" << add_fetch_nat_field(constr, field, options); - if (field.name) { - ss << ", \"" << field_name << '"'; - } - ss << ')'; - actions += Action{std::move(ss)}; - return; - } - if (sz.is_fixed() && !(sz.min_size() & 0xff) && any_bits) { - // field has fixed size, and either its bits can have arbitrary values (and it has no references) - std::ostringstream ss; - if (output_print_simple_field(ss, field, field_name, expr)) { - actions += Action{std::move(ss)}; - return; - } - } - bool cond_chain = (expr->tp == TypeExpr::te_CondType); - if (!cond_chain && !is_simple) { - if (field.name) { - actions += Action{std::string{"pp.field(\""} + field_name + "\")"}; - } else { - actions += Action{"pp.field()"}; - } - } - if (expr->negated) { - // the field type has some "negative" parameters, which will be computed while checking this field - // must invoke the correct validate_skip or skip method for the type in question - assert(!cond_chain); - std::ostringstream ss; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100, true); - ss << '.'; - } - ss << "print_skip(pp, cs"; - output_negative_type_arguments(ss, expr); - ss << ")"; - actions += Action{std::move(ss)}; - add_postponed_equate_actions(); - return; - } - // remaining case: general positive type expression - std::ostringstream ss; - std::string tail; - while (expr->tp == TypeExpr::te_CondType) { - // optimization for (chains of) conditional types ( x?type ) - assert(expr->args.size() == 2); - ss << "(!"; - output_cpp_expr(ss, expr->args[0], 30); - ss << " || "; - expr = expr->args[1]; - tail += ')'; - } - if (output_print_simple_field(ss, field, field_name, expr)) { - ss << tail; - actions += Action{std::move(ss)}; - return; - } - if (cond_chain) { - if (field.name) { - ss << "(pp.field(\"" + field_name + "\") && "; - } else { - ss << "(pp.field() && "; - } - tail += ')'; - } - if (expr->tp != TypeExpr::te_Ref) { - // field type is not a reference, generate a type expression and invoke skip/validate_skip method - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << "print_skip(pp, cs)" << tail; - actions += Action{std::move(ss)}; - return; - } - // general reference type, invoke print_ref() - expr = expr->args[0]; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << "print_ref(pp, cs.fetch_ref())" << tail; - actions += Action{ss.str()}; -} - -void CppTypeCode::generate_print_cons_method(std::ostream& os, std::string nl, int cidx, int options) { - const Constructor& constr = *(type.constructors.at(cidx)); - init_cons_context(constr); - identify_cons_params(constr, options); - identify_cons_neg_params(constr, options); - add_cons_tag_check(constr, cidx, options); - bool do_open = !constr.is_enum; - if (do_open) { - if (constr.constr_name) { - actions += Action{std::string{"pp.open(\""} + constr.get_name() + "\")"}; - } else { - actions += Action{"pp.open()"}; - } - } else { - actions += Action{std::string{"pp.cons(\""} + constr.get_name() + "\")"}; - } - for (const Field& field : constr.fields) { - if (!field.implicit) { - generate_print_field(constr, field, options); - } else if (!field.constraint) { - compute_implicit_field(constr, field, options); - } else { - add_constraint_check(constr, field, options); - } - } - add_remaining_param_constraints_check(constr, options); - if (do_open) { - actions += Action{"pp.close()"}; - } - output_actions(os, nl, options); - clear_context(); -} - -void CppTypeCode::generate_print_method(std::ostream& os, int options) { - bool ret_ext = options & 2; - os << "\nbool " << cpp_type_class_name << "::print_skip(PrettyPrinter& pp, vm::CellSlice& cs"; - if (ret_ext) { - os << skip_extra_args; - } - os << ") const {"; - if (cons_num > 1) { - os << "\n switch (get_tag(cs)) {\n"; - for (int i = 0; i < cons_num; i++) { - os << " case " << cons_enum_name[i] << ":"; - generate_print_cons_method(os, "\n ", i, options & ~4); - os << "\n"; - } - os << " }\n return pp.fail(\"unknown constructor for " << type.get_name() << "\");\n"; - } else if (cons_num == 1) { - generate_print_cons_method(os, "\n ", 0, options | 4); - os << "\n"; - } else { - os << "\n return pp.fail(\"no constructors for " << type.get_name() << "\");\n"; - } - os << "}\n"; -} - -void CppTypeCode::bind_record_fields(const CppTypeCode::ConsRecord& rec, int options) { - bool direct = options & 8; - bool read_only = options & 32; - for (const ConsField& fi : rec.cpp_fields) { - int i = fi.orig_idx; - assert(field_vars.at(i).empty() && !field_var_set.at(i)); - if (!read_only || !rec.constr.fields.at(i).implicit) { - field_vars[i] = direct ? fi.name : std::string{"data."} + fi.name; - field_var_set[i] = read_only; - } - } -} - -void CppTypeCode::output_fetch_field(std::ostream& os, std::string field_var, const TypeExpr* expr, cpp_val_type cvt) { - int i = expr->is_integer(); - MinMaxSize sz = expr->compute_size(); - int l = (sz.is_fixed() ? sz.convert_min_size() : -1); - switch (cvt) { - case ct_slice: - os << "cs.fetch_subslice_" << (sz.max_size() & 0xff ? "ext_" : "") << "to("; - output_cpp_sizeof_expr(os, expr, 0); - os << ", " << field_var << ")"; - return; - case ct_bitstring: - assert(!(sz.max_size() & 0xff)); - os << "cs.fetch_bitstring_to("; - output_cpp_sizeof_expr(os, expr, 0); - os << ", " << field_var << ")"; - return; - case ct_bits: - assert(l >= 0 && l < 0x10000); - os << "cs.fetch_bits_to(" << field_var << ".bits(), " << l << ")"; - return; - case ct_cell: - assert(l == 0x10000); - os << "cs.fetch_ref_to(" << field_var << ")"; - return; - case ct_bool: - assert(i > 0 && l == 1); - os << "cs.fetch_bool_to(" << field_var << ")"; - return; - case ct_int32: - case ct_uint32: - case ct_int64: - case ct_uint64: - assert(i && l <= 64); - os << "cs.fetch_" << (i > 0 ? "u" : "") << "int_to("; - output_cpp_sizeof_expr(os, expr, 0); - os << ", " << field_var << ")"; - return; - case ct_integer: - assert(i); - os << "cs.fetch_" << (i > 0 ? "u" : "") << "int256_to("; - output_cpp_sizeof_expr(os, expr, 0); - os << ", " << field_var << ")"; - return; - default: - break; - } - throw src::Fatal{"cannot fetch a field of unknown scalar type"}; -} - -void CppTypeCode::output_fetch_subrecord(std::ostream& os, std::string field_name, const ConsRecord* subrec) { - assert(subrec); - os << subrec->cpp_type.cpp_type_var_name << ".cell_unpack(cs.fetch_ref(), " << field_name << ")"; -} - -void CppTypeCode::generate_unpack_field(const CppTypeCode::ConsField& fi, const Constructor& constr, const Field& field, - int options) { - int i = field.field_idx; - const TypeExpr* expr = field.type; - MinMaxSize sz = expr->compute_size(); - bool any_bits = expr->compute_any_bits(); - bool validating = (options & 1); - cpp_val_type cvt = fi.ctype; - // std::cerr << "field `" << field.get_name() << "` size is " << sz << "; fixed=" << sz.is_fixed() << "; any=" << any_bits << std::endl; - if (field.used || expr->is_nat_subtype) { - assert(expr->is_nat_subtype && "cannot use fields of non-`#` type"); - assert(cvt == ct_int32 || cvt == ct_bool); - add_fetch_nat_field(constr, field, options); - return; - } - if (sz.is_fixed() && cvt != ct_enum && (!validating || (!(sz.min_size() & 0xff) && any_bits))) { - // field has fixed size, and either its bits can have arbitrary values (and it has no references) - // ... or we are not validating - // simply skip the necessary amount of bits - // NB: if the field is a reference, and we are not validating, we arrive here - if (cvt == ct_cell) { - assert(sz.min_size() == 1); - } - std::ostringstream ss; - if (cvt == ct_subrecord && field.subrec) { - output_fetch_subrecord(ss, field_vars.at(i), fi.subrec); - } else { - output_fetch_field(ss, field_vars.at(i), expr, cvt); - } - actions += Action{std::move(ss)}; - field_var_set[i] = true; - return; - } - if (expr->negated) { - // the field type has some "negative" parameters, which will be computed while checking this field - // must invoke the correct validate_skip or skip method for the type in question - std::ostringstream ss; - assert(cvt == ct_slice); - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100, true); - ss << '.'; - } - ss << (validating ? "validate_fetch_to(ops, cs, weak, " : "fetch_to(cs, ") << field_vars.at(i); - output_negative_type_arguments(ss, expr); - ss << ")"; - actions += Action{std::move(ss)}; - add_postponed_equate_actions(); - field_var_set[i] = true; - return; - } - // at this point, if the field type is a reference, we must be validating - if (expr->tp == TypeExpr::te_Ref && expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type)) { - // field type is a reference to a cell with arbitrary contents - assert(cvt == ct_cell); - actions += Action{"cs.fetch_ref_to(" + field_vars.at(i) + ")"}; - field_var_set[i] = true; - return; - } - // remaining case: general positive type expression - std::ostringstream ss; - std::string tail; - while (expr->tp == TypeExpr::te_CondType) { - // optimization for (chains of) conditional types ( x?type ) - assert(expr->args.size() == 2); - ss << "(!"; - output_cpp_expr(ss, expr->args[0], 30); - ss << " || "; - expr = expr->args[1]; - tail = std::string{")"} + tail; - } - if ((!validating || any_bits) && can_compute_sizeof(expr) && cvt != ct_enum) { - // field size can be computed at run-time, and either the contents is arbitrary, or we are not validating - output_fetch_field(ss, field_vars.at(i), expr, cvt); - field_var_set[i] = true; - ss << tail; - actions += Action{std::move(ss)}; - return; - } - if (expr->tp != TypeExpr::te_Ref) { - // field type is not a reference, generate a type expression and invoke skip/validate_skip method - assert(cvt == ct_slice || cvt == ct_enum); - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << (validating ? "validate_" : "") << "fetch_" << (cvt == ct_enum ? "enum_" : "") - << (validating ? "to(ops, cs, weak, " : "to(cs, ") << field_vars.at(i) << ")" << tail; - field_var_set[i] = true; - actions += Action{std::move(ss)}; - return; - } - // the (remaining) field type is a reference - if (!validating || (expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type))) { - // the subcase when the field type is either a reference to a cell with arbitrary contents - // or it is a reference, and we are not validating, so we simply skip the reference - assert(cvt == ct_cell); - ss << "cs.fetch_ref_to(" << field_vars.at(i) << ")" << tail; - field_var_set[i] = true; - actions += Action{std::move(ss)}; - return; - } - // general reference type, invoke validate_skip_ref() - // (notice that we are necessarily validating at this point) - expr = expr->args[0]; - assert(cvt == ct_cell); - ss << "(cs.fetch_ref_to(" << field_vars.at(i) << ") && "; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << "validate_ref(ops, " << field_vars.at(i) << "))" << tail; - actions += Action{ss.str()}; -} - -void CppTypeCode::generate_unpack_method(std::ostream& os, CppTypeCode::ConsRecord& rec, int options) { - std::ostringstream tmp; - if (!rec.declare_record_unpack(tmp, "", options)) { - return; - } - tmp.clear(); - os << "\n"; - bool res = rec.declare_record_unpack(os, "", options | 3072); - DCHECK(res); - if (options & 16) { - // cell unpack version - os << "\n if (cell_ref.is_null()) { return false; }" - << "\n auto cs = load_cell_slice(std::move(cell_ref));" - << "\n return " << (options & 1 ? "validate_" : "") << "unpack"; - if (!(options & 8)) { - os << "("; - if (options & 1) { - os << "ops, "; - } - os << "cs, data"; - } else { - os << "_" << cons_enum_name.at(rec.cons_idx) << "(cs"; - for (const auto& f : rec.cpp_fields) { - os << ", " << f.name; - } - } - if (options & 2) { - os << skip_extra_args_pass; - } - os << ") && cs.empty_ext();\n}\n"; - return; - } - init_cons_context(rec.constr); - bind_record_fields(rec, options); - identify_cons_params(rec.constr, options); - identify_cons_neg_params(rec.constr, options); - add_cons_tag_check(rec.constr, rec.cons_idx, 9 /* (options & 1) | 8 */); - auto it = rec.cpp_fields.cbegin(), end = rec.cpp_fields.cend(); - for (const Field& field : rec.constr.fields) { - if (field.constraint) { - add_constraint_check(rec.constr, field, options); - continue; - } - if (!field.implicit) { - assert(it < end && it->orig_idx == field.field_idx); - generate_unpack_field(*it++, rec.constr, field, options); - } else { - if (it < end && it->orig_idx == field.field_idx) { - ++it; - } - compute_implicit_field(rec.constr, field, options); - } - } - assert(it == end); - add_remaining_param_constraints_check(rec.constr, options); - output_actions(os, "\n ", options | 4); - clear_context(); - os << "\n}\n"; -} - -void CppTypeCode::output_store_field(std::ostream& os, std::string field_var, const TypeExpr* expr, cpp_val_type cvt) { - int i = expr->is_integer(); - MinMaxSize sz = expr->compute_size(); - int l = (sz.is_fixed() ? sz.convert_min_size() : -1); - switch (cvt) { - case ct_slice: - os << "cb.append_cellslice_chk(" << field_var << ", "; - output_cpp_sizeof_expr(os, expr, 0); - os << ")"; - return; - case ct_bitstring: - assert(!(sz.max_size() & 0xff)); - os << "cb.append_bitstring_chk(" << field_var << ", "; - output_cpp_sizeof_expr(os, expr, 0); - os << ")"; - return; - case ct_bits: - assert(l >= 0 && l < 0x10000); - os << "cb.store_bits_bool(" << field_var << ".cbits(), " << l << ")"; - return; - case ct_cell: - assert(l == 0x10000); - os << "cb.store_ref_bool(" << field_var << ")"; - return; - case ct_bool: - assert(i > 0 && l == 1); - // os << "cb.store_bool(" << field_var << ")"; - // return; - // fall through - case ct_int32: - case ct_uint32: - case ct_int64: - case ct_uint64: - assert(i && l <= 64); - os << "cb.store_" << (i > 0 ? "u" : "") << "long_rchk_bool(" << field_var << ", "; - output_cpp_sizeof_expr(os, expr, 0); - os << ")"; - return; - case ct_integer: - assert(i); - os << "cb.store_int256_bool(" << field_var << ", "; - output_cpp_sizeof_expr(os, expr, 0); - os << (i > 0 ? ", false)" : ")"); - return; - default: - break; - } - throw src::Fatal{"cannot store a field of unknown scalar type"}; -} - -void CppTypeCode::add_store_subrecord(std::string field_name, const ConsRecord* subrec) { - assert(subrec); - needs_tmp_cell = true; - std::ostringstream ss; - ss << subrec->cpp_type.cpp_type_var_name << ".cell_pack(tmp_cell, " << field_name << ")"; - actions += Action{std::move(ss)}; - actions += Action{"cb.store_ref_bool(std::move(tmp_cell))"}; -} - -void CppTypeCode::generate_pack_field(const CppTypeCode::ConsField& fi, const Constructor& constr, const Field& field, - int options) { - int i = field.field_idx; - const TypeExpr* expr = field.type; - MinMaxSize sz = expr->compute_size(); - bool any_bits = expr->compute_any_bits(); - bool validating = (options & 1); - cpp_val_type cvt = fi.ctype; - // std::cerr << "field `" << field.get_name() << "` size is " << sz << "; fixed=" << sz.is_fixed() << "; any=" << any_bits << std::endl; - if (field.used || expr->is_nat_subtype) { - assert(expr->is_nat_subtype && "cannot use fields of non-`#` type"); - assert(cvt == ct_int32 || cvt == ct_bool); - add_store_nat_field(constr, field, options); - return; - } - if (sz.is_fixed() && cvt != ct_enum && (!validating || (!(sz.min_size() & 0xff) && any_bits))) { - // field has fixed size, and either its bits can have arbitrary values (and it has no references) - // ... or we are not validating - // simply skip the necessary amount of bits - // NB: if the field is a reference, and we are not validating, we arrive here - if (cvt == ct_cell) { - assert(sz.min_size() == 1); - } - if (cvt == ct_subrecord && field.subrec) { - add_store_subrecord(field_vars.at(i), fi.subrec); - } else { - std::ostringstream ss; - output_store_field(ss, field_vars.at(i), expr, cvt); - actions += Action{std::move(ss)}; - } - field_var_set[i] = true; - return; - } - if (expr->negated) { - // the field type has some "negative" parameters, which will be computed while checking this field - // must invoke the correct validate_skip or skip method for the type in question - std::ostringstream ss; - assert(cvt == ct_slice); - ss << "tlb::" << (validating ? "validate_" : "") << "store_from(cb, "; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 5, true); - } else { - ss << "*this"; - } - ss << ", " << field_vars.at(i); - output_negative_type_arguments(ss, expr); - ss << ")"; - actions += Action{std::move(ss)}; - add_postponed_equate_actions(); - field_var_set[i] = true; - return; - } - // at this point, if the field type is a reference, we must be validating - if (expr->tp == TypeExpr::te_Ref && expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type)) { - // field type is a reference to a cell with arbitrary contents - assert(cvt == ct_cell); - actions += Action{"cb.store_ref_bool(" + field_vars.at(i) + ")"}; - field_var_set[i] = true; - return; - } - // remaining case: general positive type expression - std::ostringstream ss; - std::string tail; - while (expr->tp == TypeExpr::te_CondType) { - // optimization for (chains of) conditional types ( x?type ) - assert(expr->args.size() == 2); - ss << "(!"; - output_cpp_expr(ss, expr->args[0], 30); - ss << " || "; - expr = expr->args[1]; - tail = std::string{")"} + tail; - } - if ((!validating || any_bits) && can_compute_sizeof(expr) && cvt != ct_enum) { - // field size can be computed at run-time, and either the contents is arbitrary, or we are not validating - output_store_field(ss, field_vars.at(i), expr, cvt); - field_var_set[i] = true; - ss << tail; - actions += Action{std::move(ss)}; - return; - } - if (expr->tp != TypeExpr::te_Ref) { - // field type is not a reference, generate a type expression and invoke skip/validate_skip method - assert(cvt == ct_slice || cvt == ct_enum); - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << (validating ? "validate_" : "") << "store_" << (cvt == ct_enum ? "enum_" : "") << "from(cb, " - << field_vars.at(i) << ")" << tail; - field_var_set[i] = true; - actions += Action{std::move(ss)}; - return; - } - // the (remaining) field type is a reference - if (!validating || (expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Cell_type || expr->args[0]->type_applied == Any_type))) { - // the subcase when the field type is either a reference to a cell with arbitrary contents - // or it is a reference, and we are not validating, so we simply skip the reference - assert(cvt == ct_cell); - ss << "cb.store_ref_bool(" << field_vars.at(i) << ")" << tail; - field_var_set[i] = true; - actions += Action{std::move(ss)}; - return; - } - // general reference type, invoke validate_skip_ref() - // (notice that we are necessarily validating at this point) - expr = expr->args[0]; - assert(cvt == ct_cell); - ss << "(cb.store_ref_bool(" << field_vars.at(i) << ") && "; - if (!is_self(expr, constr)) { - output_cpp_expr(ss, expr, 100); - ss << '.'; - } - ss << "validate_ref(ops, " << field_vars.at(i) << "))" << tail; - actions += Action{ss.str()}; -} - -void CppTypeCode::generate_pack_method(std::ostream& os, CppTypeCode::ConsRecord& rec, int options) { - std::ostringstream tmp; - if (!rec.declare_record_pack(tmp, "", options)) { - return; - } - tmp.clear(); - os << "\n"; - bool res = rec.declare_record_pack(os, "", options | 3072); - DCHECK(res); - if (options & 16) { - // cell pack version - os << "\n vm::CellBuilder cb;" - << "\n return " << (options & 1 ? "validate_" : "") << "pack"; - if (!(options & 8)) { - os << "(cb, data"; - } else { - os << "_" << cons_enum_name.at(rec.cons_idx) << "(cb"; - for (const auto& f : rec.cpp_fields) { - // skip SOME implicit fields ??? - if (f.implicit) { - } else if (f.get_cvt().needs_move()) { - os << ", std::move(" << f.name << ")"; - } else { - os << ", " << f.name; - } - } - } - if (options & 2) { - os << skip_extra_args_pass; - } - os << ") && std::move(cb).finalize_to(cell_ref);\n}\n"; - return; - } - init_cons_context(rec.constr); - bind_record_fields(rec, options | 32); - identify_cons_params(rec.constr, options); - identify_cons_neg_params(rec.constr, options); - add_cons_tag_store(rec.constr, rec.cons_idx); - auto it = rec.cpp_fields.cbegin(), end = rec.cpp_fields.cend(); - for (const Field& field : rec.constr.fields) { - if (field.constraint) { - add_constraint_check(rec.constr, field, options); - continue; - } - if (!field.implicit) { - assert(it < end && it->orig_idx == field.field_idx); - generate_pack_field(*it++, rec.constr, field, options); - } else { - if (it < end && it->orig_idx == field.field_idx) { - ++it; - } - compute_implicit_field(rec.constr, field, options); - } - } - assert(it == end); - add_remaining_param_constraints_check(rec.constr, options); - output_actions(os, "\n ", options | 4); - clear_context(); - os << "\n}\n"; -} - -void CppTypeCode::generate_ext_fetch_to(std::ostream& os, int options) { - std::string validate = (options & 1) ? "validate_" : ""; - os << "\nbool " << cpp_type_class_name << "::" << validate << "fetch_to(vm::CellSlice& cs, Ref& res" - << skip_extra_args << ") const {\n" - << " res = Ref{true, cs};\n" - << " return " << validate << "skip(cs" << skip_extra_args_pass << ") && res.unique_write().cut_tail(cs);\n" - << "}\n"; -} - -void CppTypeCode::ConsRecord::declare_record(std::ostream& os, std::string nl, int options) { - bool force = options & 1024; - if (declared) { - return; - } - if (!force) { - os << nl << "struct " << cpp_name; - if (!inline_record) { - os << ";\n"; - return; - } - } else { - os << "\n" << nl << "struct " << cpp_type.cpp_type_class_name << "::" << cpp_name; - } - os << " {\n"; - os << nl << " typedef " << cpp_type.cpp_type_class_name << " type_class;\n"; - CppIdentSet rec_cpp_ids; - recover_idents(rec_cpp_ids); - std::size_t n = cpp_fields.size(); - for (const ConsField& fi : cpp_fields) { - os << nl << " "; - fi.print_type(os); - os << " " << fi.name << "; \t// "; - if (fi.field.name) { - os << fi.field.get_name() << " : "; - } - fi.field.type->show(os, &constr); - os << std::endl; - } - if (n) { - os << nl << " " << cpp_name << "() = default;\n"; - std::vector ctor_args; - os << nl << " " << cpp_name << "("; - int i = 0, j = 0; - for (const ConsField& fi : cpp_fields) { - if (!fi.implicit) { - std::string arg = rec_cpp_ids.new_ident(std::string{"_"} + fi.name); - ctor_args.push_back(arg); - if (i++) { - os << ", "; - } - fi.print_type(os, true); - os << " " << arg; - } - } - os << ") : "; - i = 0; - for (const ConsField& fi : cpp_fields) { - if (i++) { - os << ", "; - } - os << fi.name << "("; - if (fi.implicit) { - os << (fi.ctype == ct_int32 ? "-1" : "nullptr"); - } else if (fi.get_cvt().needs_move()) { - os << "std::move(" << ctor_args.at(j++) << ")"; - } else { - os << ctor_args.at(j++); - } - os << ")"; - } - os << " {}\n"; - } - os << nl << "};\n"; - declared = true; -} - -bool CppTypeCode::ConsRecord::declare_record_unpack(std::ostream& os, std::string nl, int options) { - bool is_ok = false; - bool cell = options & 16; - std::string slice_arg = cell ? "Ref cell_ref" : "vm::CellSlice& cs"; - std::string fun_name = (options & 1) ? "validate_unpack" : "unpack"; - if (cell) { - fun_name = std::string{"cell_"} + fun_name; - } - std::string class_name; - if (options & 2048) { - class_name = cpp_type.cpp_type_class_name + "::"; - } - if (!(options & 8)) { - os << nl << "bool " << class_name << fun_name << "(" << slice_arg << ", " << class_name << cpp_name << "& data"; - is_ok = true; - } else if (is_small) { - os << nl << "bool " << class_name << fun_name << "_" << cpp_type.cons_enum_name.at(cons_idx) << "(" << slice_arg; - for (const auto& f : cpp_fields) { - os << ", " << f.get_cvt() << "& " << f.name; - } - is_ok = true; - } - if (is_ok) { - if (options & 2) { - os << cpp_type.skip_extra_args; - } - os << ") const" << (options & 1024 ? " {" : ";\n"); - } - return is_ok; -} - -bool CppTypeCode::ConsRecord::declare_record_pack(std::ostream& os, std::string nl, int options) { - bool is_ok = false; - bool cell = options & 16; - std::string builder_arg = cell ? "Ref& cell_ref" : "vm::CellBuilder& cb"; - std::string fun_name = (options & 1) ? "validate_pack" : "pack"; - if (cell) { - fun_name = std::string{"cell_"} + fun_name; - } - std::string class_name; - if (options & 2048) { - class_name = cpp_type.cpp_type_class_name + "::"; - } - if (!(options & 8)) { - os << nl << "bool " << class_name << fun_name << "(" << builder_arg << ", const " << class_name << cpp_name - << "& data"; - is_ok = true; - } else if (is_small) { - os << nl << "bool " << class_name << fun_name << "_" << cpp_type.cons_enum_name.at(cons_idx) << "(" << builder_arg; - for (const auto& f : cpp_fields) { - // skip SOME implicit fields ??? - if (!f.implicit) { - os << ", " << f.get_cvt() << " " << f.name; - } - } - is_ok = true; - } - if (is_ok) { - if (options & 2) { - os << cpp_type.skip_extra_args; - } - os << ") const" << (options & 1024 ? " {" : ";\n"); - } - return is_ok; -} - -void CppTypeCode::generate_fetch_enum_method(std::ostream& os, int options) { - int minl = type.size.convert_min_size(), maxl = type.size.convert_max_size(); - bool exact = type.cons_all_exact(); - std::string ctag = incremental_cons_tags ? "(unsigned)t" : "cons_tag[t]"; - os << "\nbool " << cpp_type_class_name << "::fetch_enum_to(vm::CellSlice& cs, char& value) const {\n"; - if (!cons_num) { - os << " value = -1;\n" - " return false;\n"; - } else if (!maxl) { - os << " value = 0;\n" - " return true;\n"; - } else if (cons_num == 1) { - const Constructor& constr = *type.constructors.at(0); - os << " value = (cs.fetch_ulong(" << minl << ") == " << HexConstWriter{constr.tag >> (64 - constr.tag_bits)} - << ") ? 0 : -1;\n"; - os << " return !value;\n"; - } else if (minl == maxl) { - if (exact) { - os << " value = (char)cs.fetch_ulong(" << minl << ");\n"; - os << " return value >= 0;\n"; - } else { - os << " int t = get_tag(cs);\n"; - os << " value = (char)t;\n"; - os << " return t >= 0 && cs.fetch_ulong(" << minl << ") == " << ctag << ";\n"; - } - } else if (exact) { - os << " int t = get_tag(cs);\n"; - os << " value = (char)t;\n"; - os << " return t >= 0 && cs.advance(cons_len[t]);\n"; - } else { - os << " int t = get_tag(cs);\n"; - os << " value = (char)t;\n"; - os << " return t >= 0 && cs.fetch_ulong(cons_len[t]) == " << ctag << ";\n"; - } - os << "}\n"; -} - -void CppTypeCode::generate_store_enum_method(std::ostream& os, int options) { - int minl = type.size.convert_min_size(), maxl = type.size.convert_max_size(); - bool exact = type.cons_all_exact(); - std::string ctag = incremental_cons_tags ? "value" : "cons_tag[value]"; - os << "\nbool " << cpp_type_class_name << "::store_enum_from(vm::CellBuilder& cb, int value) const {\n"; - if (!cons_num) { - os << " return false;\n"; - } else if (!maxl) { - os << " return !value;\n"; - } else if (cons_num == 1) { - const Constructor& constr = *type.constructors.at(0); - os << " return !value && cb.store_long_bool(" << HexConstWriter{constr.tag >> (64 - constr.tag_bits)} << ", " - << minl << ");\n"; - } else if (minl == maxl) { - if (exact) { - os << " return cb.store_long_rchk_bool(value, " << minl << ");\n"; - } else if (incremental_cons_tags && cons_num > (1 << (minl - 1))) { - os << " return cb.store_uint_less(" << cons_num << ", value);\n"; - } else { - os << " return (unsigned)value < " << cons_num << " && cb.store_long_bool(" << ctag << ", " << minl << ");\n"; - } - } else { - os << " return (unsigned)value < " << cons_num << " && cb.store_long_bool(" << ctag << ", cons_len[value]);\n"; - } - os << "}\n"; -} - -void CppTypeCode::generate_print_type_body(std::ostream& os, std::string nl) { - std::string name = type.type_name ? type.get_name() : cpp_type_class_name; - if (!tot_params) { - os << nl << "return os << \"" << name << "\";"; - return; - } - os << nl << "return os << \"(" << name; - for (int i = 0; i < tot_params; i++) { - if (type_param_is_neg[i]) { - os << " ~" << type_param_name[i]; - } else { - os << " \" << " << type_param_name[i] << " << \""; - } - } - os << ")\";"; -} - -void CppTypeCode::generate_header(std::ostream& os, int options) { - os << "\nstruct " << cpp_type_class_name << " final : TLB_Complex {\n"; - generate_cons_enum(os); - generate_cons_tag_info(os, " ", 1); - if (params) { - generate_type_fields(os, options); - generate_type_constructor(os, options); - } - for (int i = 0; i < cons_num; i++) { - records.at(i).declare_record(os, " ", options); - } - if (type.is_special) { - os << " bool always_special() const override {\n"; - os << " return true;\n }\n"; - } - int sz = type.size.min_size(); - sz = ((sz & 0xff) << 16) | (sz >> 8); - if (simple_get_size) { - os << " int get_size(const vm::CellSlice& cs) const override {\n"; - os << " return " << SizeWriter{sz} << ";\n }\n"; - } - os << " bool skip(vm::CellSlice& cs) const override"; - if (!inline_skip) { - os << ";\n"; - } else if (sz) { - os << " {\n return cs.advance" << (sz < 0x10000 ? "(" : "_ext(") << SizeWriter{sz} << ");\n }\n"; - } else { - os << " {\n return true;\n }\n"; - } - if (ret_params) { - os << " bool skip(vm::CellSlice& cs" << skip_extra_args << ") const;\n"; - } - os << " bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override"; - if (!inline_validate_skip) { - os << ";\n"; - } else if (sz) { - os << " {\n return cs.advance(" << SizeWriter{sz} << ");\n }\n"; - } else { - os << " {\n return true;\n }\n"; - } - if (ret_params) { - os << " bool validate_skip(int *ops, vm::CellSlice& cs, bool weak" << skip_extra_args << ") const;\n"; - os << " bool fetch_to(vm::CellSlice& cs, Ref& res" << skip_extra_args << ") const;\n"; - } - if (type.is_simple_enum) { - os << " bool fetch_enum_to(vm::CellSlice& cs, char& value) const;\n"; - os << " bool store_enum_from(vm::CellBuilder& cb, int value) const;\n"; - } - for (int i = 0; i < cons_num; i++) { - records[i].declare_record_unpack(os, " ", 2); - records[i].declare_record_unpack(os, " ", 10); - records[i].declare_record_unpack(os, " ", 18); - records[i].declare_record_unpack(os, " ", 26); - records[i].declare_record_pack(os, " ", 2); - records[i].declare_record_pack(os, " ", 10); - records[i].declare_record_pack(os, " ", 18); - records[i].declare_record_pack(os, " ", 26); - } - os << " bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;\n"; - if (ret_params) { - os << " bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs" << skip_extra_args << ") const;\n"; - } - os << " std::ostream& print_type(std::ostream& os) const override {"; - generate_print_type_body(os, "\n "); - os << "\n }\n"; - os << " int check_tag(const vm::CellSlice& cs) const override;\n"; - os << " int get_tag(const vm::CellSlice& cs) const override"; - if (inline_get_tag) { - os << " {"; - generate_get_tag_body(os, "\n "); - os << "\n }\n"; - } else { - os << ";\n"; - } - os << "};\n"; - for (int i = 0; i < cons_num; i++) { - records.at(i).declare_record(os, "", options | 1024); - } - if (!cpp_type_var_name.empty()) { - os << "\nextern const " << cpp_type_class_name << " " << cpp_type_var_name << ";\n"; - } -} - -void CppTypeCode::generate_body(std::ostream& os, int options) { - generate_cons_tag_info(os, "", 2); - if (!inline_get_tag) { - os << "\nint " << cpp_type_class_name << "::get_tag(const vm::CellSlice& cs) const {"; - generate_get_tag_body(os, "\n "); - os << "\n}\n"; - } - generate_check_tag_method(os); - options &= -4; - if (!inline_skip) { - generate_skip_method(os, options); - } - if (ret_params) { - generate_skip_method(os, options + 2); - } - if (!inline_validate_skip) { - generate_skip_method(os, options + 1); - } - if (ret_params) { - generate_skip_method(os, options + 3); - generate_ext_fetch_to(os, options); - } - if (type.is_simple_enum) { - generate_fetch_enum_method(os, options); - generate_store_enum_method(os, options); - } - for (int i = 0; i < cons_num; i++) { - ConsRecord& rec = records.at(i); - generate_unpack_method(os, rec, 2); - generate_unpack_method(os, rec, 10); - generate_unpack_method(os, rec, 18); - generate_unpack_method(os, rec, 26); - } - for (int i = 0; i < cons_num; i++) { - ConsRecord& rec = records.at(i); - generate_pack_method(os, rec, 2); - generate_pack_method(os, rec, 10); - generate_pack_method(os, rec, 18); - generate_pack_method(os, rec, 26); - } - generate_print_method(os, options + 1); - if (ret_params) { - generate_print_method(os, options + 3); - } - if (!cpp_type_var_name.empty()) { - os << "\nconst " << cpp_type_class_name << " " << cpp_type_var_name << ";"; - } - os << std::endl; -} - -void CppTypeCode::generate(std::ostream& os, int options) { - std::string type_name = type.get_name(); - if (!type.type_name && type.is_auto) { - type_name = cpp_type_class_name; - } - if (options & 1) { - os << "\n//\n// headers for " << (type.is_auto ? "auxiliary " : "") << "type `" << type_name << "`\n//\n"; - generate_header(os, options); - } else if (options & 2) { - std::ostringstream tmp; - generate_header(tmp, options | 1); - } - if (options & 2) { - os << "\n//\n// code for " << (type.is_auto ? "auxiliary " : "") << "type `" << type_name << "`\n//\n"; - generate_body(os, options); - } -} - -void generate_type_constant(std::ostream& os, int i, TypeExpr* expr, std::string cpp_name, int mode) { - if (!mode) { - os << "// " << expr << std::endl; - os << "extern "; - } - std::string cls_name = "TLB"; - int fake_arg = -1; - cls_name = compute_type_expr_class_name(expr, fake_arg); - os << "const " << cls_name << ' ' << cpp_name; - if (!mode) { - os << ";\n"; - return; - } - int c = 0; - if (fake_arg >= 0) { - os << '{' << fake_arg; - c++; - } - for (const TypeExpr* arg : expr->args) { - if (!arg->negated) { - assert(arg->is_constexpr); - os << (c++ ? ", " : "{"); - if (arg->is_nat) { - os << arg->value; - } else { - os << const_type_expr_cpp_idents.at(arg->is_constexpr); - } - } - } - if (c) { - os << '}'; - } - os << ";\n"; -} - -void generate_type_constants(std::ostream& os, int mode) { - os << "\n// " << (mode ? "definitions" : "declarations") << " of constant types used\n\n"; - for (int i = 1; i <= const_type_expr_num; i++) { - TypeExpr* expr = const_type_expr[i]; - if (!expr->is_nat && !const_type_expr_simple[i]) { - generate_type_constant(os, i, expr, const_type_expr_cpp_idents[i], mode); - } - } -} - -void generate_register_function(std::ostream& os, int mode) { - os << "\n// " << (mode ? "definition" : "declaration") << " of type name registration function\n"; - if (!mode) { - os << "extern bool register_simple_types(std::function func);\n"; - return; - } - os << "bool register_simple_types(std::function func) {\n"; - os << " return "; - int k = 0; - for (int i = builtin_types_num; i < types_num; i++) { - Type& type = types[i]; - CppTypeCode& cc = *cpp_type[i]; - if (!cc.cpp_type_var_name.empty() && type.type_name) { - if (k++) { - os << "\n && "; - } - os << "func(\"" << type.get_name() << "\", &" << cc.cpp_type_var_name << ")"; - } - } - if (!k) { - os << "true"; - } - os << ";\n}\n\n"; -} - -void assign_const_type_cpp_idents() { - const_type_expr_cpp_idents.resize(const_type_expr_num + 1, ""); - const_type_expr_simple.resize(const_type_expr_num + 1, false); - for (int i = 1; i <= const_type_expr_num; i++) { - const TypeExpr* expr = const_type_expr[i]; - if (!expr->is_nat) { - if (expr->tp == TypeExpr::te_Ref && expr->args[0]->tp == TypeExpr::te_Apply && - (expr->args[0]->type_applied == Any_type || expr->args[0]->type_applied == Cell_type)) { - const_type_expr_cpp_idents[i] = "t_RefCell"; - const_type_expr_simple[i] = true; - continue; - } - if (expr->tp == TypeExpr::te_Apply) { - const Type* typ = expr->type_applied; - int idx = typ->type_idx; - if (typ == Any_type || typ == Cell_type || typ == Nat_type) { - const_type_expr_cpp_idents[i] = (typ == Nat_type ? "t_Nat" : "t_Anything"); - const_type_expr_simple[i] = true; - continue; - } - if (idx >= builtin_types_num && idx < types_num && !cpp_type[idx]->params) { - const_type_expr_cpp_idents[i] = cpp_type[idx]->cpp_type_var_name; - const_type_expr_simple[i] = true; - continue; - } - } - std::ostringstream ss; - ss << "t"; - expr->const_type_name(ss); - const_type_expr_cpp_idents[i] = global_cpp_ids.new_ident(ss.str()); - } - } -} - -std::string cpp_namespace = "tlb"; -std::vector cpp_namespace_list; -std::string tlb_library_header_name = "tl/tlblib.hpp"; - -void split_namespace_id() { - auto prev_it = cpp_namespace.cbegin(); - for (auto it = cpp_namespace.cbegin(); it != cpp_namespace.cend(); ++it) { - if (it[0] == ':' && it + 2 != cpp_namespace.cend() && it[1] == ':') { - if (prev_it != it) { - cpp_namespace_list.emplace_back(prev_it, it); - } - ++it; - prev_it = it + 1; - } - } - if (prev_it != cpp_namespace.cend()) { - cpp_namespace_list.emplace_back(prev_it, cpp_namespace.cend()); - } -} - -std::vector type_gen_order; - -void prepare_generate_cpp(int options = 0) { - std::vector> pairs; - pairs.reserve(types_num - builtin_types_num); - for (int i = builtin_types_num; i < types_num; i++) { - pairs.emplace_back(types.at(i).last_declared, i); - } - std::sort(pairs.begin(), pairs.end()); - type_gen_order.reserve(pairs.size()); - for (auto z : pairs) { - type_gen_order.push_back(z.second); - } - cpp_type.resize(types_num); - for (int i : type_gen_order) { - Type& type = types[i]; - cpp_type[i] = std::make_unique(type); - CppTypeCode& cc = *cpp_type[i]; - if (!cpp_type[i] || !cc.is_ok()) { - throw src::Fatal{std::string{"cannot generate c++ code for type `"} + type.get_name() + "`"}; - } - } - split_namespace_id(); - assign_const_type_cpp_idents(); -} - -bool generate_prepared; -bool gen_cpp; -bool gen_hpp; -bool append_suffix; - -void generate_cpp_output_to(std::ostream& os, int options = 0, std::vector include_files = {}) { - if (!generate_prepared) { - prepare_generate_cpp(options); - generate_prepared = true; - } - if (options & 1) { - os << "#pragma once\n"; - } - for (auto s : include_files) { - if (s.size() >= 10 && s.substr(s.size() - 10) == "tlblib.hpp") { - os << "#include <" << s << ">\n"; - } else { - os << "#include \"" << s << "\"\n"; - } - } - os << "/*\n *\n * AUTO-GENERATED FROM"; - for (auto s : source_list) { - if (s.empty()) { - os << " stdin"; - } else { - os << " `" << s << "`"; - } - } - os << "\n *\n */\n"; - for (int i = 0; i < builtin_types_num; i++) { - Type& type = types[i]; - if (type.used) { - os << "// uses built-in type `" << type.get_name() << "`\n"; - } - } - for (auto cpp_nsp : cpp_namespace_list) { - os << "\nnamespace " << cpp_nsp << " {" << std::endl; - }; - if (cpp_namespace != "tlb") { - os << "using namespace ::tlb;\n"; - } - os << "using td::Ref;\n" - << "using vm::CellSlice;\n" - << "using vm::Cell;\n" - << "using td::RefInt256;\n"; - for (int pass = 1; pass <= 2; pass++) { - if (options & pass) { - for (int i : type_gen_order) { - CppTypeCode& cc = *cpp_type[i]; - cc.generate(os, (options & -4) | pass); - } - generate_type_constants(os, pass - 1); - generate_register_function(os, pass - 1); - } - } - for (auto it = cpp_namespace_list.rbegin(); it != cpp_namespace_list.rend(); ++it) { - os << "\n} // namespace " << *it << std::endl; - } -} - -void generate_cpp_output_to(std::string filename, int options = 0, std::vector include_files = {}) { - std::stringstream ss; - generate_cpp_output_to(ss, options, std::move(include_files)); - auto new_content = ss.str(); - auto r_old_content = td::read_file_str(filename); - if (r_old_content.is_ok() && r_old_content.ok() == new_content) { - return; - } - std::ofstream os{filename}; - if (!os) { - throw src::Fatal{std::string{"cannot create output file `"} + filename + "`"}; - } - os << new_content; -} - -void generate_cpp_output(std::string filename = "", int options = 0) { - if (!gen_cpp && !gen_hpp) { - gen_cpp = gen_hpp = true; - } - options &= ~3; - options |= (gen_hpp ? 1 : 0) | (gen_cpp << 1); - if (filename.empty()) { - generate_cpp_output_to(std::cout, options, {tlb_library_header_name}); - } else if (!append_suffix) { - generate_cpp_output_to(filename, options, {tlb_library_header_name}); - } else { - if (gen_hpp) { - generate_cpp_output_to(filename + ".h", options & ~2, {tlb_library_header_name}); - } - if (gen_cpp) { - generate_cpp_output_to(filename + ".cpp", options & ~1, {filename + ".h"}); - } - } -} - -} // namespace tlbc diff --git a/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.h b/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.h deleted file mode 100644 index 351f9257..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlbc-gen-cpp.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace tlbc { - -extern std::set forbidden_cpp_idents, local_forbidden_cpp_idents; - -struct CppIdentSet { - std::set cpp_idents; - const std::set* extra_forbidden_idents; - CppIdentSet(const std::set* forbid = nullptr) : extra_forbidden_idents(forbid) { - } - static std::string compute_cpp_ident(std::string orig_ident, int count = 0); - std::string new_ident(std::string orig_ident, int count = 0, std::string suffix = ""); - bool insert(std::string ident) { - return cpp_idents.insert(ident).second; - } - bool defined(std::string ident) { - return cpp_idents.count(ident); - } - bool is_good_ident(std::string ident); - void clear() { - cpp_idents.clear(); - } -}; - -extern CppIdentSet global_cpp_ids; - -struct Action { - int fixed_size; - bool is_pure; - bool is_constraint; - std::string action; - Action(int _size) : fixed_size(_size), is_pure(false), is_constraint(false) { - } - Action(std::string _action, bool _cst = false) - : fixed_size(-1), is_pure(false), is_constraint(_cst), action(_action) { - } - Action(const std::ostringstream& ss, bool _cst = false) - : fixed_size(-1), is_pure(false), is_constraint(_cst), action(ss.str()) { - } - Action(std::ostringstream&& ss, bool _cst = false) - : fixed_size(-1), is_pure(false), is_constraint(_cst), action(std::move(ss).str()) { - } - void show(std::ostream& os) const; - bool may_combine(const Action& next) const; - bool operator+=(const Action& next); -}; - -enum cpp_val_type { - ct_unknown, - ct_void = 1, - ct_slice = 2, - ct_cell = 3, - ct_typeref = 4, - ct_typeptr = 5, - ct_bits = 6, - ct_bitstring = 7, - ct_integer = 8, - ct_bool = 10, - ct_enum = 11, - ct_int32 = 12, - ct_uint32 = 13, - ct_int64 = 14, - ct_uint64 = 15, - ct_subrecord = 16 -}; - -struct CppValType { - cpp_val_type vt; - int size; - CppValType(cpp_val_type _vt = ct_unknown, int _size = -1) : vt(_vt), size(_size) { - } - cpp_val_type get() const { - return vt; - } - void show(std::ostream& os, bool pass_value = false) const; - bool needs_move() const; -}; - -extern std::ostream& operator<<(std::ostream& os, CppValType cvt); - -class CppTypeCode { - Type& type; - bool ok; - bool builtin; - bool inline_get_tag; - bool inline_skip; - bool inline_validate_skip; - bool simple_get_size; - bool simple_cons_tags; - bool incremental_cons_tags; - - public: - int params; - int tot_params; - int ret_params; - int cons_num; - int common_cons_len; - std::vector cons_enum_name; - std::vector cons_enum_value; - std::vector cons_tag_map; - std::vector cons_tag_exact; - std::vector cons_idx_by_enum; - std::string cpp_type_var_name; - std::string cpp_type_class_name; - std::string cpp_type_template_name; - - struct ConsRecord; - - struct ConsField { - const Field& field; - const ConsRecord* subrec; - std::string name; - cpp_val_type ctype; - int size; - int orig_idx; - bool implicit; - ConsField(const Field& _field, std::string _name, cpp_val_type _ctype, int _size, int _idx, - const ConsRecord* _subrec = nullptr, bool _implicit = false) - : field(_field), subrec(_subrec), name(_name), ctype(_ctype), size(_size), orig_idx(_idx), implicit(_implicit) { - assert(ctype != ct_subrecord || subrec); - } - CppValType get_cvt() const { - return {ctype, size}; - } - void print_type(std::ostream& os, bool pass_value = false) const; - }; - - struct ConsRecord { - const CppTypeCode& cpp_type; - const Constructor& constr; - int cons_idx; - bool is_trivial; - bool is_small; - bool triv_conflict; - bool has_trivial_name; - bool inline_record; - bool declared; - cpp_val_type equiv_cpp_type; - std::vector equiv_cpp_types; - std::string cpp_name; - std::vector cpp_fields; - ConsRecord(const CppTypeCode& _cpp_type, const Constructor& _constr, int idx, bool _triv = false) - : cpp_type(_cpp_type), constr(_constr), cons_idx(idx), is_trivial(_triv), declared(false) { - } - bool recover_idents(CppIdentSet& idents) const; - void declare_record(std::ostream& os, std::string nl, int options); - bool declare_record_unpack(std::ostream& os, std::string nl, int options); - bool declare_record_pack(std::ostream& os, std::string nl, int options); - void print_full_name(std::ostream& os) const; - }; - std::vector records; - - private: - std::vector type_param_name; - std::vector type_param_is_nat; - std::vector type_param_is_neg; - std::string template_args; - std::string constructor_args; - std::string skip_extra_args; - std::string skip_extra_args_pass; - CppIdentSet local_cpp_ids; - bool init(); - - public: - CppTypeCode(Type& _type) : type(_type), local_cpp_ids(&local_forbidden_cpp_idents) { - ok = init(); - } - bool is_ok() const { - return ok; - } - void generate(std::ostream& os, int options = 0); - - private: - bool compute_simple_cons_tags(); - bool check_incremental_cons_tags() const; - unsigned long long compute_selector_mask() const; - void assign_class_name(); - void assign_cons_names(); - void assign_class_field_names(); - void assign_cons_values(); - void assign_record_cons_names(); - void generate_cons_enum(std::ostream& os); - void generate_type_constructor(std::ostream& os, int options); - void generate_type_fields(std::ostream& os, int options); - void generate_header(std::ostream& os, int options = 0); - void generate_body(std::ostream& os, int options = 0); - void generate_cons_len_array(std::ostream& os, std::string nl, int options = 0); - void generate_cons_tag_array(std::ostream& os, std::string nl, int options = 0); - void generate_cons_tag_info(std::ostream& os, std::string nl, int options = 0); - void generate_skip_method(std::ostream& os, int options = 0); - void generate_skip_cons_method(std::ostream& os, std::string nl, int cidx, int options); - void generate_cons_tag_check(std::ostream& os, std::string nl, int cidx, bool force = false); - void generate_check_tag_method(std::ostream& os); - void generate_unpack_method(std::ostream& os, ConsRecord& rec, int options); - void generate_pack_method(std::ostream& os, ConsRecord& rec, int options); - void generate_ext_fetch_to(std::ostream& os, int options); - void generate_fetch_enum_method(std::ostream& os, int options); - void generate_store_enum_method(std::ostream& os, int options); - void generate_print_type_body(std::ostream& os, std::string nl); - void generate_print_method(std::ostream& os, int options = 0); - void generate_print_cons_method(std::ostream& os, std::string nl, int cidx, int options); - void generate_get_tag_body(std::ostream& os, std::string nl); - void generate_get_tag_subcase(std::ostream& os, std::string nl, const BinTrie* trie, int depth) const; - void generate_get_tag_param(std::ostream& os, std::string nl, unsigned long long tag, - unsigned long long params = std::numeric_limits::max()) const; - void generate_get_tag_param1(std::ostream& os, std::string nl, const char A[4], - const std::string param_names[1]) const; - void generate_get_tag_param2(std::ostream& os, std::string nl, const char A[4][4], - const std::string param_names[2]) const; - void generate_get_tag_param3(std::ostream& os, std::string nl, const char A[4][4][4], - const std::string param_names[3]) const; - bool match_param_pattern(std::ostream& os, std::string nl, const char A[4], int mask, std::string pattern, - std::string param_name) const; - std::string get_nat_param_name(int idx) const; - void generate_tag_pfx_selector(std::ostream& os, std::string nl, const BinTrie& trie, int d, int min_size) const; - bool generate_get_tag_pfx_distinguisher(std::ostream& os, std::string nl, const std::vector& constr_list, - bool in_block) const; - - private: - std::vector actions; - int incomplete; - int tmp_ints; - bool needs_tmp_cell; - std::vector tmp_vars; - std::vector field_vars; - std::vector field_var_set; - std::vector param_var_set; - std::vector param_constraint_used; - std::vector> postponed_equate; - CppIdentSet tmp_cpp_ids; - void clear_context(); - void init_cons_context(const Constructor& constr); - std::string new_tmp_var(std::string hint); - std::string new_tmp_var(); - void add_action(const Action& act); - void output_actions(std::ostream& os, std::string nl, int options); - void output_cpp_expr(std::ostream& os, const TypeExpr* expr, int prio = 0, bool allow_type_neg = false) const; - void output_cpp_sizeof_expr(std::ostream& os, const TypeExpr* expr, int prio) const; - void output_negative_type_arguments(std::ostream& os, const TypeExpr* expr); - bool can_compute(const TypeExpr* expr) const; - bool can_use_to_compute(const TypeExpr* expr, int i) const; - bool can_compute_sizeof(const TypeExpr* expr) const; - bool is_self(const TypeExpr* expr, const Constructor& constr) const; - void add_compute_actions(const TypeExpr* expr, int i, std::string bind_to); - void identify_cons_params(const Constructor& constr, int options); - void identify_cons_neg_params(const Constructor& constr, int options); - void bind_record_fields(const ConsRecord& rec, int options); - void add_cons_tag_check(const Constructor& constr, int cidx, int options); - void add_cons_tag_store(const Constructor& constr, int cidx); - std::string add_fetch_nat_field(const Constructor& constr, const Field& field, int options); - void add_store_nat_field(const Constructor& constr, const Field& field, int options); - void add_remaining_param_constraints_check(const Constructor& constr, int options); - void compute_implicit_field(const Constructor& constr, const Field& field, int options); - bool add_constraint_check(const Constructor& constr, const Field& field, int options); - void add_postponed_equate_actions(); - void output_fetch_field(std::ostream& os, std::string field_name, const TypeExpr* expr, cpp_val_type cvt); - void output_fetch_subrecord(std::ostream& os, std::string field_name, const ConsRecord* subrec); - void output_store_field(std::ostream& os, std::string field_name, const TypeExpr* expr, cpp_val_type cvt); - void add_store_subrecord(std::string field_name, const ConsRecord* subrec); - void generate_skip_field(const Constructor& constr, const Field& field, int options); - void generate_print_field(const Constructor& constr, const Field& field, int options); - bool output_print_simple_field(std::ostream& os, const Field& field, std::string field_name, const TypeExpr* expr); - void generate_unpack_field(const ConsField& fi, const Constructor& constr, const Field& field, int options); - void generate_pack_field(const ConsField& fi, const Constructor& constr, const Field& field, int options); -}; - -extern std::vector> cpp_type; - -extern bool add_type_members; - -} // namespace tlbc diff --git a/submodules/ton/tonlib-src/crypto/tl/tlbc.cpp b/submodules/ton/tonlib-src/crypto/tl/tlbc.cpp deleted file mode 100644 index 127eacb0..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlbc.cpp +++ /dev/null @@ -1,3167 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "parser/srcread.h" -#include "parser/lexer.h" -#include "parser/symtable.h" -#include "td/utils/Slice-decl.h" -#include "td/utils/format.h" -#include "td/utils/crypto.h" -#include "tlbc-aux.h" -#include "tlbc-data.h" -#include "tlbc-gen-cpp.h" - -int verbosity; - -namespace src { - -/* - * - * KEYWORD DEFINITION - * - */ - -enum { _Eof = -1, _Ident = 0, _Number, _Special, _Eq = 0x80, _Leq, _Geq, _Neq, _Type, _EMPTY }; - -void define_keywords() { - sym::symbols.add_kw_char('+') - .add_kw_char('-') - .add_kw_char('*') - .add_kw_char(':') - .add_kw_char(';') - .add_kw_char('(') - .add_kw_char(')') - .add_kw_char('{') - .add_kw_char('}') - .add_kw_char('[') - .add_kw_char(']') - .add_kw_char('=') - .add_kw_char('_') - .add_kw_char('?') - .add_kw_char('.') - .add_kw_char('~') - .add_kw_char('^'); - - sym::symbols.add_keyword("==", _Eq) - .add_keyword("<=", _Leq) - .add_keyword(">=", _Geq) - .add_keyword("!=", _Neq) - .add_keyword("Type", _Type) - .add_keyword("EMPTY", _EMPTY); -} - -// parses constant bitstrings in format \#[0-9a-f]*_? or \$[01]*_? -unsigned long long get_special_value(std::string str) { - std::size_t i = 1, n = str.size(); - if (n <= 1) { - return 0; - } - unsigned long long val = 0; - int bits = 0; - if (str[0] == '#') { - for (; i < n; i++) { - int c = str[i]; - if (c == '_') { - break; - } - if (c >= '0' && c <= '9') { - c -= '0'; - } else if (c >= 'A' && c <= 'F') { - c -= 'A' - 10; - } else if (c >= 'a' && c <= 'f') { - c -= 'a' - 10; - } else { - return 0; - } - if (bits > 60) { - return 0; - } - val |= (unsigned long long)c << (60 - bits); - bits += 4; - } - } else if (str[0] == '$') { - if (str[1] != '_') { - for (; i < n; i++) { - int c = str[i]; - c -= '0'; - if (c & -2) { - return 0; - } - if (bits > 63) { - return 0; - } - val |= (unsigned long long)c << (63 - bits); - bits++; - } - } - } else { - return 0; - } - if (i < n - 1) { - return 0; - } - if (i == n - 1 && bits) { - // trailing _ - while (bits && !((val >> (64 - bits)) & 1)) { - --bits; - } - if (bits) { - --bits; - } - } - if (bits == 64) { - return 0; - } - return val | (1ULL << (63 - bits)); -} - -int lexem_is_special(std::string str) { - return get_special_value(str) ? Lexem::Special : 0; -} - -} // namespace src - -namespace sym { - -enum class IdSc : char { undef = 0, lc = 1, uc = 2, blc = 3 }; -// subclass: -// 1 = first letter or first letter after last . is lowercase -// 2 = ... uppercase -// 3 = 1 + first character (after last ., if present) is a ! -// 0 = else -int compute_symbol_subclass(std::string str) { - IdSc res = IdSc::undef; - int t = 0, s = 0; - for (char c : str) { - if (c == '.') { - res = IdSc::undef; - s = t = 0; - } else if (res == IdSc::undef) { - if (!s) { - s = (c == '!' ? 1 : -1); - } - if ((c | 0x20) >= 'a' && (c | 0x20) <= 'z') { - res = (c & 0x20 ? IdSc::lc : IdSc::uc); - } - if (t && (((unsigned)c & 0xc0) == 0x80)) { - t = (t << 6) | ((unsigned)c & 0x3f); - if (t >= 0x410 && t < 0x450) { - res = (t < 0x430 ? IdSc::uc : IdSc::lc); - } - } - t = (((unsigned)c & 0xe0) == 0xc0 ? (c & 0x1f) : 0); - } - } - if (s == 1 && res == IdSc::lc) { - res = IdSc::blc; - } - return (int)res; -} - -inline bool is_lc_ident(sym_idx_t idx) { - auto sc = symbols.get_subclass(idx); - return sc == (int)IdSc::lc || sc == (int)IdSc::blc; -} - -inline bool is_spec_lc_ident(sym_idx_t idx) { - auto sc = symbols.get_subclass(idx); - return sc == (int)IdSc::blc; -} - -inline bool is_uc_ident(sym_idx_t idx) { - return symbols.get_subclass(idx) == (int)IdSc::uc; -} - -} // namespace sym - -namespace tlbc { - -td::LinearAllocator AR(1 << 22); - -/* - * - * AUXILIARY DATA TYPES - * - */ - -// headers are in tlbc-aux.h - -std::ostream& operator<<(std::ostream& os, const BitPfxCollection& p) { - p.show(os); - return os; -} - -void BitPfxCollection::show(std::ostream& os) const { - char first = '{'; - for (unsigned long long val : pfx) { - os << first; - while (val & (All - 1)) { - os << (val >> 63); - val <<= 1; - } - os << '*'; - first = ','; - } - if (first == '{') { - os << '{'; - } - os << '}'; -} - -void BitPfxCollection::merge_back(unsigned long long z) { - if (!pfx.size()) { - pfx.push_back(z); - return; - } - unsigned long long w = td::lower_bit64(z); - while (pfx.size()) { - unsigned long long t = z ^ pfx.back(); - if (!t) { - return; - } - if (t != (w << 1)) { - break; - } - z -= w; - w <<= 1; - pfx.pop_back(); - } - pfx.push_back(z); -} - -BitPfxCollection& BitPfxCollection::operator*=(unsigned long long prepend) { - if (!prepend) { - clear(); - return *this; - } - if (prepend == All) { - return *this; - } - int l = 63 - td::count_trailing_zeroes_non_zero64(prepend); - prepend &= prepend - 1; - std::size_t i, j = 0, n = pfx.size(); - for (i = 0; i < n; i++) { - unsigned long long z = pfx[i], zw = td::lower_bit64(z); - z >>= l; - z |= prepend; - if (!(zw >> l)) { - z |= 1; - } - if (!j || pfx[j - 1] != z) { - pfx[j++] = z; - } - } - pfx.resize(j); - return *this; -} - -BitPfxCollection BitPfxCollection::operator*(unsigned long long prepend) const { - if (!prepend) { - return BitPfxCollection{}; - } - if (prepend == All) { - return *this; - } - BitPfxCollection res; - res.pfx.reserve(pfx.size()); - int l = 63 - td::count_trailing_zeroes_non_zero64(prepend); - prepend &= prepend - 1; - std::size_t i, n = pfx.size(); - for (i = 0; i < n; i++) { - unsigned long long z = pfx[i], zw = td::lower_bit64(z); - z >>= l; - z |= prepend; - if (!(zw >> l)) { - z |= 1; - } - res.merge_back(z); - } - return res; -} - -BitPfxCollection BitPfxCollection::operator+(const BitPfxCollection& other) const { - if (!other.pfx.size()) { - return *this; - } - if (!pfx.size()) { - return other; - } - BitPfxCollection res; - res.pfx.reserve(pfx.size() + other.pfx.size()); - std::size_t i = 0, j = 0, m = pfx.size(), n = other.pfx.size(); - struct Interval { - unsigned long long z, a, b; - void operator=(unsigned long long _z) { - z = _z; - a = (_z & (_z - 1)); - b = (_z | (_z - 1)); - } - bool contains(const Interval& other) const { - return a <= other.a && other.b <= b; - } - }; - Interval U, V; - U = pfx[0]; - V = other.pfx[0]; - while (i < m && j < n) { - if (U.b < V.b || (U.b == V.b && U.a >= V.a)) { - if (U.a < V.a) { - res.merge_back(U.z); - } - if (++i == m) { - break; - } - U = pfx[i]; - } else { - if (V.a < U.a) { - res.merge_back(V.z); - } - if (++j == n) { - break; - } - V = other.pfx[j]; - } - } - while (i < m) { - res.merge_back(pfx[i++]); - } - while (j < n) { - res.merge_back(other.pfx[j++]); - } - return res; -} - -bool BitPfxCollection::operator+=(const BitPfxCollection& other) { - BitPfxCollection tmp = *this + other; - if (*this == tmp) { - return false; - } else { - *this = tmp; - return true; - } -} - -void AdmissibilityInfo::set_all(bool val) { - dim = 0; - info.clear(); - info.resize(1, val); -} - -std::ostream& operator<<(std::ostream& os, const AdmissibilityInfo& p) { - p.show(os); - return os; -} - -void AdmissibilityInfo::show(std::ostream& os) const { - os << '['; - for (bool x : info) { - os << (int)x; - } - os << ']'; -} - -void AdmissibilityInfo::extend(int dim1) { - if (dim < dim1) { - std::size_t i, n = info.size(), n1 = (size_t(1) << (2 * dim1)); - assert(n); - info.resize(n1); - for (i = n; i < n1; i++) { - info[i] = info[i - n]; - } - dim = dim1; - } -} - -void AdmissibilityInfo::operator|=(const AdmissibilityInfo& other) { - extend(other.dim); - std::size_t i, j, n = info.size(), n1 = other.info.size(); - assert(n1 && !(n1 & (n1 - 1))); - for (i = j = 0; i < n; i++) { - info[i] = info[i] | other.info[j]; - j = (j + 1) & (n1 - 1); - } -} - -void AdmissibilityInfo::set_by_pattern(int pdim, int pattern[]) { - extend(pdim); - std::size_t n = info.size(); - for (std::size_t x = 0; x < n; x++) { - std::size_t y = x; - bool f = true; - for (int i = 0; i < pdim; i++) { - if (!((pattern[i] >> (y & 3)) & 1)) { - f = false; - break; - } - y >>= 2; - } - if (f) { - info[x] = true; - } - } -} - -int AdmissibilityInfo::conflicts_at(const AdmissibilityInfo& other) const { - std::size_t i, n1 = info.size(), n2 = other.info.size(), n = std::max(n1, n2); - for (i = 0; i < n; i++) { - if (info[i & (n1 - 1)] && other.info[i & (n2 - 1)]) { - return (int)i; - } - } - return -1; -} - -bool AdmissibilityInfo::extract1(char A[4], char tag, int p1) const { - char B[4]; - std::memset(B, 0, sizeof(B)); - p1 <<= 1; - std::size_t n = info.size() - 1; - for (std::size_t x = 0; x <= n; x++) { - if (info[x]) { - B[(x >> p1) & 3] = 1; - } - } - int m1 = ((n >> p1) & 3); - for (int i = 0; i < 4; i++) { - if (B[i & m1]) { - if (A[i] && A[i] != tag) { - A[i] = -1; - return false; - } - A[i] = tag; - } - } - return true; -} - -bool AdmissibilityInfo::extract2(char A[4][4], char tag, int p1, int p2) const { - char B[4][4]; - std::memset(B, 0, sizeof(B)); - p1 <<= 1; - p2 <<= 1; - std::size_t n = info.size() - 1; - for (std::size_t x = 0; x <= n; x++) { - if (info[x]) { - B[(x >> p1) & 3][(x >> p2) & 3] = 1; - } - } - int m1 = ((n >> p1) & 3); - int m2 = ((n >> p2) & 3); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - if (B[i & m1][j & m2]) { - if (A[i][j] && A[i][j] != tag) { - A[i][j] = -1; - return false; - } - A[i][j] = tag; - } - } - } - return true; -} - -bool AdmissibilityInfo::extract3(char A[4][4][4], char tag, int p1, int p2, int p3) const { - char B[4][4][4]; - std::memset(B, 0, sizeof(B)); - p1 <<= 1; - p2 <<= 1; - p3 <<= 1; - std::size_t n = info.size() - 1; - for (std::size_t x = 0; x <= n; x++) { - if (info[x]) { - B[(x >> p1) & 3][(x >> p2) & 3][(x >> p3) & 3] = 1; - } - } - int m1 = ((n >> p1) & 3); - int m2 = ((n >> p2) & 3); - int m3 = ((n >> p3) & 3); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - for (int k = 0; k < 4; k++) { - if (B[i & m1][j & m2][k & m3]) { - if (A[i][j][k] && A[i][j][k] != tag) { - A[i][j][k] = -1; - return false; - } - A[i][j][k] = tag; - } - } - } - } - return true; -} - -void ConflictGraph::set_clique(ConflictSet set) { - if (set.x) { - for (int i = 0; i < 64; i++) { - if (set[i]) { - g[i] |= set; - } - } - } -} - -std::ostream& operator<<(std::ostream& os, const BinTrie& bt) { - bt.show(os); - return os; -} - -void BinTrie::show(std::ostream& os, unsigned long long pfx) const { - unsigned long long x = pfx, u = (td::lower_bit64(x) >> 1); - while (x & ((1ULL << 63) - 1)) { - os << (x >> 63); - x <<= 1; - } - os << " t=" << tag << "; dt=" << down_tag << "; ud=" << useful_depth << std::endl; - if (left) { - left->show(os, pfx - u); - } - if (right) { - right->show(os, pfx + u); - } -} - -void BinTrie::ins_path(unsigned long long path, unsigned long long new_tag) { - if (!path || !new_tag) { - return; - } - if (!(path & ((1ULL << 63) - 1))) { - tag |= new_tag; - return; - } else if ((long long)path >= 0) { - left = insert_path(std::move(left), path << 1, new_tag); - } else { - right = insert_path(std::move(right), path << 1, new_tag); - } - if (left && right) { - tag |= left->tag & right->tag; - } -} - -std::unique_ptr BinTrie::insert_path(std::unique_ptr root, unsigned long long path, - unsigned long long tag) { - if (!path || !tag) { - return root; - } - if (root) { - root->ins_path(path, tag); - return root; - } - if (!(path & ((1ULL << 63) - 1))) { - return std::make_unique(tag); - } - if ((long long)path >= 0) { - return std::make_unique(0, insert_path({}, path << 1, tag), std::unique_ptr{}); - } else { - return std::make_unique(0, std::unique_ptr{}, insert_path({}, path << 1, tag)); - } -} - -std::unique_ptr BinTrie::insert_paths(std::unique_ptr root, const BitPfxCollection& paths, - unsigned long long tag) { - if (tag) { - for (auto x : paths.pfx) { - root = insert_path(std::move(root), x, tag); - } - } - return root; -} - -unsigned long long BinTrie::lookup_tag(unsigned long long path) const { - const BinTrie* node = lookup_node_const(path); - return node ? node->tag : 0; -} - -BinTrie* BinTrie::lookup_node(unsigned long long path) { - if (!path) { - return nullptr; - } - if (!(path & ((1ULL << 63) - 1))) { - return this; - } - if ((long long)path >= 0) { - return left ? left->lookup_node(path << 1) : nullptr; - } else { - return right ? right->lookup_node(path << 1) : nullptr; - } -} - -const BinTrie* BinTrie::lookup_node_const(unsigned long long path) const { - if (!path) { - return nullptr; - } - if (!(path & ((1ULL << 63) - 1))) { - return this; - } - if ((long long)path >= 0) { - return left ? left->lookup_node_const(path << 1) : nullptr; - } else { - return right ? right->lookup_node_const(path << 1) : nullptr; - } -} - -void BinTrie::set_conflict_graph(ConflictGraph& gr, unsigned long long colors) const { - colors |= tag; - if (!left || !right) { - gr.set_clique(ConflictSet{colors}); - } - if (left) { - left->set_conflict_graph(gr, colors); - } - if (right) { - right->set_conflict_graph(gr, colors); - } -} - -int BinTrie::compute_useful_depth(unsigned long long colors) { - int res = 0; // useless; - down_tag = tag = colors |= tag; - if (left) { - res = left->compute_useful_depth(colors); - down_tag |= left->down_tag; - } - if (right) { - res = std::max(res, right->compute_useful_depth(colors)); - down_tag |= right->down_tag; - } - if (res > 0) { - return useful_depth = res + 1; - } - if (left && right && (left->down_tag & ~right->down_tag) != 0 && (right->down_tag & ~left->down_tag) != 0) { - return useful_depth = 1; - } - return useful_depth = 0; -} - -unsigned long long BinTrie::build_submap(int depth, unsigned long long A[]) const { - if (!depth) { - A[0] = down_tag | (useful_depth ? (1ULL << 63) : 0); - return down_tag != 0; - } - int n = (1 << (depth - 1)); - unsigned long long r1 = 0, r2 = 0; - if (left) { - r1 = left->build_submap(depth - 1, A); - } else { - std::memset(A, 0, n * 8); - } - if (right) { - r2 = right->build_submap(depth - 1, A + n); - } else { - std::memset(A + n, 0, n * 8); - } - if (A[n] != A[n - 1] || (long long)A[n] < 0) { - r2 |= 1; - } else { - r2 &= ~1; - } - return r1 | (r2 << n); -} - -unsigned long long BinTrie::build_submap_at(int depth, unsigned long long A[], unsigned long long pfx) const { - const BinTrie* node = lookup_node_const(pfx); - if (!node) { - std::memset(A, 0, 8 << depth); - return 0; - } - return node->build_submap(depth, A); -} - -unsigned long long BinTrie::find_conflict_path(unsigned long long colors, unsigned long long mask) const { - colors |= tag & mask; - if (!left && !right) { - return colors & (colors - 1) ? (1ULL << 63) : 0; - } - if (!left) { - if (colors & (colors - 1)) { - return (1ULL << 62); // $0 - } else { - unsigned long long x = right->find_conflict_path(colors, mask); - return x ? ((x >> 1) | (1ULL << 63)) : 0; - } - } else if (!right) { - if (colors & (colors - 1)) { - return (3ULL << 62); // $1 - } else { - return left->find_conflict_path(colors, mask) >> 1; - } - } - unsigned long long x = left->find_conflict_path(colors, mask); - unsigned long long y = right->find_conflict_path(colors, mask); - if (td::lower_bit64(y) > td::lower_bit64(x)) { - return (y >> 1) | (1ULL << 63); - } else { - return x >> 1; - } -} - -std::ostream& operator<<(std::ostream& os, MinMaxSize t) { - t.show(os); - return os; -} - -void MinMaxSize::normalize() { - if (minmax_size & (0xfff800f8U * 0x100000001ULL)) { - nrm(0xf8, 0x7); - nrm(0xfff80000U, 0x7ff00); - nrm(0xf8ULL << 32, 7ULL << 32); - nrm(0xfff80000ULL << 32, 0x7ff00ULL << 32); - } -} - -MinMaxSize::unpacked::unpacked(MinMaxSize val) { - val.normalize(); - max_refs = val.minmax_size & 0xff; - max_bits = (val.minmax_size >> 8) & 0x7ff; - min_refs = (val.minmax_size >> 32) & 0xff; - min_bits = (val.minmax_size >> 40) & 0x7ff; -} - -MinMaxSize MinMaxSize::unpacked::pack() const { - unsigned long long t = ((unsigned long long)(min_bits * 0x100 + min_refs) << 32); - t += (max_bits * 0x100 + max_refs); - return MinMaxSize{t}; -} - -MinMaxSize& MinMaxSize::repeat(int count) { - if (count <= 0) { - return clear(); - } - if (count == 1) { - return *this; - } - unpacked z{*this}; - count = std::min(count, 1024); - z.max_refs = std::min(z.max_refs * count, 7U); - z.max_bits = std::min(z.max_bits * count, 0x7ffU); - z.min_refs = std::min(z.min_refs * count, 7U); - z.min_bits = std::min(z.min_bits * count, 0x7ffU); - return *this = z.pack(); -} - -MinMaxSize& MinMaxSize::repeat_at_least(int count) { - count = std::min(std::max(count, 0), 1024); - unpacked z{*this}; - if (z.max_refs) { - z.max_refs = 7; - } - if (z.max_bits) { - z.max_bits = 0x7ff; - } - z.min_refs = std::min(z.min_refs * count, 7U); - z.min_bits = std::min(z.min_bits * count, 0x7ffU); - return *this = z.pack(); -} - -MinMaxSize& MinMaxSize::operator|=(MinMaxSize y) { - unpacked z{*this}, w{y}; - z.min_refs = std::min(z.min_refs, w.min_refs); - z.min_bits = std::min(z.min_bits, w.min_bits); - z.max_refs = std::max(z.max_refs, w.max_refs); - z.max_bits = std::max(z.max_bits, w.max_bits); - return *this = z.pack(); -} - -void MinMaxSize::show(std::ostream& os) const { - unpacked z{*this}; - z.show(os); -} - -void MinMaxSize::unpacked::show(std::ostream& os) const { - bool fixed = (min_bits == max_bits && min_refs == max_refs); - if (fixed) { - os << '='; - } - if (min_bits >= 1024 && min_refs >= 7) { - os << "infty"; - } else { - os << min_bits; - if (min_refs) { - os << "+" << min_refs << "R"; - } - } - if (!fixed) { - os << ".."; - if (max_bits >= 1024 && max_refs >= 7) { - os << "infty"; - } else { - os << max_bits; - if (max_refs) { - os << "+" << max_refs << "R"; - } - } - } -} - -} // namespace tlbc - -namespace tlbc { - -using src::Lexem; -using src::Lexer; -using sym::sym_idx_t; - -/* - * - * DATA TYPES: Type Expressions, Types, Constructors - * - */ - -// headers in tlbc-data.h - -std::ostream& operator<<(std::ostream& os, const TypeExpr* te) { - if (te) { - te->show(os); - } else { - os << "(null-type)"; - } - return os; -} - -std::ostream& operator<<(std::ostream& os, const Constructor& cs) { - cs.show(os); - return os; -} - -TypeExpr type_Type{{}, TypeExpr::te_Type}; - -TypeExpr* const_type_expr[TypeExpr::max_const_expr]; -int const_type_expr_num; - -TypeExpr* TypeExpr::const_htable[TypeExpr::const_htable_size]; - -sym_idx_t Nat_name, Eq_name, Less_name, Leq_name; -Type* Nat_type; -Type *Eq_type, *Less_type, *Leq_type; -Type *NatWidth_type, *NatLess_type, *NatLeq_type, *Int_type, *UInt_type; -Type* Bits_type; -Type *Any_type, *Cell_type; - -int types_num, builtin_types_num; -std::vector types; - -int Type::last_declared_counter; - -void TypeExpr::check_mode(const src::SrcLocation& loc, int mode) { - if (!(mode & (1 << (is_nat ? 1 : 0)))) { - if (is_nat) { - throw src::ParseError{loc, "type expression required"}; - } else { - throw src::ParseError{loc, "integer expression required"}; - } - } - if (tchk_only && !(mode & 8)) { - throw src::ParseError{where, "type expression can be used only in a type-checking context"}; - } -} - -bool TypeExpr::no_tchk() const { - if (tchk_only) { - throw src::ParseError{where, "type expression can be used only in a type-checking context"}; - return false; - } - return true; -} - -TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, unsigned int_const) { - return new (AR) TypeExpr{loc, te_IntConst, (int)int_const}; -} - -TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, std::string int_const) { - char* end_ptr = 0; - long long value = -1; - if (!int_const.empty()) { - value = std::strtoll(int_const.c_str(), &end_ptr, 0); - } - if (value < 0 || value >= (1LL << 31) || end_ptr != int_const.c_str() + int_const.size()) { - throw src::ParseError{loc, "integer constant does not fit in an unsigned 31-bit integer"}; - } - return mk_intconst(loc, (unsigned)value); -} - -TypeExpr* TypeExpr::mk_apply_gen(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2) { - if (expr1->tp != te_Apply) { - throw src::ParseError{loc, "cannot apply one expression to the other"}; - } - expr1->args.push_back(expr2); - return expr1; -} - -TypeExpr* TypeExpr::mk_mulint(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2) { - if (expr1->tp != te_IntConst && expr2->tp != te_IntConst) { - throw src::ParseError{loc, "multiplication allowed only by constant values"}; - } - if (expr2->tp != te_IntConst) { - std::swap(expr1, expr2); - } - if (!expr1->is_nat) { - throw src::ParseError{expr1->where, "argument to integer multiplication should be a number"}; - } - if (expr1->tp == te_IntConst) { - long long product = (long long)expr1->value * expr2->value; - if (product < 0 || product >= (1LL << 31)) { - throw src::ParseError{loc, "product does not git in 31 bits"}; - } - return mk_intconst(loc, (unsigned)product); - } - int val = expr2->value; - if (!val) { - return expr2; - } - // delete expr2; - return new (AR) TypeExpr{loc, te_MulConst, val, {expr1}, expr1->negated}; -} - -TypeExpr* TypeExpr::mk_apply(const src::SrcLocation& loc, int tp, TypeExpr* expr1, TypeExpr* expr2) { - TypeExpr* expr = new (AR) TypeExpr{loc, tp, 0, {expr1, expr2}}; - return expr; -} - -TypeExpr* TypeExpr::mk_cellref(const src::SrcLocation& loc, TypeExpr* expr1) { - TypeExpr* expr = new (AR) TypeExpr{loc, te_Ref, 0, {expr1}}; - return expr; -} - -Field& Constructor::new_field(const src::SrcLocation& field_where, bool implicit, sym_idx_t name = 0) { - assert((long)fields_num == (long)fields.size()); - if (name) { - sym::SymDef* sym_def = sym::lookup_symbol(name, 1); - if (sym_def) { - throw src::ParseError{field_where, "redefined field or parameter"}; - } - } - fields.emplace_back(field_where, implicit, fields_num++, name); - return fields.back(); -} - -std::string Field::get_name() const { - return sym::symbols.get_name(name); -} - -// register symbol in local symbol table -void Field::register_sym() const { - if (name) { - sym::SymDef* sym_def = sym::lookup_symbol(name, 1); - if (sym_def) { - throw src::ParseError{loc, "redefined field or parameter"}; - } else { - sym_def = sym::define_symbol(name, true, loc); - if (!sym_def) { - throw src::ParseError{loc, "cannot register field"}; - } - } - delete sym_def->value; - sym_def->value = new SymVal((int)SymVal::_Param, field_idx, type); - } -} - -bool TypeExpr::close(const src::SrcLocation& loc) { - if (tp != te_Apply) { - return true; - } - Type* type = type_applied; - assert(type); - if (type->arity < 0) { - type->arity = (int)args.size(); - type->args.resize(type->arity, 0); - } else if (type->arity != (int)args.size()) { - throw src::ParseError{where, - std::string{"operator `"} + sym::symbols.get_name(type->type_name) + - "` applied with incorrect number of arguments, partial type applications not supported"}; - return false; - } - is_nat_subtype = type->produces_nat; - bool is_eq = (type == Eq_type); - int neg_cnt = 0; - for (int i = 0; i < type->arity; i++) { - TypeExpr* arg = args[i]; - int& x = type->args[i]; - if (arg->negated) { - ++neg_cnt; - negated = true; - if (!is_eq) { - if (x & Type::_IsPos) { - throw src::ParseError{arg->where, std::string{"passed an argument of incorrect polarity to `"} + - sym::symbols.get_name(type->type_name) + "`"}; - } - x |= Type::_IsNeg; - } else if (neg_cnt == 2) { - throw src::ParseError{loc, "cannot equate two expressions of negative polarity"}; - } - } - arg->no_tchk(); - if (arg->is_nat) { - x |= Type::_IsNat; - } else { - x |= Type::_IsType; - if (arg->negated) { - throw src::ParseError{arg->where, "cannot use negative types as arguments to other types"}; - } - } - } - tchk_only = negated = neg_cnt; - return true; -} - -TypeExpr* TypeExpr::mk_apply_empty(const src::SrcLocation& loc, sym_idx_t name, Type* type_applied) { - TypeExpr* expr = new (AR) TypeExpr{loc, te_Apply, name}; - expr->type_applied = type_applied; - expr->is_nat_subtype = (type_applied->produces_nat && !type_applied->arity); - return expr; -} - -void Type::print_name(std::ostream& os) const { - if (type_name) { - os << sym::symbols.get_name(type_name); - } else { - os << "TYPE_" << type_idx; - } -} - -std::string Type::get_name() const { - if (type_name) { - return sym::symbols.get_name(type_name); - } else { - std::ostringstream os; - os << "TYPE_" << type_idx; - return os.str(); - } -} - -std::string Constructor::get_name() const { - return sym::symbols.get_name(constr_name); -} - -std::string Constructor::get_qualified_name() const { - return type_defined->get_name() + "::" + get_name(); -} - -void TypeExpr::show(std::ostream& os, const Constructor* cs, int prio, int mode) const { - if (mode & 2) { - prio = 0; - } - switch (tp) { - case te_Type: - os << "Type"; - break; - case te_Param: { - int i = value; - sym_idx_t param_name = 0; - if (cs && i >= 0 && i < cs->fields_num) { - param_name = cs->fields.at(i).name; - } - if (negated ^ (mode & 1)) { - os << '~'; - } - if (param_name > 0) { - os << sym::symbols.get_name(param_name); - } else { - os << '_' << i + 1; - } - break; - } - case te_Apply: - if (!args.size() && !type_applied->type_name && type_applied->constr_num == 1 && - !type_applied->constructors.at(0)->constr_name && - !(type_applied->constructors[0]->tag & ((1ULL << 63) - 1))) { - type_applied->constructors[0]->show(os, mode | 4); - } else { - if (prio > 90 && args.size()) { - os << '('; - } - type_applied->print_name(os); - for (TypeExpr* arg : args) { - os << ' '; // priority 90 - arg->show(os, cs, 91, mode); - } - if (prio > 90 && args.size()) { - os << ')'; - } - } - break; - case te_Add: { - assert(args.size() == 2); - if (prio > 20) { - os << '('; - } - args[0]->show(os, cs, 20, mode); - os << " + "; // priority 20 - args[1]->show(os, cs, 21, mode); - if (prio > 20) { - os << ')'; - } - break; - } - case te_GetBit: { - assert(args.size() == 2); - if (prio > 97) { - os << '('; - } - args[0]->show(os, cs, 98, mode); - os << "."; // priority 20 - args[1]->show(os, cs, 98, mode); - if (prio > 97) { - os << ')'; - } - break; - } - case te_IntConst: { - assert(args.empty()); - os << value; - break; - } - case te_MulConst: { - if (prio > 30) { - os << '('; - } - assert(args.size() == 1); - os << value << " * "; // priority 30 - args[0]->show(os, cs, 31, mode); - if (prio > 30) { - os << ')'; - } - break; - } - case te_Tuple: { - assert(args.size() == 2); - if (prio > 30) { - os << '('; - } - args[0]->show(os, cs, 30, mode); - os << " * "; // priority 30 - args[1]->show(os, cs, 31, mode); - if (prio > 30) { - os << ')'; - } - break; - } - case te_CondType: { - assert(args.size() == 2); - if (prio > 95) { - os << '('; - } - args[0]->show(os, cs, 96, mode); - os << "?"; // priority 95 - args[1]->show(os, cs, 96, mode); - if (prio > 95) { - os << ')'; - } - break; - } - case te_Ref: { - assert(args.size() == 1); - os << '^'; // priority 100 - args[0]->show(os, cs, 100, mode); - break; - } - default: - os << "(unknown-type)"; - } -} - -bool TypeExpr::equal(const TypeExpr& other) const { - if (tp != other.tp || value != other.value || type_applied != other.type_applied || - args.size() != other.args.size()) { - return false; - } - for (std::size_t i = 0; i < args.size(); i++) { - if (!args[i]->equal(*other.args[i])) { - return false; - } - } - return true; -} - -// 0 = 0, 1 = 1, 2 = any even >= 2, 3 = any odd >= 3 -// (We work in N/(4~2), or in the free semilattice generated by it.) -int abstract_nat_const(int value) { - return 1 << ((value & 1) + (value >= 2 ? 2 : 0)); -} - -unsigned char abstract_add_base_table[4][4] = {{0, 1, 2, 3}, {1, 2, 3, 2}, {2, 3, 2, 3}, {3, 2, 3, 2}}; -unsigned char abstract_mul_base_table[4][4] = {{0, 0, 0, 0}, {0, 1, 2, 3}, {0, 2, 2, 2}, {0, 3, 2, 3}}; -unsigned char abstract_getbit_b_table[4][4] = {{1, 1, 1, 1}, {2, 1, 1, 1}, {1, 3, 3, 3}, {2, 3, 3, 3}}; - -unsigned char abstract_add_table[16][16]; -unsigned char abstract_mul_table[16][16]; -unsigned char abstract_getbit_table[16][16]; - -void compute_semilat_table(unsigned char table[16][16], const unsigned char base_table[4][4]) { - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - int res = 0; - for (int i = 0; i < 4; i++) { - if ((x >> i) & 1) { - for (int j = 0; j < 4; j++) { - if ((y >> j) & 1) { - res |= 1 << base_table[i][j]; - } - } - } - } - table[x][y] = (unsigned char)res; - } - } -} - -void compute_semilat_b_table(unsigned char table[16][16], const unsigned char b_table[4][4]) { - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - int res = 0; - for (int i = 0; i < 4; i++) { - if ((x >> i) & 1) { - for (int j = 0; j < 4; j++) { - if ((y >> j) & 1) { - res |= b_table[i][j]; - } - } - } - } - table[x][y] = (unsigned char)res; - } - } -} - -void init_abstract_tables() { - compute_semilat_table(abstract_add_table, abstract_add_base_table); - compute_semilat_table(abstract_mul_table, abstract_mul_base_table); - compute_semilat_b_table(abstract_getbit_table, abstract_getbit_b_table); -} - -int abstract_add(int x, int y) { - return abstract_add_table[x & 15][y & 15]; -} - -int abstract_mul(int x, int y) { - return abstract_mul_table[x & 15][y & 15]; -} - -int abstract_getbit(int x, int y) { - return abstract_getbit_table[x & 15][y & 15]; -} - -int TypeExpr::abstract_interpret_nat() const { - if (!is_nat || tchk_only) { - return 0; - } - switch (tp) { - case te_Param: - return 0xf; // for now, natural parameters can take arbitrary values - case te_Add: - assert(args.size() == 2); - return abstract_add(args[0]->abstract_interpret_nat(), args[1]->abstract_interpret_nat()); - case te_GetBit: - assert(args.size() == 2); - return abstract_getbit(args[0]->abstract_interpret_nat(), args[1]->abstract_interpret_nat()); - case te_IntConst: - return abstract_nat_const(value); - case te_MulConst: - assert(args.size() == 1); - return abstract_mul(args[0]->abstract_interpret_nat(), abstract_nat_const(value)); - default: - return 0xf; - } -} - -MinMaxSize TypeExpr::compute_size() const { - if (is_nat) { - return {0}; - } - switch (tp) { - case te_Type: - return {0}; - case te_Param: - return {MinMaxSize::Any}; // any size possible for type parameters - case te_Ref: { - assert(args.size() == 1); - bool f = args[0]->compute_size().is_possible(); - return f ? MinMaxSize::OneRef : MinMaxSize::Impossible; - } - case te_CondType: { - assert(args.size() == 2); - int z = args[0]->abstract_interpret_nat(); - if (!(z & ~1)) { - return {0}; // always 0 - } else { - MinMaxSize t = args[1]->compute_size(); - if (z & 1) { - t.clear_min(); - } - return t; - } - } - case te_Tuple: { - assert(args.size() == 2); - int z = args[0]->abstract_interpret_nat(); - if (!(z & ~1)) { - return {0}; // always 0 - } else { - MinMaxSize t = args[1]->compute_size(); - if (args[0]->tp == te_IntConst) { - t.repeat(args[0]->value); - return t; - } - if (z & 1) { - t.clear_min(); // zero repetition count possible - } - if (z & 12) { - // may be repeated more than once - int n = ((z & 1) ? 0 : ((z & 2) ? 1 : 2)); // minimal value of repetition count - t.repeat_at_least(n); // repetition count >= n - } - return t; - } - } - case te_Apply: { - if (args.size() == 1 && args[0]->tp == te_IntConst) { - int n = args[0]->value; - if (type_applied == NatWidth_type || type_applied == Int_type || type_applied == UInt_type || - type_applied == Bits_type) { - return MinMaxSize::fixed_size(std::min(n, 2047)); - } else if (type_applied == NatLeq_type) { - return MinMaxSize::fixed_size(32 - td::count_leading_zeroes32(n)); - } else if (type_applied == NatLess_type) { - return MinMaxSize::fixed_size(n ? 32 - td::count_leading_zeroes32(n - 1) : 2047); - } - } - return type_applied->size; - } - } // end switch - return {}; -} - -bool TypeExpr::compute_any_bits() const { - if (is_nat) { - return true; - } - switch (tp) { - case te_Type: - return true; - case te_Param: - return false; - case te_Ref: - return true; - case te_Tuple: - case te_CondType: { - assert(args.size() == 2); - int z = args[0]->abstract_interpret_nat(); - if (!(z & ~1)) { - return true; // always 0 - } else { - return args[1]->compute_any_bits(); - } - } - case te_Apply: { - if (args.size() == 1 && args[0]->tp == te_IntConst) { - int n = args[0]->value; - if (type_applied == NatLeq_type) { - return !(n & (n + 1)); - } else if (type_applied == NatLess_type) { - return !(n & (n - 1)); - } - } - return type_applied->any_bits; - } - } // end switch - return false; -} - -int TypeExpr::is_integer() const { - if (is_nat) { - return 1; - } - if (tp != te_Apply) { - return 0; - } - const Type* ta = type_applied; - if (ta == Int_type) { - return -1; - } else if (ta == UInt_type) { - return 1; - } - if (ta->is_bool) { - return 1; - } - if (ta->is_builtin) { - return ta->is_integer; - } - return 0; -} - -bool TypeExpr::is_ref_to_anon() const { - return tp == te_Ref && args.at(0)->is_anon(); -} - -bool TypeExpr::is_anon() const { - return tp == te_Apply && args.empty() && type_applied->is_anon; -} - -unsigned long long TypeExpr::compute_hash() const { - unsigned long long h = tp * 17239ULL + value * 23917ULL + 1; - if (type_applied) { - h += 239017 * type_applied->type_idx; - } - for (const TypeExpr* arg : args) { - h *= 170239; - if (!arg->negated) { - h += arg->is_constexpr; - } - } - return h; -} - -bool TypeExpr::detect_constexpr() { - if (is_constexpr) { - return true; - } - bool c = !negated; - for (TypeExpr* arg : args) { - if (!arg->detect_constexpr() && !arg->negated) { - c = false; - } - } - if (!c || tp == te_Param) { - return false; - } - unsigned long long hash = compute_hash(); - unsigned long long h1 = hash % const_htable_size, h2 = 1 + hash % (const_htable_size + 1); - while (const_htable[h1]) { - TypeExpr* other = const_htable[h1]; - if (other->tp == tp && other->value == value && other->type_applied == type_applied && - other->args.size() == args.size()) { - bool match = true; - for (std::size_t i = 0; i < args.size(); i++) { - if (other->args[i]->negated != args[i]->negated || other->args[i]->is_constexpr != args[i]->is_constexpr) { - match = false; - break; - } - } - if (match) { - is_constexpr = other->is_constexpr; - assert(is_constexpr); - return true; - } - } - h1 += h2; - if (h1 >= const_htable_size) { - h1 -= const_htable_size; - } - } - assert(const_type_expr_num < max_const_expr - 1); - const_type_expr[is_constexpr = ++const_type_expr_num] = this; - const_htable[h1] = this; - return true; -} - -void TypeExpr::const_type_name(std::ostream& os) const { - if (negated) { - return; - } - switch (tp) { - case te_Type: - os << "_Type"; - return; - case te_Param: - return; - case te_Add: - args[0]->const_type_name(os); - os << "_plus"; - args[1]->const_type_name(os); - return; - case te_GetBit: - args[0]->const_type_name(os); - os << "_bit"; - args[1]->const_type_name(os); - return; - case te_IntConst: - os << "_" << value; - return; - case te_MulConst: - os << "_mul" << value; - return; - case te_Ref: - os << "_Ref"; - args[0]->const_type_name(os); - return; - case te_Tuple: - os << "_tuple"; - args[0]->const_type_name(os); - args[1]->const_type_name(os); - return; - case te_CondType: - os << "_if"; - args[0]->const_type_name(os); - args[1]->const_type_name(os); - return; - case te_Apply: - os << '_'; - if (type_applied->produces_nat) { - if (type_applied == Nat_type) { - os << "nat"; - } else if (type_applied == NatWidth_type) { - os << "natwidth"; - } else if (type_applied == NatLeq_type) { - os << "natleq"; - } else if (type_applied == NatLess_type) { - os << "natless"; - } - } else { - os << type_applied->get_name(); - } - for (const TypeExpr* arg : args) { - arg->const_type_name(os); - } - return; - } -} - -bool TypeExpr::bind_value(bool value_negated, Constructor& cs, bool checking_type) { - // if checking_type == false: - // negated = false, value_negated = false: compute expression, compare to value (only for integers) - // negated = false, value_negated = true: compute expression, return it to the "value" - // negated = true, value_negated = false: assign the value to the expression to compute some of the variables present in the expression - // if checking_type == true: - // value_negated must be false - /* (debug output) - std::cerr << "binding " << (value_negated ? "negative" : "positive") << " value to expression " << (checking_type ? "of type " : ""); - show(std::cerr, &cs); - std::cerr << std::endl; - */ - if (!checking_type) { - no_tchk(); - } else { - if (is_nat) { - throw src::ParseError{where, "cannot use check a type against an integer expression"}; - } - if (value_negated) { - throw src::ParseError{where, "cannot compute a value knowing only its type"}; - } - } - if (negated && value_negated) { - // both the expression and the value cannot be negative - throw src::ParseError{where, "expression has wrong polarity"}; - } - if (!is_nat) { - // for type expressions: - if (value_negated) { - // cannot "return" values that are not integer (i.e. types) - // throw src::ParseError{where, "cannot assign or return type expressions"}; - // in reality, this check should be only when parsing type parameters after constructors - } - if (!checking_type) { - // "true" equality/assignment of type expressions - if (!negated && !value_negated) { - if (tp == te_Apply && args.empty()) { - throw src::ParseError{where, "use of a global type or an undeclared variable"}; - } else { - throw src::ParseError{where, "cannot check type expressions for equality"}; - } - } - // available only if the expression is a free variable - if (negated && tp != te_Param) { - throw src::ParseError{where, "types can be assigned only to free type variables"}; - } - } - } - switch (tp) { - case te_Add: { - assert(is_nat && args.size() == 2 && !(args[0]->negated && args[1]->negated)); - assert(negated == (args[0]->negated || args[1]->negated)); - int i = args[0]->negated; - args[i]->bind_value(negated, cs); - args[1 - i]->bind_value(false, cs); - return true; - } - case te_IntConst: { - assert(is_nat && !negated); - return true; - } - case te_MulConst: { - assert(is_nat && args.size() == 1 && value > 0); - assert(negated == args[0]->negated); - args[0]->bind_value(value_negated, cs); - return true; - } - case te_GetBit: { - assert(is_nat && args.size() == 2 && !args[0]->negated && !args[1]->negated); - assert(!negated); - args[0]->bind_value(false, cs); - args[1]->bind_value(false, cs); - return true; - } - case te_Type: { - assert(!is_nat && !negated); - return true; - } - case te_Param: { - assert(value >= 0 && value < cs.fields_num); - Field& field = cs.fields.at(value); - if (!negated || checking_type) { - if (!field.known) { - throw src::ParseError{where, - std::string{"variable `"} + field.get_name() + "` used before being assigned to"}; - } else { - field.used = true; - } - } else if (!field.known) { - field.known = true; - // where.show_note(std::string{"variable `"} + field.get_name() + "` is assigned a value here"); - } - return true; - } - case te_Apply: - if (type_applied == Eq_type) { - assert(args.size() == 2 && !(args[0]->negated && args[1]->negated)); - assert(negated == (args[0]->negated || args[1]->negated)); - int i = args[0]->negated; - args[i]->bind_value(negated, cs); - args[1 - i]->bind_value(false, cs); - return true; - } else { - assert(!negated || checking_type); - for (TypeExpr* arg : args) { - if (!arg->negated) { - arg->bind_value(true, cs); - } - } - for (TypeExpr* arg : args) { - if (arg->negated) { - arg->bind_value(false, cs); - } - } - return true; - } - case te_CondType: - case te_Tuple: { - assert(args.size() == 2); - assert(!negated && !args[0]->negated && !args[1]->negated); - assert(args[0]->is_nat); - assert(!args[1]->is_nat); - args[0]->bind_value(true, cs); - args[1]->bind_value(true, cs); - return true; - } - case te_Ref: { - assert(args.size() == 1); - return args[0]->bind_value(value_negated, cs, checking_type); - } - default: - throw src::ParseError{where, "cannot bind a value to an expression of unknown sort"}; - } - return true; -} - -void parse_implicit_param(Lexer& lex, Constructor& cs) { - // ident : # or ident : Type - if (lex.tp() != src::_Ident) { - lex.expect(src::_Ident); - } - Field& field = cs.new_field(lex.cur().loc, true, lex.cur().val); - lex.next(); - lex.expect(':'); - if (lex.tp() != src::_Type && (lex.tp() != src::_Ident || lex.cur().val != Nat_name)) { - throw src::ParseError{lex.cur().loc, "either `Type` or `#` implicit parameter type expected"}; - } - if (lex.tp() == src::_Type) { - field.type = &type_Type; - } else { - field.type = TypeExpr::mk_apply_empty(lex.cur().loc, Nat_name, Nat_type); - assert(Nat_type->produces_nat); - assert(!Nat_type->arity); - assert(field.type->is_nat_subtype); - } - lex.next(); - field.register_sym(); -} - -sym::SymDef* register_new_type(const src::SrcLocation& loc, sym_idx_t name) { - // unknown identifier, declare new type - if (!sym::is_uc_ident(name)) { - throw src::ParseError{loc, std::string{"implicitly defined type `"} + sym::symbols.get_name(name) + - "` must begin with an uppercase letter"}; - } - sym::SymDef* sym_def = sym::define_global_symbol(name, true, loc); - assert(sym_def); - types.emplace_back(types_num++, name); - sym_def->value = new SymValType{&types.back()}; - return sym_def; -} - -void show_tag(std::ostream& os, unsigned long long tag) { - if (!tag) { - return; - } - if (!(tag & ((1ULL << 59) - 1))) { - os << '$'; - int c = 0; - while (tag & ((1ULL << 63) - 1)) { - os << (tag >> 63); - tag <<= 1; - ++c; - } - if (!c) { - os << '_'; - } - } else { - os << '#'; - while (tag & ((1ULL << 63) - 1)) { - static const char hex_digits[] = "0123456789abcdef"; - os << hex_digits[tag >> 60]; - tag <<= 4; - } - if (!tag) { - os << '_'; - } - } -} - -void Constructor::show(std::ostream& os, int mode) const { - if (mode & 4) { - os << '['; - } else { - os << sym::symbols.get_name(constr_name); - } - if (!(mode & 8)) { - show_tag(os, tag); - } - for (const Field& field : fields) { - os << ' '; - if (field.implicit || field.constraint) { - if (!(mode & 2)) { - os << '{'; - } - if (field.name) { - os << field.get_name() << ':'; - } - field.type->show(os, this, 0, mode & ~1); - if (!(mode & 2)) { - os << '}'; - } - } else { - if (field.name) { - os << field.get_name() << ':'; - } - field.type->show(os, this, 95, mode & ~1); - } - } - if (mode & 4) { - os << " ]"; - return; - } - os << " = "; - if (type_defined) { - type_defined->print_name(os); - } else { - os << sym::symbols.get_name(type_name); - } - for (int i = 0; i < type_arity; i++) { - os << ' '; - if (param_negated.at(i)) { - os << '~'; - } - params.at(i)->show(os, this, 100, mode | 1); - } - if (!(mode & 2)) { - os << ';'; - } -} - -unsigned long long Constructor::compute_tag() const { - std::ostringstream os; - show(os, 10); - unsigned crc = td::crc32(td::Slice{os.str()}); - if (verbosity > 2) { - std::cerr << "crc32('" << os.str() << "') = " << std::hex << crc << std::dec << std::endl; - } - return ((unsigned long long)crc << 32) | 0x80000000; -} - -bool Constructor::compute_is_fwd() { - if (constr_name || tag_bits || type_arity || fields_num != 1) { - return is_fwd = false; - } - return is_fwd = (!fields[0].implicit && !fields[0].constraint); -} - -bool show_tag_warnings; - -void Constructor::check_assign_tag() { - if (constr_name && (!tag || (tag & (1ULL << 63)) == (1ULL << 63))) { - unsigned long long computed_tag = compute_tag(); - if (!tag) { - set_tag(computed_tag); - if (show_tag_warnings) { - std::ostringstream os; - os << "constructor `" << sym::symbols.get_name(type_name) << "::" << sym::symbols.get_name(constr_name) - << "` had no tag, assigned "; - show_tag(os, computed_tag); - where.show_warning(os.str()); - } - } else if (tag != computed_tag && show_tag_warnings) { - std::ostringstream os; - os << "constructor `" << sym::symbols.get_name(type_name) << "::" << sym::symbols.get_name(constr_name) - << "` has explicit tag "; - show_tag(os, tag); - os << " different from its computed tag "; - show_tag(os, computed_tag); - where.show_warning(os.str()); - } - } else if (!constr_name && !tag) { - set_tag(1ULL << 63); - } -} - -void Type::bind_constructor(const src::SrcLocation& loc, Constructor* cs) { - if (is_final) { - throw src::ParseError{loc, std::string{"cannot add new constructor `"} + sym::symbols.get_name(cs->constr_name) + - "` to a finalized type `" + sym::symbols.get_name(type_name) + "`"}; - } - if (arity < 0) { - arity = cs->type_arity; - assert(arity >= 0); - args.resize(arity, 0); - } else { - if (arity != cs->type_arity) { - throw src::ParseError{loc, std::string{"parametrized type `"} + sym::symbols.get_name(type_name) + - "` redefined with different arity"}; - } - } - assert(arity == cs->type_arity && arity == (int)cs->params.size() && cs->params.size() == cs->param_negated.size()); - int true_params = 0; - for (int i = 0; i < arity; i++) { - auto expr = cs->params.at(i); - bool negated = cs->param_negated.at(i); - int& x = args[i]; - x |= (expr->is_nat ? _IsNat : _IsType); - if ((x & (_IsNat | _IsType)) == (_IsNat | _IsType)) { - throw src::ParseError{expr->where, std::string{"formal parameter to type `"} + sym::symbols.get_name(type_name) + - "` has incorrect type"}; - } - x |= (negated ? _IsNeg : _IsPos); - if ((x & (_IsPos | _IsNeg)) == (_IsPos | _IsNeg)) { - throw src::ParseError{expr->where, std::string{"formal parameter to type `"} + sym::symbols.get_name(type_name) + - "` has incorrect polarity"}; - } - if (cs->param_const_val.at(i) < 0) { - x |= _NonConst; - } - true_params += !negated; - } - assert(cs->fields_num >= 0 && (long long)cs->fields_num == (long long)cs->fields.size()); - int explicit_fields = 0; - for (Field& field : cs->fields) { - if (field.constraint) { - field.type->bind_value(false, *cs, true); - field.known = true; - } else if (!field.implicit) { - ++explicit_fields; - field.type->bind_value(false, *cs, true); - if (!field.known) { - // field.loc.show_note(std::string{"variable `"} + field.get_name() + "` is assigned a value here"); - } - field.known = true; - } - } - cs->is_enum = !explicit_fields; - cs->is_simple_enum = (cs->is_enum && !true_params); - for (int i = 0; i < arity; i++) { - auto expr = cs->params[i]; - bool negated = cs->param_negated[i]; - if (negated) { - expr->bind_value(true, *cs); - } - } - for (Field& field : cs->fields) { - if (!field.known) { - throw src::ParseError{field.loc, std::string{"field `"} + field.get_name() + "` is left unbound"}; - } - } - if (cs->constr_name) { - for (auto c : constructors) { - if (c->constr_name == cs->constr_name) { - std::string tname = sym::symbols.get_name(type_name); - std::string cname = tname + "::" + sym::symbols.get_name(cs->constr_name); - c->where.show_note(std::string{"constructor `"} + cname + "` first defined here"); - throw src::ParseError{cs->where, std::string{"constructor `"} + cname + "` redefined"}; - } - } - } - if (!cs->type_defined && cs->type_name == type_name) { - cs->type_defined = this; - } - cs->check_assign_tag(); - cs->compute_is_fwd(); - is_enum &= cs->is_enum; - is_simple_enum &= cs->is_simple_enum; - if (constr_num && (is_special != cs->is_special)) { - throw src::ParseError{cs->where, std::string{"type `"} + sym::symbols.get_name(type_name) + - "` has mixed special and non-special constructors"}; - } - is_special = cs->is_special; - ++(constr_num); - constructors.push_back(cs); -} - -bool Type::unique_constructor_equals(const Constructor& cs, bool allow_other_names) const { - return constr_num == 1 && constructors.at(0)->isomorphic_to(cs, allow_other_names); -} - -bool Constructor::isomorphic_to(const Constructor& cs, bool allow_other_names) const { - if (constr_name != cs.constr_name || tag != cs.tag || fields_num != cs.fields_num || type_arity != cs.type_arity || - params.size() != cs.params.size()) { - return false; - } - for (int i = 0; i < fields_num; i++) { - if (!fields.at(i).isomorphic_to(cs.fields.at(i), allow_other_names)) { - return false; - } - } - for (std::size_t i = 0; i < params.size(); i++) { - if (!params.at(i)->equal(*cs.params.at(i))) { - return false; - } - } - return true; -} - -bool Field::isomorphic_to(const Field& f, bool allow_other_names) const { - if (f.field_idx != field_idx || f.implicit != implicit || f.constraint != constraint || - (!allow_other_names && f.name != name)) { - return false; - } - return f.type->equal(*type); -} - -/* - * - * TL-B SOURCE PARSER - * - */ - -void parse_field_list(Lexer& lex, Constructor& cs); - -TypeExpr* parse_anonymous_constructor(Lexer& lex, Constructor& cs) { - sym::open_scope(lex); - Constructor* cs2 = new (AR) Constructor(lex.cur().loc); // anonymous constructor - parse_field_list(lex, *cs2); - if (lex.tp() != ']') { - lex.expect(']'); - } - cs2->set_tag(1ULL << 63); - for (int i = builtin_types_num; i < types_num; i++) { - if (types.at(i).is_auto && types[i].is_final && types[i].unique_constructor_equals(*cs2)) { - sym::close_scope(lex); - if (types[i].parent_type_idx >= 0) { - types[i].parent_type_idx = -2; - } - delete cs2; - return TypeExpr::mk_apply_empty(lex.cur().loc, 0, &types[i]); - } - } - types.emplace_back(types_num++, 0); - Type* type = &types.back(); // anonymous type - type->bind_constructor(lex.cur().loc, cs2); - type->is_final = true; - type->is_auto = true; - type->is_anon = true; - type->renew_last_declared(); - sym::close_scope(lex); - return TypeExpr::mk_apply_empty(lex.cur().loc, 0, type); -} - -TypeExpr* parse_expr(Lexer& lex, Constructor& cs, int mode); - -// ( E ) | [ {field-def} ] | id | ~id | num | ^T -TypeExpr* parse_term(Lexer& lex, Constructor& cs, int mode) { - if (lex.tp() == '(') { - lex.next(); - TypeExpr* expr = parse_expr(lex, cs, mode); - expr->check_mode(lex.cur().loc, mode); - lex.expect(')'); - return expr; - } - if (lex.tp() == src::_Number) { - TypeExpr* expr = TypeExpr::mk_intconst(lex.cur().loc, lex.cur().str); - expr->check_mode(lex.cur().loc, mode); - lex.next(); - return expr; - } - if (lex.tp() == '[') { - lex.next(); - TypeExpr* expr = parse_anonymous_constructor(lex, cs); - expr->check_mode(lex.cur().loc, mode); - lex.expect(']'); - return expr; - } - if (lex.tp() == '^') { - src::SrcLocation loc = lex.cur().loc; - lex.next(); - TypeExpr* expr = parse_term(lex, cs, mode & ~2); - expr->close(lex.cur().loc); - if (expr->is_nat) { - throw src::ParseError{loc, "cannot create a cell reference type to a natural number"}; - } - return TypeExpr::mk_cellref(loc, expr); - } - bool negate = false; - if (lex.tp() == '~') { - lex.next(); - if (lex.tp() != src::_Ident) { - lex.expect(src::_Ident, "field identifier"); - } - negate = true; - } - if (lex.tp() == src::_Ident) { - sym_idx_t name = lex.cur().val; - sym::SymDef* sym_def = sym::lookup_symbol(name); - if (!sym_def) { - if (negate) { - throw src::ParseError{lex.cur().loc, "field identifier expected"}; - } - sym_def = register_new_type(lex.cur().loc, name); - if (verbosity > 2) { - std::cerr << "implicitly defined new type `" << sym::symbols.get_name(name) << "`" << std::endl; - } - } - if (!sym_def->value) { - throw src::ParseError{lex.cur().loc, "global symbol has no value"}; - } - if (sym_def->value->type == sym::SymValBase::_Typename) { - // found a global type identifier - if (negate) { - throw src::ParseError{lex.cur().loc, "cannot negate a type"}; - } - SymValType* svt = dynamic_cast(sym_def->value); - assert(svt && svt->type_ref); - (svt->type_ref->used)++; - auto res = TypeExpr::mk_apply_empty(lex.cur().loc, name, svt->type_ref); - lex.next(); - return res; - } - SymVal* sym_val = dynamic_cast(sym_def->value); - if (sym_def->value->type != sym::SymValBase::_Param || !sym_val) { - throw src::ParseError{lex.cur().loc, "field identifier expected"}; - } - if (sym_def->level != sym::scope_level) { - throw src::ParseError{lex.cur().loc, std::string{"cannot access field `"} + lex.cur().str + "` from outer scope"}; - } - int i = sym_val->idx; - assert(i >= 0 && i < cs.fields_num); - auto res = new (AR) TypeExpr{lex.cur().loc, TypeExpr::te_Param, i}; - auto field_type = cs.fields[i].type; - assert(field_type); - if ((mode & 4) && !cs.fields[i].known) { - // auto-negate, used for parsing type parameters in constructor RHS - negate = true; - } - res->is_nat = field_type->is_nat_subtype; - // std::cerr << "using field " << lex.cur().str << "; is_nat_subtype = " << res->is_nat << std::endl; - if (!res->is_nat && field_type->tp != TypeExpr::te_Type) { - throw src::ParseError{lex.cur().loc, - "cannot use a field in an expression unless it is either an integer or a type"}; - } - if (negate && !cs.fields[i].implicit) { - throw src::ParseError{lex.cur().loc, "cannot negate an explicit field"}; - } - res->negated = negate; - res->check_mode(lex.cur().loc, mode); - lex.next(); - return res; - } else { - lex.expect(src::_Ident, "type identifier"); - return nullptr; - } -} - -// E[.E] -TypeExpr* parse_expr97(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_term(lex, cs, mode | 3); - if (lex.tp() == '.') { - src::SrcLocation where = lex.cur().loc; - expr->close(lex.cur().loc); - // std::cerr << "parse ., mode " << mode << std::endl; - if (!(mode & 2)) { - throw src::ParseError{where, "bitfield expression cannot be used instead of a type expression"}; - } - if (!expr->is_nat) { - throw src::ParseError{where, "cannot apply bit selection operator `.` to types"}; - } - lex.next(); - TypeExpr* expr2 = parse_term(lex, cs, mode & ~1); - expr2->close(lex.cur().loc); - if (expr->negated || expr2->negated) { - throw src::ParseError{where, "cannot apply bit selection operator `.` to values of negative polarity"}; - } - expr = TypeExpr::mk_apply(where, TypeExpr::te_GetBit, expr, expr2); - } - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -// E ? E [ : E ] -TypeExpr* parse_expr95(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_expr97(lex, cs, mode | 3); - if (lex.tp() != '?') { - expr->check_mode(lex.cur().loc, mode); - return expr; - } - src::SrcLocation where = lex.cur().loc; - expr->close(where); - if (!expr->is_nat) { - throw src::ParseError{where, "cannot apply `?` with non-integer selectors"}; - } - lex.next(); - TypeExpr* expr2 = parse_term(lex, cs, mode & ~10); - expr2->close(lex.cur().loc); - expr2->no_tchk(); - expr = TypeExpr::mk_apply(where, TypeExpr::te_CondType, expr, expr2); - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -// E E -TypeExpr* parse_expr90(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_expr95(lex, cs, mode | 3); - while (lex.tp() == '(' || lex.tp() == src::_Ident || lex.tp() == src::_Number || lex.tp() == '~' || lex.tp() == '^' || - lex.tp() == '[') { - TypeExpr* expr2 = parse_expr95(lex, cs, mode | 3); - expr2->close(lex.cur().loc); - expr = TypeExpr::mk_apply_gen(lex.cur().loc, expr, expr2); - } - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -// E * E -TypeExpr* parse_expr30(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_expr90(lex, cs, mode); - while (lex.tp() == '*') { - src::SrcLocation where = lex.cur().loc; - expr->close(lex.cur().loc); - if (!expr->is_nat) { - throw src::ParseError{where, "cannot apply `*` to types"}; - } - lex.next(); - TypeExpr* expr2 = parse_expr90(lex, cs, mode); - expr2->close(lex.cur().loc); - if (expr2->is_nat) { - expr = TypeExpr::mk_mulint(where, expr, expr2); - } else { - expr2->no_tchk(); - expr = TypeExpr::mk_apply(where, TypeExpr::te_Tuple, expr, expr2); - } - } - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -// E + E -TypeExpr* parse_expr20(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_expr30(lex, cs, mode); - while (lex.tp() == '+') { - src::SrcLocation where = lex.cur().loc; - expr->close(lex.cur().loc); - // std::cerr << "parse +, mode " << mode << std::endl; - if (!(mode & 2)) { - throw src::ParseError{where, "sum cannot be used instead of a type expression"}; - } - if (!expr->is_nat) { - throw src::ParseError{where, "cannot apply `+` to types"}; - } - lex.next(); - TypeExpr* expr2 = parse_expr30(lex, cs, mode & ~1); - expr2->close(lex.cur().loc); - if (expr->negated && expr2->negated) { - throw src::ParseError{where, "cannot add two values of negative polarity"}; - } - bool negated = expr->negated | expr2->negated; - expr = TypeExpr::mk_apply(where, TypeExpr::te_Add, expr, expr2); - expr->negated = negated; - } - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -// E | E = E | E <= E | E < E | E >= E | E > E -TypeExpr* parse_expr10(Lexer& lex, Constructor& cs, int mode) { - TypeExpr* expr = parse_expr20(lex, cs, mode | 3); - int op = lex.tp(); - if (!(op == '=' || op == '<' || op == '>' || op == src::_Leq || op == src::_Geq)) { - expr->check_mode(lex.cur().loc, mode); - return expr; - } - // std::cerr << "parse <=>, mode " << mode << std::endl; - sym_idx_t op_name = lex.cur().val; - src::SrcLocation where = lex.cur().loc; - expr->close(where); - if (!(mode & 1)) { - throw src::ParseError{where, "comparison result used as an integer"}; - } - if (!expr->is_nat) { - throw src::ParseError{where, "cannot apply integer comparison to types"}; - } - lex.next(); - TypeExpr* expr2 = parse_expr20(lex, cs, (mode & ~1) | 2); - expr2->close(lex.cur().loc); - if (!expr2->is_nat) { - throw src::ParseError{lex.cur().loc, "cannot apply integer comparison to types"}; - } - if (op == '>') { - std::swap(expr, expr2); - op = '<'; - op_name = Less_name; - } else if (op == src::_Geq) { - std::swap(expr, expr2); - op = src::_Leq; - op_name = Leq_name; - } - auto sym_def = sym::lookup_symbol(op_name, 2); - assert(sym_def); - auto sym_val = dynamic_cast(sym_def->value); - assert(sym_val); - auto expr0 = TypeExpr::mk_apply_empty(where, op_name, sym_val->type_ref); - expr = TypeExpr::mk_apply_gen(where, std::move(expr0), expr); - expr = TypeExpr::mk_apply_gen(lex.cur().loc, expr, std::move(expr2)); - expr->check_mode(lex.cur().loc, mode); - return expr; -} - -TypeExpr* parse_expr(Lexer& lex, Constructor& cs, int mode) { - return parse_expr10(lex, cs, mode); -} - -void parse_param(Lexer& lex, Constructor& cs, bool named) { - // [ ( ident | _ ) : ] type-expr - src::SrcLocation loc = lex.cur().loc; - if (named && lex.tp() == '_') { - lex.next(); - lex.expect(':'); - named = false; - } - sym_idx_t param_name = 0; - if (named) { - if (lex.tp() != src::_Ident) { - lex.expect(src::_Ident); - } - param_name = lex.cur().val; - lex.next(); - lex.expect(':'); - } - Field& field = cs.new_field(loc, false, param_name); - field.type = parse_expr95(lex, cs, 9); // must be a type expression - field.type->close(lex.cur().loc); - field.type->detect_constexpr(); - field.subrec = field.type->is_ref_to_anon(); - CHECK(!field.name || !field.subrec); - field.register_sym(); -} - -void parse_constraint(Lexer& lex, Constructor& cs) { - Field& field = cs.new_field(lex.cur().loc, true, 0); - field.type = parse_expr(lex, cs, 9); // must be a type expression - field.type->close(lex.cur().loc); - field.type->detect_constexpr(); - field.constraint = true; - field.register_sym(); -} - -void parse_field_list(Lexer& lex, Constructor& cs) { - while (lex.tp() != '=' && lex.tp() != ']') { - if (lex.tp() == '{') { - // either an implicit parameter or a constraint - lex.next(); - if (lex.tp() == src::_Ident && lex.peek().tp == ':') { - parse_implicit_param(lex, cs); - } else { - parse_constraint(lex, cs); - } - lex.expect('}'); - } else if ((lex.tp() == src::_Ident || lex.tp() == '_') && lex.peek().tp == ':') { - parse_param(lex, cs, true); - } else { - parse_param(lex, cs, false); - } - } -} - -void parse_constructor_def(Lexer& lex) { - if (lex.tp() != '_' && (lex.tp() != src::_Ident || !sym::is_lc_ident(lex.cur().val))) { - throw src::ParseError{lex.cur().loc, "constructor name lowercase identifier expected"}; - } - bool is_special = sym::is_spec_lc_ident(lex.cur().val); - sym::open_scope(lex); - Lexem constr_lex = lex.cur(); - int orig_types_num = types_num; - sym_idx_t constr_name = (lex.tp() == src::_Ident ? lex.cur().val : 0); - src::SrcLocation where = lex.cur().loc; - lex.next(); - unsigned long long tag = 0; - if (lex.tp() == src::_Special) { - tag = src::get_special_value(lex.cur().str); - assert(tag); - lex.next(); - } - //std::cerr << "parsing constructor `" << sym::symbols.get_name(constr_name) << "` with tag " << std::hex << tag - // << std::dec << std::endl; - auto cs_ref = new (AR) Constructor(where, constr_name, 0, tag); - Constructor& cs = *cs_ref; - cs.is_special = is_special; - parse_field_list(lex, cs); - lex.expect('='); - if (lex.tp() != src::_Ident || !sym::is_uc_ident(lex.cur().val)) { - throw src::ParseError{lex.cur().loc, "type name uppercase identifier expected"}; - } - Lexem type_lex = lex.cur(); - sym_idx_t type_name = lex.cur().val; - sym::SymDef* sym_def = sym::lookup_symbol(type_name, 2); - if (!sym_def) { - sym_def = register_new_type(lex.cur().loc, type_name); - if (verbosity > 2) { - std::cerr << "defined new type `" << sym::symbols.get_name(type_name) << "`" << std::endl; - } - assert(sym_def); - } - if (!sym_def || !sym_def->value || sym_def->value->type != sym::SymValBase::_Typename) { - throw src::ParseError{lex.cur().loc, "parametrized type identifier expected"}; - } - SymValType* sym_val = dynamic_cast(sym_def->value); - assert(sym_val); - cs.type_name = type_name; - cs.type_arity = 0; - Type* type = cs.type_defined = sym_val->type_ref; - if (type->is_final) { - throw src::ParseError{lex.cur().loc, - std::string{"cannot add new constructor to a finalized type `"} + lex.cur().str + "`"}; - } - lex.next(); - while (lex.tp() != ';') { - bool negate = (lex.tp() == '~'); - if (negate) { - lex.next(); - } - TypeExpr* type_param = parse_term(lex, cs, negate ? 3 : 7); - type_param->close(lex.cur().loc); - int const_val = (!negate && type_param->tp == TypeExpr::te_IntConst) ? type_param->value : -1; - if (!negate) { - //std::cerr << "binding value to type parameter expression "; - //type_param->show(std::cerr, &cs); - //std::cerr << std::endl; - type_param->bind_value(negate, cs); - } else if (!type_param->is_nat) { - throw src::ParseError{type_param->where, "cannot return type expressions"}; - } - cs.params.push_back(type_param); - cs.param_negated.push_back(negate); - cs.param_const_val.push_back(const_val); - ++cs.type_arity; - } - if (lex.tp() != ';') { - lex.expect(';'); - } - type->bind_constructor(lex.cur().loc, cs_ref); - type->renew_last_declared(); - lex.expect(';'); - sym::close_scope(lex); - for (int i = orig_types_num; i < types_num; i++) { - if (types.at(i).is_auto && types[i].parent_type_idx == -1) { - types[i].parent_type_idx = type->type_idx; - } - } -} - -/* - * - * SOURCE PARSER (TOP LEVEL) - * - */ - -std::vector source_fdescr; - -bool parse_source(std::istream* is, src::FileDescr* fdescr) { - src::SourceReader reader{is, fdescr}; - src::Lexer lex{reader, true, "(){}:;? #$. ^~ #", "//", "/*", "*/"}; - while (lex.tp() != src::_Eof) { - parse_constructor_def(lex); - // std::cerr << lex.cur().str << '\t' << lex.cur().name_str() << std::endl; - } - return true; -} - -bool parse_source_file(const char* filename) { - if (!filename || !*filename) { - throw src::Fatal{"source file name is an empty string"}; - } - src::FileDescr* cur_source = new src::FileDescr{filename}; - source_fdescr.push_back(cur_source); - std::ifstream ifs{filename}; - if (ifs.fail()) { - throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"}; - } - return parse_source(&ifs, cur_source); -} - -bool parse_source_stdin() { - src::FileDescr* cur_source = new src::FileDescr{"stdin", true}; - source_fdescr.push_back(cur_source); - return parse_source(&std::cin, cur_source); -} - -/* - * - * BUILT-IN TYPE DEFINITIONS - * - */ - -Type* define_builtin_type(std::string name_str, std::string args, bool produces_nat, int size = -1, int min_size = -1, - bool any_bits = false, int is_int = 0) { - sym_idx_t name = sym::symbols.lookup_add(name_str); - assert(name_str.size() && name); - int arity = (int)args.size(); - types.emplace_back(types_num++, name, produces_nat, arity, true, true); - auto type = &types.back(); - type->args.resize(arity, 0); - int f = (name_str != "#" ? Type::_IsPos : 0); - for (int i = 0; i < arity; i++) { - type->args[i] = f | (args[i] == '#' ? Type::_IsNat : Type::_IsType); - } - if (is_int) { - type->is_integer = (char)is_int; - } - auto sym_def = sym::define_global_symbol(name, true); - assert(sym_def); - sym_def->value = new (AR) SymValType{type}; - if (size < 0) { - type->size = MinMaxSize::Any; - } else if (min_size >= 0 && min_size != size) { - type->size = MinMaxSize::size_range(min_size, size); - } else { - type->size = MinMaxSize::fixed_size(size); - type->has_fixed_size = true; - } - type->any_bits = any_bits; - return type; -} - -Type* lookup_type(std::string name_str) { - sym_idx_t name = sym::symbols.lookup(name_str); - if (name) { - auto sym_def = sym::lookup_symbol(name); - if (sym_def) { - auto sym_val = dynamic_cast(sym_def->value); - if (sym_val) { - return sym_val->type_ref; - } - } - } - return nullptr; -} - -void define_builtins() { - types.reserve(10000); - Nat_type = define_builtin_type("#", "", true, 32, 32, true); - NatWidth_type = define_builtin_type("##", "#", true, 32, 0, true); - NatLess_type = define_builtin_type("#<", "#", true, 32, 0); - NatLeq_type = define_builtin_type("#<=", "#", true, 32, 0); - Any_type = define_builtin_type("Any", "", false); - Cell_type = define_builtin_type("Cell", "", false); - Int_type = define_builtin_type("int", "#", false, 257, 0, true, -1); - UInt_type = define_builtin_type("uint", "#", false, 256, 0, true, 1); - Bits_type = define_builtin_type("bits", "#", false, 1023, 0, true, 0); - for (int i = 1; i <= 257; i++) { - char buff[8]; - sprintf(buff, "uint%d", i); - define_builtin_type(buff + 1, "", false, i, i, true, -1); - if (i < 257) { - define_builtin_type(buff, "", false, i, i, true, 1); - } - } - for (int i = 1; i <= 1023; i++) { - char buff[12]; - sprintf(buff, "bits%d", i); - define_builtin_type(buff, "", false, i, i, true, 0); - } - Eq_type = define_builtin_type("=", "##", false, 0, 0, true); - Less_type = define_builtin_type("<", "##", false, 0, 0, true); - Leq_type = define_builtin_type("<=", "##", false, 0, 0, true); - Nat_name = sym::symbols.lookup("#"); - Eq_name = sym::symbols.lookup("="); - Less_name = sym::symbols.lookup("<"); - Leq_name = sym::symbols.lookup("<="); - builtin_types_num = types_num; -} - -/* - * - * SCHEME PROCESSING AND CHECKING - * - */ - -bool Type::cons_all_exact() const { - unsigned long long sum = 0; - for (const auto& cons : constructors) { - sum += (1ULL << (63 - cons->tag_bits)); - } - return sum == (1ULL << 63); -} - -int Type::cons_common_len() const { - if (!constr_num) { - return -1; - } - int len = constructors.at(0)->tag_bits; - for (const auto cons : constructors) { - if (cons->tag_bits != len) { - return -1; - } - } - return len; -} - -bool Constructor::compute_admissible_params() { - int dim = 0; - int abs_param[4]; - for (std::size_t i = 0; i < params.size(); i++) { - if (!param_negated[i] && params[i]->is_nat) { - int t = params[i]->abstract_interpret_nat(); - assert(t >= 0 && t <= 15); - // std::cerr << "abstract_interpret( " << params[i] << " ) = " << t << std::endl; - abs_param[dim++] = t; - if (!t) { - admissible_params.clear_all(); - return false; - } - if (dim == 4) { - break; - } - } - } - while (dim > 0 && abs_param[dim - 1] == 15) { - --dim; - } - if (!dim) { - admissible_params.set_all(); - return true; - } - admissible_params.set_by_pattern(dim, abs_param); - return true; -} - -bool Type::compute_admissible_params() { - bool admissible = false; - for (Constructor* cs : constructors) { - admissible |= cs->compute_admissible_params(); - admissible_params |= cs->admissible_params; - } - return admissible; -} - -void compute_admissible_params() { - for (int i = builtin_types_num; i < types_num; i++) { - (void)types[i].compute_admissible_params(); - } -} - -bool Constructor::recompute_begins_with() { - for (const Field& field : fields) { - if (!field.implicit && !field.constraint) { - TypeExpr* expr = field.type; - if (expr->tp == TypeExpr::te_Ref) { - continue; - } - if (expr->tp != TypeExpr::te_Apply) { - break; - } - BitPfxCollection add = expr->type_applied->begins_with * tag; - return (begins_with += add); - } - } - BitPfxCollection add{tag}; - if (begins_with == add) { - return false; - } - begins_with += add; - return true; -} - -bool Type::recompute_begins_with() { - bool changes = false; - for (Constructor* cs : constructors) { - if (cs->recompute_begins_with()) { - changes |= (begins_with += cs->begins_with); - } - } - return changes; -} - -void compute_begins_with() { - bool changes = true; - while (changes) { - changes = false; - for (int i = builtin_types_num; i < types_num; i++) { - changes |= types[i].recompute_begins_with(); - } - } -} - -bool Constructor::recompute_minmax_size() { - MinMaxSize sz = MinMaxSize::fixed_size(tag_bits); - for (const Field& field : fields) { - if (!field.implicit && !field.constraint) { - sz += field.type->compute_size(); - } - } - if (sz == size) { - return false; - } - size = sz; - has_fixed_size = sz.is_fixed(); - return true; -} - -bool Type::recompute_minmax_size() { - MinMaxSize sz; - bool changes = false; - for (Constructor* cs : constructors) { - changes |= cs->recompute_minmax_size(); - sz |= cs->size; - } - if (sz == size) { - return changes; - } - size = sz; - has_fixed_size = sz.is_fixed(); - return true; -} - -void compute_minmax_sizes() { - bool changes = true; - while (changes) { - changes = false; - for (int i = builtin_types_num; i < types_num; i++) { - changes |= types[i].recompute_minmax_size(); - } - } -} - -bool Constructor::recompute_any_bits() { - bool res = true; - for (const Field& field : fields) { - if (!field.implicit && !field.constraint) { - res &= field.type->compute_any_bits(); - } - } - if (res == any_bits) { - return false; - } - any_bits = res; - return true; -} - -bool Type::recompute_any_bits() { - bool res = begins_with.is_all(); - bool changes = false; - for (Constructor* cs : constructors) { - changes |= cs->recompute_any_bits(); - res &= cs->any_bits; - } - if (res == any_bits) { - return changes; - } - any_bits = res; - return true; -} - -void compute_any_bits() { - bool changes = true; - while (changes) { - changes = false; - for (int i = builtin_types_num; i < types_num; i++) { - changes |= types[i].recompute_any_bits(); - } - } -} - -void Type::detect_basic_types() { - if (!arity && constr_num > 0 && size.is_fixed() && any_bits) { - is_unit = !size.min_size(); - is_bool = (size.min_size() == 0x100); - } -} - -void detect_basic_types() { - for (int i = builtin_types_num; i < types_num; i++) { - types[i].detect_basic_types(); - } -} - -int show_size_warnings() { - int errors = 0; - for (int i = builtin_types_num; i < types_num; i++) { - Type& type = types[i]; - if (!type.size.fits_into_cell() || !type.size.is_possible()) { - std::cerr << "error: type `" << type.get_name() << "`" - << (!type.size.is_possible() ? " cannot be instantiated" : " never fits into a cell") << " (size " - << type.size << ")\n"; - ++errors; - } - for (Constructor* cs : type.constructors) { - if (!cs->size.fits_into_cell() || !cs->size.is_possible()) { - std::cerr << "error: constructor `" << cs->get_qualified_name() << "`" - << (!cs->size.is_possible() ? " cannot be instantiated" : " never fits into a cell") << " (size " - << cs->size << ")\n"; - cs->show(std::cerr); - std::cerr << std::endl; - cs->where.show_note("defined here"); - ++errors; - } - } - } - return errors; -} - -bool Type::is_const_arg(int p) const { - return (args.at(p) & (_IsType | _IsNat | _IsPos | _IsNeg | _NonConst)) == (_IsNat | _IsPos); -} - -int Type::detect_const_params() { - for (int i = 0; i < arity; i++) { - if (is_const_arg(i)) { - return const_param_idx = i; - } - } - return const_param_idx = -1; -} - -std::vector Type::get_all_param_values(int p) const { - if (p < 0 || p >= arity) { - return {}; - } - std::vector res; - res.reserve(constr_num); - for (const Constructor* cs : constructors) { - res.push_back(cs->param_const_val.at(p)); - } - std::sort(res.begin(), res.end()); - res.erase(std::unique(res.begin(), res.end()), res.end()); - return res; -} - -std::vector Type::get_constr_by_param_value(int p, int pv) const { - std::vector res; - if (p < 0 || p >= arity) { - return res; - } - for (int i = 0; i < constr_num; i++) { - if (constructors[i]->param_const_val[p] == pv) { - res.push_back(i); - } - } - return res; -} - -void Type::compute_constructor_trie() { - if (cs_trie || !constr_num) { - return; - } - unsigned long long z = 1; - for (Constructor* cs : constructors) { - if (!z) { - throw src::ParseError{cs->where, - std::string{"cannot work with more than 64 constructors for type `"} + get_name() + "`"}; - } - cs_trie = BinTrie::insert_paths(std::move(cs_trie), cs->begins_with, z); - z <<= 1; - } - if (cs_trie) { - useful_depth = cs_trie->compute_useful_depth(); - is_pfx_determ = !cs_trie->find_conflict_path(); - } else { - useful_depth = 0; - is_pfx_determ = true; - } -} - -bool Type::check_conflicts() { - compute_constructor_trie(); - int cp = detect_const_params(); - is_param_pfx_determ = is_param_determ = is_determ = true; - is_const_param_determ = is_const_param_pfx_determ = (cp >= 0); - if (!constr_num || !cs_trie) { - return false; - } - assert(constr_num <= 64); - // std::cerr << "prefix trie for constructors of `" << get_name() << "`" << std::endl; - // cs_trie->show(std::cerr); - ConflictGraph pfx_cg; - cs_trie->set_conflict_graph(pfx_cg); - for (int i = 0; i < constr_num; i++) { - AdmissibilityInfo& ap1 = constructors[i]->admissible_params; - for (int j = 0; j < i; j++) { - bool cp_same = (constructors[i]->get_const_param(cp) == constructors[j]->get_const_param(cp)); - if (cp_same) { - is_const_param_determ = false; - if (pfx_cg[i][j]) { - is_const_param_pfx_determ = false; - } - } - if (ap1.conflicts_with(constructors[j]->admissible_params)) { - is_param_determ = false; - if (pfx_cg[i][j]) { - is_param_pfx_determ = false; - if (cp_same) { - conflict1 = j; - conflict2 = i; - is_determ = false; - } - } - } - } - } - return !is_determ; -} - -void Type::show_constructor_conflict() { - assert(cs_trie); - assert(conflict1 != conflict2); - int i = conflict1, j = conflict2; - assert(i >= 0 && i <= j && j < 64 && j < constr_num); - unsigned long long mask = (1ULL << i) | (1ULL << j); - unsigned long long pfx = cs_trie->find_conflict_path(0, mask); - assert(pfx); - ConflictSet cs_set{cs_trie->lookup_tag(pfx)}; - std::cerr << "found conflict between constructors of type `" << get_name() << "`: prefix "; - show_tag(std::cerr, pfx); - AdmissibilityInfo& info1 = constructors[i]->admissible_params; - AdmissibilityInfo& info2 = constructors[j]->admissible_params; - bool need_params = !(info1.is_set_all() && info2.is_set_all()); - int params = info1.conflicts_at(info2); - assert(params >= 0); - for (int s = 0; s < 64 && s < constr_num; s++) { - if (cs_set[s] && - !(need_params ? constructors[s]->admissible_params[params] : constructors[s]->admissible_params.is_set_all())) { - cs_set.remove(s); - } - } - assert(cs_set[i] && cs_set[j]); - std::cerr << " can be present in " << cs_set.size() << " constructors:" << std::endl; - for (int s = 0; s < 64 && s < constr_num; s++) { - if (cs_set[s]) { - std::cerr << "\t"; - constructors[s]->show(std::cerr); - std::cerr << std::endl; - constructors[s]->where.show_note("defined here"); - } - } - if (need_params) { - std::cerr << "when type parameters are instantiated as " << get_name(); - char nat = 'a', t = 'A'; - for (int x : args) { - if (x & _IsNeg) { - std::cerr << " ~" << (x & _IsNat ? nat++ : t++); - } else if (x & _IsType) { - std::cerr << ' ' << t++; - } else { - std::cerr << ' ' << (params & 3); - if (params & 2) { - std::cerr << "+2*" << nat++; - } - } - } - std::cerr << std::endl; - } -} - -int check_conflicts() { - int c = 0; - for (int i = builtin_types_num; i < types_num; i++) { - if (types[i].check_conflicts()) { - ++c; - types[i].show_constructor_conflict(); - } - } - return c; -} - -void check_scheme() { - compute_admissible_params(); - compute_begins_with(); - compute_minmax_sizes(); - compute_any_bits(); - detect_basic_types(); - if (show_size_warnings()) { - throw src::Fatal{"invalid scheme: some constructors or types cannot be instantiated or do not fit into cells"}; - } - if (check_conflicts()) { - throw src::Fatal{"invalid scheme: have conflicts between constructors of some types"}; - } -} - -void dump_all_types() { - std::cerr << types_num << " types defined, out of them " << builtin_types_num << " built-in, " - << types_num - builtin_types_num << " user-defined\n"; - for (int i = 0; i < builtin_types_num; i++) { - Type& type = types[i]; - if (type.used) { - std::cerr << "built-in type #" << i << ": `" << type.get_name() << "`, arity " << type.arity << "; prefixes " - << type.begins_with << "; size " << type.size; - if (type.is_unit) { - std::cerr << " (UNIT)"; - } - if (type.is_bool) { - std::cerr << " (BOOL)"; - } - std::cerr << std::endl; - } - } - for (int i = builtin_types_num; i < types_num; i++) { - Type& type = types[i]; - std::cerr << "type #" << i << ": `" << type.get_name() << "`, arity " << type.arity << ", " << type.constr_num - << " constructors\n"; - if (type.const_param_idx >= 0) { - std::cerr << " constant parameters:"; - for (int j = 0; j < type.arity; j++) { - std::cerr << (type.is_const_arg(j) ? " const" : " *"); - } - std::cerr << std::endl; - } - for (Constructor* cs : type.constructors) { - std::cerr << " constructor `" << cs->get_name() << "`" << (cs->is_fwd ? " (simple forwarder)\n\t" : "\n\t"); - cs->show(std::cerr); - std::cerr << "\n\tbegins with " << cs->begins_with << std::endl; - if (!cs->admissible_params.is_set_all()) { - std::cerr << "\tadmissibility " << cs->admissible_params << std::endl; - } - if (type.const_param_idx >= 0) { - std::cerr << "\tconstant parameter #" << type.const_param_idx + 1 << " = " - << cs->get_const_param(type.const_param_idx) << std::endl; - } - std::cerr << "\tsize " << cs->size << (cs->has_fixed_size ? " (fixed)" : "") - << (cs->any_bits ? " (any bits)" : "") << std::endl; - for (const Field& field : cs->fields) { - std::cerr << "\t\tfield `" << field.get_name() << "`: " << field.type << " (used=" << field.used - << ") (is_nat_subtype=" << field.type->is_nat_subtype << ")\n"; - } - } - if (type.is_unit) { - std::cerr << " (UNIT)\n"; - } - if (type.is_bool) { - std::cerr << " (BOOL)\n"; - } - if (type.is_enum) { - std::cerr << (type.is_simple_enum ? " (SIMPLE ENUM)" : " (ENUM)") << std::endl; - } - if (type.constr_num > 1) { - std::cerr << " constructor detection: "; - if (type.is_pfx_determ) { - std::cerr << "PFX(" << type.useful_depth << ") "; - } - if (type.is_param_determ) { - std::cerr << "PARAM "; - } - if (type.is_const_param_determ) { - std::cerr << "CONST_PARAM "; - } - if (type.is_const_param_pfx_determ && !type.is_pfx_determ && !type.is_const_param_determ) { - std::cerr << "PFX(" << type.useful_depth << ")+CONST_PARAM "; - } - if (type.is_param_pfx_determ && !type.is_pfx_determ && !type.is_param_determ && !type.is_const_param_pfx_determ) { - std::cerr << "PFX(" << type.useful_depth << ")+PARAM "; - } - if (type.is_determ && !type.is_const_param_pfx_determ && !type.is_param_pfx_determ) { - std::cerr << "PFX(" << type.useful_depth << ")+CONST_PARAM+PARAM "; - } - if (!type.is_determ) { - std::cerr << ""; - } - std::cerr << std::endl; - } - std::cerr << " type size " << type.size << (type.has_fixed_size ? " (fixed)" : "") - << (type.any_bits ? " (any bits)" : "") << std::endl; - std::cerr << " type begins with " << type.begins_with << std::endl; - if (!type.admissible_params.is_set_all()) { - std::cerr << " type admissibility " << type.admissible_params << std::endl; - } - std::cerr << std::endl; - if (!type.constr_num && !type.is_final) { - sym::SymDef* sym_def = sym::lookup_symbol(type.type_name); - assert(sym_def); - throw src::ParseError{ - sym_def ? sym_def->loc : src::SrcLocation{}, - std::string{"implicitly defined type `"} + sym::symbols.get_name(type.type_name) + "` has no constructors"}; - } - } -} - -void dump_all_constexpr() { - std::cerr << "****************\n" << const_type_expr_num << " constant expressions:\n"; - for (int i = 1; i <= const_type_expr_num; i++) { - std::cerr << "expr #" << i << ": " << const_type_expr[i] << std::endl; - } -} - -/* - * - * CODE GENERATION - * - */ - -std::vector source_list; - -void register_source(std::string source) { - source_list.push_back(source); -} - -} // namespace tlbc - -#include "tlbc-gen-cpp.cpp" - -/* - * - * TLBC MAIN - * - */ - -void usage(const char* progname) { - std::cerr << "usage: " << progname - << " [-v][-i][-h][-c][-z][-t][-T][-q][-n][-o] { ...}\n" - << "-v\tIncrease verbosity level\n" - << "-t\tShow tag mismatch warnings\n" - << "-q\tOmit code generation (TLB scheme check only)\n" - << "-h\tGenerate C++ header file only (usually .h or .hpp)\n" - << "-c\tGenerate C++ source file only (usually .cpp)\n" - << "-T\tAdd type pointer members into generated C++ data record classes\n" - << "-z\tAppend .cpp or .hpp to output filename\n" - << "-n\tPut generated code into specified namespace (default `tlb`)\n"; - std::exit(2); -} - -std::string output_filename; - -int main(int argc, char* const argv[]) { - int i; - bool interactive = false; - bool no_code_gen = false; - while ((i = getopt(argc, argv, "chin:o:qTtvz")) != -1) { - switch (i) { - case 'i': - interactive = true; - break; - case 'v': - ++verbosity; - break; - case 'o': - output_filename = optarg; - break; - case 'c': - tlbc::gen_cpp = true; - break; - case 'h': - tlbc::gen_hpp = true; - break; - case 'q': - no_code_gen = true; - break; - case 'n': - tlbc::cpp_namespace = optarg; - break; - case 'T': - tlbc::add_type_members = true; - break; - case 't': - tlbc::show_tag_warnings = true; - break; - case 'z': - tlbc::append_suffix = true; - break; - default: - usage(argv[0]); - } - } - if (verbosity >= 3) { - tlbc::show_tag_warnings = true; - } - - src::define_keywords(); - tlbc::init_abstract_tables(); - tlbc::define_builtins(); - - int ok = 0, proc = 0; - try { - while (optind < argc) { - tlbc::register_source(argv[optind]); - ok += tlbc::parse_source_file(argv[optind++]); - proc++; - } - if (interactive) { - tlbc::register_source(""); - ok += tlbc::parse_source_stdin(); - proc++; - } - if (ok < proc) { - throw src::Fatal{"output code generation omitted because of errors"}; - } - if (!proc) { - throw src::Fatal{"no source files, no output"}; - } - tlbc::check_scheme(); - if (verbosity > 0) { - tlbc::dump_all_types(); - tlbc::dump_all_constexpr(); - } - if (!no_code_gen) { - tlbc::init_forbidden_cpp_idents(); - tlbc::generate_cpp_output(output_filename); - } - } catch (src::Fatal& fatal) { - std::cerr << "fatal: " << fatal << std::endl; - std::exit(1); - } catch (src::Error& error) { - std::cerr << error << std::endl; - std::exit(1); - } -} diff --git a/submodules/ton/tonlib-src/crypto/tl/tlblib.cpp b/submodules/ton/tonlib-src/crypto/tl/tlblib.cpp deleted file mode 100644 index d0c1b538..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlblib.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include - -namespace tlb { - -const False t_False; -const True t_True; -const Unit t_Unit; - -const Bool t_Bool; - -const Int t_int8{8}, t_int16{16}, t_int24{24}, t_int32{32}, t_int64{64}, t_int128{128}, t_int256{256}, t_int257{257}; -const UInt t_uint8{8}, t_uint16{16}, t_uint24{24}, t_uint32{32}, t_uint64{64}, t_uint128{128}, t_uint256{256}; -const NatWidth t_Nat{32}; - -const Anything t_Anything; -const RefAnything t_RefCell; - -std::string TLB::get_type_name() const { - std::ostringstream os; - print_type(os); - return os.str(); -} - -bool Bool::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - int t = get_tag(cs); - return cs.advance(1) && pp.out(t ? "bool_true" : "bool_false"); -} - -bool NatWidth::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - long long value = (long long)cs.fetch_ulong(32); - return value >= 0 && pp.out_int(value); -} - -bool NatLeq::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - long long value = (long long)as_uint(cs); - return value >= 0 && skip(cs) && pp.out_int(value); -} - -bool NatLess::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - long long value = (long long)as_uint(cs); - return value >= 0 && skip(cs) && pp.out_int(value); -} - -bool TupleT::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - pp.open("tuple "); - pp.os << n << " ["; - pp.mode_nl(); - int i = n; - for (; i > 0; --i) { - if (!X.print_skip(pp, cs)) { - return false; - } - pp.mode_nl(); - } - return pp.close("]"); -} - -bool CondT::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - return (n > 0 ? X.print_skip(pp, cs) : (!n && pp.out("()"))); -} - -bool Int::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - if (n <= 64) { - long long value; - return cs.fetch_int_to(n, value) && pp.out_int(value); - } else { - return pp.out_integer(cs.fetch_int256(n, true)); - } -} - -bool UInt::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - if (n <= 64) { - unsigned long long value; - return cs.fetch_uint_to(n, value) && pp.out_uint(value); - } else { - return pp.out_integer(cs.fetch_int256(n, false)); - } -} - -bool Bits::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - if (cs.have(n)) { - pp.os << 'x' << cs.fetch_bits(n).to_hex(); - return true; - } else { - return false; - } -} - -bool TupleT::skip(vm::CellSlice& cs) const { - int i = n; - for (; i > 0; --i) { - if (!X.skip(cs)) { - break; - } - } - return !i; -} - -bool TupleT::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int i = n; - for (; i > 0; --i) { - if (!X.validate_skip(ops, cs, weak)) { - break; - } - } - return !i; -} - -bool TLB::validate_ref_internal(int* ops, Ref cell_ref, bool weak) const { - if (ops && --*ops < 0) { - return false; - } - bool is_special; - auto cs = load_cell_slice_special(std::move(cell_ref), is_special); - return always_special() ? is_special : (is_special ? weak : (validate_skip(ops, cs) && cs.empty_ext())); -} - -bool TLB::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - pp.open("raw@"); - pp << *this << ' '; - vm::CellSlice cs_copy{cs}; - int size_limit = pp.limit; - if (!validate_skip(&size_limit, cs) || !cs_copy.cut_tail(cs)) { - return pp.fail("invalid value"); - } - pp.raw_nl(); - return (cs_copy.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close()) || - pp.fail("raw value too long"); -} - -bool TLB::print_special(PrettyPrinter& pp, vm::CellSlice& cs) const { - pp.open("raw@"); - pp << *this << ' '; - pp.raw_nl(); - return (cs.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close()) || pp.fail("raw value too long"); -} - -bool TLB::print_ref(PrettyPrinter& pp, Ref cell_ref) const { - if (cell_ref.is_null()) { - return pp.fail("null cell reference"); - } - if (!pp.register_recursive_call()) { - return pp.fail("too many recursive calls while printing a TL-B value"); - } - bool is_special; - auto cs = load_cell_slice_special(std::move(cell_ref), is_special); - if (is_special) { - return print_special(pp, cs); - } else { - return print_skip(pp, cs) && (cs.empty_ext() || pp.fail("extra data in cell")); - } -} - -bool TLB::print_skip(std::ostream& os, vm::CellSlice& cs, int indent, int rec_limit) const { - PrettyPrinter pp{os, indent}; - pp.set_limit(rec_limit); - return pp.fail_unless(print_skip(pp, cs)); -} - -bool TLB::print(std::ostream& os, const vm::CellSlice& cs, int indent, int rec_limit) const { - PrettyPrinter pp{os, indent}; - pp.set_limit(rec_limit); - return pp.fail_unless(print(pp, cs)); -} - -bool TLB::print_ref(std::ostream& os, Ref cell_ref, int indent, int rec_limit) const { - PrettyPrinter pp{os, indent}; - pp.set_limit(rec_limit); - return pp.fail_unless(print_ref(pp, std::move(cell_ref))); -} - -std::string TLB::as_string_skip(vm::CellSlice& cs, int indent) const { - std::ostringstream os; - print_skip(os, cs, indent); - return os.str(); -} - -std::string TLB::as_string(const vm::CellSlice& cs, int indent) const { - std::ostringstream os; - print(os, cs, indent); - return os.str(); -} - -std::string TLB::as_string_ref(Ref cell_ref, int indent) const { - std::ostringstream os; - print_ref(os, std::move(cell_ref), indent); - return os.str(); -} - -PrettyPrinter::~PrettyPrinter() { - if (failed || level) { - if (nl_used) { - nl(-2 * level); - } - os << "PRINTING FAILED"; - while (level > 0) { - os << ')'; - --level; - } - } - if (nl_used) { - os << std::endl; - } -} - -bool PrettyPrinter::fail(std::string msg) { - os << "" << std::endl; - failed = true; - return false; -} - -bool PrettyPrinter::mkindent(int delta) { - indent += delta; - for (int i = 0; i < indent; i++) { - os << ' '; - } - nl_used = true; - return true; -} - -bool PrettyPrinter::nl(int delta) { - os << std::endl; - return mkindent(delta); -} -bool PrettyPrinter::raw_nl(int delta) { - os << std::endl; - indent += delta; - nl_used = true; - return true; -} - -bool PrettyPrinter::open(std::string msg) { - os << "(" << msg; - indent += 2; - level++; - return true; -} - -bool PrettyPrinter::close() { - return close(""); -} - -bool PrettyPrinter::close(std::string msg) { - if (level <= 0) { - return fail("cannot close scope"); - } - indent -= 2; - --level; - os << msg << ")"; - return true; -} - -bool PrettyPrinter::mode_nl() { - if (mode & 1) { - return nl(); - } else { - os << ' '; - return true; - } -} - -bool PrettyPrinter::field(std::string name) { - mode_nl(); - os << name << ':'; - return true; -} - -bool PrettyPrinter::field() { - mode_nl(); - return true; -} - -bool PrettyPrinter::field_int(long long x, std::string name) { - os << ' ' << name << ':' << x; - return true; -} - -bool PrettyPrinter::field_int(long long x) { - os << ' ' << x; - return true; -} - -bool PrettyPrinter::field_uint(unsigned long long x, std::string name) { - os << ' ' << name << ':' << x; - return true; -} - -bool PrettyPrinter::field_uint(unsigned long long x) { - os << ' ' << x; - return true; -} - -bool PrettyPrinter::fetch_bits_field(vm::CellSlice& cs, int n) { - os << " x"; - return cs.have(n) && out(cs.fetch_bits(n).to_hex()); -} - -bool PrettyPrinter::fetch_bits_field(vm::CellSlice& cs, int n, std::string name) { - os << ' ' << name << ":x"; - return cs.have(n) && out(cs.fetch_bits(n).to_hex()); -} - -bool PrettyPrinter::fetch_int_field(vm::CellSlice& cs, int n) { - return cs.have(n) && field_int(cs.fetch_long(n)); -} - -bool PrettyPrinter::fetch_int_field(vm::CellSlice& cs, int n, std::string name) { - return cs.have(n) && field_int(cs.fetch_long(n), name); -} - -bool PrettyPrinter::fetch_uint_field(vm::CellSlice& cs, int n) { - return cs.have(n) && field_uint(cs.fetch_ulong(n)); -} - -bool PrettyPrinter::fetch_uint_field(vm::CellSlice& cs, int n, std::string name) { - return cs.have(n) && field_uint(cs.fetch_ulong(n), name); -} - -bool PrettyPrinter::fetch_int256_field(vm::CellSlice& cs, int n) { - os << ' '; - return out_integer(cs.fetch_int256(n, true)); -} - -bool PrettyPrinter::fetch_int256_field(vm::CellSlice& cs, int n, std::string name) { - os << ' ' << name << ':'; - return out_integer(cs.fetch_int256(n, true)); -} - -bool PrettyPrinter::fetch_uint256_field(vm::CellSlice& cs, int n) { - os << ' '; - return out_integer(cs.fetch_int256(n, false)); -} - -bool PrettyPrinter::fetch_uint256_field(vm::CellSlice& cs, int n, std::string name) { - os << ' ' << name << ':'; - return out_integer(cs.fetch_int256(n, false)); -} - -} // namespace tlb - -namespace tlb { - -bool TypenameLookup::register_types(typename TypenameLookup::register_func_t func) { - return func([this](const char* name, const TLB* tp) { return register_type(name, tp); }); -} - -bool TypenameLookup::register_type(const char* name, const TLB* tp) { - if (!name || !tp) { - return false; - } - auto res = types.emplace(name, tp); - return res.second; -} - -const TLB* TypenameLookup::lookup(std::string str) const { - auto it = types.find(str); - return it != types.end() ? it->second : nullptr; -} - -const TLB* TypenameLookup::lookup(td::Slice str) const { - auto it = std::lower_bound(types.begin(), types.end(), str, - [](const auto& x, const auto& y) { return td::Slice(x.first) < y; }); - return it != types.end() && td::Slice(it->first) == str ? it->second : nullptr; -} - -} // namespace tlb diff --git a/submodules/ton/tonlib-src/crypto/tl/tlblib.hpp b/submodules/ton/tonlib-src/crypto/tl/tlblib.hpp deleted file mode 100644 index b3260a74..00000000 --- a/submodules/ton/tonlib-src/crypto/tl/tlblib.hpp +++ /dev/null @@ -1,1083 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include "vm/cellslice.h" - -namespace tlb { - -using td::Ref; -using vm::CellSlice; - -struct PrettyPrinter; - -class TLB { - public: - enum { default_validate_max_cells = 1024 }; - virtual ~TLB() = default; - virtual int get_size(const vm::CellSlice& cs) const { - return -1; - } - virtual bool skip(vm::CellSlice& cs) const { - return cs.skip_ext(get_size(cs)); - } - virtual bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const { - return cs.have_ext(get_size(cs)); - } - virtual bool validate_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const { - return (int)cs.size_ext() == get_size(cs); - } - bool validate_upto(int ops, const vm::CellSlice& cs, bool weak = false) const { - return validate(&ops, cs, weak); - } - bool validate_exact_upto(int ops, const vm::CellSlice& cs, bool weak = false) const { - return validate_exact(&ops, cs, weak); - } - bool validate_csr(int* ops, Ref cs_ref, bool weak = false) const { - return cs_ref.not_null() && validate_skip_exact(ops, cs_ref.write(), weak); - } - bool validate_csr(int ops, Ref cs_ref, bool weak = false) const { - return validate_csr(&ops, std::move(cs_ref), weak); - } - bool validate_csr(Ref cs_ref, bool weak = false) const { - return validate_csr(default_validate_max_cells, std::move(cs_ref), weak); - } - Ref fetch(vm::CellSlice& cs) const { - return cs.fetch_subslice_ext(get_size(cs)); - } - Ref prefetch(const vm::CellSlice& cs) const { - return cs.prefetch_subslice_ext(get_size(cs)); - } - virtual Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const { - return validate(ops, cs, weak) ? cs.fetch_subslice_ext(get_size(cs)) : Ref{}; - } - virtual Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const { - return validate(ops, cs, weak) ? cs.prefetch_subslice_ext(get_size(cs)) : Ref{}; - } - bool fetch_to(vm::CellSlice& cs, Ref& res) const { - return (res = fetch(cs)).not_null(); - } - bool validate_fetch_to(int* ops, vm::CellSlice& cs, Ref& res, bool weak = false) const { - return (res = validate_fetch(ops, cs, weak)).not_null(); - } - bool store_from(vm::CellBuilder& cb, Ref field) const { - return field.not_null() && get_size(*field) == (int)field->size_ext() && cb.append_cellslice_bool(std::move(field)); - } - bool validate_store_from(int* ops, vm::CellBuilder& cb, Ref field, bool weak = false) const { - if (field.is_null()) { - return false; - } - vm::CellSlice cs{*field}; - return validate_skip(ops, cs, weak) && cs.empty_ext() && cb.append_cellslice_bool(std::move(field)); - } - virtual bool extract(vm::CellSlice& cs) const { - return cs.only_ext(get_size(cs)); - } - virtual bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const { - return validate(ops, cs, weak) && extract(cs); - } - int get_size_by_skip(const vm::CellSlice& cs) const { - vm::CellSlice copy{cs}; - return skip(copy) ? copy.subtract_base_ext(cs) : -1; - } - virtual bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const { - return validate(ops, cs, weak) && skip(cs); - } - bool validate_skip_upto(int ops, vm::CellSlice& cs, bool weak = false) const { - return validate_skip(&ops, cs, weak); - } - bool validate_skip_exact(int* ops, vm::CellSlice& cs, bool weak = false) const { - return validate_skip(ops, cs, weak) && cs.empty_ext(); - } - bool validate_by_skip(int* ops, const vm::CellSlice& cs, bool weak = false) const { - vm::CellSlice copy{cs}; - return validate_skip(ops, copy, weak); - } - bool validate_by_skip_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const { - vm::CellSlice copy{cs}; - return validate_skip_exact(ops, copy, weak); - } - bool extract_by_skip(vm::CellSlice& cs) const { - vm::CellSlice copy{cs}; - return skip(copy) && cs.cut_tail(copy); - } - bool validate_extract_by_skip(int* ops, vm::CellSlice& cs, bool weak = false) const { - vm::CellSlice copy{cs}; - return validate_skip(ops, copy, weak) && cs.cut_tail(copy); - } - Ref validate_fetch_by_skip(int* ops, vm::CellSlice& cs, bool weak = false) const { - Ref copy{true, cs}; - return validate_skip(ops, cs, weak) && copy.unique_write().cut_tail(cs) ? copy : Ref{}; - } - Ref validate_prefetch_by_skip(int* ops, const vm::CellSlice& cs, bool weak = false) const { - vm::CellSlice copy{cs}; - return validate_skip(ops, copy, false) ? cs.prefetch_subslice_ext(copy.subtract_base_ext(cs)) - : Ref{}; - } - virtual bool skip_copy(vm::CellBuilder& cb, vm::CellSlice& cs) const { - return cb.append_cellslice_bool(fetch(cs)); - } - virtual bool copy(vm::CellBuilder& cb, const vm::CellSlice& cs) const { - return cb.append_cellslice_bool(prefetch(cs)); - } - virtual bool always_special() const { - return false; - } - virtual int get_tag(const vm::CellSlice& cs) const { - return -1; - } - virtual int check_tag(const vm::CellSlice& cs) const { - return get_tag(cs); - } - bool has_valid_tag(const vm::CellSlice& cs) const { - return check_tag(cs) >= 0; - } - virtual long long as_int(const vm::CellSlice& cs) const { - return -1; - } - virtual unsigned long long as_uint(const vm::CellSlice& cs) const { - return static_cast(-1); - } - virtual td::RefInt256 as_integer(const vm::CellSlice& cs) const { - return {}; - } - virtual td::RefInt256 as_integer_skip(vm::CellSlice& cs) const { - return {}; - } - virtual td::RefInt256 as_integer(Ref cs) const { - return as_integer(*cs); - } - bool as_integer_skip_to(vm::CellSlice& cs, td::RefInt256& res) const { - return (res = as_integer_skip(cs)).not_null(); - } - bool as_integer_to(const vm::CellSlice& cs, td::RefInt256& res) const { - return (res = as_integer(cs)).not_null(); - } - bool as_integer_to(Ref cs_ref, td::RefInt256& res) const { - return (res = as_integer(std::move(cs_ref))).not_null(); - } - bool validate_ref(int* ops, Ref cell_ref, bool weak = false) const { - return cell_ref.not_null() && validate_ref_internal(ops, std::move(cell_ref), weak); - } - bool validate_ref(int ops, Ref cell_ref, bool weak = false) const { - return validate_ref(&ops, std::move(cell_ref), weak); - } - bool validate_ref(Ref cell_ref, bool weak = false) const { - return validate_ref(default_validate_max_cells, std::move(cell_ref), weak); - } - bool force_validate_ref(int* ops, Ref cell_ref) const { - return cell_ref.not_null() && validate_ref_internal(ops, std::move(cell_ref), false); - } - bool force_validate_ref(int ops, Ref cell_ref) const { - return force_validate_ref(&ops, std::move(cell_ref)); - } - bool force_validate_ref(Ref cell_ref) const { - return force_validate_ref(default_validate_max_cells, std::move(cell_ref)); - } - bool validate_skip_ref(int* ops, vm::CellSlice& cs, bool weak = false) const { - return validate_ref(ops, cs.fetch_ref(), weak); - } - bool validate_skip_ref(int ops, vm::CellSlice& cs, bool weak = false) const { - return validate_skip_ref(&ops, cs, weak); - } - virtual bool null_value(vm::CellBuilder& cb) const { - return false; - } - virtual bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const { - return false; - } - virtual bool store_long(vm::CellBuilder& cb, long long value) const { - return store_integer_value(cb, td::BigInt256{value}); - } - virtual bool store_integer_ref(vm::CellBuilder& cb, td::RefInt256 value) const { - return value.not_null() && store_integer_value(cb, *value); - } - bool pack_integer(Ref& csr, td::RefInt256 value) const { - vm::CellBuilder cb; - return store_integer_ref(cb, value) && (csr = vm::load_cell_slice_ref(cb.finalize())).not_null(); - } - virtual bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - td::RefInt256 x = as_integer_skip(cs1), y = as_integer_skip(cs2); - return x.not_null() && y.not_null() && store_integer_ref(cb, x += std::move(y)); - } - // result: -1 = error, 0 = ok (zero), 1 = ok - virtual int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const { - td::RefInt256 x = as_integer_skip(cs1), y = as_integer_skip(cs2); - return x.not_null() && y.not_null() && store_integer_ref(cb, x -= std::move(y)) ? (td::sgn(x) ? 1 : 0) : -1; - } - template - bool unpack(Ref cs_ref, Args&... args) const { - return cs_ref.not_null() && unpack(cs_ref.write(), args...) && cs_ref->empty_ext(); - } - virtual std::ostream& print_type(std::ostream& os) const { - return os << ""; - } - std::string get_type_name() const; - virtual bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const; - virtual bool print(PrettyPrinter& pp, const vm::CellSlice& cs) const { - vm::CellSlice cs_copy{cs}; - return print_skip(pp, cs_copy); - } - bool print_special(PrettyPrinter& pp, vm::CellSlice& cs) const; - bool print_ref(PrettyPrinter& pp, Ref cell_ref) const; - bool print(PrettyPrinter& pp, Ref cs_ref) const { - return print(pp, *cs_ref); - } - bool print_skip(std::ostream& os, vm::CellSlice& cs, int indent = 0, int rec_limit = 0) const; - bool print(std::ostream& os, const vm::CellSlice& cs, int indent = 0, int rec_limit = 0) const; - bool print(std::ostream& os, Ref cs_ref, int indent = 0, int rec_limit = 0) const { - return print(os, *cs_ref, indent, rec_limit); - } - bool print_ref(std::ostream& os, Ref cell_ref, int indent = 0, int rec_limit = 0) const; - bool print_ref(int rec_limit, std::ostream& os, Ref cell_ref, int indent = 0) const { - return print_ref(os, std::move(cell_ref), indent, rec_limit); - } - std::string as_string_skip(vm::CellSlice& cs, int indent = 0) const; - std::string as_string(const vm::CellSlice& cs, int indent = 0) const; - std::string as_string(Ref cs_ref, int indent = 0) const { - return cs_ref.not_null() ? as_string(*cs_ref, indent) : ""; - } - std::string as_string_ref(Ref cell_ref, int indent = 0) const; - static inline size_t nat_abs(int x) { - return (x > 1) * 2 + (x & 1); - } - - protected: - bool validate_ref_internal(int* ops, Ref cell_ref, bool weak = false) const; -}; - -static inline std::ostream& operator<<(std::ostream& os, const TLB& type) { - return type.print_type(os); -} - -struct TLB_Complex : TLB { - bool skip(vm::CellSlice& cs) const override { - return validate_skip(nullptr, cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override = 0; - int get_size(const vm::CellSlice& cs) const override { - return get_size_by_skip(cs); - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return validate_by_skip(ops, cs, weak); - } - bool validate_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return validate_by_skip_exact(ops, cs, weak); - } - bool extract(vm::CellSlice& cs) const override { - return extract_by_skip(cs); - } - bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return validate_extract_by_skip(ops, cs, weak); - } - Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return validate_fetch_by_skip(ops, cs, weak); - } - Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return validate_prefetch_by_skip(ops, cs, weak); - } - td::RefInt256 as_integer(const vm::CellSlice& cs) const override { - vm::CellSlice copy{cs}; - auto res = as_integer_skip(copy); - return res.not_null() && copy.empty_ext() ? std::move(res) : td::RefInt256{}; - } - td::RefInt256 as_integer(Ref cs) const override { - auto res = as_integer_skip(cs.write()); - return res.not_null() && cs->empty_ext() ? std::move(res) : td::RefInt256{}; - } -}; - -class TlbTypeHolder : public td::CntObject { - const TLB* type{nullptr}; - char* data{nullptr}; - - public: - TlbTypeHolder() = default; - TlbTypeHolder(const TLB* _type) : type(_type), data(nullptr) { - } - TlbTypeHolder(const TLB* _type, char* _data) : type(_type), data(_data) { - } - ~TlbTypeHolder() override { - free(data); - } - const TLB* get() const { - return type; - } - const TLB& operator*() const { - return *type; - } - const TLB* operator->() const { - return type; - } -}; - -static inline bool add_chk(int x, int y, int z) { - return x + y == z && z >= 0; -} - -static inline bool add_r1(int& x, int y, int z) { - return z >= y && (x = z - y) >= 0; -} - -static inline bool add_r3(int& x, int y, int& z) { - return (z = (x + y)) >= 0; -} - -static inline bool mul_chk(int x, int y, int z) { - return (long long)x * y == z; -} - -static inline bool mul_r1(int& x, int y, int z) { - return y && !(z % y) && (x = z / y) >= 0; -} - -static inline bool mul_r3(int x, int y, int& z) { - unsigned long long t = (unsigned long long)x * y; - if (t <= 0x7fffffff) { - z = (int)t; - return true; - } else { - return false; - } -} - -static inline int mul_bound(int x, int y) { - unsigned long long t = (unsigned long long)x * y; - return t <= 0x7fffffff ? (int)t : 0x7fffffff; -} - -// templatized unpack functions -template -bool unpack(vm::CellSlice& cs, R& rec, Args&... args) { - return (typename R::type_class{}).unpack(cs, rec, args...); -} - -template -bool unpack_exact(vm::CellSlice& cs, R& rec, Args&... args) { - return (typename R::type_class{}).unpack(cs, rec, args...) && cs.empty_ext(); -} - -template -bool type_unpack(vm::CellSlice& cs, const T& type, R& rec, Args&... args) { - return type.unpack(cs, rec, args...); -} - -template -bool type_unpack_exact(vm::CellSlice& cs, const T& type, R& rec, Args&... args) { - return type.unpack(cs, rec, args...) && cs.empty_ext(); -} - -template -bool csr_unpack(Ref csr, R& rec, Args&... args) { - return (typename R::type_class{}).unpack(csr.write(), rec, args...) && csr->empty_ext(); -} - -template -bool csr_unpack_safe(Ref csr, R& rec, Args&... args) { - return csr.not_null() && (typename R::type_class{}).unpack(csr.write(), rec, args...) && csr->empty_ext(); -} - -template -bool unpack_cell(Ref cell, R& rec, Args&... args) { - vm::CellSlice cs = vm::load_cell_slice(std::move(cell)); - return cs.is_valid() && (typename R::type_class{}).unpack(cs, rec, args...) && cs.empty_ext(); -} - -template -bool unpack_cell_inexact(Ref cell, R& rec, Args&... args) { - vm::CellSlice cs = vm::load_cell_slice(std::move(cell)); - return cs.is_valid() && (typename R::type_class{}).unpack(cs, rec, args...); -} - -template -bool type_unpack_cell(Ref cell, const T& type, R& rec, Args&... args) { - vm::CellSlice cs = vm::load_cell_slice(std::move(cell)); - return cs.is_valid() && type.unpack(cs, rec, args...) && cs.empty_ext(); -} - -template -bool csr_type_unpack(Ref csr, const T& type, R& rec, Args&... args) { - return type.unpack(csr.write(), rec, args...) && csr->empty_ext(); -} - -template -bool csr_unpack_inexact(Ref csr, R& rec, Args&... args) { - return (typename R::type_class{}).unpack(csr.write(), rec, args...); -} - -template -bool csr_type_unpack_inexact(Ref csr, const T& type, R& rec, Args&... args) { - return type.unpack(csr.write(), rec, args...); -} - -template -bool csr_unpack_skip(Ref& csr, R& rec, Args&... args) { - return (typename R::type_class{}).unpack(csr.write(), rec, args...); -} - -template -bool csr_type_unpack_skip(Ref& csr, const T& type, R& rec, Args&... args) { - return type.unpack(csr.write(), rec, args...); -} - -// templatized pack functions -template -bool pack(vm::CellBuilder& cb, const R& rec, Args&... args) { - return (typename R::type_class{}).pack(cb, rec, args...); -} - -template -bool type_pack(vm::CellBuilder& cb, const T& type, const R& rec, Args&... args) { - return type.pack(cb, rec, args...); -} - -template -bool pack_cell(Ref& cell, const R& rec, Args&... args) { - vm::CellBuilder cb; - return pack(cb, rec, args...) && cb.finalize_to(cell); -} - -template -bool type_pack_cell(Ref& cell, const T& type, const R& rec, Args&... args) { - vm::CellBuilder cb; - return type.pack(cb, rec, args...) && cb.finalize_to(cell); -} - -template -bool csr_pack(Ref& csr, const R& rec, Args&... args) { - vm::CellBuilder cb; - Ref cell; - return pack(cb, rec, args...) && cb.finalize_to(cell) && (csr = vm::load_cell_slice_ref(std::move(cell))).not_null(); -} - -template -bool csr_type_pack(Ref& csr, const T& type, const R& rec, Args&... args) { - vm::CellBuilder cb; - Ref cell; - return type.pack(cb, rec, args...) && cb.finalize_to(cell) && - (csr = vm::load_cell_slice_ref(std::move(cell))).not_null(); -} - -// templatized store_from function - -template -bool store_from(vm::CellBuilder& cb, const T& tlb_type, Ref field, Args&... args) { - if (field.is_null()) { - return false; - } - vm::CellSlice cs{*field}; - return tlb_type.skip(cs, args...) && cs.empty_ext() && cb.append_cellslice_bool(std::move(field)); -} - -} // namespace tlb - -namespace tlb { - -struct PrettyPrinter { - enum { default_print_limit = 4096 }; - std::ostream& os; - int indent; - int level; - bool failed; - bool nl_used; - int mode; - int limit{default_print_limit}; - PrettyPrinter(std::ostream& _os, int _indent = 0, int _mode = 1) - : os(_os), indent(_indent), level(0), failed(false), nl_used(false), mode(_mode) { - } - PrettyPrinter(int _limit, std::ostream& _os, int _indent = 0, int _mode = 1) - : os(_os), indent(_indent), level(0), failed(false), nl_used(false), mode(_mode), limit(_limit) { - } - ~PrettyPrinter(); - bool ok() const { - return !failed && !level; - } - bool fail_unless(bool res) { - if (!res) { - failed = true; - } - return res; - } - bool fail(std::string msg); - bool nl(int delta = 0); - bool raw_nl(int delta = 0); - bool mkindent(int delta = 0); - bool mode_nl(); - bool open(std::string msg = ""); - bool close(); - bool close(std::string msg); - bool field(std::string name); - bool field(); - bool field_int(long long value); - bool field_int(long long value, std::string name); - bool field_uint(unsigned long long value); - bool field_uint(unsigned long long value, std::string name); - bool register_recursive_call() { - return limit--; - } - void set_limit(int new_limit) { - if (new_limit > 0) { - limit = new_limit; - } - } - bool out(std::string str) { - os << str; - return true; - } - bool out_int(long long value) { - os << value; - return true; - } - bool out_uint(unsigned long long value) { - os << value; - return true; - } - bool out_integer(td::RefInt256 value) { - if (value.not_null()) { - os << std::move(value); - return true; - } else { - return false; - } - } - bool cons(std::string str) { - return out(str); - } - bool fetch_bits_field(vm::CellSlice& cs, int n); - bool fetch_bits_field(vm::CellSlice& cs, int n, std::string name); - bool fetch_int_field(vm::CellSlice& cs, int n); - bool fetch_int_field(vm::CellSlice& cs, int n, std::string name); - bool fetch_uint_field(vm::CellSlice& cs, int n); - bool fetch_uint_field(vm::CellSlice& cs, int n, std::string name); - bool fetch_int256_field(vm::CellSlice& cs, int n); - bool fetch_int256_field(vm::CellSlice& cs, int n, std::string name); - bool fetch_uint256_field(vm::CellSlice& cs, int n); - bool fetch_uint256_field(vm::CellSlice& cs, int n, std::string name); - template - PrettyPrinter& operator<<(const T& value) { - os << value; - return *this; - } -}; - -} // namespace tlb - -namespace tlb { - -class TypenameLookup { - std::map types; - - public: - typedef std::function simple_register_func_t; - typedef std::function register_func_t; - TypenameLookup() = default; - TypenameLookup(register_func_t func) { - register_types(func); - } - bool register_type(const char* name, const TLB* tp); - bool register_types(register_func_t func); - const TLB* lookup(std::string str) const; - const TLB* lookup(td::Slice str) const; -}; - -} // namespace tlb - -namespace tlb { - -struct False final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return -1; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "False"; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return false; - } -}; - -extern const False t_False; - -struct True final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return 0; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "True"; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return pp.out("true"); - } -}; - -extern const True t_True; - -struct Unit final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return 0; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "Unit"; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return pp.out("()"); - } -}; - -struct FwdT final : TLB { - const TLB& X; - FwdT(const TLB& _X) : X(_X) { - } - int get_size(const vm::CellSlice& cs) const override { - return X.get_size(cs); - } - bool skip(vm::CellSlice& cs) const override { - return X.skip(cs); - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return X.validate(ops, cs, weak); - } - Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return X.validate_fetch(ops, cs, weak); - } - Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return X.validate_prefetch(ops, cs, weak); - } - bool extract(vm::CellSlice& cs) const override { - return X.extract(cs); - } - bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return X.validate_extract(ops, cs, weak); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return X.validate_skip(ops, cs, weak); - } - bool skip_copy(vm::CellBuilder& cb, vm::CellSlice& cs) const override { - return X.skip_copy(cb, cs); - } - bool copy(vm::CellBuilder& cb, const vm::CellSlice& cs) const override { - return X.copy(cb, cs); - } - int get_tag(const vm::CellSlice& cs) const override { - return X.get_tag(cs); - } - long long as_int(const vm::CellSlice& cs) const override { - return X.as_int(cs); - } - unsigned long long as_uint(const vm::CellSlice& cs) const override { - return X.as_uint(cs); - } - td::RefInt256 as_integer(const vm::CellSlice& cs) const override { - return X.as_integer(cs); - } - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override { - return X.as_integer_skip(cs); - } - td::RefInt256 as_integer(Ref cs) const override { - return X.as_integer(std::move(cs)); - } - bool null_value(vm::CellBuilder& cb) const override { - return X.null_value(cb); - } - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override { - return X.store_integer_value(cb, value); - } - bool store_integer_ref(vm::CellBuilder& cb, td::RefInt256 value) const override { - return X.store_integer_ref(cb, std::move(value)); - } - bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override { - return X.add_values(cb, cs1, cs2); - } - std::ostream& print_type(std::ostream& os) const override { - return X.print_type(os); - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return X.print_skip(pp, cs); - } -}; - -extern const Unit t_Unit; - -struct Bool final : TLB { - enum { bool_false = 0, bool_true = 1 }; - int get_size(const vm::CellSlice& cs) const override { - return 1; - } - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "Bool"; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -extern const Bool t_Bool; - -struct NatWidth final : TLB { - int n; - NatWidth(int _n) : n(_n) { - } - int get_size(const vm::CellSlice& cs) const override { - return n <= 32 ? n : -1; - } - td::RefInt256 as_integer(const vm::CellSlice& cs) const override { - return cs.prefetch_int256(n, false); - } - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override { - return cs.fetch_int256(n, false); - } - unsigned long long as_uint(const vm::CellSlice& cs) const override { - return n <= 32 ? cs.prefetch_ulong(n) : -1; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(## " << n << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -extern const NatWidth t_Nat; - -struct NatLess final : TLB { - int n, w; - NatLess(int _n) : n(_n - 1), w(32 - td::count_leading_zeroes32(_n - 1)) { - } - int get_size(const vm::CellSlice& cs) const override { - return n >= 0 ? w : -1; - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return n >= 0 && (unsigned)cs.prefetch_ulong(w) <= (unsigned)n; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return n >= 0 && (unsigned)cs.fetch_ulong(w) <= (unsigned)n; - } - unsigned long long as_uint(const vm::CellSlice& cs) const override { - unsigned long long r = cs.prefetch_ulong(w); - return n >= 0 && (unsigned)r <= (unsigned)n ? r : std::numeric_limits::max(); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(#< " << n << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -struct NatLeq final : TLB { - int n, w; - NatLeq(int _n) : n(_n), w(32 - td::count_leading_zeroes32(_n)) { - } - int get_size(const vm::CellSlice& cs) const override { - return n >= 0 ? w : -1; - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return n >= 0 && (unsigned)cs.prefetch_ulong(w) <= (unsigned)n; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return n >= 0 && (unsigned)cs.fetch_ulong(w) <= (unsigned)n; - } - unsigned long long as_uint(const vm::CellSlice& cs) const override { - unsigned long long r = cs.prefetch_ulong(w); - return n >= 0 && (unsigned)r <= (unsigned)n ? r : std::numeric_limits::max(); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(#<= " << n << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -struct TupleT final : TLB_Complex { - int n; - const TLB& X; - TupleT(int _n, const TLB& _X) : n(_n), X(_X) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -struct CondT final : TLB_Complex { - int n; - const TLB& X; - CondT(int _n, const TLB& _X) : n(_n), X(_X) { - } - bool skip(vm::CellSlice& cs) const override { - return !n || X.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return !n || (n > 0 && X.validate_skip(ops, cs, weak)); - } - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(CondT " << n << ' ' << X << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -template -struct Cond final : TLB_Complex { - int n; - T field_type; - template - Cond(int _n, Args... args) : n(_n), field_type(args...) { - } - bool skip(vm::CellSlice& cs) const override { - return !n || field_type.skip(cs); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return !n || (n > 0 && field_type.validate_skip(ops, cs, weak)); - } - int get_tag(const vm::CellSlice& cs) const override { - return 0; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(Cond " << n << ' ' << field_type << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return (n > 0 ? field_type.print_skip(pp, cs) : (!n && pp.out("()"))); - } -}; - -struct Int final : TLB { - int n; - Int(int _n) : n(_n) { - } - int get_size(const vm::CellSlice& cs) const override { - return n; - } - td::RefInt256 as_integer(const vm::CellSlice& cs) const override { - return cs.prefetch_int256(n, true); - } - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override { - return cs.fetch_int256(n, true); - } - long long as_int(const vm::CellSlice& cs) const override { - return n <= 64 ? cs.prefetch_long(n) : (1ULL << 63); - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(n); - } - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override { - return cb.store_int256_bool(value, n, true); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "int" << n; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -extern const Int t_int8, t_int16, t_int24, t_int32, t_int64, t_int128, t_int256, t_int257; - -struct UInt final : TLB { - int n; - UInt(int _n) : n(_n) { - } - int get_size(const vm::CellSlice& cs) const override { - return n; - } - td::RefInt256 as_integer(const vm::CellSlice& cs) const override { - return cs.prefetch_int256(n, false); - } - td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override { - return cs.fetch_int256(n, false); - } - unsigned long long as_uint(const vm::CellSlice& cs) const override { - return n <= 64 ? cs.prefetch_ulong(n) : -1; - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(n); - } - bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override { - return cb.store_int256_bool(value, n, false); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "uint" << n; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -extern const UInt t_uint8, t_uint16, t_uint24, t_uint32, t_uint64, t_uint128, t_uint256; - -struct Bits final : TLB { - int n; - Bits(int _n) : n(_n) { - } - int get_size(const vm::CellSlice& cs) const override { - return n; - } - bool null_value(vm::CellBuilder& cb) const override { - return cb.store_zeroes_bool(n); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "bits" << n; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -template -struct Maybe : TLB_Complex { - T field_type; - template - Maybe(Args... args) : field_type(args...) { - } - bool skip(vm::CellSlice& cs) const override; - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override; - int get_tag(const vm::CellSlice& cs) const override { - return cs.have(1) ? (int)cs.prefetch_ulong(1) : -1; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(Maybe " << field_type << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -template -bool Maybe::skip(vm::CellSlice& cs) const { - int t = get_tag(cs); - if (t > 0) { - return cs.advance(1) && field_type.skip(cs); - } else if (!t) { - return cs.advance(1); - } else { - return false; - } -} - -template -bool Maybe::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const { - int t = get_tag(cs); - if (t > 0) { - return cs.advance(1) && field_type.validate_skip(ops, cs, weak); - } else if (!t) { - return cs.advance(1); - } else { - return false; - } -} - -template -bool Maybe::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - if (!get_tag(cs)) { - return cs.advance(1) && pp.out("nothing"); - } else { - return cs.advance(1) && pp.open("just ") && field_type.print_skip(pp, cs) && pp.close(); - } -} - -struct RefAnything final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return 0x10000; - } - std::ostream& print_type(std::ostream& os) const override { - return os << "^Cell"; - } -}; - -extern const RefAnything t_RefCell; - -struct Anything final : TLB { - int get_size(const vm::CellSlice& cs) const override { - return cs.size_ext(); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "Any"; - } -}; - -extern const Anything t_Anything; - -template -struct RefTo final : TLB { - T ref_type; - template - RefTo(Args... args) : ref_type(args...) { - } - int get_size(const vm::CellSlice& cs) const override { - return 0x10000; - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return cs.size_refs() ? ref_type.validate_ref(ops, cs.prefetch_ref(), weak) : false; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return ref_type.validate_skip_ref(ops, cs, weak); - } - std::ostream& print_type(std::ostream& os) const override { - return os << '^' << ref_type; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return pp.out("^") && ref_type.print_ref(pp, cs.fetch_ref()); - } -}; - -struct RefT final : TLB { - const TLB& X; - RefT(const TLB& _X) : X(_X) { - } - int get_size(const vm::CellSlice& cs) const override { - return 0x10000; - } - bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override { - return X.validate_ref(ops, cs.prefetch_ref(), weak); - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return X.validate_skip_ref(ops, cs, weak); - } - std::ostream& print_type(std::ostream& os) const override { - return os << '^' << X; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override { - return pp.out("^") && X.print_ref(pp, cs.fetch_ref()); - } -}; - -template -struct Either final : TLB_Complex { - T1 left_type; - T2 right_type; - bool skip(vm::CellSlice& cs) const override { - return cs.have(1) ? (cs.fetch_ulong(1) ? right_type.skip(cs) : left_type.skip(cs)) : false; - } - bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override { - return cs.have(1) - ? (cs.fetch_ulong(1) ? right_type.validate_skip(ops, cs, weak) : left_type.validate_skip(ops, cs, weak)) - : false; - } - int get_tag(const vm::CellSlice& cs) const override { - return (int)cs.prefetch_ulong(1); - } - std::ostream& print_type(std::ostream& os) const override { - return os << "(Either " << left_type << ' ' << right_type << ')'; - } - bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override; -}; - -template -bool Either::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { - if (!get_tag(cs)) { - return cs.advance(1) && pp.open("left ") && left_type.print_skip(pp, cs) && pp.close(); - } else { - return cs.advance(1) && pp.open("right ") && right_type.print_skip(pp, cs) && pp.close(); - } -} - -} // namespace tlb diff --git a/submodules/ton/tonlib-src/crypto/vm/arithops.cpp b/submodules/ton/tonlib-src/crypto/vm/arithops.cpp deleted file mode 100644 index 823b4408..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/arithops.cpp +++ /dev/null @@ -1,946 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/arithops.h" -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" -#include "common/bigint.hpp" -#include "common/refint.h" - -namespace vm { - -int exec_push_tinyint4(VmState* st, unsigned args) { - int x = (int)((args + 5) & 15) - 5; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHINT " << x; - stack.push_smallint(x); - return 0; -} - -std::string dump_push_tinyint4(CellSlice&, unsigned args) { - int x = (int)((args + 5) & 15) - 5; - std::ostringstream os{"PUSHINT "}; - os << x; - return os.str(); -} - -int exec_push_tinyint8(VmState* st, unsigned args) { - int x = (signed char)args; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHINT " << x; - stack.push_smallint(x); - return 0; -} - -std::string dump_op_tinyint8(const char* op_prefix, CellSlice&, unsigned args) { - int x = (signed char)args; - std::ostringstream os{op_prefix}; - os << x; - return os.str(); -} - -int exec_push_smallint(VmState* st, unsigned args) { - int x = (short)args; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHINT " << x; - stack.push_smallint(x); - return 0; -} - -std::string dump_push_smallint(CellSlice&, unsigned args) { - int x = (short)args; - std::ostringstream os{"PUSHINT "}; - os << x; - return os.str(); -} - -int exec_push_int(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - int l = (int)(args & 31) + 2; - if (!cs.have(pfx_bits + 3 + l * 8)) { - throw VmError{Excno::inv_opcode, "not enough bits for integer constant in PUSHINT"}; - } - cs.advance(pfx_bits); - td::RefInt256 x = cs.fetch_int256(3 + l * 8); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHINT " << x; - stack.push_int(std::move(x)); - return 0; -} - -std::string dump_push_int(CellSlice& cs, unsigned args, int pfx_bits) { - int l = (int)(args & 31) + 2; - if (!cs.have(pfx_bits + 3 + l * 8)) { - return ""; - } - cs.advance(pfx_bits); - td::RefInt256 x = cs.fetch_int256(3 + l * 8); - std::ostringstream os{"PUSHINT "}; - os << x; - return os.str(); -} - -int compute_len_push_int(const CellSlice& cs, unsigned args, int pfx_bits) { - int l = (int)(args & 31) + 2; - if (!cs.have(pfx_bits + 3 + l * 8)) { - return 0; - } else { - return pfx_bits + 3 + l * 8; - } -} - -int exec_push_pow2(VmState* st, unsigned args) { - int x = (args & 255) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHPOW2 " << x; - td::RefInt256 r{true}; - r.unique_write().set_pow2(x); - stack.push(std::move(r)); - return 0; -} - -int exec_push_nan(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHNAN"; - td::RefInt256 r{true}; - r.unique_write().invalidate(); - stack.push(std::move(r)); - return 0; -} - -int exec_push_pow2dec(VmState* st, unsigned args) { - int x = (args & 255) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHPOW2DEC " << x; - td::RefInt256 r{true}; - r.unique_write().set_pow2(x).add_tiny(-1).normalize(); - stack.push(std::move(r)); - return 0; -} - -int exec_push_negpow2(VmState* st, unsigned args) { - int x = (args & 255) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHNEGPOW2 " << x; - td::RefInt256 r{true}; - r.unique_write().set_pow2(x).negate().normalize(); - stack.push(std::move(r)); - return 0; -} - -void register_int_const_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0x7, 4, 4, dump_push_tinyint4, exec_push_tinyint4)) - .insert(OpcodeInstr::mkfixed(0x80, 8, 8, std::bind(dump_op_tinyint8, "PUSHINT ", _1, _2), exec_push_tinyint8)) - .insert(OpcodeInstr::mkfixed(0x81, 8, 16, dump_push_smallint, exec_push_smallint)) - .insert(OpcodeInstr::mkextrange(0x82 << 5, (0x82 << 5) + 31, 13, 5, dump_push_int, exec_push_int, - compute_len_push_int)) - .insert(OpcodeInstr::mkfixedrange(0x8300, 0x83ff, 16, 8, instr::dump_1c_l_add(1, "PUSHPOW2 "), exec_push_pow2)) - .insert(OpcodeInstr::mksimple(0x83ff, 16, "PUSHNAN", exec_push_nan)) - .insert(OpcodeInstr::mkfixed(0x84, 8, 8, instr::dump_1c_l_add(1, "PUSHPOW2DEC "), exec_push_pow2dec)) - .insert(OpcodeInstr::mkfixed(0x85, 8, 8, instr::dump_1c_l_add(1, "PUSHNEGPOW2 "), exec_push_negpow2)); -} - -int exec_add(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ADD"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() + std::move(y), quiet); - return 0; -} - -int exec_sub(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SUB"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() - std::move(y), quiet); - return 0; -} - -int exec_subr(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SUBR"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(std::move(y) - stack.pop_int(), quiet); - return 0; -} - -int exec_negate(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NEGATE"; - stack.check_underflow(1); - stack.push_int_quiet(-stack.pop_int(), quiet); - return 0; -} - -int exec_inc(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute INC"; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() + 1, quiet); - return 0; -} - -int exec_dec(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DEC"; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() - 1, quiet); - return 0; -} - -int exec_add_tinyint8(VmState* st, unsigned args, bool quiet) { - int x = (signed char)args; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ADDINT " << x; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() + x, quiet); - return 0; -} - -int exec_mul_tinyint8(VmState* st, unsigned args, bool quiet) { - int x = (signed char)args; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute MULINT " << x; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() * x, quiet); - return 0; -} - -int exec_mul(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute MUL"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() * std::move(y), quiet); - return 0; -} - -void register_add_mul_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xa0, 8, "ADD", std::bind(exec_add, _1, false))) - .insert(OpcodeInstr::mksimple(0xa1, 8, "SUB", std::bind(exec_sub, _1, false))) - .insert(OpcodeInstr::mksimple(0xa2, 8, "SUBR", std::bind(exec_subr, _1, false))) - .insert(OpcodeInstr::mksimple(0xa3, 8, "NEGATE", std::bind(exec_negate, _1, false))) - .insert(OpcodeInstr::mksimple(0xa4, 8, "INC", std::bind(exec_inc, _1, false))) - .insert(OpcodeInstr::mksimple(0xa5, 8, "DEC", std::bind(exec_dec, _1, false))) - .insert(OpcodeInstr::mkfixed(0xa6, 8, 8, std::bind(dump_op_tinyint8, "ADDINT ", _1, _2), - std::bind(exec_add_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mkfixed(0xa7, 8, 8, std::bind(dump_op_tinyint8, "MULINT ", _1, _2), - std::bind(exec_mul_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mksimple(0xa8, 8, "MUL", std::bind(exec_mul, _1, false))); - cp0.insert(OpcodeInstr::mksimple(0xb7a0, 16, "QADD", std::bind(exec_add, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7a1, 16, "QSUB", std::bind(exec_sub, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7a2, 16, "QSUBR", std::bind(exec_subr, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7a3, 16, "QNEGATE", std::bind(exec_negate, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7a4, 16, "QINC", std::bind(exec_inc, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7a5, 16, "QDEC", std::bind(exec_dec, _1, true))) - .insert(OpcodeInstr::mkfixed(0xb7a6, 16, 8, std::bind(dump_op_tinyint8, "QADDINT ", _1, _2), - std::bind(exec_add_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mkfixed(0xb7a7, 16, 8, std::bind(dump_op_tinyint8, "QMULINT ", _1, _2), - std::bind(exec_mul_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mksimple(0xb7a8, 16, "QMUL", std::bind(exec_mul, _1, true))); -} - -int exec_divmod(VmState* st, unsigned args, int quiet) { - int round_mode = (int)(args & 3) - 1; - if (!(args & 12) || round_mode == 2) { - throw VmError{Excno::inv_opcode}; - } - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DIV/MOD " << (args & 15); - stack.check_underflow(2); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - switch ((args >> 2) & 3) { - case 1: - stack.push_int_quiet(td::div(std::move(x), std::move(y), round_mode), quiet); - break; - case 2: - stack.push_int_quiet(td::mod(std::move(x), std::move(y), round_mode), quiet); - break; - case 3: { - auto dm = td::divmod(std::move(x), std::move(y), round_mode); - stack.push_int_quiet(std::move(dm.first), quiet); - stack.push_int_quiet(std::move(dm.second), quiet); - break; - } - } - return 0; -} - -std::string dump_divmod(CellSlice&, unsigned args, bool quiet) { - int round_mode = (int)(args & 3); - if (!(args & 12) || round_mode == 3) { - return ""; - } - std::string s = (args & 4) ? "DIV" : ""; - if (args & 8) { - s += "MOD"; - } - if (quiet) { - s = "Q" + s; - } - return s + "FRC"[round_mode]; -} - -int exec_shrmod(VmState* st, unsigned args, int mode) { - int y = -1; - if (mode & 2) { - y = (args & 0xff) + 1; - args >>= 8; - } - int round_mode = (int)(args & 3) - 1; - if (!(args & 12) || round_mode == 2) { - throw VmError{Excno::inv_opcode}; - } - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SHR/MOD " << (args & 15) << ',' << y; - if (!(mode & 2)) { - stack.check_underflow(2); - y = stack.pop_smallint_range(256); - } else { - stack.check_underflow(1); - } - if (!y) { - round_mode = -1; - } - auto x = stack.pop_int(); - switch ((args >> 2) & 3) { - case 1: - stack.push_int_quiet(td::rshift(std::move(x), y, round_mode), mode & 1); - break; - case 3: - stack.push_int_quiet(td::rshift(x, y, round_mode), mode & 1); - // fallthrough - case 2: - x.write().mod_pow2(y, round_mode).normalize(); - stack.push_int_quiet(std::move(x), mode & 1); - break; - } - return 0; -} - -std::string dump_shrmod(CellSlice&, unsigned args, int mode) { - int y = -1; - if (mode & 2) { - y = (args & 0xff) + 1; - args >>= 8; - } - int round_mode = (int)(args & 3); - if (!(args & 12) || round_mode == 3) { - return ""; - } - std::string s; - switch (args & 12) { - case 4: - s = "RSHIFT"; - break; - case 8: - s = "MODPOW2"; - break; - case 12: - s = "RSHIFTMOD"; - break; - } - if (mode & 1) { - s = "Q" + s; - } - s += "FRC"[round_mode]; - if (mode & 2) { - char buff[8]; - sprintf(buff, " %d", y); - s += buff; - } - return s; -} - -int exec_muldivmod(VmState* st, unsigned args, int quiet) { - int round_mode = (int)(args & 3) - 1; - if (!(args & 12) || round_mode == 2) { - throw VmError{Excno::inv_opcode}; - } - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute MULDIV/MOD " << (args & 15); - stack.check_underflow(3); - auto z = stack.pop_int(); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y); - auto q = td::make_refint(); - tmp.mod_div(*z, q.unique_write(), round_mode); - switch ((args >> 2) & 3) { - case 1: - q.unique_write().normalize(); - stack.push_int_quiet(std::move(q), quiet); - break; - case 3: - q.unique_write().normalize(); - stack.push_int_quiet(std::move(q), quiet); - // fallthrough - case 2: - stack.push_int_quiet(td::make_refint(tmp), quiet); - break; - } - return 0; -} - -std::string dump_muldivmod(CellSlice&, unsigned args, bool quiet) { - int round_mode = (int)(args & 3); - if (!(args & 12) || round_mode == 3) { - return ""; - } - std::string s = (args & 4) ? "MULDIV" : "MUL"; - if (args & 8) { - s += "MOD"; - } - if (quiet) { - s = "Q" + s; - } - return s + "FRC"[round_mode]; -} - -int exec_mulshrmod(VmState* st, unsigned args, int mode) { - int z = -1; - if (mode & 2) { - z = (args & 0xff) + 1; - args >>= 8; - } - int round_mode = (int)(args & 3) - 1; - if (!(args & 12) || round_mode == 2) { - throw VmError{Excno::inv_opcode}; - } - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute MULSHR/MOD " << (args & 15) << ',' << z; - if (!(mode & 2)) { - stack.check_underflow(3); - z = stack.pop_smallint_range(256); - } else { - stack.check_underflow(2); - } - if (!z) { - round_mode = -1; - } - auto y = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y); - switch ((args >> 2) & 3) { - case 1: - tmp.rshift(z, round_mode).normalize(); - stack.push_int_quiet(td::make_refint(tmp), mode & 1); - break; - case 3: { - typename td::BigInt256::DoubleInt tmp2{tmp}; - tmp2.rshift(z, round_mode).normalize(); - stack.push_int_quiet(td::make_refint(tmp2), mode & 1); - } - // fallthrough - case 2: - tmp.mod_pow2(z, round_mode).normalize(); - stack.push_int_quiet(td::make_refint(tmp), mode & 1); - break; - } - return 0; -} - -std::string dump_mulshrmod(CellSlice&, unsigned args, int mode) { - int y = -1; - if (mode & 2) { - y = (args & 0xff) + 1; - args >>= 8; - } - int round_mode = (int)(args & 3); - if (!(args & 12) || round_mode == 3) { - return ""; - } - std::string s; - switch (args & 12) { - case 4: - s = "MULRSHIFT"; - break; - case 8: - s = "MULMODPOW2"; - break; - case 12: - s = "MULRSHIFTMOD"; - break; - } - if (mode & 1) { - s = "Q" + s; - } - s += "FRC"[round_mode]; - if (mode & 2) { - char buff[8]; - sprintf(buff, " %d", y); - s += buff; - } - return s; -} - -int exec_shldivmod(VmState* st, unsigned args, int mode) { - int y = -1; - if (mode & 2) { - y = (args & 0xff) + 1; - args >>= 8; - } - int round_mode = (int)(args & 3) - 1; - if (!(args & 12) || round_mode == 2) { - throw VmError{Excno::inv_opcode}; - } - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SHLDIV/MOD " << (args & 15) << ',' << y; - if (!(mode & 2)) { - stack.check_underflow(3); - y = stack.pop_smallint_range(256); - } else { - stack.check_underflow(2); - } - auto z = stack.pop_int(); - auto x = stack.pop_int(); - typename td::BigInt256::DoubleInt tmp{*x}; - tmp <<= y; - switch ((args >> 2) & 3) { - case 1: { - auto q = td::make_refint(); - tmp.mod_div(*z, q.unique_write(), round_mode); - q.unique_write().normalize(); - stack.push_int_quiet(std::move(q), mode & 1); - break; - } - case 3: { - auto q = td::make_refint(); - tmp.mod_div(*z, q.unique_write(), round_mode); - q.unique_write().normalize(); - stack.push_int_quiet(std::move(q), mode & 1); - stack.push_int_quiet(td::make_refint(tmp), mode & 1); - break; - } - case 2: { - typename td::BigInt256::DoubleInt tmp2; - tmp.mod_div(*z, tmp2, round_mode); - stack.push_int_quiet(td::make_refint(tmp), mode & 1); - break; - } - } - return 0; -} - -std::string dump_shldivmod(CellSlice&, unsigned args, bool quiet) { - int round_mode = (int)(args & 3); - if (!(args & 12) || round_mode == 3) { - return ""; - } - std::string s = (args & 4) ? "LSHIFTDIV" : "LSHIFT"; - if (args & 8) { - s += "MOD"; - } - if (quiet) { - s = "Q" + s; - } - return s + "FRC"[round_mode]; -} - -void register_div_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0xa90, 12, 4, std::bind(dump_divmod, _1, _2, false), - std::bind(exec_divmod, _1, _2, false))) - .insert(OpcodeInstr::mkfixed(0xa92, 12, 4, std::bind(dump_shrmod, _1, _2, 0), std::bind(exec_shrmod, _1, _2, 0))) - .insert(OpcodeInstr::mkfixed(0xa93, 12, 12, std::bind(dump_shrmod, _1, _2, 2), std::bind(exec_shrmod, _1, _2, 2))) - .insert(OpcodeInstr::mkfixed(0xa98, 12, 4, std::bind(dump_muldivmod, _1, _2, false), - std::bind(exec_muldivmod, _1, _2, false))) - .insert(OpcodeInstr::mkfixed(0xa9a, 12, 4, std::bind(dump_mulshrmod, _1, _2, 0), - std::bind(exec_mulshrmod, _1, _2, 0))) - .insert(OpcodeInstr::mkfixed(0xa9b, 12, 12, std::bind(dump_mulshrmod, _1, _2, 2), - std::bind(exec_mulshrmod, _1, _2, 2))) - .insert(OpcodeInstr::mkfixed(0xa9c, 12, 4, std::bind(dump_shldivmod, _1, _2, 0), - std::bind(exec_shldivmod, _1, _2, 0))) - .insert(OpcodeInstr::mkfixed(0xa9d, 12, 12, std::bind(dump_shldivmod, _1, _2, 2), - std::bind(exec_shldivmod, _1, _2, 2))); - cp0.insert(OpcodeInstr::mkfixed(0xb7a90, 20, 4, std::bind(dump_divmod, _1, _2, true), - std::bind(exec_divmod, _1, _2, true))) - .insert( - OpcodeInstr::mkfixed(0xb7a92, 20, 4, std::bind(dump_shrmod, _1, _2, 1), std::bind(exec_shrmod, _1, _2, 1))) - // .insert(OpcodeInstr::mkfixed(0xb7a93, 20, 12, std::bind(dump_shrmod, _1, _2, 3), std::bind(exec_shrmod, _1, _2, 3))) - .insert(OpcodeInstr::mkfixed(0xb7a98, 20, 4, std::bind(dump_muldivmod, _1, _2, true), - std::bind(exec_muldivmod, _1, _2, true))) - .insert(OpcodeInstr::mkfixed(0xb7a9a, 20, 4, std::bind(dump_mulshrmod, _1, _2, 1), - std::bind(exec_mulshrmod, _1, _2, 1))) - // .insert(OpcodeInstr::mkfixed(0xb7a9b, 20, 12, std::bind(dump_mulshrmod, _1, _2, 3), std::bind(exec_mulshrmod, _1, _2, 3))) - .insert(OpcodeInstr::mkfixed(0xb7a9c, 20, 4, std::bind(dump_shldivmod, _1, _2, 1), - std::bind(exec_shldivmod, _1, _2, 1))) - // .insert(OpcodeInstr::mkfixed(0xb7a9d, 20, 12, std::bind(dump_shldivmod, _1, _2, 3), std::bind(exec_shldivmod, _1, _2, 3))) - ; -} - -int exec_lshift_tinyint8(VmState* st, unsigned args, bool quiet) { - int x = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute LSHIFT " << x; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() << x, quiet); - return 0; -} - -int exec_rshift_tinyint8(VmState* st, unsigned args, bool quiet) { - int x = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute RSHIFT " << x; - stack.check_underflow(1); - stack.push_int_quiet(stack.pop_int() >> x, quiet); - return 0; -} - -int exec_lshift(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute LSHIFT"; - stack.check_underflow(2); - int x = stack.pop_smallint_range(1023); - stack.push_int_quiet(stack.pop_int() << x, quiet); - return 0; -} - -int exec_rshift(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute RSHIFT"; - stack.check_underflow(2); - int x = stack.pop_smallint_range(1023); - stack.push_int_quiet(stack.pop_int() >> x, quiet); - return 0; -} - -int exec_pow2(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute POW2"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(1023); - td::RefInt256 r{true}; - r.unique_write().set_pow2(x); - stack.push_int_quiet(std::move(r), quiet); - return 0; -} - -int exec_and(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute AND"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() & std::move(y), quiet); - return 0; -} - -int exec_or(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute OR"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() | std::move(y), quiet); - return 0; -} - -int exec_xor(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XOR"; - stack.check_underflow(2); - auto y = stack.pop_int(); - stack.push_int_quiet(stack.pop_int() ^ std::move(y), quiet); - return 0; -} - -int exec_not(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NOT"; - stack.check_underflow(1); - stack.push_int_quiet(~stack.pop_int(), quiet); - return 0; -} - -int exec_fits_tinyint8(VmState* st, unsigned args, bool quiet) { - int y = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute FITS " << y; - stack.check_underflow(1); - auto x = stack.pop_int(); - if (!x->signed_fits_bits(y)) { - x.write().invalidate(); - } - stack.push_int_quiet(std::move(x), quiet); - return 0; -} - -int exec_ufits_tinyint8(VmState* st, unsigned args, bool quiet) { - int y = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute UFITS " << y; - stack.check_underflow(1); - auto x = stack.pop_int(); - if (!x->unsigned_fits_bits(y)) { - x.write().invalidate(); - } - stack.push_int_quiet(std::move(x), quiet); - return 0; -} - -int exec_fits(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute FITSX"; - stack.check_underflow(2); - int y = stack.pop_smallint_range(1023); - auto x = stack.pop_int(); - if (!x->signed_fits_bits(y)) { - x.write().invalidate(); - } - stack.push_int_quiet(std::move(x), quiet); - return 0; -} - -int exec_ufits(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute UFITSX"; - stack.check_underflow(2); - int y = stack.pop_smallint_range(1023); - auto x = stack.pop_int(); - if (!x->unsigned_fits_bits(y)) { - x.write().invalidate(); - } - stack.push_int_quiet(std::move(x), quiet); - return 0; -} - -int exec_bitsize(VmState* st, bool sgnd, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (sgnd ? "" : "U") << "BITSIZE"; - stack.check_underflow(1); - auto x = stack.pop_int(); - int y = x->bit_size(sgnd); - if (y < 0x7fffffff) { - stack.push_smallint(y); - } else if (!quiet) { - throw VmError{Excno::range_chk, "CHKSIZE for negative integer"}; - } else { - stack.push_int_quiet(td::make_refint(), quiet); - } - return 0; -} - -void register_shift_logic_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0xaa, 8, 8, instr::dump_1c_l_add(1, "LSHIFT "), - std::bind(exec_lshift_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mkfixed(0xab, 8, 8, instr::dump_1c_l_add(1, "RSHIFT "), - std::bind(exec_rshift_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mksimple(0xac, 8, "LSHIFT", std::bind(exec_lshift, _1, false))) - .insert(OpcodeInstr::mksimple(0xad, 8, "RSHIFT", std::bind(exec_rshift, _1, false))) - .insert(OpcodeInstr::mksimple(0xae, 8, "POW2", std::bind(exec_pow2, _1, false))) - .insert(OpcodeInstr::mksimple(0xb0, 8, "AND", std::bind(exec_and, _1, false))) - .insert(OpcodeInstr::mksimple(0xb1, 8, "OR", std::bind(exec_or, _1, false))) - .insert(OpcodeInstr::mksimple(0xb2, 8, "XOR", std::bind(exec_xor, _1, false))) - .insert(OpcodeInstr::mksimple(0xb3, 8, "NOT", std::bind(exec_not, _1, false))) - .insert(OpcodeInstr::mkfixed(0xb4, 8, 8, instr::dump_1c_l_add(1, "FITS "), - std::bind(exec_fits_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mkfixed(0xb5, 8, 8, instr::dump_1c_l_add(1, "UFITS "), - std::bind(exec_ufits_tinyint8, _1, _2, false))) - .insert(OpcodeInstr::mksimple(0xb600, 16, "FITSX", std::bind(exec_fits, _1, false))) - .insert(OpcodeInstr::mksimple(0xb601, 16, "UFITSX", std::bind(exec_ufits, _1, false))) - .insert(OpcodeInstr::mksimple(0xb602, 16, "BITSIZE", std::bind(exec_bitsize, _1, true, false))) - .insert(OpcodeInstr::mksimple(0xb603, 16, "UBITSIZE", std::bind(exec_bitsize, _1, false, false))); - cp0.insert(OpcodeInstr::mkfixed(0xb7aa, 16, 8, instr::dump_1c_l_add(1, "QLSHIFT "), - std::bind(exec_lshift_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mkfixed(0xb7ab, 16, 8, instr::dump_1c_l_add(1, "QRSHIFT "), - std::bind(exec_rshift_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mksimple(0xb7ac, 16, "QLSHIFT", std::bind(exec_lshift, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7ad, 16, "QRSHIFT", std::bind(exec_rshift, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7ae, 16, "QPOW2", std::bind(exec_pow2, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b0, 16, "QAND", std::bind(exec_and, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b1, 16, "QOR", std::bind(exec_or, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b2, 16, "QXOR", std::bind(exec_xor, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b3, 16, "QNOT", std::bind(exec_not, _1, true))) - .insert(OpcodeInstr::mkfixed(0xb7b4, 16, 8, instr::dump_1c_l_add(1, "QFITS "), - std::bind(exec_fits_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mkfixed(0xb7b5, 16, 8, instr::dump_1c_l_add(1, "QUFITS "), - std::bind(exec_ufits_tinyint8, _1, _2, true))) - .insert(OpcodeInstr::mksimple(0xb7b600, 24, "QFITSX", std::bind(exec_fits, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b601, 24, "QUFITSX", std::bind(exec_ufits, _1, true))) - .insert(OpcodeInstr::mksimple(0xb7b602, 24, "QBITSIZE", std::bind(exec_bitsize, _1, true, true))) - .insert(OpcodeInstr::mksimple(0xb7b603, 24, "QUBITSIZE", std::bind(exec_bitsize, _1, false, true))); -} - -int exec_minmax(VmState* st, int mode) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (mode & 1 ? "Q" : "") << (mode & 2 ? "MIN" : "") << (mode & 4 ? "MAX" : ""); - stack.check_underflow(2); - auto x = stack.pop_int(); - auto y = stack.pop_int(); - if (!x->is_valid()) { - y = x; - } else if (!y->is_valid()) { - x = y; - } else if (cmp(x, y) > 0) { - swap(x, y); - } - if (mode & 2) { - stack.push_int_quiet(std::move(x), mode & 1); - } - if (mode & 4) { - stack.push_int_quiet(std::move(y), mode & 1); - } - return 0; -} - -int exec_abs(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (quiet ? "QABS" : "ABS"); - stack.check_underflow(1); - auto x = stack.pop_int(); - if (x->is_valid() && x->sgn() < 0) { - stack.push_int_quiet(-std::move(x), quiet); - } else { - stack.push_int_quiet(std::move(x), quiet); - } - return 0; -} - -void register_other_arith_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xb608, 16, "MIN", std::bind(exec_minmax, _1, 2))) - .insert(OpcodeInstr::mksimple(0xb609, 16, "MAX", std::bind(exec_minmax, _1, 4))) - .insert(OpcodeInstr::mksimple(0xb60a, 16, "MINMAX", std::bind(exec_minmax, _1, 6))) - .insert(OpcodeInstr::mksimple(0xb60b, 16, "ABS", std::bind(exec_abs, _1, false))); - cp0.insert(OpcodeInstr::mksimple(0xb7b608, 24, "QMIN", std::bind(exec_minmax, _1, 3))) - .insert(OpcodeInstr::mksimple(0xb7b609, 24, "QMAX", std::bind(exec_minmax, _1, 5))) - .insert(OpcodeInstr::mksimple(0xb7b60a, 24, "QMINMAX", std::bind(exec_minmax, _1, 7))) - .insert(OpcodeInstr::mksimple(0xb7b60b, 24, "QABS", std::bind(exec_abs, _1, true))); -} - -int exec_sgn(VmState* st, int mode, bool quiet, const char* name) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1); - auto x = stack.pop_int(); - if (!x->is_valid()) { - stack.push_int_quiet(std::move(x), quiet); - } else { - int y = td::sgn(std::move(x)); - stack.push_smallint(((mode >> (4 + y * 4)) & 15) - 8); - } - return 0; -} - -int exec_cmp(VmState* st, int mode, bool quiet, const char* name) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - auto y = stack.pop_int(); - auto x = stack.pop_int(); - if (!x->is_valid() || !y->is_valid()) { - stack.push_int_quiet(std::move(x), quiet); - } else { - int z = td::cmp(std::move(x), std::move(y)); - stack.push_smallint(((mode >> (4 + z * 4)) & 15) - 8); - } - return 0; -} - -int exec_cmp_int(VmState* st, unsigned args, int mode, bool quiet, const char* name) { - int y = (signed char)args; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name << "INT " << y; - stack.check_underflow(1); - auto x = stack.pop_int(); - if (!x->is_valid()) { - stack.push_int_quiet(std::move(x), quiet); - } else { - int z = td::cmp(std::move(x), y); - stack.push_smallint(((mode >> (4 + z * 4)) & 15) - 8); - } - return 0; -} - -int exec_is_nan(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ISNAN"; - stack.check_underflow(1); - auto x = stack.pop_int(); - stack.push_smallint(x->is_valid() ? 0 : -1); - return 0; -} - -int exec_chk_nan(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CHKNAN"; - stack.check_underflow(1); - auto x = stack.pop_int(); - stack.push_int(std::move(x)); - return 0; -} - -void register_int_cmp_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xb8, 8, "SGN", std::bind(exec_sgn, _1, 0x987, false, "SGN"))) - .insert(OpcodeInstr::mksimple(0xb9, 8, "LESS", std::bind(exec_cmp, _1, 0x887, false, "LESS"))) - .insert(OpcodeInstr::mksimple(0xba, 8, "EQUAL", std::bind(exec_cmp, _1, 0x878, false, "EQUAL"))) - .insert(OpcodeInstr::mksimple(0xbb, 8, "LEQ", std::bind(exec_cmp, _1, 0x877, false, "LEQ"))) - .insert(OpcodeInstr::mksimple(0xbc, 8, "GREATER", std::bind(exec_cmp, _1, 0x788, false, "GREATER"))) - .insert(OpcodeInstr::mksimple(0xbd, 8, "NEQ", std::bind(exec_cmp, _1, 0x787, false, "NEQ"))) - .insert(OpcodeInstr::mksimple(0xbe, 8, "GEQ", std::bind(exec_cmp, _1, 0x778, false, "GEQ"))) - .insert(OpcodeInstr::mksimple(0xbf, 8, "CMP", std::bind(exec_cmp, _1, 0x987, false, "CMP"))) - .insert(OpcodeInstr::mkfixed(0xc0, 8, 8, std::bind(dump_op_tinyint8, "EQINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x878, false, "EQ"))) - .insert(OpcodeInstr::mkfixed(0xc1, 8, 8, std::bind(dump_op_tinyint8, "LESSINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x887, false, "LESS"))) - .insert(OpcodeInstr::mkfixed(0xc2, 8, 8, std::bind(dump_op_tinyint8, "GTINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x788, false, "GT"))) - .insert(OpcodeInstr::mkfixed(0xc3, 8, 8, std::bind(dump_op_tinyint8, "NEQINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x787, false, "NEQ"))) - .insert(OpcodeInstr::mksimple(0xc4, 8, "ISNAN", exec_is_nan)) - .insert(OpcodeInstr::mksimple(0xc5, 8, "CHKNAN", exec_chk_nan)); - cp0.insert(OpcodeInstr::mksimple(0xb7b8, 16, "QSGN", std::bind(exec_sgn, _1, 0x987, true, "QSGN"))) - .insert(OpcodeInstr::mksimple(0xb7b9, 16, "QLESS", std::bind(exec_cmp, _1, 0x887, true, "QLESS"))) - .insert(OpcodeInstr::mksimple(0xb7ba, 16, "QEQUAL", std::bind(exec_cmp, _1, 0x878, true, "QEQUAL"))) - .insert(OpcodeInstr::mksimple(0xb7bb, 16, "QLEQ", std::bind(exec_cmp, _1, 0x877, true, "QLEQ"))) - .insert(OpcodeInstr::mksimple(0xb7bc, 16, "QGREATER", std::bind(exec_cmp, _1, 0x788, true, "QGREATER"))) - .insert(OpcodeInstr::mksimple(0xb7bd, 16, "QNEQ", std::bind(exec_cmp, _1, 0x787, true, "QNEQ"))) - .insert(OpcodeInstr::mksimple(0xb7be, 16, "QGEQ", std::bind(exec_cmp, _1, 0x778, true, "QGEQ"))) - .insert(OpcodeInstr::mksimple(0xb7bf, 16, "QCMP", std::bind(exec_cmp, _1, 0x987, true, "QCMP"))) - .insert(OpcodeInstr::mkfixed(0xb7c0, 16, 8, std::bind(dump_op_tinyint8, "QEQINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x878, true, "QEQ"))) - .insert(OpcodeInstr::mkfixed(0xb7c1, 16, 8, std::bind(dump_op_tinyint8, "QLESSINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x887, true, "QLESS"))) - .insert(OpcodeInstr::mkfixed(0xb7c2, 16, 8, std::bind(dump_op_tinyint8, "QGTINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x788, true, "QGT"))) - .insert(OpcodeInstr::mkfixed(0xb7c3, 16, 8, std::bind(dump_op_tinyint8, "QNEQINT ", _1, _2), - std::bind(exec_cmp_int, _1, _2, 0x787, true, "QNEQ"))); -} - -void register_arith_ops(OpcodeTable& cp0) { - register_int_const_ops(cp0); - register_add_mul_ops(cp0); - register_div_ops(cp0); - register_shift_logic_ops(cp0); - register_other_arith_ops(cp0); - register_int_cmp_ops(cp0); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/arithops.h b/submodules/ton/tonlib-src/crypto/vm/arithops.h deleted file mode 100644 index 63adcf7c..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/arithops.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_arith_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/atom.cpp b/submodules/ton/tonlib-src/crypto/vm/atom.cpp deleted file mode 100644 index a7d5486a..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/atom.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "atom.h" - -namespace vm { -using td::Ref; - -std::atomic Atom::hashtable[hashtable_size] = {}; -std::atomic Atom::atoms_defined{0}; -std::atomic Atom::anon_atoms{0}; - -void Atom::print_to(std::ostream& os) const { - if (name_.empty()) { - os << "atom#" << index_; - } else { - os << name_; - } -} - -std::string Atom::make_name() const { - char buffer[16]; - sprintf(buffer, "atom#%d", index_); - return buffer; -} - -std::ostream& operator<<(std::ostream& os, const Atom& atom) { - atom.print_to(os); - return os; -} - -std::ostream& operator<<(std::ostream& os, Ref atom_ref) { - atom_ref->print_to(os); - return os; -} - -std::pair Atom::compute_hash(td::Slice name) { - unsigned h1 = 1, h2 = 1; - for (std::size_t i = 0; i < name.size(); i++) { - h1 = (239 * h1 + (unsigned char)name[i]) % hashtable_size; - h2 = (17 * h2 + (unsigned char)name[i]) % (hashtable_size - 1); - } - return std::make_pair(h1, h2 + 1); -} - -Ref Atom::find(td::Slice name, bool create) { - auto hash = compute_hash(name); - while (true) { - auto& pos = hashtable[hash.first]; - Atom* ptr = pos.load(std::memory_order_acquire); - if (ptr) { - if (ptr->name_as_slice() == name) { - return Ref(ptr); - } - } else if (!create) { - return {}; - } else { - Atom* p2 = new Atom(name.str(), hash.first); - Atom* p1 = nullptr; - if (pos.compare_exchange_strong(p1, p2)) { - atoms_defined.fetch_add(1, std::memory_order_relaxed); - return Ref(p2); - } - delete p2; - CHECK(p1); - if (p1->name_as_slice() == name) { - return Ref(p1); - } - } - hash.first += hash.second; - if (hash.first >= hashtable_size) { - hash.first -= hashtable_size; - } - } -} - -Ref Atom::anon() { - int c = anon_atoms.fetch_add(1, std::memory_order_relaxed); - return Ref{true, "", ~c}; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/atom.h b/submodules/ton/tonlib-src/crypto/vm/atom.h deleted file mode 100644 index 9946a9ff..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/atom.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include "vm/stack.hpp" -#include "td/utils/Slice.h" - -namespace vm { -using td::Ref; - -class Atom : public td::CntObject { - std::string name_; - int index_; - static constexpr unsigned hashtable_size = 170239; - static std::atomic hashtable[hashtable_size]; - static std::atomic atoms_defined; - static std::atomic anon_atoms; - static std::pair compute_hash(td::Slice name); - - public: - Atom(const Atom&) = delete; - Atom &operator=(const Atom&) = delete; - Atom(Atom&&) = delete; - Atom &operator=(Atom&&) = delete; - ~Atom() override = default; - Atom(std::string name, int index) : name_(name), index_(index) { - } - static Ref anon(); - static Ref find(td::Slice name, bool create = false); - static Ref create(td::Slice name) { - return find(std::move(name), true); - } - std::string name() const { - return name_; - } - std::string name_ext() const { - return name_.empty() ? make_name() : name_; - } - td::Slice name_as_slice() const { - return td::Slice{name_}; - } - int index() const { - return index_; - } - void print_to(std::ostream& os) const; - - private: - std::string make_name() const; -}; - -std::ostream& operator<<(std::ostream& os, const Atom& atom); -std::ostream& operator<<(std::ostream& os, Ref atom_ref); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/boc.cpp b/submodules/ton/tonlib-src/crypto/vm/boc.cpp deleted file mode 100644 index 5ab6f5ea..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/boc.cpp +++ /dev/null @@ -1,1158 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include "vm/boc.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "td/utils/bits.h" -#include "td/utils/Slice-decl.h" -#include "td/utils/format.h" -#include "td/utils/crypto.h" - -namespace vm { -using td::Ref; - -td::Status CellSerializationInfo::init(td::Slice data, int ref_byte_size) { - if (data.size() < 2) { - return td::Status::Error(PSLICE() << "Not enough bytes " << td::tag("got", data.size()) - << td::tag("expected", "at least 2")); - } - TRY_STATUS(init(data.ubegin()[0], data.ubegin()[1], ref_byte_size)); - if (data.size() < end_offset) { - return td::Status::Error(PSLICE() << "Not enough bytes " << td::tag("got", data.size()) - << td::tag("expected", end_offset)); - } - return td::Status::OK(); -} - -td::Status CellSerializationInfo::init(td::uint8 d1, td::uint8 d2, int ref_byte_size) { - refs_cnt = d1 & 7; - level_mask = Cell::LevelMask(d1 >> 5); - special = (d1 & 8) != 0; - with_hashes = (d1 & 16) != 0; - - if (refs_cnt > 4) { - if (refs_cnt != 7 || !with_hashes) { - return td::Status::Error("Invalid first byte"); - } - refs_cnt = 0; - // ... - // do not deserialize absent cells! - return td::Status::Error("TODO: absent cells"); - } - - hashes_offset = 2; - auto n = level_mask.get_hashes_count(); - depth_offset = hashes_offset + (with_hashes ? n * Cell::hash_bytes : 0); - data_offset = depth_offset + (with_hashes ? n * Cell::depth_bytes : 0); - data_len = (d2 >> 1) + (d2 & 1); - data_with_bits = (d2 & 1) != 0; - refs_offset = data_offset + data_len; - end_offset = refs_offset + refs_cnt * ref_byte_size; - - return td::Status::OK(); -} - -td::Result CellSerializationInfo::get_bits(td::Slice cell) const { - if (data_with_bits) { - DCHECK(data_len != 0); - int last = cell[data_offset + data_len - 1]; - if (!(last & 0x7f)) { - return td::Status::Error("overlong encoding"); - } - return td::narrow_cast((data_len - 1) * 8 + 7 - td::count_trailing_zeroes_non_zero32(last)); - } else { - return td::narrow_cast(data_len * 8); - } -} - -// TODO: check usage when result is empty -td::Result> CellSerializationInfo::create_data_cell(td::Slice cell_slice, - td::Span> refs) const { - CellBuilder cb; - TRY_RESULT(bits, get_bits(cell_slice)); - cb.store_bits(cell_slice.ubegin() + data_offset, bits); - DCHECK(refs_cnt == (td::int64)refs.size()); - for (int k = 0; k < refs_cnt; k++) { - cb.store_ref(std::move(refs[k])); - } - TRY_RESULT(res, cb.finalize_novm_nothrow(special)); - CHECK(!res.is_null()); - if (res->is_special() != special) { - return td::Status::Error("is_special mismatch"); - } - if (res->get_level_mask() != level_mask) { - return td::Status::Error("level mask mismatch"); - } - //return res; - if (with_hashes) { - auto hash_n = level_mask.get_hashes_count(); - if (res->get_hash().as_slice() != - cell_slice.substr(hashes_offset + Cell::hash_bytes * (hash_n - 1), Cell::hash_bytes)) { - return td::Status::Error("representation hash mismatch"); - } - if (res->get_depth() != - DataCell::load_depth( - cell_slice.substr(depth_offset + Cell::depth_bytes * (hash_n - 1), Cell::depth_bytes).ubegin())) { - return td::Status::Error("depth mismatch"); - } - - bool check_all_hashes = true; - for (unsigned level_i = 0, hash_i = 0, level = level_mask.get_level(); check_all_hashes && level_i < level; - level_i++) { - if (!level_mask.is_significant(level_i)) { - continue; - } - if (cell_slice.substr(hashes_offset + Cell::hash_bytes * hash_i, Cell::hash_bytes) != - res->get_hash(level_i).as_slice()) { - // hash mismatch - return td::Status::Error("lower hash mismatch"); - } - if (res->get_depth(level_i) != - DataCell::load_depth( - cell_slice.substr(depth_offset + Cell::depth_bytes * hash_i, Cell::depth_bytes).ubegin())) { - return td::Status::Error("lower depth mismatch"); - } - hash_i++; - } - } - return res; -} - -void BagOfCells::clear() { - cells_clear(); - roots.clear(); - root_count = 0; - serialized.clear(); -} - -int BagOfCells::set_roots(const std::vector>& new_roots) { - clear(); - return add_roots(new_roots); -} - -int BagOfCells::set_root(td::Ref new_root) { - clear(); - return add_root(std::move(new_root)); -} - -int BagOfCells::add_roots(const std::vector>& add_roots) { - int res = 0; - for (td::Ref root : add_roots) { - res += add_root(std::move(root)); - } - return res; -} - -int BagOfCells::add_root(td::Ref add_root) { - if (add_root.is_null()) { - return 0; - } - LOG_CHECK(add_root->get_virtualization() == 0) << "TODO: support serialization of virtualized cells"; - //const Cell::Hash& hash = add_root->get_hash(); - //for (const auto& root_info : roots) { - //if (root_info.cell->get_hash() == hash) { - //return 0; - //} - //} - roots.emplace_back(std::move(add_root), -1); - ++root_count; - cells_clear(); - return 1; -} - -td::Status BagOfCells::import_cells() { - cells_clear(); - for (auto& root : roots) { - auto res = import_cell(root.cell, 0); - if (res.is_error()) { - return res.move_as_error(); - } - root.idx = res.move_as_ok(); - } - //LOG(INFO) << "[cells: " << cell_count << ", refs: " << int_refs << ", bytes: " << data_bytes << "]"; - reorder_cells(); - //LOG(INFO) << "[cells: " << cell_count << ", refs: " << int_refs << ", bytes: " << data_bytes - //<< ", internal hashes: " << int_hashes << ", top hashes: " << top_hashes << "]"; - CHECK(cell_count != 0); - return td::Status::OK(); -} - -td::Result BagOfCells::import_cell(td::Ref cell, int depth) { - if (depth > max_depth) { - return td::Status::Error("error while importing a cell into a bag of cells: cell depth too large"); - } - if (cell.is_null()) { - return td::Status::Error("error while importing a cell into a bag of cells: cell is null"); - } - auto it = cells.find(cell->get_hash()); - if (it != cells.end()) { - auto pos = it->second; - cell_list_[pos].should_cache = true; - return pos; - } - if (cell->get_virtualization() != 0) { - return td::Status::Error( - "error while importing a cell into a bag of cells: cell has non-zero virtualization level"); - } - auto r_loaded_dc = cell->load_cell(); - if (r_loaded_dc.is_error()) { - return td::Status::Error("error while importing a cell into a bag of cells: " + - r_loaded_dc.move_as_error().to_string()); - } - auto loaded_dc = r_loaded_dc.move_as_ok(); - CellSlice cs(std::move(loaded_dc)); - std::array refs{-1}; - DCHECK(cs.size_refs() <= 4); - unsigned sum_child_wt = 1; - for (unsigned i = 0; i < cs.size_refs(); i++) { - auto ref = import_cell(cs.prefetch_ref(i), depth + 1); - if (ref.is_error()) { - return ref.move_as_error(); - } - refs[i] = ref.move_as_ok(); - sum_child_wt += cell_list_[refs[i]].wt; - ++int_refs; - } - DCHECK(cell_list_.size() == static_cast(cell_count)); - auto dc = cs.move_as_loaded_cell().data_cell; - auto res = cells.emplace(dc->get_hash(), cell_count); - DCHECK(res.second); - cell_list_.emplace_back(dc, dc->size_refs(), refs); - CellInfo& dc_info = cell_list_.back(); - dc_info.hcnt = static_cast(dc->get_level_mask().get_hashes_count()); - dc_info.wt = static_cast(std::min(0xffU, sum_child_wt)); - dc_info.new_idx = -1; - data_bytes += dc->get_serialized_size(); - return cell_count++; -} - -void BagOfCells::reorder_cells() { - int_hashes = 0; - for (int i = cell_count - 1; i >= 0; --i) { - CellInfo& dci = cell_list_[i]; - int s = dci.ref_num, c = s, sum = max_cell_whs - 1, mask = 0; - for (int j = 0; j < s; ++j) { - CellInfo& dcj = cell_list_[dci.ref_idx[j]]; - int limit = (max_cell_whs - 1 + j) / s; - if (dcj.wt <= limit) { - sum -= dcj.wt; - --c; - mask |= (1 << j); - } - } - if (c) { - for (int j = 0; j < s; ++j) { - if (!(mask & (1 << j))) { - CellInfo& dcj = cell_list_[dci.ref_idx[j]]; - int limit = sum++ / c; - if (dcj.wt > limit) { - dcj.wt = static_cast(limit); - } - } - } - } - } - for (int i = 0; i < cell_count; i++) { - CellInfo& dci = cell_list_[i]; - int s = dci.ref_num, sum = 1; - for (int j = 0; j < s; ++j) { - sum += cell_list_[dci.ref_idx[j]].wt; - } - DCHECK(sum <= max_cell_whs); - if (sum <= dci.wt) { - dci.wt = static_cast(sum); - } else { - dci.wt = 0; - int_hashes += dci.hcnt; - } - } - top_hashes = 0; - for (auto& root_info : roots) { - auto& cell_info = cell_list_[root_info.idx]; - if (cell_info.is_root_cell) { - cell_info.is_root_cell = true; - if (cell_info.wt) { - top_hashes += cell_info.hcnt; - } - } - } - if (cell_count > 0) { - rv_idx = 0; - cell_list_tmp.clear(); - cell_list_tmp.reserve(cell_count); - - for (const auto& root_info : roots) { - revisit(root_info.idx, 0); - revisit(root_info.idx, 1); - } - for (const auto& root_info : roots) { - revisit(root_info.idx, 2); - } - for (auto& root_info : roots) { - root_info.idx = cell_list_[root_info.idx].new_idx; - } - - DCHECK(rv_idx == cell_count); - //DCHECK(cell_list.back().new_idx == cell_count - 1); - DCHECK(cell_list_.size() == cell_list_tmp.size()); - cell_list_ = std::move(cell_list_tmp); - cell_list_tmp.clear(); - } -} - -// force=0 : previsit (recursively until special cells are found; then visit them) -// force=1 : visit (allocate and process all children) -// force=2 : allocate (assign a new index; can be run only after visiting) -int BagOfCells::revisit(int cell_idx, int force) { - DCHECK(cell_idx >= 0 && cell_idx < cell_count); - CellInfo& dci = cell_list_[cell_idx]; - if (dci.new_idx >= 0) { - return dci.new_idx; - } - if (!force) { - // previsit - if (dci.new_idx != -1) { - // already previsited or visited - return dci.new_idx; - } - int n = dci.ref_num; - for (int j = n - 1; j >= 0; --j) { - int child_idx = dci.ref_idx[j]; - // either previsit or visit child, depending on whether it is special - revisit(dci.ref_idx[j], cell_list_[child_idx].is_special()); - } - return dci.new_idx = -2; // mark as previsited - } - if (force > 1) { - // time to allocate - auto i = dci.new_idx = rv_idx++; - cell_list_tmp.emplace_back(std::move(dci)); - return i; - } - if (dci.new_idx == -3) { - // already visited - return dci.new_idx; - } - if (dci.is_special()) { - // if current cell is special, previsit it first - revisit(cell_idx, 0); - } - // visit children - int n = dci.ref_num; - for (int j = n - 1; j >= 0; --j) { - revisit(dci.ref_idx[j], 1); - } - // allocate children - for (int j = n - 1; j >= 0; --j) { - dci.ref_idx[j] = revisit(dci.ref_idx[j], 2); - } - return dci.new_idx = -3; // mark as visited (and all children processed) -} - -td::uint64 BagOfCells::compute_sizes(int mode, int& r_size, int& o_size) { - int rs = 0, os = 0; - if (!root_count || !data_bytes) { - r_size = o_size = 0; - return 0; - } - while (cell_count >= (1 << (rs << 3))) { - rs++; - } - td::uint64 hashes = - (((mode & Mode::WithTopHash) ? top_hashes : 0) + ((mode & Mode::WithIntHashes) ? int_hashes : 0)) * - (Cell::hash_bytes + Cell::depth_bytes); - td::uint64 data_bytes_adj = data_bytes + (unsigned long long)int_refs * rs + hashes; - td::uint64 max_offset = (mode & Mode::WithCacheBits) ? data_bytes_adj * 2 : data_bytes_adj; - while (max_offset >= (1ULL << (os << 3))) { - os++; - } - if (rs > 4 || os > 8) { - r_size = o_size = 0; - return 0; - } - r_size = rs; - o_size = os; - return data_bytes_adj; -} - -std::size_t BagOfCells::estimate_serialized_size(int mode) { - if ((mode & Mode::WithCacheBits) && !(mode & Mode::WithIndex)) { - info.invalidate(); - return 0; - } - auto data_bytes_adj = compute_sizes(mode, info.ref_byte_size, info.offset_byte_size); - if (!data_bytes_adj) { - info.invalidate(); - return 0; - } - info.valid = true; - info.has_crc32c = mode & Mode::WithCRC32C; - info.has_index = mode & Mode::WithIndex; - info.has_cache_bits = mode & Mode::WithCacheBits; - info.root_count = root_count; - info.cell_count = cell_count; - info.absent_count = dangle_count; - int crc_size = info.has_crc32c ? 4 : 0; - info.roots_offset = 4 + 1 + 1 + 3 * info.ref_byte_size + info.offset_byte_size; - info.index_offset = info.roots_offset + info.root_count * info.ref_byte_size; - info.data_offset = info.index_offset; - if (info.has_index) { - info.data_offset += (long long)cell_count * info.offset_byte_size; - } - info.magic = Info::boc_generic; - info.data_size = data_bytes_adj; - info.total_size = info.data_offset + data_bytes_adj + crc_size; - auto res = td::narrow_cast_safe(info.total_size); - if (res.is_error()) { - return 0; - } - return res.ok(); -} - -BagOfCells& BagOfCells::serialize(int mode) { - std::size_t size_est = estimate_serialized_size(mode); - if (!size_est) { - serialized.clear(); - return *this; - } - serialized.resize(size_est); - if (serialize_to(const_cast(serialized.data()), serialized.size(), mode) != size_est) { - serialized.clear(); - } - return *this; -} - -std::string BagOfCells::serialize_to_string(int mode) { - std::size_t size_est = estimate_serialized_size(mode); - if (!size_est) { - return {}; - } - std::string res; - res.resize(size_est, 0); - if (serialize_to(const_cast(reinterpret_cast(res.data())), res.size(), mode) == - res.size()) { - return res; - } else { - return {}; - } -} - -td::Result BagOfCells::serialize_to_slice(int mode) { - std::size_t size_est = estimate_serialized_size(mode); - if (!size_est) { - return td::Status::Error("no cells to serialize to this bag of cells"); - } - td::BufferSlice res(size_est); - if (serialize_to(const_cast(reinterpret_cast(res.data())), res.size(), mode) == - res.size()) { - return std::move(res); - } else { - return td::Status::Error("error while serializing a bag of cells: actual serialized size differs from estimated"); - } -} - -std::string BagOfCells::extract_string() const { - return std::string{serialized.data(), serialized.data() + serialized.size()}; -} - -void BagOfCells::store_uint(unsigned long long value, unsigned bytes) { - unsigned char* ptr = store_ptr += bytes; - store_chk(); - while (bytes) { - *--ptr = value & 0xff; - value >>= 8; - --bytes; - } - DCHECK(!bytes); -} - -//serialized_boc#672fb0ac has_idx:(## 1) has_crc32c:(## 1) -// has_cache_bits:(## 1) flags:(## 2) { flags = 0 } -// size:(## 3) { size <= 4 } -// off_bytes:(## 8) { off_bytes <= 8 } -// cells:(##(size * 8)) -// roots:(##(size * 8)) -// absent:(##(size * 8)) { roots + absent <= cells } -// tot_cells_size:(##(off_bytes * 8)) -// index:(cells * ##(off_bytes * 8)) -// cell_data:(tot_cells_size * [ uint8 ]) -// = BagOfCells; -std::size_t BagOfCells::serialize_to(unsigned char* buffer, std::size_t buff_size, int mode) { - std::size_t size_est = estimate_serialized_size(mode); - if (!size_est || size_est > buff_size) { - return 0; - } - init_store(buffer, buffer + size_est); - store_uint(info.magic, 4); - - td::uint8 byte{0}; - if (info.has_index) { - byte |= 1 << 7; - } - if (info.has_crc32c) { - byte |= 1 << 6; - } - if (info.has_cache_bits) { - byte |= 1 << 5; - } - // 3, 4 - flags - if (info.ref_byte_size < 1 || info.ref_byte_size > 7) { - return 0; - } - byte |= static_cast(info.ref_byte_size); - store_uint(byte, 1); - - store_uint(info.offset_byte_size, 1); - store_ref(cell_count); - store_ref(root_count); - store_ref(0); - store_offset(info.data_size); - for (const auto& root_info : roots) { - int k = cell_count - 1 - root_info.idx; - DCHECK(k >= 0 && k < cell_count); - store_ref(k); - } - DCHECK(store_ptr - buffer == (long long)info.index_offset); - DCHECK((unsigned)cell_count == cell_list_.size()); - if (info.has_index) { - std::size_t offs = 0; - for (int i = cell_count - 1; i >= 0; --i) { - const Ref& dc = cell_list_[i].dc_ref; - bool with_hash = (mode & Mode::WithIntHashes) && !cell_list_[i].wt; - if (cell_list_[i].is_root_cell && (mode & Mode::WithTopHash)) { - with_hash = true; - } - offs += dc->get_serialized_size(with_hash) + dc->size_refs() * info.ref_byte_size; - auto fixed_offset = offs; - if (info.has_cache_bits) { - fixed_offset = offs * 2 + cell_list_[i].should_cache; - } - store_offset(fixed_offset); - } - DCHECK(offs == info.data_size); - } - DCHECK(store_ptr - buffer == (long long)info.data_offset); - unsigned char* keep_ptr = store_ptr; - for (int i = 0; i < cell_count; ++i) { - const auto& dc_info = cell_list_[cell_count - 1 - i]; - const Ref& dc = dc_info.dc_ref; - bool with_hash = (mode & Mode::WithIntHashes) && !dc_info.wt; - if (dc_info.is_root_cell && (mode & Mode::WithTopHash)) { - with_hash = true; - } - int s = dc->serialize(store_ptr, 256, with_hash); - store_ptr += s; - store_chk(); - DCHECK(dc->size_refs() == dc_info.ref_num); - // std::cerr << (dc_info.is_special() ? '*' : ' ') << i << '<' << (int)dc_info.wt << ">:"; - for (unsigned j = 0; j < dc_info.ref_num; ++j) { - int k = cell_count - 1 - dc_info.ref_idx[j]; - DCHECK(k > i && k < cell_count); - store_ref(k); - // std::cerr << ' ' << k; - } - // std::cerr << std::endl; - } - store_chk(); - DCHECK(store_ptr - keep_ptr == (long long)info.data_size); - DCHECK(store_end - store_ptr == (info.has_crc32c ? 4 : 0)); - if (info.has_crc32c) { - // compute crc32c of buffer .. store_ptr - unsigned crc = td::crc32c(td::Slice{buffer, store_ptr}); - store_uint(td::bswap32(crc), 4); - } - DCHECK(store_empty()); - return store_ptr - buffer; -} - -unsigned long long BagOfCells::Info::read_int(const unsigned char* ptr, unsigned bytes) { - unsigned long long res = 0; - while (bytes > 0) { - res = (res << 8) + *ptr++; - --bytes; - } - return res; -} - -void BagOfCells::Info::write_int(unsigned char* ptr, unsigned long long value, int bytes) { - ptr += bytes; - while (bytes) { - *--ptr = value & 0xff; - value >>= 8; - --bytes; - } - DCHECK(!bytes); -} - -long long BagOfCells::Info::parse_serialized_header(const td::Slice& slice) { - invalidate(); - int sz = static_cast(std::min(slice.size(), static_cast(0xffff))); - if (sz < 4) { - return -10; // want at least 10 bytes - } - const unsigned char* ptr = slice.ubegin(); - magic = (unsigned)read_int(ptr, 4); - has_crc32c = false; - has_index = false; - has_cache_bits = false; - ref_byte_size = 0; - offset_byte_size = 0; - root_count = cell_count = absent_count = -1; - index_offset = data_offset = data_size = total_size = 0; - if (magic != boc_generic && magic != boc_idx && magic != boc_idx_crc32c) { - magic = 0; - return 0; - } - if (sz < 5) { - return -10; - } - td::uint8 byte = ptr[4]; - if (magic == boc_generic) { - has_index = (byte >> 7) % 2 == 1; - has_crc32c = (byte >> 6) % 2 == 1; - has_cache_bits = (byte >> 5) % 2 == 1; - } else { - has_index = true; - has_crc32c = magic == boc_idx_crc32c; - } - if (has_cache_bits && !has_index) { - return 0; - } - ref_byte_size = byte & 7; - if (ref_byte_size > 4 || ref_byte_size < 1) { - return 0; - } - if (sz < 6) { - return -7 - 3 * ref_byte_size; - } - offset_byte_size = ptr[5]; - if (offset_byte_size > 8 || offset_byte_size < 1) { - return 0; - } - roots_offset = 6 + 3 * ref_byte_size + offset_byte_size; - ptr += 6; - sz -= 6; - if (sz < ref_byte_size) { - return -static_cast(roots_offset); - } - cell_count = (int)read_ref(ptr); - if (cell_count <= 0) { - cell_count = -1; - return 0; - } - if (sz < 2 * ref_byte_size) { - return -static_cast(roots_offset); - } - root_count = (int)read_ref(ptr + ref_byte_size); - if (root_count <= 0) { - root_count = -1; - return 0; - } - index_offset = roots_offset; - if (magic == boc_generic) { - index_offset += (long long)root_count * ref_byte_size; - has_roots = true; - } else { - if (root_count != 1) { - return 0; - } - } - data_offset = index_offset; - if (has_index) { - data_offset += (long long)cell_count * offset_byte_size; - } - if (sz < 3 * ref_byte_size) { - return -static_cast(roots_offset); - } - absent_count = (int)read_ref(ptr + 2 * ref_byte_size); - if (absent_count < 0 || absent_count > cell_count) { - return 0; - } - if (sz < 3 * ref_byte_size + offset_byte_size) { - return -static_cast(roots_offset); - } - data_size = read_offset(ptr + 3 * ref_byte_size); - if (data_size > ((unsigned long long)cell_count << 10)) { - return 0; - } - if (data_size > (1ull << 40)) { - return 0; // bag of cells with more than 1TiB data is unlikely - } - if (data_size < cell_count * (2ull + ref_byte_size) - ref_byte_size) { - return 0; // invalid header, too many cells for this amount of data bytes - } - valid = true; - total_size = data_offset + data_size + (has_crc32c ? 4 : 0); - return total_size; -} - -td::Result BagOfCells::get_cell_slice(int idx, td::Slice data) { - unsigned long long offs = get_idx_entry(idx - 1); - unsigned long long offs_end = get_idx_entry(idx); - if (offs > offs_end || offs_end > data.size()) { - return td::Status::Error(PSLICE() << "invalid index entry [" << offs << "; " << offs_end << "], " - << td::tag("data.size()", data.size())); - } - return data.substr(offs, td::narrow_cast(offs_end - offs)); -} - -td::Result> BagOfCells::deserialize_cell(int idx, td::Slice cells_slice, - td::Span> cells_span, - std::vector* cell_should_cache) { - TRY_RESULT(cell_slice, get_cell_slice(idx, cells_slice)); - std::array, 4> refs_buf; - - CellSerializationInfo cell_info; - TRY_STATUS(cell_info.init(cell_slice, info.ref_byte_size)); - if (cell_info.end_offset != cell_slice.size()) { - return td::Status::Error("unused space in cell serialization"); - } - - auto refs = td::MutableSpan>(refs_buf).substr(0, cell_info.refs_cnt); - for (int k = 0; k < cell_info.refs_cnt; k++) { - int ref_idx = (int)info.read_ref(cell_slice.ubegin() + cell_info.refs_offset + k * info.ref_byte_size); - if (ref_idx <= idx) { - return td::Status::Error(PSLICE() << "bag-of-cells error: reference #" << k << " of cell #" << idx - << " is to cell #" << ref_idx << " with smaller index"); - } - if (ref_idx >= cell_count) { - return td::Status::Error(PSLICE() << "bag-of-cells error: reference #" << k << " of cell #" << idx - << " is to non-existent cell #" << ref_idx << ", only " << cell_count - << " cells are defined"); - } - refs[k] = cells_span[cell_count - ref_idx - 1]; - if (cell_should_cache) { - auto& cnt = (*cell_should_cache)[ref_idx]; - if (cnt < 2) { - cnt++; - } - } - } - - return cell_info.create_data_cell(cell_slice, refs); -} - -td::Result BagOfCells::deserialize(const td::Slice& data, int max_roots) { - clear(); - long long size_est = info.parse_serialized_header(data); - //LOG(INFO) << "estimated size " << size_est << ", true size " << data.size(); - if (size_est == 0) { - return td::Status::Error(PSLICE() << "cannot deserialize bag-of-cells: invalid header, error " << size_est); - } - if (size_est < 0) { - //LOG(ERROR) << "cannot deserialize bag-of-cells: not enough bytes (" << data.size() << " present, " << -size_est - //<< " required)"; - return size_est; - } - - if (size_est > (long long)data.size()) { - //LOG(ERROR) << "cannot deserialize bag-of-cells: not enough bytes (" << data.size() << " present, " << size_est - //<< " required)"; - return -size_est; - } - //LOG(INFO) << "estimated size " << size_est << ", true size " << data.size(); - if (info.root_count > max_roots) { - return td::Status::Error("Bag-of-cells has more root cells than expected"); - } - if (info.has_crc32c) { - unsigned crc_computed = td::crc32c(td::Slice{data.ubegin(), data.uend() - 4}); - unsigned crc_stored = td::as(data.uend() - 4); - if (crc_computed != crc_stored) { - return td::Status::Error(PSLICE() << "bag-of-cells CRC32C mismatch: expected " << td::format::as_hex(crc_computed) - << ", found " << td::format::as_hex(crc_stored)); - } - } - - cell_count = info.cell_count; - std::vector cell_should_cache; - if (info.has_cache_bits) { - cell_should_cache.resize(cell_count, 0); - } - roots.clear(); - roots.resize(info.root_count); - auto* roots_ptr = data.substr(info.roots_offset).ubegin(); - for (int i = 0; i < info.root_count; i++) { - int idx = 0; - if (info.has_roots) { - idx = (int)info.read_ref(roots_ptr + i * info.ref_byte_size); - } - if (idx < 0 || idx >= info.cell_count) { - return td::Status::Error(PSLICE() << "bag-of-cells invalid root index " << idx); - } - roots[i].idx = info.cell_count - idx - 1; - if (info.has_cache_bits) { - auto& cnt = cell_should_cache[idx]; - if (cnt < 2) { - cnt++; - } - } - } - if (info.has_index) { - index_ptr = data.substr(info.index_offset).ubegin(); - // TODO: should we validate index here - } else { - index_ptr = nullptr; - unsigned long long cur = 0; - custom_index.reserve(info.cell_count); - - auto cells_slice = data.substr(info.data_offset, info.data_size); - - for (int i = 0; i < info.cell_count; i++) { - CellSerializationInfo cell_info; - auto status = cell_info.init(cells_slice, info.ref_byte_size); - if (status.is_error()) { - return td::Status::Error(PSLICE() - << "invalid bag-of-cells failed to deserialize cell #" << i << " " << status.error()); - } - cells_slice = cells_slice.substr(cell_info.end_offset); - cur += cell_info.end_offset; - custom_index.push_back(cur); - } - if (!cells_slice.empty()) { - return td::Status::Error(PSLICE() << "invalid bag-of-cells last cell #" << info.cell_count - 1 << ": end offset " - << cur << " is different from total data size " << info.data_size); - } - } - auto cells_slice = data.substr(info.data_offset, info.data_size); - std::vector> cell_list; - cell_list.reserve(cell_count); - std::array, 4> refs_buf; - for (int i = 0; i < cell_count; i++) { - // reconstruct cell with index cell_count - 1 - i - int idx = cell_count - 1 - i; - auto r_cell = deserialize_cell(idx, cells_slice, cell_list, info.has_cache_bits ? &cell_should_cache : nullptr); - if (r_cell.is_error()) { - return td::Status::Error(PSLICE() << "invalid bag-of-cells failed to deserialize cell #" << idx << " " - << r_cell.error()); - } - cell_list.push_back(r_cell.move_as_ok()); - DCHECK(cell_list.back().not_null()); - } - if (info.has_cache_bits) { - for (int idx = 0; idx < cell_count; idx++) { - auto should_cache = cell_should_cache[idx] > 1; - auto stored_should_cache = get_cache_entry(idx); - if (should_cache != stored_should_cache) { - return td::Status::Error(PSLICE() << "invalid bag-of-cells cell #" << idx << " has wrong cache flag " - << stored_should_cache); - } - } - } - custom_index.clear(); - index_ptr = nullptr; - root_count = info.root_count; - dangle_count = info.absent_count; - for (auto& root_info : roots) { - root_info.cell = cell_list[root_info.idx]; - } - cell_list.clear(); - return size_est; -} - -unsigned long long BagOfCells::get_idx_entry(int index) { - auto raw = get_idx_entry_raw(index); - if (info.has_cache_bits) { - raw /= 2; - } - return raw; -} - -bool BagOfCells::get_cache_entry(int index) { - if (!info.has_cache_bits) { - return true; - } - if (!info.has_index) { - return true; - } - auto raw = get_idx_entry_raw(index); - return raw % 2 == 1; -} - -unsigned long long BagOfCells::get_idx_entry_raw(int index) { - if (index < 0) { - return 0; - } - if (!info.has_index) { - return custom_index.at(index); - } else if (index < info.cell_count && index_ptr) { - return info.read_offset(index_ptr + (long)index * info.offset_byte_size); - } else { - // throw ? - return 0; - } -} - -/* - * - * Simple BoC serialization/deserialization functions - * - */ - -td::Result> std_boc_deserialize(td::Slice data, bool can_be_empty) { - if (data.empty() && can_be_empty) { - return Ref(); - } - BagOfCells boc; - auto res = boc.deserialize(data, 1); - if (res.is_error()) { - return res.move_as_error(); - } - if (boc.get_root_count() != 1) { - return td::Status::Error("bag of cells is expected to have exactly one root"); - } - auto root = boc.get_root_cell(); - if (root.is_null()) { - return td::Status::Error("bag of cells has null root cell (?)"); - } - if (root->get_level() != 0) { - return td::Status::Error("bag of cells has a root with non-zero level"); - } - return std::move(root); -} - -td::Result>> std_boc_deserialize_multi(td::Slice data, int max_roots) { - if (data.empty()) { - return std::vector>{}; - } - BagOfCells boc; - auto res = boc.deserialize(data, max_roots); - if (res.is_error()) { - return res.move_as_error(); - } - int n = boc.get_root_count(); - std::vector> roots; - for (int i = 0; i < n; i++) { - auto root = boc.get_root_cell(i); - if (root.is_null()) { - return td::Status::Error("bag of cells has a null root cell (?)"); - } - if (root->get_level() != 0) { - return td::Status::Error("bag of cells has a root with non-zero level"); - } - roots.emplace_back(std::move(root)); - } - return std::move(roots); -} - -td::Result std_boc_serialize(Ref root, int mode) { - if (root.is_null()) { - return td::Status::Error("cannot serialize a null cell reference into a bag of cells"); - } - BagOfCells boc; - boc.add_root(std::move(root)); - auto res = boc.import_cells(); - if (res.is_error()) { - return res.move_as_error(); - } - return boc.serialize_to_slice(mode); -} - -td::Result std_boc_serialize_multi(std::vector> roots, int mode) { - if (roots.empty()) { - return td::BufferSlice{}; - } - BagOfCells boc; - boc.add_roots(std::move(roots)); - auto res = boc.import_cells(); - if (res.is_error()) { - return res.move_as_error(); - } - return boc.serialize_to_slice(mode); -} - -/* - * - * Cell storage statistics - * - */ - -bool CellStorageStat::compute_used_storage(Ref cs_ref, bool kill_dup, unsigned skip_count_root) { - clear(); - return add_used_storage(std::move(cs_ref), kill_dup, skip_count_root) && clear_seen(); -} - -bool CellStorageStat::compute_used_storage(const CellSlice& cs, bool kill_dup, unsigned skip_count_root) { - clear(); - return add_used_storage(cs, kill_dup, skip_count_root) && clear_seen(); -} - -bool CellStorageStat::compute_used_storage(CellSlice&& cs, bool kill_dup, unsigned skip_count_root) { - clear(); - return add_used_storage(std::move(cs), kill_dup, skip_count_root) && clear_seen(); -} - -bool CellStorageStat::compute_used_storage(Ref cell, bool kill_dup, unsigned skip_count_root) { - clear(); - return add_used_storage(std::move(cell), kill_dup, skip_count_root) && clear_seen(); -} - -bool CellStorageStat::add_used_storage(Ref cs_ref, bool kill_dup, unsigned skip_count_root) { - if (cs_ref->is_unique()) { - return add_used_storage(std::move(cs_ref.unique_write()), kill_dup, skip_count_root); - } else { - return add_used_storage(*cs_ref, kill_dup, skip_count_root); - } -} - -bool CellStorageStat::add_used_storage(const CellSlice& cs, bool kill_dup, unsigned skip_count_root) { - if (!(skip_count_root & 1)) { - ++cells; - } - if (!(skip_count_root & 2)) { - bits += cs.size(); - } - for (unsigned i = 0; i < cs.size_refs(); i++) { - if (!add_used_storage(cs.prefetch_ref(i), kill_dup)) { - return false; - } - } - return true; -} - -bool CellStorageStat::add_used_storage(CellSlice&& cs, bool kill_dup, unsigned skip_count_root) { - if (!(skip_count_root & 1)) { - ++cells; - } - if (!(skip_count_root & 2)) { - bits += cs.size(); - } - while (cs.size_refs()) { - if (!add_used_storage(cs.fetch_ref(), kill_dup)) { - return false; - } - } - return true; -} - -bool CellStorageStat::add_used_storage(Ref cell, bool kill_dup, unsigned skip_count_root) { - if (cell.is_null()) { - return false; - } - if (kill_dup) { - auto ins = seen.insert(cell->get_hash()); - if (!ins.second) { - return true; - } - } - vm::CellSlice cs{vm::NoVm{}, std::move(cell)}; - return add_used_storage(std::move(cs), kill_dup, skip_count_root); -} - -void NewCellStorageStat::add_cell(Ref cell) { - dfs(std::move(cell), true, false); -} -void NewCellStorageStat::add_proof(Ref cell, const CellUsageTree* usage_tree) { - CHECK(usage_tree); - usage_tree_ = usage_tree; - dfs(std::move(cell), false, true); -} -void NewCellStorageStat::add_cell_and_proof(Ref cell, const CellUsageTree* usage_tree) { - CHECK(usage_tree); - usage_tree_ = usage_tree; - dfs(std::move(cell), true, true); -} - -NewCellStorageStat::Stat NewCellStorageStat::tentative_add_cell(Ref cell) const { - NewCellStorageStat stat; - stat.parent_ = this; - stat.add_cell(std::move(cell)); - return stat.get_stat(); -} - -NewCellStorageStat::Stat NewCellStorageStat::tentative_add_proof(Ref cell, - const CellUsageTree* usage_tree) const { - NewCellStorageStat stat; - stat.parent_ = this; - stat.add_proof(std::move(cell), usage_tree); - return stat.get_proof_stat(); -} - -void NewCellStorageStat::dfs(Ref cell, bool need_stat, bool need_proof_stat) { - if (cell.is_null()) { - // FIXME: save error flag? - return; - } - if (need_stat) { - stat_.internal_refs++; - if ((parent_ && parent_->seen_.count(cell->get_hash()) != 0) || !seen_.insert(cell->get_hash()).second) { - need_stat = false; - } else { - stat_.cells++; - } - } - - if (need_proof_stat) { - auto tree_node = cell->get_tree_node(); - if (!tree_node.empty() && tree_node.is_from_tree(usage_tree_)) { - proof_stat_.external_refs++; - need_proof_stat = false; - } else { - proof_stat_.internal_refs++; - if ((parent_ && parent_->proof_seen_.count(cell->get_hash()) != 0) || - !proof_seen_.insert(cell->get_hash()).second) { - need_proof_stat = false; - } else { - proof_stat_.cells++; - } - } - } - - if (!need_proof_stat && !need_stat) { - return; - } - vm::CellSlice cs{vm::NoVm{}, std::move(cell)}; - if (need_stat) { - stat_.bits += cs.size(); - } - if (need_proof_stat) { - proof_stat_.bits += cs.size(); - } - while (cs.size_refs()) { - dfs(cs.fetch_ref(), need_stat, need_proof_stat); - } -} - -bool VmStorageStat::add_storage(Ref cell) { - if (cell.is_null() || !check_visited(cell)) { - return true; - } - if (cells >= limit) { - return false; - } - ++cells; - bool special; - auto cs = load_cell_slice_special(std::move(cell), special); - return cs.is_valid() && add_storage(std::move(cs)); -} - -bool VmStorageStat::add_storage(const CellSlice& cs) { - bits += cs.size(); - refs += cs.size_refs(); - for (unsigned i = 0; i < cs.size_refs(); i++) { - if (!add_storage(cs.prefetch_ref(i))) { - return false; - } - } - return true; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/boc.h b/submodules/ton/tonlib-src/crypto/vm/boc.h deleted file mode 100644 index cc277a8c..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/boc.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include "vm/cells.h" -#include "td/utils/Status.h" -#include "td/utils/buffer.h" -#include "td/utils/HashMap.h" -#include "td/utils/HashSet.h" - -namespace vm { -using td::Ref; - -class NewCellStorageStat { - public: - NewCellStorageStat() { - } - - struct Stat { - Stat() { - } - Stat(td::uint64 cells_, td::uint64 bits_, td::uint64 internal_refs_ = 0, td::uint64 external_refs_ = 0) - : cells(cells_), bits(bits_), internal_refs(internal_refs_), external_refs(external_refs_) { - } - td::uint64 cells{0}; - td::uint64 bits{0}; - td::uint64 internal_refs{0}; - td::uint64 external_refs{0}; - - auto key() const { - return std::make_tuple(cells, bits, internal_refs, external_refs); - } - bool operator==(const Stat& other) const { - return key() == other.key(); - } - Stat& operator=(const Stat& other) = default; - Stat& operator+=(const Stat& other) { - cells += other.cells; - bits += other.bits; - internal_refs += other.internal_refs; - external_refs += other.external_refs; - return *this; - } - Stat operator+(const Stat& other) const { - return Stat{cells + other.cells, bits + other.bits, internal_refs + other.internal_refs, - external_refs + other.external_refs}; - } - bool fits_uint32() const { - return !((cells | bits | internal_refs | external_refs) >> 32); - } - void set_zero() { - cells = bits = internal_refs = external_refs = 0; - } - }; - - Stat get_stat() const { - return stat_; - } - - Stat get_proof_stat() const { - return proof_stat_; - } - - Stat get_total_stat() const { - return stat_ + proof_stat_; - } - - void add_cell(Ref cell); - void add_proof(Ref cell, const CellUsageTree* usage_tree); - void add_cell_and_proof(Ref cell, const CellUsageTree* usage_tree); - Stat tentative_add_cell(Ref cell) const; - Stat tentative_add_proof(Ref cell, const CellUsageTree* usage_tree) const; - void set_zero() { - stat_.set_zero(); - proof_stat_.set_zero(); - } - - private: - const CellUsageTree* usage_tree_; - std::set seen_; - Stat stat_; - std::set proof_seen_; - Stat proof_stat_; - const NewCellStorageStat* parent_{nullptr}; - - void dfs(Ref cell, bool need_stat, bool need_proof_stat); -}; - -struct CellStorageStat { - unsigned long long cells; - unsigned long long bits; - unsigned long long public_cells; - std::set seen; - CellStorageStat() : cells(0), bits(0), public_cells(0) { - } - bool clear_seen() { - seen.clear(); - return true; - } - void clear() { - cells = bits = public_cells = 0; - clear_seen(); - } - bool compute_used_storage(Ref cs_ref, bool kill_dup = true, unsigned skip_count_root = 0); - bool compute_used_storage(const CellSlice& cs, bool kill_dup = true, unsigned skip_count_root = 0); - bool compute_used_storage(CellSlice&& cs, bool kill_dup = true, unsigned skip_count_root = 0); - bool compute_used_storage(Ref cell, bool kill_dup = true, unsigned skip_count_root = 0); - - bool add_used_storage(Ref cs_ref, bool kill_dup = true, unsigned skip_count_root = 0); - bool add_used_storage(const CellSlice& cs, bool kill_dup = true, unsigned skip_count_root = 0); - bool add_used_storage(CellSlice&& cs, bool kill_dup = true, unsigned skip_count_root = 0); - bool add_used_storage(Ref cell, bool kill_dup = true, unsigned skip_count_root = 0); -}; - -struct VmStorageStat { - td::uint64 cells{0}, bits{0}, refs{0}, limit; - td::HashSet visited; - VmStorageStat(td::uint64 _limit) : limit(_limit) { - } - bool add_storage(Ref cell); - bool add_storage(const CellSlice& cs); - bool check_visited(const CellHash& cell_hash) { - return visited.insert(cell_hash).second; - } - bool check_visited(const Ref& cell) { - return check_visited(cell->get_hash()); - } -}; - -struct CellSerializationInfo { - bool special; - Cell::LevelMask level_mask; - - bool with_hashes; - size_t hashes_offset; - size_t depth_offset; - - size_t data_offset; - size_t data_len; - bool data_with_bits; - - size_t refs_offset; - int refs_cnt; - - size_t end_offset; - - td::Status init(td::Slice data, int ref_byte_size); - td::Status init(td::uint8 d1, td::uint8 d2, int ref_byte_size); - td::Result get_bits(td::Slice cell) const; - - td::Result> create_data_cell(td::Slice data, td::Span> refs) const; -}; - -class BagOfCells { - public: - enum { hash_bytes = vm::Cell::hash_bytes, default_max_roots = 16384 }; - enum Mode { WithIndex = 1, WithCRC32C = 2, WithTopHash = 4, WithIntHashes = 8, WithCacheBits = 16, max = 31 }; - enum { max_cell_whs = 64 }; - using Hash = Cell::Hash; - struct Info { - enum : td::uint32 { boc_idx = 0x68ff65f3, boc_idx_crc32c = 0xacc3a728, boc_generic = 0xb5ee9c72 }; - - unsigned magic; - int root_count; - int cell_count; - int absent_count; - int ref_byte_size; - int offset_byte_size; - bool valid; - bool has_index; - bool has_roots{false}; - bool has_crc32c; - bool has_cache_bits; - unsigned long long roots_offset, index_offset, data_offset, data_size, total_size; - Info() : magic(0), valid(false) { - } - void invalidate() { - valid = false; - } - long long parse_serialized_header(const td::Slice& slice); - unsigned long long read_int(const unsigned char* ptr, unsigned bytes); - unsigned long long read_ref(const unsigned char* ptr) { - return read_int(ptr, ref_byte_size); - } - unsigned long long read_offset(const unsigned char* ptr) { - return read_int(ptr, offset_byte_size); - } - void write_int(unsigned char* ptr, unsigned long long value, int bytes); - void write_ref(unsigned char* ptr, unsigned long long value) { - write_int(ptr, value, ref_byte_size); - } - void write_offset(unsigned char* ptr, unsigned long long value) { - write_int(ptr, value, offset_byte_size); - } - }; - - private: - int cell_count{0}, root_count{0}, dangle_count{0}, int_refs{0}; - int int_hashes{0}, top_hashes{0}; - int max_depth{1024}; - Info info; - unsigned long long data_bytes{0}; - unsigned char* store_ptr{nullptr}; - unsigned char* store_end{nullptr}; - td::HashMap cells; - struct CellInfo { - Ref dc_ref; - std::array ref_idx; - unsigned char ref_num; - unsigned char wt; - unsigned char hcnt; - int new_idx; - bool should_cache{false}; - bool is_root_cell{false}; - CellInfo() : ref_num(0) { - } - CellInfo(Ref _dc) : dc_ref(std::move(_dc)), ref_num(0) { - } - CellInfo(Ref _dc, int _refs, const std::array& _ref_list) - : dc_ref(std::move(_dc)), ref_idx(_ref_list), ref_num(static_cast(_refs)) { - } - bool is_special() const { - return !wt; - } - }; - std::vector cell_list_; - struct RootInfo { - RootInfo() = default; - RootInfo(Ref cell, int idx) : cell(std::move(cell)), idx(idx) { - } - Ref cell; - int idx{-1}; - }; - std::vector cell_list_tmp; - std::vector roots; - std::vector serialized; - const unsigned char* index_ptr{nullptr}; - const unsigned char* data_ptr{nullptr}; - std::vector custom_index; - - public: - void clear(); - int set_roots(const std::vector>& new_roots); - int set_root(td::Ref new_root); - int add_roots(const std::vector>& add_roots); - int add_root(td::Ref add_root); - td::Status import_cells() TD_WARN_UNUSED_RESULT; - BagOfCells() = default; - std::size_t estimate_serialized_size(int mode = 0); - BagOfCells& serialize(int mode = 0); - std::string serialize_to_string(int mode = 0); - td::Result serialize_to_slice(int mode = 0); - std::size_t serialize_to(unsigned char* buffer, std::size_t buff_size, int mode = 0); - std::string extract_string() const; - - td::Result deserialize(const td::Slice& data, int max_roots = default_max_roots); - td::Result deserialize(const unsigned char* buffer, std::size_t buff_size, - int max_roots = default_max_roots) { - return deserialize(td::Slice{buffer, buff_size}, max_roots); - } - int get_root_count() const { - return root_count; - } - Ref get_root_cell(int idx = 0) const { - return (idx >= 0 && idx < root_count) ? roots.at(idx).cell : Ref{}; - } - - static int precompute_cell_serialization_size(const unsigned char* cell, std::size_t len, int ref_size, - int* refs_num_ptr = nullptr); - - private: - int rv_idx; - td::Result import_cell(td::Ref cell, int depth); - void cells_clear() { - cell_count = 0; - int_refs = 0; - data_bytes = 0; - cells.clear(); - cell_list_.clear(); - } - td::uint64 compute_sizes(int mode, int& r_size, int& o_size); - void init_store(unsigned char* from, unsigned char* to) { - store_ptr = from; - store_end = to; - } - void store_chk() const { - DCHECK(store_ptr <= store_end); - } - bool store_empty() const { - return store_ptr == store_end; - } - void store_uint(unsigned long long value, unsigned bytes); - void store_ref(unsigned long long value) { - store_uint(value, info.ref_byte_size); - } - void store_offset(unsigned long long value) { - store_uint(value, info.offset_byte_size); - } - void reorder_cells(); - int revisit(int cell_idx, int force = 0); - unsigned long long get_idx_entry_raw(int index); - unsigned long long get_idx_entry(int index); - bool get_cache_entry(int index); - td::Result get_cell_slice(int index, td::Slice data); - td::Result> deserialize_cell(int index, td::Slice data, td::Span> cells, - std::vector* cell_should_cache); -}; - -td::Result> std_boc_deserialize(td::Slice data, bool can_be_empty = false); -td::Result std_boc_serialize(Ref root, int mode = 0); - -td::Result>> std_boc_deserialize_multi(td::Slice data, - int max_roots = BagOfCells::default_max_roots); -td::Result std_boc_serialize_multi(std::vector> root, int mode = 0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/box.hpp b/submodules/ton/tonlib-src/crypto/vm/box.hpp deleted file mode 100644 index 68b131ce..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/box.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/stack.hpp" - -namespace vm { -using td::Ref; - -class Box : public td::CntObject { - mutable StackEntry data_; - - public: - Box() = default; - Box(const Box&) = default; - Box(Box&&) = default; - template - Box(Args... args) : data_{std::move(args...)} { - } - ~Box() override = default; - Box(const StackEntry& data) : data_(data) { - } - Box(StackEntry&& data) : data_(std::move(data)) { - } - void operator=(const StackEntry& data) const { - data_ = data; - } - void operator=(StackEntry&& data) const { - data_ = data; - } - void set(const StackEntry& data) const { - data_ = data; - } - void set(StackEntry&& data) const { - data_ = data; - } - const StackEntry& get() const { - return data_; - } - void clear() const { - data_.clear(); - } - bool empty() const { - return data_.empty(); - } -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cellops.cpp b/submodules/ton/tonlib-src/crypto/vm/cellops.cpp deleted file mode 100644 index 1dfb69fb..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cellops.cpp +++ /dev/null @@ -1,1454 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/cellops.h" -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vmstate.h" -#include "vm/vm.h" -#include "common/bigint.hpp" -#include "common/refint.h" - -namespace vm { - -int exec_push_ref(VmState* st, CellSlice& cs, int mode, int pfx_bits) { - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "no references left for a PUSHREF instruction"}; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHREF" << (mode == 2 ? "CONT" : (mode == 1 ? "SLICE" : "")) << " (" - << cell->get_hash().to_hex() << ")"; - switch (mode) { - default: - case 0: - stack.push_cell(std::move(cell)); - break; - case 1: - stack.push_cellslice(load_cell_slice_ref(std::move(cell))); - break; - case 2: - stack.push_cont(Ref{true, load_cell_slice_ref(std::move(cell)), st->get_cp()}); - break; - } - return 0; -} - -std::string dump_push_ref(CellSlice& cs, unsigned args, int pfx_bits, std::string name) { - if (!cs.have_refs(1)) { - return ""; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - return name + " (" + cell->get_hash().to_hex() + ")"; -} - -int compute_len_push_ref(const CellSlice& cs, unsigned args, int pfx_bits) { - return cs.have_refs(1) ? (0x10000 + pfx_bits) : 0; -} - -std::string dump_push_ref2(CellSlice& cs, unsigned args, int pfx_bits, std::string name) { - if (!cs.have_refs(2)) { - return ""; - } - cs.advance(pfx_bits); - auto cell1 = cs.fetch_ref(), cell2 = cs.fetch_ref(); - return name + " (" + cell1->get_hash().to_hex() + ") (" + cell2->get_hash().to_hex() + ")"; -} - -int compute_len_push_ref2(const CellSlice& cs, unsigned args, int pfx_bits) { - return cs.have_refs(2) ? (0x20000 + pfx_bits) : 0; -} - -int exec_push_slice_common(VmState* st, CellSlice& cs, unsigned data_bits, unsigned refs, int pfx_bits) { - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a PUSHSLICE instruction"}; - } - if (!cs.have_refs(refs)) { - throw VmError{Excno::inv_opcode, "not enough references for a PUSHSLICE instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits, refs); - slice.unique_write().remove_trailing(); - VM_LOG(st) << "execute PUSHSLICE " << slice; - stack.push(std::move(slice)); - return 0; -} - -std::string dump_push_slice_common(CellSlice& cs, unsigned data_bits, unsigned refs, int pfx_bits, - const char* name = "PUSHSLICE ") { - if (!cs.have(pfx_bits + data_bits) || !cs.have_refs(refs)) { - return ""; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits, refs); - slice.unique_write().remove_trailing(); - std::ostringstream os{name}; - slice->dump_hex(os, 1, false); - return os.str(); -} - -int compute_len_push_slice_common(const CellSlice& cs, unsigned data_bits, unsigned refs, int pfx_bits) { - unsigned bits = pfx_bits + data_bits; - return cs.have(bits) && cs.have_refs(refs) ? (refs << 16) + bits : 0; -} - -int exec_push_slice(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - return exec_push_slice_common(st, cs, (args & 15) * 8 + 4, 0, pfx_bits); -} - -std::string dump_push_slice(CellSlice& cs, unsigned args, int pfx_bits) { - return dump_push_slice_common(cs, (args & 15) * 8 + 4, 0, pfx_bits); -} - -int compute_len_push_slice(const CellSlice& cs, unsigned args, int pfx_bits) { - return compute_len_push_slice_common(cs, (args & 15) * 8 + 4, 0, pfx_bits); -} - -int exec_push_slice_r(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = ((args >> 5) & 3) + 1; - unsigned data_bits = (args & 31) * 8 + 1; - return exec_push_slice_common(st, cs, data_bits, refs, pfx_bits); -} - -std::string dump_push_slice_r(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = ((args >> 5) & 3) + 1; - unsigned data_bits = (args & 31) * 8 + 1; - return dump_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -int compute_len_push_slice_r(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = ((args >> 5) & 3) + 1; - unsigned data_bits = (args & 31) * 8 + 1; - return compute_len_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -int exec_push_slice_r2(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 7; - unsigned data_bits = (args & 127) * 8 + 6; - return exec_push_slice_common(st, cs, data_bits, refs, pfx_bits); -} - -std::string dump_push_slice_r2(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 7; - unsigned data_bits = (args & 127) * 8 + 6; - return dump_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -int compute_len_push_slice_r2(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 7; - unsigned data_bits = (args & 127) * 8 + 6; - return compute_len_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -int exec_push_cont(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 3; - unsigned data_bits = (args & 127) * 8; - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a PUSHCONT instruction"}; - } - if (!cs.have_refs(refs)) { - throw VmError{Excno::inv_opcode, "not enough references for a PUSHCONT instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits, refs); - - VM_LOG(st) << "execute PUSHCONT " << slice; - - stack.push_cont(Ref{true, std::move(slice), st->get_cp()}); - return 0; -} - -std::string dump_push_cont(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 3; - unsigned data_bits = (args & 127) * 8; - if (!cs.have(pfx_bits + data_bits) || !cs.have_refs(refs)) { - return ""; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits, refs); - std::ostringstream os{"PUSHCONT "}; - slice->dump_hex(os, 1, false); - return os.str(); -} - -int compute_len_push_cont(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 7) & 3; - unsigned data_bits = (args & 127) * 8; - return compute_len_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -int exec_push_cont_simple(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned data_bits = (args & 15) * 8; - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a PUSHCONT instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits); - VM_LOG(st) << "execute PUSHCONT " << slice; - stack.push_cont(Ref{true, std::move(slice), st->get_cp()}); - return 0; -} - -std::string dump_push_cont_simple(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned data_bits = (args & 15) * 8; - if (!cs.have(pfx_bits + data_bits)) { - return ""; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits); - std::ostringstream os{"PUSHCONT "}; - slice->dump_hex(os, 1, false); - return os.str(); -} - -int compute_len_push_cont_simple(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned data_bits = (args & 15) * 8; - return compute_len_push_slice_common(cs, data_bits, 0, pfx_bits); -} - -void register_cell_const_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkext(0x88, 8, 0, std::bind(dump_push_ref, _1, _2, _3, "PUSHREF"), - std::bind(exec_push_ref, _1, _2, 0, _4), compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0x89, 8, 0, std::bind(dump_push_ref, _1, _2, _3, "PUSHREFSLICE"), - std::bind(exec_push_ref, _1, _2, 1, _4), compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0x8a, 8, 0, std::bind(dump_push_ref, _1, _2, _3, "PUSHREFCONT"), - std::bind(exec_push_ref, _1, _2, 2, _4), compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0x8b, 8, 4, dump_push_slice, exec_push_slice, compute_len_push_slice)) - .insert(OpcodeInstr::mkext(0x8c, 8, 7, dump_push_slice_r, exec_push_slice_r, compute_len_push_slice_r)) - .insert(OpcodeInstr::mkextrange((0x8d * 8) << 7, (0x8d * 8 + 5) << 7, 18, 10, dump_push_slice_r2, - exec_push_slice_r2, compute_len_push_slice_r2)) - .insert(OpcodeInstr::mkext(0x8e / 2, 7, 9, dump_push_cont, exec_push_cont, compute_len_push_cont)) - .insert(OpcodeInstr::mkext(9, 4, 4, dump_push_cont_simple, exec_push_cont_simple, compute_len_push_cont_simple)); -} - -int exec_un_cs_cmp(VmState* st, const char* name, const std::function)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1); - stack.push_smallint(func(stack.pop_cellslice()) ? -1 : 0); - return 0; -} - -int exec_iun_cs_cmp(VmState* st, const char* name, const std::function)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1); - stack.push_smallint(func(stack.pop_cellslice())); - return 0; -} - -int exec_bin_cs_cmp(VmState* st, const char* name, const std::function, Ref)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - auto cs2 = stack.pop_cellslice(); - auto cs1 = stack.pop_cellslice(); - stack.push_smallint(func(cs1, cs2) ? -1 : 0); - return 0; -} - -int exec_ibin_cs_cmp(VmState* st, const char* name, const std::function, Ref)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - auto cs2 = stack.pop_cellslice(); - auto cs1 = stack.pop_cellslice(); - stack.push_smallint(func(cs1, cs2)); - return 0; -} - -namespace { - -using namespace std::placeholders; - -void reg_un_cs_cmp(OpcodeTable& cp, unsigned code, unsigned len, const char* name, - std::function)> func) { - cp.insert(OpcodeInstr::mksimple(code, len, name, std::bind(exec_un_cs_cmp, _1, name, std::move(func)))); -} - -void reg_iun_cs_cmp(OpcodeTable& cp, unsigned code, unsigned len, const char* name, - std::function)> func) { - cp.insert(OpcodeInstr::mksimple(code, len, name, std::bind(exec_iun_cs_cmp, _1, name, std::move(func)))); -} - -void reg_bin_cs_cmp(OpcodeTable& cp, unsigned code, unsigned len, const char* name, - std::function, Ref)> func) { - cp.insert(OpcodeInstr::mksimple(code, len, name, std::bind(exec_bin_cs_cmp, _1, name, std::move(func)))); -} - -void reg_ibin_cs_cmp(OpcodeTable& cp, unsigned code, unsigned len, const char* name, - std::function, Ref)> func) { - cp.insert(OpcodeInstr::mksimple(code, len, name, std::bind(exec_ibin_cs_cmp, _1, name, std::move(func)))); -} - -} // namespace - -void register_cell_cmp_ops(OpcodeTable& cp0) { - reg_un_cs_cmp(cp0, 0xc700, 16, "SEMPTY", [](auto cs) { return cs->empty() && !cs->size_refs(); }); - reg_un_cs_cmp(cp0, 0xc701, 16, "SDEMPTY", [](auto cs) { return cs->empty(); }); - reg_un_cs_cmp(cp0, 0xc702, 16, "SREMPTY", [](auto cs) { return !cs->size_refs(); }); - reg_un_cs_cmp(cp0, 0xc703, 16, "SDFIRST", [](auto cs) { return cs->prefetch_long(1) == -1; }); - reg_ibin_cs_cmp(cp0, 0xc704, 16, "SDLEXCMP", [](auto cs1, auto cs2) { return cs1->lex_cmp(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc705, 16, "SDEQ", [](auto cs1, auto cs2) { return !cs1->lex_cmp(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc708, 16, "SDPFX", [](auto cs1, auto cs2) { return cs1->is_prefix_of(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc709, 16, "SDPFXREV", [](auto cs1, auto cs2) { return cs2->is_prefix_of(*cs1); }); - reg_bin_cs_cmp(cp0, 0xc70a, 16, "SDPPFX", [](auto cs1, auto cs2) { return cs1->is_proper_prefix_of(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc70b, 16, "SDPPFXREV", [](auto cs1, auto cs2) { return cs2->is_proper_prefix_of(*cs1); }); - reg_bin_cs_cmp(cp0, 0xc70c, 16, "SDSFX", [](auto cs1, auto cs2) { return cs1->is_suffix_of(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc70d, 16, "SDSFXREV", [](auto cs1, auto cs2) { return cs2->is_suffix_of(*cs1); }); - reg_bin_cs_cmp(cp0, 0xc70e, 16, "SDPSFX", [](auto cs1, auto cs2) { return cs1->is_proper_suffix_of(*cs2); }); - reg_bin_cs_cmp(cp0, 0xc70f, 16, "SDPSFXREV", [](auto cs1, auto cs2) { return cs2->is_proper_suffix_of(*cs1); }); - reg_iun_cs_cmp(cp0, 0xc710, 16, "SDCNTLEAD0", [](auto cs) { return cs->count_leading(0); }); - reg_iun_cs_cmp(cp0, 0xc711, 16, "SDCNTLEAD1", [](auto cs) { return cs->count_leading(1); }); - reg_iun_cs_cmp(cp0, 0xc712, 16, "SDCNTTRAIL0", [](auto cs) { return cs->count_trailing(0); }); - reg_iun_cs_cmp(cp0, 0xc713, 16, "SDCNTTRAIL1", [](auto cs) { return cs->count_trailing(1); }); -} - -int exec_new_builder(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NEWC"; - stack.push_builder(Ref{true}); - return 0; -} - -int exec_builder_to_cell(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ENDC"; - stack.check_underflow(1); - stack.push_cell(stack.pop_builder()->finalize_copy()); - return 0; -} - -int exec_builder_to_special_cell(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ENDXC"; - stack.check_underflow(2); - bool special = stack.pop_bool(); - stack.push_cell(stack.pop_builder()->finalize_copy(special)); - return 0; -} - -inline void check_space(const CellBuilder& builder, unsigned bits, unsigned refs = 0) { - if (!builder.can_extend_by(bits, refs)) { - throw VmError{Excno::cell_ov}; - } -} - -int store_int_common_fail(int code, Stack& stack, Ref builder, td::RefInt256 x, unsigned args) { - if (!(args & 2)) { - stack.push_int_quiet(std::move(x), true); - stack.push_builder(std::move(builder)); - } else { - stack.push_builder(std::move(builder)); - stack.push_int_quiet(std::move(x), true); - } - stack.push_smallint(code); - return 0; -} - -int exec_store_int_common(Stack& stack, unsigned bits, unsigned args) { - bool sgnd = !(args & 1); - Ref builder; - td::RefInt256 x; - if (!(args & 2)) { - builder = stack.pop_builder(); - x = stack.pop_int(); - } else { - x = stack.pop_int(); - builder = stack.pop_builder(); - } - if (!builder->can_extend_by(bits)) { - if (args & 4) { - return store_int_common_fail(-1, stack, std::move(builder), std::move(x), args); - } - throw VmError{Excno::cell_ov}; - } - if (!x->fits_bits(bits, sgnd)) { - if (args & 4) { - return store_int_common_fail(1, stack, std::move(builder), std::move(x), args); - } - throw VmError{Excno::range_chk}; - } - builder.write().store_int256(*x, bits, sgnd); - stack.push_builder(std::move(builder)); - if (args & 4) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_int(VmState* st, unsigned args, bool sgnd) { - unsigned bits = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ST" << (sgnd ? 'I' : 'U') << ' ' << bits; - stack.check_underflow(2); - return exec_store_int_common(stack, bits, !sgnd); -} - -int exec_store_ref(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STREF" << (quiet ? "Q\n" : "\n"); - stack.check_underflow(2); - auto builder = stack.pop_builder(); - auto cell = stack.pop_cell(); - if (!builder->can_extend_by(0, 1)) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_cell(std::move(cell)); - stack.push_builder(std::move(builder)); - stack.push_smallint(-1); - return 0; - } - builder.write().store_ref(std::move(cell)); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_ref_rev(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STREFR" << (quiet ? "Q\n" : "\n"); - stack.check_underflow(2); - auto cell = stack.pop_cell(); - auto builder = stack.pop_builder(); - if (!builder->can_extend_by(0, 1)) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(builder)); - stack.push_cell(std::move(cell)); - stack.push_smallint(-1); - return 0; - } - builder.write().store_ref(std::move(cell)); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_builder_as_ref(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STBREF\n"; - stack.check_underflow(2); - auto builder = stack.pop_builder(); - auto builder2 = stack.pop_builder(); - if (!builder->can_extend_by(0, 1)) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(builder2)); - stack.push_builder(std::move(builder)); - stack.push_smallint(-1); - return 0; - } - builder.write().store_ref(builder2->finalize_copy()); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_builder_as_ref_rev(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STBREFR\n"; - stack.check_underflow(2); - auto builder2 = stack.pop_builder(); - auto builder = stack.pop_builder(); - if (!builder->can_extend_by(0, 1)) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(builder)); - stack.push_builder(std::move(builder2)); - stack.push_smallint(-1); - return 0; - } - builder.write().store_ref(builder2->finalize_copy()); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_slice(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STSLICE\n"; - stack.check_underflow(2); - auto builder = stack.pop_builder(); - auto cs = stack.pop_cellslice(); - if (!builder->can_extend_by(cs->size(), cs->size_refs())) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_cellslice(std::move(cs)); - stack.push_builder(std::move(builder)); - stack.push_smallint(-1); - return 0; - } - cell_builder_add_slice(builder.write(), *cs); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_slice_rev(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STSLICER\n"; - stack.check_underflow(2); - auto cs = stack.pop_cellslice(); - auto builder = stack.pop_builder(); - if (!builder->can_extend_by(cs->size(), cs->size_refs())) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(builder)); - stack.push_cellslice(std::move(cs)); - stack.push_smallint(-1); - return 0; - } - cell_builder_add_slice(builder.write(), *cs); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_builder(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STB\n"; - stack.check_underflow(2); - auto builder = stack.pop_builder(); - auto cb2 = stack.pop_builder(); - if (!builder->can_extend_by(cb2->size(), cb2->size_refs())) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(cb2)); - stack.push_builder(std::move(builder)); - stack.push_smallint(-1); - return 0; - } - builder.write().append_builder(std::move(cb2)); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_builder_rev(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STBR\n"; - stack.check_underflow(2); - auto cb2 = stack.pop_builder(); - auto builder = stack.pop_builder(); - if (!builder->can_extend_by(cb2->size(), cb2->size_refs())) { - if (!quiet) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(builder)); - stack.push_builder(std::move(cb2)); - stack.push_smallint(-1); - return 0; - } - builder.write().append_builder(std::move(cb2)); - stack.push_builder(std::move(builder)); - if (quiet) { - stack.push_smallint(0); - } - return 0; -} - -int exec_store_int_var(VmState* st, unsigned args) { - bool sgnd = !(args & 1); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ST" << (sgnd ? 'I' : 'U') << 'X' << ((args & 2) ? "R" : "") << ((args & 4) ? "Q\n" : "\n"); - stack.check_underflow(3); - unsigned bits = stack.pop_smallint_range(256 + sgnd); - return exec_store_int_common(stack, bits, args); -} - -std::string dump_store_int_var(CellSlice& cs, unsigned args) { - bool sgnd = !(args & 1); - std::string s = "ST"; - s += sgnd ? 'I' : 'U'; - s += 'X'; - if (args & 2) { - s += 'R'; - } - if (args & 4) { - s += 'Q'; - } - return s; -} - -int exec_store_int_fixed(VmState* st, unsigned args) { - unsigned bits = (args & 0xff) + 1; - args >>= 8; - bool sgnd = !(args & 1); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ST" << (sgnd ? 'I' : 'U') << ((args & 2) ? "R" : "") << ((args & 4) ? "Q " : " ") << bits; - stack.check_underflow(2); - return exec_store_int_common(stack, bits, args); -} - -std::string dump_store_int_fixed(CellSlice& cs, unsigned args) { - unsigned bits = (args & 0xff) + 1; - bool sgnd = !(args & 0x100); - std::ostringstream s{"ST"}; - s << (sgnd ? 'I' : 'U'); - if (args & 0x200) { - s << 'R'; - } - if (args & 0x400) { - s << 'Q'; - } - s << ' ' << bits; - return s.str(); -} - -int exec_store_const_ref(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args & 1) + 1; - if (!cs.have_refs(refs)) { - throw VmError{Excno::inv_opcode, "no references left for a STREFCONST instruction"}; - } - cs.advance(pfx_bits); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STREF" << refs << "CONST\n"; - stack.check_underflow(1); - auto builder = stack.pop_builder(); - check_space(*builder, 0, refs); - do { - builder.write().store_ref(cs.fetch_ref()); - } while (--refs > 0); - stack.push_builder(std::move(builder)); - return 0; -} - -std::string dump_store_const_ref(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args & 1) + 1; - if (!cs.have_refs(refs)) { - return ""; - } - cs.advance(pfx_bits); - cs.advance_refs(refs); - return refs > 1 ? (std::string{"STREF"} + (char)('0' + refs) + "CONST") : "STREFCONST"; -} - -int compute_len_store_const_ref(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args & 1) + 1; - return cs.have_refs(refs) ? ((refs << 16) + pfx_bits) : 0; -} - -int exec_store_le_int(VmState* st, unsigned args) { - unsigned bits = (args & 2) ? 64 : 32; - bool sgnd = !(args & 1); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ST" << (sgnd ? 'I' : 'U') << "LE" << bits / 8; - stack.check_underflow(2); - auto builder = stack.pop_builder(); - auto x = stack.pop_int(); - check_space(*builder, bits); - if (!(sgnd ? x->signed_fits_bits(bits) : x->unsigned_fits_bits(bits))) { - throw VmError{Excno::range_chk}; - } - unsigned char buff[8]; - st->ensure_throw(x->export_bytes_lsb(buff, bits >> 3, sgnd)); - builder.write().store_bytes(buff, bits >> 3); - stack.push_builder(std::move(builder)); - return 0; -} - -std::string dump_store_le_int(CellSlice& cs, unsigned args) { - bool sgnd = !(args & 1); - return std::string{"ST"} + (sgnd ? 'I' : 'U') + "LE" + ((args & 2) ? '8' : '4'); -} - -int exec_int_builder_func(VmState* st, std::string name, const std::function)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1); - stack.push_smallint(func(stack.pop_builder())); - return 0; -} - -int exec_2int_builder_func(VmState* st, std::string name, - const std::function(Ref)>& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1); - std::pair res = func(stack.pop_builder()); - stack.push_smallint(res.first); - stack.push_smallint(res.second); - return 0; -} - -int exec_builder_chk_bits(VmState* st, unsigned args, bool quiet) { - unsigned bits = (args & 0xff) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BCHKBITS" << (quiet ? "Q " : " ") << bits; - stack.check_underflow(1); - auto builder = stack.pop_builder(); - if (quiet) { - stack.push_smallint(builder->can_extend_by(bits) ? -1 : 0); - } else { - check_space(*builder, bits); - } - return 0; -} - -int exec_builder_chk_bits_refs(VmState* st, unsigned mode) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BCHK" << ((mode & 1) ? "BIT" : "") << ((mode & 2) ? "REFS" : "S") << ((mode & 4) ? "Q" : ""); - stack.check_underflow(1 + (mode & 1) + ((mode & 2) >> 1)); - unsigned refs = (mode & 2) ? stack.pop_smallint_range(7) : 0; - unsigned bits = (mode & 1) ? stack.pop_smallint_range(1023) : 0; - auto builder = stack.pop_builder(); - if (mode & 4) { - stack.push_smallint(builder->can_extend_by(bits, refs) ? -1 : 0); - } else { - check_space(*builder, bits, refs); - } - return 0; -} - -int exec_store_same(VmState* st, const char* name, int val) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2 + (val < 0)); - if (val < 0) { - val = stack.pop_smallint_range(1); - } - unsigned bits = stack.pop_smallint_range(1023); - auto builder = stack.pop_builder(); - check_space(*builder, bits); - builder.write().reserve_slice(bits) = (bool)val; - stack.push_builder(std::move(builder)); - return 0; -} - -int exec_store_const_slice(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 3) & 3; - unsigned data_bits = (args & 7) * 8 + 2; - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a STSLICECONST instruction"}; - } - if (!cs.have_refs(refs)) { - throw VmError{Excno::inv_opcode, "not enough references for a STSLICECONST instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits, refs); - slice.unique_write().remove_trailing(); - VM_LOG(st) << "execute STSLICECONST " << slice; - auto builder = stack.pop_builder(); - check_space(*builder, slice->size(), slice->size_refs()); - cell_builder_add_slice(builder.write(), *slice); - stack.push_builder(std::move(builder)); - return 0; -} - -std::string dump_store_const_slice(CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 3) & 3; - unsigned data_bits = (args & 7) * 8 + 2; - return dump_push_slice_common(cs, data_bits, refs, pfx_bits, "STSLICECONST "); -} - -int compute_len_store_const_slice(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned refs = (args >> 3) & 3; - unsigned data_bits = (args & 7) * 8 + 2; - return compute_len_push_slice_common(cs, data_bits, refs, pfx_bits); -} - -void register_cell_serialize_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xc8, 8, "NEWC", exec_new_builder)) - .insert(OpcodeInstr::mksimple(0xc9, 8, "ENDC", exec_builder_to_cell)) - .insert( - OpcodeInstr::mkfixed(0xca, 8, 8, instr::dump_1c_l_add(1, "STI "), std::bind(exec_store_int, _1, _2, true))) - .insert( - OpcodeInstr::mkfixed(0xcb, 8, 8, instr::dump_1c_l_add(1, "STU "), std::bind(exec_store_int, _1, _2, false))) - .insert(OpcodeInstr::mksimple(0xcc, 8, "STREF", std::bind(exec_store_ref, _1, false))) - .insert(OpcodeInstr::mksimple(0xcd, 8, "ENDCST", std::bind(exec_store_builder_as_ref_rev, _1, false))) - .insert(OpcodeInstr::mksimple(0xce, 8, "STSLICE", std::bind(exec_store_slice, _1, false))) - .insert(OpcodeInstr::mkfixed(0xcf00 >> 3, 13, 3, dump_store_int_var, exec_store_int_var)) - .insert(OpcodeInstr::mkfixed(0xcf08 >> 3, 13, 11, dump_store_int_fixed, exec_store_int_fixed)) - .insert(OpcodeInstr::mksimple(0xcf10, 16, "STREF", std::bind(exec_store_ref, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf11, 16, "STBREF", std::bind(exec_store_builder_as_ref, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf12, 16, "STSLICE", std::bind(exec_store_slice, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf13, 16, "STB", std::bind(exec_store_builder, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf14, 16, "STREFR", std::bind(exec_store_ref_rev, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf15, 16, "STBREFR", std::bind(exec_store_builder_as_ref_rev, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf16, 16, "STSLICER", std::bind(exec_store_slice_rev, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf17, 16, "STBR", std::bind(exec_store_builder_rev, _1, false))) - .insert(OpcodeInstr::mksimple(0xcf18, 16, "STREFQ", std::bind(exec_store_ref, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf19, 16, "STBREFQ", std::bind(exec_store_builder_as_ref, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1a, 16, "STSLICEQ", std::bind(exec_store_slice, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1b, 16, "STBQ", std::bind(exec_store_builder, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1c, 16, "STREFRQ", std::bind(exec_store_ref_rev, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1d, 16, "STBREFRQ", std::bind(exec_store_builder_as_ref_rev, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1e, 16, "STSLICERQ", std::bind(exec_store_slice_rev, _1, true))) - .insert(OpcodeInstr::mksimple(0xcf1f, 16, "STBRQ", std::bind(exec_store_builder_rev, _1, true))) - .insert(OpcodeInstr::mkextrange(0xcf20, 0xcf22, 16, 1, dump_store_const_ref, exec_store_const_ref, - compute_len_store_const_ref)) - .insert(OpcodeInstr::mksimple(0xcf23, 16, "ENDXC", exec_builder_to_special_cell)) - .insert(OpcodeInstr::mkfixed(0xcf28 >> 2, 14, 2, dump_store_le_int, exec_store_le_int)) - .insert(OpcodeInstr::mksimple( - 0xcf30, 16, "BDEPTH", - std::bind(exec_int_builder_func, _1, "BDEPTH", [](Ref b) { return b->get_depth(); }))) - .insert(OpcodeInstr::mksimple( - 0xcf31, 16, "BBITS", - std::bind(exec_int_builder_func, _1, "BBITS", [](Ref b) { return b->size(); }))) - .insert(OpcodeInstr::mksimple( - 0xcf32, 16, "BREFS", - std::bind(exec_int_builder_func, _1, "BREFS", [](Ref b) { return b->size_refs(); }))) - .insert(OpcodeInstr::mksimple( - 0xcf33, 16, "BBITREFS", - std::bind(exec_2int_builder_func, _1, "BBITSREFS", - [](Ref b) { return std::make_pair(b->size(), b->size_refs()); }))) - .insert(OpcodeInstr::mksimple( - 0xcf35, 16, "BREMBITS", - std::bind(exec_int_builder_func, _1, "BREMBITS", [](Ref b) { return b->remaining_bits(); }))) - .insert(OpcodeInstr::mksimple( - 0xcf36, 16, "BREMREFS", - std::bind(exec_int_builder_func, _1, "BREMREFS", [](Ref b) { return b->remaining_refs(); }))) - .insert(OpcodeInstr::mksimple( - 0xcf37, 16, "BREMBITREFS", - std::bind(exec_2int_builder_func, _1, "BREMBITSREFS", - [](Ref b) { return std::make_pair(b->remaining_bits(), b->remaining_refs()); }))) - .insert(OpcodeInstr::mkfixed(0xcf38, 16, 8, instr::dump_1c_l_add(1, "BCHKBITS "), - std::bind(exec_builder_chk_bits, _1, _2, false))) - .insert(OpcodeInstr::mksimple(0xcf39, 16, "BCHKBITS", std::bind(exec_builder_chk_bits_refs, _1, 1))) - .insert(OpcodeInstr::mksimple(0xcf3a, 16, "BCHKREFS", std::bind(exec_builder_chk_bits_refs, _1, 2))) - .insert(OpcodeInstr::mksimple(0xcf3b, 16, "BCHKBITREFS", std::bind(exec_builder_chk_bits_refs, _1, 3))) - .insert(OpcodeInstr::mkfixed(0xcf3c, 16, 8, instr::dump_1c_l_add(1, "BCHKBITSQ "), - std::bind(exec_builder_chk_bits, _1, _2, true))) - .insert(OpcodeInstr::mksimple(0xcf3d, 16, "BCHKBITSQ", std::bind(exec_builder_chk_bits_refs, _1, 5))) - .insert(OpcodeInstr::mksimple(0xcf3e, 16, "BCHKREFSQ", std::bind(exec_builder_chk_bits_refs, _1, 6))) - .insert(OpcodeInstr::mksimple(0xcf3f, 16, "BCHKBITREFSQ", std::bind(exec_builder_chk_bits_refs, _1, 7))) - .insert(OpcodeInstr::mksimple(0xcf40, 16, "STZEROES", std::bind(exec_store_same, _1, "STZEROES", 0))) - .insert(OpcodeInstr::mksimple(0xcf41, 16, "STONES", std::bind(exec_store_same, _1, "STONES", 1))) - .insert(OpcodeInstr::mksimple(0xcf42, 16, "STSAME", std::bind(exec_store_same, _1, "STSAME", -1))) - .insert(OpcodeInstr::mkext(0xcf80 >> 7, 9, 5, dump_store_const_slice, exec_store_const_slice, - compute_len_store_const_slice)); -} - -int exec_cell_to_slice(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CTOS"; - auto cell = stack.pop_cell(); - stack.push_cellslice(load_cell_slice_ref(std::move(cell))); - return 0; -} - -int exec_cell_to_slice_maybe_special(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCTOS"; - bool is_special; - auto cell = stack.pop_cell(); - stack.push_cellslice(load_cell_slice_ref_special(std::move(cell), is_special)); - stack.push_bool(is_special); - return 0; -} - -int exec_load_special_cell(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XLOAD" << (quiet ? "Q" : ""); - auto cell = stack.pop_cell(); - stack.push_cell(cell); - if (quiet) { - stack.push_bool(true); - } - return 0; -} - -int exec_slice_chk_empty(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ENDS"; - auto cs = stack.pop_cellslice(); - if (cs->size() || cs->size_refs()) { - throw VmError{Excno::cell_und, "extra data remaining in deserialized cell"}; - } - return 0; -} - -int exec_load_int_common(Stack& stack, unsigned bits, unsigned mode) { - auto cs = stack.pop_cellslice(); - if (!cs->have(bits)) { - if (!(mode & 4)) { - throw VmError{Excno::cell_und}; - } - if (!(mode & 2)) { - stack.push_cellslice(std::move(cs)); - } - stack.push_smallint(0); - return 0; - } - bool sgnd = !(mode & 1); - if (mode & 2) { - stack.push_int(cs->prefetch_int256(bits, sgnd)); - } else { - stack.push_int(cs.write().fetch_int256(bits, sgnd)); - stack.push_cellslice(std::move(cs)); - } - if (mode & 4) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_load_int_fixed(VmState* st, unsigned args, unsigned mode) { - unsigned bits = (args & 0xff) + 1; - bool sgnd = !(mode & 1); - VM_LOG(st) << "execute " << (mode & 2 ? "P" : "") << "LD" << (sgnd ? 'I' : 'U') << (mode & 4 ? "Q " : " ") << bits; - return exec_load_int_common(st->get_stack(), bits, mode); -} - -int exec_preload_ref_fixed(VmState* st, unsigned args) { - unsigned idx = args & 3; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PLDREFIDX " << idx; - auto cs = stack.pop_cellslice(); - if (!cs->have_refs(idx + 1)) { - throw VmError{Excno::cell_und}; - } - stack.push_cell(cs->prefetch_ref(idx)); - return 0; -} - -int exec_preload_ref(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PLDREFVAR"; - stack.check_underflow(2); - unsigned idx = stack.pop_smallint_range(3); - auto cs = stack.pop_cellslice(); - if (!cs->have_refs(idx + 1)) { - throw VmError{Excno::cell_und}; - } - stack.push_cell(cs->prefetch_ref(idx)); - return 0; -} - -int exec_load_ref(VmState* st, unsigned mode) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (mode & 2 ? "P" : "") << "LDREF" << (mode & 4 ? "Q" : ""); - auto cs = stack.pop_cellslice(); - if (!cs->have_refs()) { - if (!(mode & 4)) { - throw VmError{Excno::cell_und}; - } - stack.push_smallint(0); - return 0; - } - if (mode & 2) { - stack.push_cell(cs->prefetch_ref()); - } else { - stack.push_cell(cs.write().fetch_ref()); - stack.push_cellslice(std::move(cs)); - } - if (mode & 4) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_load_ref_rev_to_slice(VmState* st, unsigned mode) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (mode & 2 ? "P" : "") << "LDREFRTOS" << (mode & 4 ? "Q" : ""); - auto cs = stack.pop_cellslice(); - if (!cs->have_refs()) { - if (!(mode & 4)) { - throw VmError{Excno::cell_und}; - } - stack.push_smallint(0); - return 0; - } - if (mode & 2) { - stack.push_cellslice(load_cell_slice_ref(cs->prefetch_ref())); - } else { - auto cell = cs.write().fetch_ref(); - stack.push_cellslice(std::move(cs)); - stack.push_cellslice(load_cell_slice_ref(std::move(cell))); - } - if (mode & 4) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_load_slice_common(Stack& stack, unsigned bits, unsigned mode) { - auto cs = stack.pop_cellslice(); - if (!cs->have(bits)) { - if (!(mode & 2)) { - throw VmError{Excno::cell_und}; - } - if (!(mode & 1)) { - stack.push_cellslice(std::move(cs)); - } - stack.push_smallint(0); - return 0; - } - if (mode & 1) { - stack.push_cellslice(cs->prefetch_subslice(bits)); - } else { - stack.push_cellslice(cs.write().fetch_subslice(bits)); - stack.push_cellslice(std::move(cs)); - } - if (mode & 2) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_load_slice_fixed(VmState* st, unsigned args) { - unsigned bits = (args & 0xff) + 1; - VM_LOG(st) << "execute LDSLICE " << bits; - return exec_load_slice_common(st->get_stack(), bits, 0); -} - -int exec_load_int_var(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (args & 2 ? "PLD" : "LD") << (args & 1 ? "UX" : "IX") << (args & 4 ? "Q\n" : "\n"); - stack.check_underflow(2); - unsigned bits = stack.pop_smallint_range(257 - (args & 1)); - return exec_load_int_common(stack, bits, args & 7); -} - -std::string dump_load_int_var(CellSlice&, unsigned args) { - return (args & 2 ? std::string{"PLD"} : std::string{"LD"}) + (args & 1 ? "UX" : "IX") + (args & 4 ? "Q" : ""); -} - -int exec_load_int_fixed2(VmState* st, unsigned args) { - unsigned bits = (args & 0xff) + 1; - args >>= 8; - VM_LOG(st) << "execute " << (args & 2 ? "PLD" : "LD") << (args & 1 ? "U" : "I") << (args & 4 ? "Q " : " ") << bits; - return exec_load_int_common(st->get_stack(), bits, args & 7); -} - -std::string dump_load_int_fixed2(CellSlice&, unsigned args) { - std::ostringstream os{args & 0x200 ? "PLD" : "LD"}; - os << (args & 0x100 ? 'U' : 'I'); - if (args & 0x400) { - os << 'Q'; - } - os << ' ' << ((args & 0xff) + 1); - return os.str(); -} - -int exec_preload_uint_fixed_0e(VmState* st, unsigned args) { - unsigned bits = ((args & 7) + 1) << 5; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PLDUZ " << bits; - auto cs = stack.pop_cellslice(); - auto x = cs->prefetch_int256_zeroext(bits, false); - stack.push_cellslice(std::move(cs)); - stack.push_int(std::move(x)); - return 0; -} - -std::string dump_preload_uint_fixed_0e(CellSlice&, unsigned args) { - std::ostringstream os{"PLDUZ "}; - unsigned bits = ((args & 7) + 1) << 5; - os << bits; - return os.str(); -} - -int exec_load_slice(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (args & 1 ? "PLDSLICEX" : "LDSLICEX") << (args & 2 ? "Q\n" : "\n"); - stack.check_underflow(2); - unsigned bits = stack.pop_smallint_range(1023); - return exec_load_slice_common(stack, bits, args); -} - -std::string dump_load_slice(CellSlice&, unsigned args) { - return std::string{args & 1 ? "P" : ""} + "LDSLICEX" + (args & 2 ? "Q" : ""); -} - -int exec_load_slice_fixed2(VmState* st, unsigned args) { - unsigned bits = (args & 0xff) + 1; - args >>= 8; - VM_LOG(st) << "execute " << (args & 1 ? "PLDSLICE" : "LDSLICE") << (args & 2 ? "Q " : " ") << bits; - return exec_load_slice_common(st->get_stack(), bits, args); -} - -std::string dump_load_slice_fixed2(CellSlice&, unsigned args) { - unsigned bits = (args & 0xff) + 1; - std::ostringstream os{args & 0x100 ? "PLDSLICE" : "LDSLICE"}; - if (args & 0x200) { - os << 'Q'; - } - os << ' ' << bits; - return os.str(); -} - -int exec_slice_op_args(VmState* st, const char* name, unsigned max_arg1, - const std::function& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - unsigned x = stack.pop_smallint_range(max_arg1); - auto cs = stack.pop_cellslice(); - if (!func(cs.write(), x)) { - throw VmError{Excno::cell_und}; - } - stack.push_cellslice(std::move(cs)); - return 0; -} - -int exec_slice_op_args2(VmState* st, const char* name, unsigned max_arg1, unsigned max_arg2, - const std::function& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(3); - unsigned y = stack.pop_smallint_range(max_arg2); - unsigned x = stack.pop_smallint_range(max_arg1); - auto cs = stack.pop_cellslice(); - if (!func(cs.write(), x, y)) { - throw VmError{Excno::cell_und}; - } - stack.push_cellslice(std::move(cs)); - return 0; -} - -int exec_slice_begins_with_common(VmState* st, Ref cs2, bool quiet) { - Stack& stack = st->get_stack(); - auto cs = stack.pop_cellslice(); - if (!cs->has_prefix(*cs2)) { - if (!quiet) { - throw VmError{Excno::cell_und, "slice does not begin with expected data bits"}; - } - stack.push_cellslice(std::move(cs)); - stack.push_smallint(0); - return 0; - } - cs.write().advance(cs2->size()); - stack.push_cellslice(std::move(cs)); - if (quiet) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_slice_begins_with(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SDBEGINSX" << (quiet ? "Q\n" : "\n"); - stack.check_underflow(2); - return exec_slice_begins_with_common(st, stack.pop_cellslice(), quiet); -} - -int exec_slice_begins_with_const(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - bool quiet = args & 128; - unsigned data_bits = (args & 127) * 8 + 3; - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a SDBEGINS instruction"}; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits); - slice.unique_write().remove_trailing(); - VM_LOG(st) << "execute SDBEGINS" << (quiet ? "Q " : " ") << slice; - return exec_slice_begins_with_common(st, slice, quiet); -} - -std::string dump_slice_begins_with_const(CellSlice& cs, unsigned args, int pfx_bits) { - bool quiet = args & 128; - unsigned data_bits = (args & 127) * 8 + 3; - return dump_push_slice_common(cs, data_bits, 0, pfx_bits, quiet ? "SDBEGINSQ " : "SDBEGINS "); -} - -int compute_len_slice_begins_with_const(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned data_bits = (args & 127) * 8 + 3; - return compute_len_push_slice_common(cs, data_bits, 0, pfx_bits); -} - -int exec_subslice(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SUBSLICE\n"; - stack.check_underflow(5); - unsigned r2 = stack.pop_smallint_range(4), l2 = stack.pop_smallint_range(1023); - unsigned r1 = stack.pop_smallint_range(4), l1 = stack.pop_smallint_range(1023); - auto cs = stack.pop_cellslice(); - if (!cs.write().skip_first(l1, r1) || !cs.unique_write().only_first(l2, r2)) { - throw VmError{Excno::cell_und}; - } - stack.push_cellslice(std::move(cs)); - return 0; -} - -int exec_split(VmState* st, bool quiet) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SPLIT" << (quiet ? "Q\n" : "\n"); - stack.check_underflow(3); - unsigned refs = stack.pop_smallint_range(4), bits = stack.pop_smallint_range(1023); - auto cs = stack.pop_cellslice(); - if (!cs->have(bits) || !cs->have_refs(refs)) { - if (!quiet) { - throw VmError{Excno::cell_und}; - } - stack.push_cellslice(std::move(cs)); - stack.push_smallint(0); - return 0; - } - auto cs2 = cs; - cs2.write().only_first(bits, refs); - cs.write().skip_first(bits, refs); - stack.push_cellslice(std::move(cs2)); - stack.push_cellslice(std::move(cs)); - if (quiet) { - stack.push_smallint(-1); - } - return 0; -} - -int exec_slice_chk_op_args(VmState* st, const char* name, unsigned max_arg1, bool quiet, - const std::function& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - unsigned x = stack.pop_smallint_range(max_arg1); - auto cs = stack.pop_cellslice(); - bool res = func(*cs, x); - if (quiet) { - stack.push_smallint(res ? -1 : 0); - } else if (!res) { - throw VmError{Excno::cell_und}; - } - return 0; -} - -int exec_slice_chk_op_args2(VmState* st, const char* name, unsigned max_arg1, unsigned max_arg2, bool quiet, - const std::function& func) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(3); - unsigned y = stack.pop_smallint_range(max_arg2); - unsigned x = stack.pop_smallint_range(max_arg1); - auto cs = stack.pop_cellslice(); - bool res = func(*cs, x, y); - if (quiet) { - stack.push_smallint(res ? -1 : 0); - } else if (!res) { - throw VmError{Excno::cell_und}; - } - return 0; -} - -int exec_slice_bits_refs(VmState* st, unsigned mode) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute S" << (mode & 1 ? "BIT" : "") << (mode & 2 ? "REF" : "") << "S\n"; - stack.check_underflow(1); - auto cs = stack.pop_cellslice(); - if (mode & 1) { - stack.push_smallint(cs->size()); - } - if (mode & 2) { - stack.push_smallint(cs->size_refs()); - } - return 0; -} - -int exec_load_le_int(VmState* st, unsigned args) { - unsigned len = (args & 2) ? 8 : 4; - bool sgnd = !(args & 1); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (args & 4 ? "PLD" : "LD") << (sgnd ? 'I' : 'U') << "LE" << len - << (args & 8 ? "Q\n" : "\n"); - stack.check_underflow(1); - auto cs = stack.pop_cellslice(); - if (!cs->have(len << 3)) { - if (args & 8) { - if (!(args & 4)) { - stack.push_cellslice(std::move(cs)); - } - stack.push_smallint(0); - return 0; - } - throw VmError{Excno::cell_und}; - } - unsigned char buff[8]; - st->ensure_throw(cs->prefetch_bytes(buff, len)); - td::RefInt256 x{true}; - st->ensure_throw(x.unique_write().import_bytes_lsb(buff, len, sgnd)); - stack.push_int(std::move(x)); - if (!(args & 4)) { - st->ensure_throw(cs.write().advance(len << 3)); - stack.push_cellslice(std::move(cs)); - } - if (args & 8) { - stack.push_smallint(-1); - } - return 0; -} - -std::string dump_load_le_int(CellSlice& cs, unsigned args) { - bool sgnd = !(args & 1); - return std::string{args & 4 ? "P" : ""} + "LD" + (sgnd ? 'I' : 'U') + "LE" + ((args & 2) ? '8' : '4') + - (args & 8 ? "Q" : ""); -} - -int exec_load_same(VmState* st, const char* name, int x) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(1 + (x < 0)); - if (x < 0) { - x = stack.pop_smallint_range(1); - } - auto cs = stack.pop_cellslice(); - unsigned n = cs->count_leading(x); - if (n > 0) { - cs.write().advance(n); - } - stack.push_smallint(n); - stack.push_cellslice(std::move(cs)); - return 0; -} - -int exec_cell_depth(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CDEPTH"; - auto cell = stack.pop_maybe_cell(); - stack.push_smallint(cell.not_null() ? cell->get_depth() : 0); - return 0; -} - -int exec_slice_depth(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SDEPTH"; - auto cs = stack.pop_cellslice(); - stack.push_smallint(cs->get_depth()); - return 0; -} - -void register_cell_deserialize_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xd0, 8, "CTOS", exec_cell_to_slice)) - .insert(OpcodeInstr::mksimple(0xd1, 8, "ENDS", exec_slice_chk_empty)) - .insert( - OpcodeInstr::mkfixed(0xd2, 8, 8, instr::dump_1c_l_add(1, "LDI "), std::bind(exec_load_int_fixed, _1, _2, 0))) - .insert( - OpcodeInstr::mkfixed(0xd3, 8, 8, instr::dump_1c_l_add(1, "LDU "), std::bind(exec_load_int_fixed, _1, _2, 1))) - .insert(OpcodeInstr::mksimple(0xd4, 8, "LDREF", std::bind(exec_load_ref, _1, 0))) - .insert(OpcodeInstr::mksimple(0xd5, 8, "LDREFRTOS", std::bind(exec_load_ref_rev_to_slice, _1, 0))) - .insert(OpcodeInstr::mkfixed(0xd6, 8, 8, instr::dump_1c_l_add(1, "LDSLICE "), exec_load_slice_fixed)) - .insert(OpcodeInstr::mkfixed(0xd700 >> 3, 13, 3, dump_load_int_var, exec_load_int_var)) - .insert(OpcodeInstr::mkfixed(0xd708 >> 3, 13, 11, dump_load_int_fixed2, exec_load_int_fixed2)) - .insert(OpcodeInstr::mkfixed(0xd710 >> 3, 13, 3, dump_preload_uint_fixed_0e, exec_preload_uint_fixed_0e)) - .insert(OpcodeInstr::mkfixed(0xd718 >> 2, 14, 2, dump_load_slice, exec_load_slice)) - .insert(OpcodeInstr::mkfixed(0xd71c >> 2, 14, 10, dump_load_slice_fixed2, exec_load_slice_fixed2)) - .insert(OpcodeInstr::mksimple(0xd720, 16, "SDCUTFIRST", - std::bind(exec_slice_op_args, _1, "SDCUTFIRST", 1023, - [](auto& cs, unsigned bits) { return cs.only_first(bits); }))) - .insert(OpcodeInstr::mksimple(0xd721, 16, "SDSKIPFIRST", - std::bind(exec_slice_op_args, _1, "SDSKIPFIRST", 1023, - [](auto& cs, unsigned bits) { return cs.skip_first(bits); }))) - .insert(OpcodeInstr::mksimple(0xd722, 16, "SDCUTLAST", - std::bind(exec_slice_op_args, _1, "SDCUTLAST", 1023, - [](auto& cs, unsigned bits) { return cs.only_last(bits); }))) - .insert(OpcodeInstr::mksimple(0xd723, 16, "SDSKIPLAST", - std::bind(exec_slice_op_args, _1, "SDSKIPLAST", 1023, - [](auto& cs, unsigned bits) { return cs.skip_last(bits); }))) - .insert(OpcodeInstr::mksimple( - 0xd724, 16, "SDSUBSTR", - std::bind(exec_slice_op_args2, _1, "SDSUBSTR", 1023, 1023, - [](auto& cs, unsigned offs, unsigned bits) { return cs.skip_first(offs) && cs.only_first(bits); }))) - .insert(OpcodeInstr::mksimple(0xd726, 16, "SDBEGINSX", std::bind(exec_slice_begins_with, _1, false))) - .insert(OpcodeInstr::mksimple(0xd727, 16, "SDBEGINSXQ", std::bind(exec_slice_begins_with, _1, true))) - .insert(OpcodeInstr::mkext(0xd728 >> 3, 13, 8, dump_slice_begins_with_const, exec_slice_begins_with_const, - compute_len_slice_begins_with_const)) - .insert(OpcodeInstr::mksimple( - 0xd730, 16, "SCUTFIRST", - std::bind(exec_slice_op_args2, _1, "SCUTFIRST", 1023, 4, - [](auto& cs, unsigned bits, unsigned refs) { return cs.only_first(bits, refs); }))) - .insert(OpcodeInstr::mksimple( - 0xd731, 16, "SSKIPFIRST", - std::bind(exec_slice_op_args2, _1, "SSKIPFIRST", 1023, 4, - [](auto& cs, unsigned bits, unsigned refs) { return cs.skip_first(bits, refs); }))) - .insert(OpcodeInstr::mksimple( - 0xd732, 16, "SCUTLAST", - std::bind(exec_slice_op_args2, _1, "SCUTLAST", 1023, 4, - [](auto& cs, unsigned bits, unsigned refs) { return cs.only_last(bits, refs); }))) - .insert(OpcodeInstr::mksimple( - 0xd733, 16, "SSKIPLAST", - std::bind(exec_slice_op_args2, _1, "SSKIPLAST", 1023, 4, - [](auto& cs, unsigned bits, unsigned refs) { return cs.skip_last(bits, refs); }))) - .insert(OpcodeInstr::mksimple(0xd734, 16, "SUBSLICE", exec_subslice)) - .insert(OpcodeInstr::mksimple(0xd736, 16, "SPLIT", std::bind(exec_split, _1, false))) - .insert(OpcodeInstr::mksimple(0xd737, 16, "SPLITQ", std::bind(exec_split, _1, true))) - .insert(OpcodeInstr::mksimple(0xd739, 16, "XCTOS", exec_cell_to_slice_maybe_special)) - .insert(OpcodeInstr::mksimple(0xd73a, 16, "XLOAD", std::bind(exec_load_special_cell, _1, false))) - .insert(OpcodeInstr::mksimple(0xd73b, 16, "XLOADQ", std::bind(exec_load_special_cell, _1, true))) - .insert(OpcodeInstr::mksimple(0xd741, 16, "SCHKBITS", - std::bind(exec_slice_chk_op_args, _1, "SCHKBITS", 1023, false, - [](auto cs, unsigned bits) { return cs.have(bits); }))) - .insert(OpcodeInstr::mksimple(0xd742, 16, "SCHKREFS", - std::bind(exec_slice_chk_op_args, _1, "SCHKREFS", 1023, false, - [](auto cs, unsigned refs) { return cs.have_refs(refs); }))) - .insert(OpcodeInstr::mksimple( - 0xd743, 16, "SCHKBITREFS", - std::bind(exec_slice_chk_op_args2, _1, "SCHKBITREFS", 1023, 4, false, - [](auto cs, unsigned bits, unsigned refs) { return cs.have(bits) && cs.have_refs(refs); }))) - .insert(OpcodeInstr::mksimple(0xd745, 16, "SCHKBITSQ", - std::bind(exec_slice_chk_op_args, _1, "SCHKBITSQ", 1023, true, - [](auto cs, unsigned bits) { return cs.have(bits); }))) - .insert(OpcodeInstr::mksimple(0xd746, 16, "SCHKREFSQ", - std::bind(exec_slice_chk_op_args, _1, "SCHKREFSQ", 1023, true, - [](auto cs, unsigned refs) { return cs.have_refs(refs); }))) - .insert(OpcodeInstr::mksimple( - 0xd747, 16, "SCHKBITREFSQ", - std::bind(exec_slice_chk_op_args2, _1, "SCHKBITREFSQ", 1023, 4, true, - [](auto cs, unsigned bits, unsigned refs) { return cs.have(bits) && cs.have_refs(refs); }))) - .insert(OpcodeInstr::mksimple(0xd748, 16, "PLDREFVAR", exec_preload_ref)) - .insert(OpcodeInstr::mksimple(0xd749, 16, "SBITS", std::bind(exec_slice_bits_refs, _1, 1))) - .insert(OpcodeInstr::mksimple(0xd74a, 16, "SREFS", std::bind(exec_slice_bits_refs, _1, 2))) - .insert(OpcodeInstr::mksimple(0xd74b, 16, "SBITREFS", std::bind(exec_slice_bits_refs, _1, 3))) - .insert(OpcodeInstr::mkfixed(0xd74c >> 2, 14, 2, instr::dump_1c_and(3, "PLDREFIDX "), exec_preload_ref_fixed)) - .insert(OpcodeInstr::mkfixed(0xd75, 12, 4, dump_load_le_int, exec_load_le_int)) - .insert(OpcodeInstr::mksimple(0xd760, 16, "LDZEROES", std::bind(exec_load_same, _1, "LDZEROES", 0))) - .insert(OpcodeInstr::mksimple(0xd761, 16, "LDONES", std::bind(exec_load_same, _1, "LDONES", 1))) - .insert(OpcodeInstr::mksimple(0xd762, 16, "LDSAME", std::bind(exec_load_same, _1, "LDSAME", -1))) - .insert(OpcodeInstr::mksimple(0xd764, 16, "SDEPTH", exec_slice_depth)) - .insert(OpcodeInstr::mksimple(0xd765, 16, "CDEPTH", exec_cell_depth)); -} - -void register_cell_ops(OpcodeTable& cp0) { - register_cell_const_ops(cp0); - register_cell_cmp_ops(cp0); - register_cell_serialize_ops(cp0); - register_cell_deserialize_ops(cp0); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cellops.h b/submodules/ton/tonlib-src/crypto/vm/cellops.h deleted file mode 100644 index 1c08d8e3..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cellops.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cellslice.h" - -namespace vm { - -class OpcodeTable; - -void register_cell_ops(OpcodeTable &cp0); - -std::string dump_push_ref(CellSlice &cs, unsigned args, int pfx_bits, std::string name); -int compute_len_push_ref(const CellSlice &cs, unsigned args, int pfx_bits); - -std::string dump_push_ref2(CellSlice &cs, unsigned args, int pfx_bits, std::string name); -int compute_len_push_ref2(const CellSlice &cs, unsigned args, int pfx_bits); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cellparse.hpp b/submodules/ton/tonlib-src/crypto/vm/cellparse.hpp deleted file mode 100644 index 5ca3d290..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cellparse.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells.h" -#include "vm/cellslice.h" - -namespace vm { - -class CellRefParser { - Ref cs; - bool state; - - public: - CellRefParser(Ref _cs) : cs(std::move(_cs)), state(cs.not_null()) { - } - bool ok() const { - return state; - } - operator bool() const { - return state; - } - template - CellRefParser& deserialize(T& val) { - state = (state && val.deserialize(cs.write())); - return *this; - } - //template - //CellRefParser& deserialize(T& val) { - // state = val.deserialize_ext(cs.write(), state); - // return *this; - //} - template - CellRefParser& deserialize(const T& val) { - state = (state && val.deserialize(cs.write())); - return *this; - } - //template - //CellRefParser& deserialize(const T& val) { - // state = val.deserialize_ext(cs.write(), state); - // return *this; - //} -}; - -class CellParser { - CellSlice& cs; - bool state; - - public: - CellParser(CellSlice& _cs) : cs(_cs), state(true) { - } - bool ok() const { - return state; - } - operator bool() const { - return state; - } - template - CellParser& deserialize(T& val) { - state = (state && val.deserialize(cs)); - return *this; - } - // template - // CellParser& deserialize(T& val) { - // state = val.deserialize_ext(cs, state); - // return *this; - // } - template - CellParser& deserialize(const T& val) { - state = (state && val.deserialize(cs)); - return *this; - } - // template - // CellParser& deserialize(const T& val) { - // state = val.deserialize_ext(cs, state); - // return *this; - // } -}; - -template -P& operator>>(P& cp, T& val) { - return cp.deserialize(val); -} - -template -P& operator>>(P& cp, const T& val) { - return cp.deserialize(val); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells.h b/submodules/ton/tonlib-src/crypto/vm/cells.h deleted file mode 100644 index cf917eff..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "vm/cells/Cell.h" -#include "vm/cells/CellBuilder.h" -#include "vm/cells/DataCell.h" -#include "vm/cells/UsageCell.h" -#include "vm/cells/VirtualCell.h" - -// H_i(cell) = H(cell_i) -// cell.hash = sha256( -// d1, d2, -// (level == 0 || special_type == PrunnedBranch) ? data : cell_(level - 1).hash, -// for child in refs: -// child.depth, child.hash -// ) -// lower hashes of Prunned branch are calculated from its data -// cell_i.ref[j] = (special_type == MerkleProof || special_type == MerkleUpdate) ? cell.ref[j]_(i+1) : cell.ref[j]_i -// -// Ordinary cell: -// cell_i.data = cell.data -// cell_i.level_mask = cell.level_mask & ((1< == cell.level + 1 -// cell_i = if i < cell.level then prunned_cell_i -// prunned_cell.data = EXCEPTION -// prunned_cell_i.hash = -// prunned_cell.level_mask = cell.level_mask ^ (1 << cell.level) -// prunned_cell.level = -// prunned_cell_i.depth = -// -// Merkle proof -// cell.level_mask = proof_cell.level_mask >> 1 -// cell.level = == max(0, proof.cell.level - 1) -// cell_i.data = -// cell_i.level_mask = -// cell_i.ref[j] = cell.ref[j]_(i+1) -// cell_i.depth = max_j(1 + cell_i.ref[j].depth) - diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/Cell.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/Cell.cpp deleted file mode 100644 index 1c20ba41..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/Cell.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/Cell.h" -#include "vm/cells/VirtualCell.h" -#include "vm/cells/DataCell.h" - -#include - -namespace vm { -td::Status Cell::check_equals_unloaded(const Ref& other) const { - auto level_mask = get_level_mask(); - if (level_mask != other->get_level_mask()) { - return td::Status::Error("level mismatch"); - } - auto level = level_mask.get_level(); - for (unsigned i = 0; i <= level; i++) { - if (!get_level_mask().is_significant(i)) { - continue; - } - if (get_hash(i) != other->get_hash(i)) { - return td::Status::Error("hash mismatch"); - } - } - for (unsigned i = 0; i <= level; i++) { - if (!get_level_mask().is_significant(i)) { - continue; - } - if (get_depth(i) != other->get_depth(i)) { - return td::Status::Error("depth mismatch"); - } - } - return td::Status::OK(); -} - -Ref Cell::virtualize(VirtualizationParameters virt) const { - return VirtualCell::create(virt, Ref(this)); -} - -std::ostream& operator<<(std::ostream& os, const Cell& c) { - return os << c.get_hash().to_hex(); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/Cell.h b/submodules/ton/tonlib-src/crypto/vm/cells/Cell.h deleted file mode 100644 index 03f73b14..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/Cell.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "common/bitstring.h" - -#include "vm/cells/CellHash.h" -#include "vm/cells/CellTraits.h" -#include "vm/cells/CellUsageTree.h" -#include "vm/cells/LevelMask.h" -#include "vm/cells/VirtualizationParameters.h" - -#include "td/utils/Status.h" - -#include - -namespace vm { -using td::Ref; -class DataCell; - -class Cell : public CellTraits { - public: - using LevelMask = detail::LevelMask; - using VirtualizationParameters = detail::VirtualizationParameters; - struct LoadedCell { - Ref data_cell; - VirtualizationParameters virt; - CellUsageTree::NodePtr tree_node; // TODO: inline_vector? - }; - - using Hash = CellHash; - static_assert(std::is_standard_layout::value, "Cell::Hash is not a standard layout type"); - static_assert(sizeof(Hash) == hash_bytes, "Cell::Hash size is not equal to hash_bytes"); - //typedef td::BitArray hash_t; - - Cell* make_copy() const final { - throw WriteError(); - } - - // load interface - virtual td::Result load_cell() const = 0; - virtual Ref virtualize(VirtualizationParameters virt) const; - virtual td::uint32 get_virtualization() const = 0; - virtual CellUsageTree::NodePtr get_tree_node() const = 0; - virtual bool is_loaded() const = 0; - - // hash and level - virtual LevelMask get_level_mask() const = 0; - - // level helper function - td::uint32 get_level() const { - return get_level_mask().get_level(); - } - - // hash helper functions - const Hash get_hash(int level = max_level) const { - return do_get_hash(level); - } - - // depth helper function - td::uint16 get_depth(int level = max_level) const { - return do_get_depth(level); - } - - td::Status check_equals_unloaded(const Ref& other) const; - - private: - virtual td::uint16 do_get_depth(td::uint32 level) const = 0; - virtual const Hash do_get_hash(td::uint32 level) const = 0; -}; - -std::ostream& operator<<(std::ostream& os, const Cell& c); -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.cpp deleted file mode 100644 index 481c2581..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellBuilder.h" - -#include "vm/cells/CellSlice.h" -#include "vm/cells/DataCell.h" - -#include "td/utils/misc.h" -#include "td/utils/format.h" - -#include "openssl/digest.hpp" - -namespace vm { - -using td::Ref; -using td::RefAny; - -/* - * - * CELL BUILDERS - * - */ - -CellBuilder::~CellBuilder() { - get_thread_safe_counter().add(-1); -} - -CellBuilder::CellBuilder() : bits(0), refs_cnt(0) { - get_thread_safe_counter().add(+1); -} - -Ref CellBuilder::finalize_copy(bool special) const { - auto* vm_state_interface = VmStateInterface::get(); - if (vm_state_interface) { - vm_state_interface->register_cell_create(); - } - auto res = DataCell::create(data, size(), td::span(refs.data(), size_refs()), special); - if (res.is_error()) { - LOG(DEBUG) << res.error(); - throw CellWriteError{}; - } - auto cell = res.move_as_ok(); - CHECK(cell.not_null()); - if (vm_state_interface) { - vm_state_interface->register_new_cell(cell); - if (cell.is_null()) { - LOG(DEBUG) << "cannot register new data cell"; - throw CellWriteError{}; - } - } - return cell; -} - -td::Result> CellBuilder::finalize_novm_nothrow(bool special) { - auto res = DataCell::create(data, size(), td::mutable_span(refs.data(), size_refs()), special); - bits = refs_cnt = 0; - return res; -} - -Ref CellBuilder::finalize_novm(bool special) { - auto res = finalize_novm_nothrow(special); - if (res.is_error()) { - LOG(DEBUG) << res.error(); - throw CellWriteError{}; - } - CHECK(res.ok().not_null()); - return res.move_as_ok(); -} - -Ref CellBuilder::finalize(bool special) { - auto* vm_state_interface = VmStateInterface::get(); - if (!vm_state_interface) { - return finalize_novm(special); - } - vm_state_interface->register_cell_create(); - auto cell = finalize_novm(special); - vm_state_interface->register_new_cell(cell); - if (cell.is_null()) { - LOG(DEBUG) << "cannot register new data cell"; - throw CellWriteError{}; - } - return cell; -} - -Ref CellBuilder::create_pruned_branch(Ref cell, td::uint32 new_level, td::uint32 virt_level) { - if (cell->is_loaded() && cell->get_level() <= virt_level && cell->get_virtualization() == 0) { - CellSlice cs(NoVm{}, cell); - if (cs.size_refs() == 0) { - return cell; - } - } - return do_create_pruned_branch(std::move(cell), new_level, virt_level); -} - -Ref CellBuilder::do_create_pruned_branch(Ref cell, td::uint32 new_level, td::uint32 virt_level) { - auto level_mask = cell->get_level_mask().apply(virt_level); - auto level = level_mask.get_level(); - if (new_level < level + 1) { - throw CellWriteError(); - } - CellBuilder cb; - cb.store_long(static_cast(Cell::SpecialType::PrunnedBranch), 8); - cb.store_long(level_mask.apply_or(Cell::LevelMask::one_level(new_level)).get_mask(), 8); - for (td::uint32 i = 0; i <= level; i++) { - if (level_mask.is_significant(i)) { - cb.store_bytes(cell->get_hash(i).as_slice()); - } - } - for (td::uint32 i = 0; i <= level; i++) { - if (level_mask.is_significant(i)) { - cb.store_long(cell->get_depth(i), 16); - } - } - return cb.finalize(true); -} - -Ref CellBuilder::create_merkle_proof(Ref cell_proof) { - CellBuilder cb; - cb.store_long(static_cast(Cell::SpecialType::MerkleProof), 8); - cb.store_bytes(cell_proof->get_hash(0).as_slice()); - cb.store_long(cell_proof->get_depth(0), Cell::depth_bytes * 8); - cb.store_ref(cell_proof); - return cb.finalize(true); -} - -Ref CellBuilder::create_merkle_update(Ref from_proof, Ref to_proof) { - CellBuilder cb; - cb.store_long(static_cast(Cell::SpecialType::MerkleUpdate), 8); - cb.store_bytes(from_proof->get_hash(0).as_slice()); - cb.store_bytes(to_proof->get_hash(0).as_slice()); - cb.store_long(from_proof->get_depth(0), Cell::depth_bytes * 8); - cb.store_long(to_proof->get_depth(0), Cell::depth_bytes * 8); - cb.store_ref(from_proof); - cb.store_ref(to_proof); - return cb.finalize(true); -} - -void CellBuilder::reset(void) { - while (refs_cnt > 0) { - refs[--refs_cnt].clear(); - } - bits = 0; -} - -CellBuilder& CellBuilder::operator=(const CellBuilder& other) { - bits = other.bits; - refs_cnt = other.refs_cnt; - refs = other.refs; - std::memcpy(data, other.data, (bits + 7) >> 3); - return *this; -} - -CellBuilder& CellBuilder::operator=(CellBuilder&& other) { - bits = other.bits; - refs_cnt = other.refs_cnt; - refs = std::move(other.refs); - other.refs_cnt = 0; - std::memcpy(data, other.data, (bits + 7) >> 3); - return *this; -} - -bool CellBuilder::can_extend_by(std::size_t new_bits, unsigned new_refs) const { - return (new_bits <= Cell::max_bits - bits && new_refs <= (unsigned)Cell::max_refs - refs_cnt); -} - -bool CellBuilder::can_extend_by(std::size_t new_bits) const { - return new_bits <= Cell::max_bits - bits; -} - -CellBuilder& CellBuilder::store_bytes(const unsigned char* str, std::size_t len) { - ensure_throw(len <= Cell::max_bytes); - return store_bits(str, len * 8); -} - -CellBuilder& CellBuilder::store_bytes(const unsigned char* str, const unsigned char* end) { - ensure_throw(end >= str && end <= str + Cell::max_bytes); - return store_bits(str, (end - str) * 8); -} - -CellBuilder& CellBuilder::store_bytes(const char* str, std::size_t len) { - return store_bytes((const unsigned char*)(str), len); -} - -CellBuilder& CellBuilder::store_bytes(const char* str, const char* end) { - return store_bytes((const unsigned char*)(str), (const unsigned char*)(end)); -} - -CellBuilder& CellBuilder::store_bytes(td::Slice s) { - return store_bytes((const unsigned char*)(s.data()), (const unsigned char*)(s.data() + s.size())); -} - -bool CellBuilder::store_bytes_bool(const unsigned char* str, std::size_t len) { - return len <= Cell::max_bytes && store_bits_bool(str, len * 8); -} - -bool CellBuilder::store_bytes_bool(const char* str, std::size_t len) { - return len <= Cell::max_bytes && store_bits_bool((const unsigned char*)str, len * 8); -} - -bool CellBuilder::store_bytes_bool(td::Slice s) { - return store_bytes_bool((const unsigned char*)s.data(), s.size()); -} - -bool CellBuilder::store_bits_bool(const unsigned char* str, std::size_t bit_count, int bit_offset) { - unsigned pos = bits; - if (!prepare_reserve(bit_count)) { - return false; - } - td::bitstring::bits_memcpy(data, pos, str, bit_offset, bit_count); - return true; -} - -CellBuilder& CellBuilder::store_bits(const unsigned char* str, std::size_t bit_count, int bit_offset) { - unsigned pos = bits; - ensure_throw(prepare_reserve(bit_count)); - td::bitstring::bits_memcpy(data, pos, str, bit_offset, bit_count); - return *this; -} - -CellBuilder& CellBuilder::store_bits(const td::BitSlice& bs) { - return store_bits(bs.get_ptr(), bs.size(), bs.get_offs()); -} - -CellBuilder& CellBuilder::store_bits(const char* str, std::size_t bit_count, int bit_offset) { - return store_bits((const unsigned char*)str, bit_count, bit_offset); -} - -CellBuilder& CellBuilder::store_bits(td::ConstBitPtr bs, std::size_t bit_count) { - return store_bits(bs.ptr, bit_count, bs.offs); -} - -bool CellBuilder::store_bits_bool(td::ConstBitPtr bs, std::size_t bit_count) { - return store_bits_bool(bs.ptr, bit_count, bs.offs); -} - -CellBuilder& CellBuilder::store_bits_same(std::size_t bit_count, bool val) { - unsigned pos = bits; - if (prepare_reserve(bit_count)) { - td::bitstring::bits_memset(data, pos, val, bit_count); - } - return *this; -} - -bool CellBuilder::store_bits_same_bool(std::size_t bit_count, bool val) { - unsigned pos = bits; - if (!prepare_reserve(bit_count)) { - return false; - } - td::bitstring::bits_memset(data, pos, val, bit_count); - return true; -} - -inline bool CellBuilder::prepare_reserve(std::size_t bit_count) { - if (!can_extend_by(bit_count)) { - return false; - } else { - bits += (unsigned)bit_count; - return true; - } -} - -td::BitSliceWrite CellBuilder::reserve_slice(std::size_t bit_count) { - unsigned offs = bits; - if (prepare_reserve(bit_count)) { - return td::BitSliceWrite{Ref{this}, data, offs, (unsigned)bit_count}; - } else { - return td::BitSliceWrite{}; - } -} - -CellBuilder& CellBuilder::reserve_slice(std::size_t bit_count, td::BitSliceWrite& bsw) { - unsigned offs = bits; - if (prepare_reserve(bit_count)) { - bsw.assign(Ref{this}, data, offs, (unsigned)bit_count); - } else { - bsw.forget(); - } - return *this; -} - -bool CellBuilder::store_bool_bool(bool val) { - if (can_extend_by_fast(1)) { - store_long(val, 1); - return true; - } else { - return false; - } -} - -bool CellBuilder::store_long_bool(long long val, unsigned val_bits) { - if (val_bits > 64 || !can_extend_by(val_bits)) { - return false; - } - store_long(val, val_bits); - return true; -} - -bool CellBuilder::store_long_rchk_bool(long long val, unsigned val_bits) { - if (val_bits > 64 || !can_extend_by(val_bits)) { - return false; - } - if (val_bits < 64 && (val < static_cast(std::numeric_limits::max() << (val_bits - 1)) || - val >= (1LL << (val_bits - 1)))) { - return false; - } - store_long(val, val_bits); - return true; -} - -bool CellBuilder::store_ulong_rchk_bool(unsigned long long val, unsigned val_bits) { - if (val_bits > 64 || !can_extend_by(val_bits)) { - return false; - } - if (val_bits < 64 && val >= (1ULL << val_bits)) { - return false; - } - store_long(val, val_bits); - return true; -} - -CellBuilder& CellBuilder::store_long(long long val, unsigned val_bits) { - return store_long_top(val << (64 - val_bits), val_bits); -} - -CellBuilder& CellBuilder::store_long_top(unsigned long long val, unsigned top_bits) { - unsigned pos = bits; - auto reserve_ok = prepare_reserve(top_bits); - ensure_throw(reserve_ok); - td::bitstring::bits_store_long_top(data, pos, val, top_bits); - return *this; -} - -bool CellBuilder::store_uint_less(unsigned upper_bound, unsigned long long val) { - return val < upper_bound && store_long_bool(val, 32 - td::count_leading_zeroes32(upper_bound - 1)); -} - -bool CellBuilder::store_uint_leq(unsigned upper_bound, unsigned long long val) { - return val <= upper_bound && store_long_bool(val, 32 - td::count_leading_zeroes32(upper_bound)); -} - -bool CellBuilder::store_int256_bool(const td::BigInt256& val, unsigned val_bits, bool sgnd) { - unsigned pos = bits; - if (!prepare_reserve(val_bits)) { - return false; - } - if (val.export_bits(data, pos, val_bits, sgnd)) { - return true; - } else { - bits = pos; - return false; - } -} - -CellBuilder& CellBuilder::store_int256(const td::BigInt256& val, unsigned val_bits, bool sgnd) { - return ensure_pass(store_int256_bool(val, val_bits, sgnd)); -} - -bool CellBuilder::store_int256_bool(td::RefInt256 val, unsigned val_bits, bool sgnd) { - return val.not_null() && store_int256_bool(*val, val_bits, sgnd); -} - -bool CellBuilder::store_builder_ref_bool(vm::CellBuilder&& cb) { - return store_ref_bool(cb.finalize()); -} - -bool CellBuilder::store_ref_bool(Ref ref) { - if (refs_cnt < Cell::max_refs && ref.not_null()) { - refs[refs_cnt++] = std::move(ref); - return true; - } else { - return false; - } -} - -CellBuilder& CellBuilder::store_ref(Ref ref) { - return ensure_pass(store_ref_bool(std::move(ref))); -} - -td::uint16 CellBuilder::get_depth() const { - int d = 0; - for (unsigned i = 0; i < refs_cnt; i++) { - d = std::max(d, 1 + refs[i]->get_depth()); - } - return static_cast(d); -} - -bool CellBuilder::append_data_cell_bool(const DataCell& cell) { - unsigned len = cell.size(); - if (can_extend_by(len, cell.size_refs())) { - unsigned pos = bits; - ensure_throw(prepare_reserve(len)); - td::bitstring::bits_memcpy(data, pos, cell.get_data(), 0, len); - for (unsigned i = 0; i < cell.size_refs(); i++) { - refs[refs_cnt++] = cell.get_ref(i); - } - return true; - } else { - return false; - } -} - -CellBuilder& CellBuilder::append_data_cell(const DataCell& cell) { - return ensure_pass(append_data_cell_bool(cell)); -} - -bool CellBuilder::append_data_cell_bool(Ref cell_ref) { - return append_data_cell_bool(*cell_ref); -} - -CellBuilder& CellBuilder::append_data_cell(Ref cell_ref) { - return ensure_pass(append_data_cell_bool(std::move(cell_ref))); -} - -bool CellBuilder::append_builder_bool(const CellBuilder& cb) { - unsigned len = cb.size(); - if (can_extend_by(len, cb.size_refs())) { - unsigned pos = bits; - ensure_throw(prepare_reserve(len)); - td::bitstring::bits_memcpy(data, pos, cb.get_data(), 0, len); - for (unsigned i = 0; i < cb.size_refs(); i++) { - refs[refs_cnt++] = cb.get_ref(i); - } - return true; - } else { - return false; - } -} - -CellBuilder& CellBuilder::append_builder(const CellBuilder& cb) { - return ensure_pass(append_builder_bool(cb)); -} - -bool CellBuilder::append_builder_bool(Ref cb_ref) { - return append_builder_bool(*cb_ref); -} - -CellBuilder& CellBuilder::append_builder(Ref cb_ref) { - return ensure_pass(append_builder_bool(std::move(cb_ref))); -} - -bool CellBuilder::append_cellslice_bool(const CellSlice& cs) { - unsigned len = cs.size(); - if (can_extend_by(len, cs.size_refs())) { - int pos = bits; - ensure_throw(prepare_reserve(len)); - td::bitstring::bits_memcpy(td::BitPtr{data, pos}, cs.data_bits(), len); - for (unsigned i = 0; i < cs.size_refs(); i++) { - refs[refs_cnt++] = cs.prefetch_ref(i); - } - return true; - } else { - return false; - } -} - -CellBuilder& CellBuilder::append_cellslice(const CellSlice& cs) { - return ensure_pass(append_cellslice_bool(cs)); -} - -bool CellBuilder::append_cellslice_bool(Ref cs_ref) { - return cs_ref.not_null() && append_cellslice_bool(*cs_ref); -} - -CellBuilder& CellBuilder::append_cellslice(Ref cs) { - return ensure_pass(append_cellslice_bool(cs)); -} - -bool CellBuilder::append_cellslice_chk(const CellSlice& cs, unsigned size_ext) { - return cs.size_ext() == size_ext && append_cellslice_bool(cs); -} - -bool CellBuilder::append_cellslice_chk(Ref cs_ref, unsigned size_ext) { - return cs_ref.not_null() && append_cellslice_chk(*cs_ref, size_ext); -} - -CellSlice CellSlice::clone() const { - CellBuilder cb; - Ref cell; - if (cb.append_cellslice_bool(*this) && cb.finalize_to(cell)) { - return CellSlice{NoVmOrd(), std::move(cell)}; - } else { - return {}; - } -} - -bool CellBuilder::append_bitstring(const td::BitString& bs) { - return store_bits_bool(bs.cbits(), bs.size()); -} - -bool CellBuilder::append_bitstring(Ref bs_ref) { - return bs_ref.not_null() && append_bitstring(*bs_ref); -} - -bool CellBuilder::append_bitstring_chk(const td::BitString& bs, unsigned size) { - return bs.size() == size && store_bits_bool(bs.cbits(), size); -} - -bool CellBuilder::append_bitstring_chk(Ref bs_ref, unsigned size) { - return bs_ref.not_null() && append_bitstring_chk(*bs_ref, size); -} - -bool CellBuilder::append_bitslice(const td::BitSlice& bs) { - return store_bits_bool(bs.bits(), bs.size()); -} - -bool CellBuilder::store_maybe_ref(Ref cell) { - if (cell.is_null()) { - return store_long_bool(0, 1); - } else { - return store_long_bool(1, 1) && store_ref_bool(std::move(cell)); - } -} - -void CellBuilder::flush(unsigned char d[2]) const { - assert(refs_cnt <= Cell::max_refs && bits <= Cell::max_bits); - - unsigned l = (bits >> 3); - if (bits & 7) { - int m = (0x80 >> (bits & 7)); - data[l] = static_cast((data[l] & -m) | m); - d[1] = static_cast(2 * l + 1); - } else { - d[1] = static_cast(2 * l); - } - d[0] = static_cast(refs_cnt); -} - -const unsigned char* CellBuilder::compute_hash(unsigned char buffer[Cell::hash_bytes]) const { - unsigned char tmp[2]; - flush(tmp); - digest::SHA256 hasher(tmp, 2); - hasher.feed(data, (bits + 7) >> 3); - for (unsigned i = 0; i < refs_cnt; i++) { - hasher.feed(refs[i]->get_hash().as_slice().data(), Cell::hash_bytes); - } - auto extracted_size = hasher.extract(buffer); - DCHECK(extracted_size == Cell::hash_bytes); - return buffer; -} - -int CellBuilder::serialize(unsigned char* buff, int buff_size) const { - int len = get_serialized_size(); - if (len > buff_size) { - return 0; - } - flush(buff); - std::memcpy(buff + 2, data, len - 2); - return len; -} - -CellBuilder* CellBuilder::make_copy() const { - CellBuilder* c = new CellBuilder(); - c->bits = bits; - std::memcpy(c->data, data, (bits + 7) >> 3); - c->refs_cnt = refs_cnt; - for (unsigned i = 0; i < refs_cnt; i++) { - c->refs[i] = refs[i]; - } - return c; -} - -CellSlice CellBuilder::as_cellslice() const& { - return CellSlice{finalize_copy()}; -} - -Ref CellBuilder::as_cellslice_ref() const& { - return Ref{true, finalize_copy()}; -} - -CellSlice CellBuilder::as_cellslice() && { - return CellSlice{finalize()}; -} - -Ref CellBuilder::as_cellslice_ref() && { - return Ref{true, finalize()}; -} - -bool CellBuilder::contents_equal(const CellSlice& cs) const { - if (size() != cs.size() || size_refs() != cs.size_refs()) { - return false; - } - if (td::bitstring::bits_memcmp(data_bits(), cs.data_bits(), size())) { - return false; - } - for (unsigned i = 0; i < size_refs(); i++) { - if (refs[i]->get_hash() != cs.prefetch_ref(i)->get_hash()) { - return false; - } - } - return true; -} - -std::string CellBuilder::serialize() const { - unsigned char buff[Cell::max_serialized_bytes]; - int len = serialize(buff, sizeof(buff)); - return std::string(buff, buff + len); -} - -std::string CellBuilder::to_hex() const { - unsigned char buff[Cell::max_serialized_bytes]; - int len = serialize(buff, sizeof(buff)); - char hex_buff[Cell::max_serialized_bytes * 2 + 1]; - for (int i = 0; i < len; i++) { - sprintf(hex_buff + 2 * i, "%02x", buff[i]); - } - return hex_buff; -} - -std::ostream& operator<<(std::ostream& os, const CellBuilder& cb) { - return os << cb.to_hex(); -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.h deleted file mode 100644 index 954a1ac0..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellBuilder.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/DataCell.h" -#include "vm/cells/VirtualCell.h" -#include "vm/vmstate.h" -#include "common/refint.h" - -#include "td/utils/ThreadSafeCounter.h" - -namespace vm { - -class CellSlice; -class DataCell; - -class CellBuilder : public td::CntObject { - public: - struct CellWriteError {}; - struct CellCreateError {}; - - private: - unsigned bits; - unsigned refs_cnt; - std::array, Cell::max_refs> refs; - mutable unsigned char data[Cell::max_bytes]; - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("CellBuilder"); - return res; - } - - public: - CellBuilder(); - virtual ~CellBuilder() override; - - static Ref create_pruned_branch(Ref cell, td::uint32 new_level, td::uint32 virt_level = Cell::max_level); - static Ref do_create_pruned_branch(Ref cell, td::uint32 new_level, - td::uint32 virt_level = Cell::max_level); - static Ref create_merkle_proof(Ref cell_proof); - static Ref create_merkle_update(Ref from_proof, Ref to_proof); - - unsigned get_refs_cnt() const { - return refs_cnt; - } - unsigned get_bits() const { - return bits; - } - unsigned size_refs() const { - return refs_cnt; - } - unsigned size() const { - return bits; - } - unsigned size_ext() const { - return (refs_cnt << 16) + bits; - } - unsigned remaining_bits() const { - return Cell::max_bits - bits; - } - unsigned remaining_refs() const { - return Cell::max_refs - refs_cnt; - } - const unsigned char* get_data() const { - return data; - } - td::uint16 get_depth() const; - td::ConstBitPtr data_bits() const { - return data; - } - Ref get_ref(unsigned idx) const { - return idx < refs_cnt ? refs[idx] : Ref{}; - } - void reset(); - bool reset_bool() { - reset(); - return true; - } - CellBuilder& operator=(const CellBuilder&); - CellBuilder& operator=(CellBuilder&&); - CellBuilder& store_bytes(const char* str, std::size_t len); - CellBuilder& store_bytes(const char* str, const char* end); - CellBuilder& store_bytes(const unsigned char* str, std::size_t len); - CellBuilder& store_bytes(const unsigned char* str, const unsigned char* end); - CellBuilder& store_bytes(td::Slice s); - bool store_bytes_bool(const unsigned char* str, std::size_t len); - bool store_bytes_bool(const char* str, std::size_t len); - bool store_bytes_bool(td::Slice s); - CellBuilder& store_bits(const unsigned char* str, std::size_t bit_count, int bit_offset = 0); - CellBuilder& store_bits(const char* str, std::size_t bit_count, int bit_offset = 0); - CellBuilder& store_bits(td::ConstBitPtr bs, std::size_t bit_count); - CellBuilder& store_bits(const td::BitSlice& bs); - CellBuilder& store_bits_same(std::size_t bit_count, bool val); - bool store_bits_bool(const unsigned char* str, std::size_t bit_count, int bit_offset = 0); - bool store_bits_bool(td::ConstBitPtr bs, std::size_t bit_count); - template - bool store_bits_bool(const T& ba) { - return store_bits_bool(ba.bits(), ba.size()); - } - bool store_bits_same_bool(std::size_t bit_count, bool val); - CellBuilder& store_zeroes(std::size_t bit_count) { - return store_bits_same(bit_count, false); - } - CellBuilder& store_ones(std::size_t bit_count) { - return store_bits_same(bit_count, true); - } - bool store_zeroes_bool(std::size_t bit_count) { - return store_bits_same_bool(bit_count, false); - } - bool store_ones_bool(std::size_t bit_count) { - return store_bits_same_bool(bit_count, true); - } - td::BitSliceWrite reserve_slice(std::size_t bit_count); - CellBuilder& reserve_slice(std::size_t bit_count, td::BitSliceWrite& bsw); - bool store_long_bool(long long val, unsigned val_bits = 64); - bool store_long_rchk_bool(long long val, unsigned val_bits = 64); - bool store_ulong_rchk_bool(unsigned long long val, unsigned val_bits = 64); - bool store_uint_less(unsigned upper_bound, unsigned long long val); - bool store_uint_leq(unsigned upper_bound, unsigned long long val); - CellBuilder& store_long(long long val, unsigned val_bits = 64); - // bool store_long_top_bool(unsigned long long val, unsigned top_bits); - CellBuilder& store_long_top(unsigned long long val, unsigned top_bits); - bool store_bool_bool(bool val); - bool store_int256_bool(const td::BigInt256& val, unsigned val_bits, bool sgnd = true); - bool store_int256_bool(td::RefInt256 val, unsigned val_bits, bool sgnd = true); - bool store_uint256_bool(const td::BigInt256& val, unsigned val_bits) { - return store_int256_bool(val, val_bits, false); - } - bool store_uint256_bool(td::RefInt256 val, unsigned val_bits) { - return store_int256_bool(std::move(val), val_bits, false); - } - CellBuilder& store_int256(const td::BigInt256& val, unsigned val_bits, bool sgnd = true); - CellBuilder& store_uint256(const td::BigInt256& val, unsigned val_bits) { - return store_int256(val, val_bits, false); - } - bool store_builder_ref_bool(vm::CellBuilder&& cb); - bool store_ref_bool(Ref r); - CellBuilder& store_ref(Ref r); - bool append_data_cell_bool(const DataCell& cell); - CellBuilder& append_data_cell(const DataCell& cell); - bool append_data_cell_bool(Ref cell_ref); - CellBuilder& append_data_cell(Ref cell_ref); - bool append_builder_bool(const CellBuilder& cb); - CellBuilder& append_builder(const CellBuilder& cb); - bool append_builder_bool(Ref cb_ref); - CellBuilder& append_builder(Ref cb_ref); - bool append_cellslice_bool(const CellSlice& cs); - CellBuilder& append_cellslice(const CellSlice& cs); - bool append_cellslice_bool(Ref cs_ref); - CellBuilder& append_cellslice(Ref cs_ref); - bool append_cellslice_chk(const CellSlice& cs, unsigned size_ext); - bool append_cellslice_chk(Ref cs, unsigned size_ext); - bool append_bitstring(const td::BitString& bs); - bool append_bitstring(Ref bs_ref); - bool append_bitstring_chk(const td::BitString& bs, unsigned size); - bool append_bitstring_chk(Ref bs, unsigned size); - bool append_bitslice(const td::BitSlice& bs); - bool store_maybe_ref(Ref cell); - bool contents_equal(const CellSlice& cs) const; - CellBuilder* make_copy() const override; - bool can_extend_by(std::size_t bits) const; - bool can_extend_by(std::size_t bits, unsigned refs) const; - Ref finalize_copy(bool special = false) const; - Ref finalize(bool special = false); - Ref finalize_novm(bool special = false); - td::Result> finalize_novm_nothrow(bool special = false); - bool finalize_to(Ref& res, bool special = false) { - return (res = finalize(special)).not_null(); - } - CellSlice as_cellslice() const &; - CellSlice as_cellslice() &&; - Ref as_cellslice_ref() const &; - Ref as_cellslice_ref() &&; - static td::int64 get_total_cell_builders() { - return get_thread_safe_counter().sum(); - } - int get_serialized_size() const { - return ((bits + 23) >> 3); - } - int serialize(unsigned char* buff, int buff_size) const; - std::string serialize() const; - std::string to_hex() const; - const unsigned char* compute_hash(unsigned char buffer[Cell::hash_bytes]) const; - - const CellBuilder& ensure_pass(bool cond) const { - ensure_throw(cond); - return *this; - } - CellBuilder& ensure_pass(bool cond) { - ensure_throw(cond); - return *this; - } - void ensure_throw(bool cond) const { - if (!cond) { - throw CellCreateError{}; - } - } - - private: - void flush(unsigned char d[2]) const; - bool prepare_reserve(std::size_t bit_count); - bool can_extend_by_fast(unsigned bits_req) const { - return (int)bits <= (int)(Cell::max_bits - bits_req); - } - bool can_extend_by_fast(unsigned bits_req, unsigned refs_req) const { - return (int)bits <= (int)(Cell::max_bits - bits_req) && (int)refs_cnt <= (int)(Cell::max_refs - refs_req); - } - bool can_extend_by_fast2(unsigned bits_req) const { - return bits + bits_req <= Cell::max_bits; - } - bool can_extend_by_fast2(unsigned bits_req, unsigned refs_req) const { - return bits + bits_req <= Cell::max_bits && refs_cnt + refs_req <= Cell::max_refs; - } -}; - -std::ostream& operator<<(std::ostream& os, const CellBuilder& cb); - -template -CellBuilder& operator<<(CellBuilder& cb, const T& val) { - return cb.ensure_pass(val.serialize(cb)); -} - -template -Ref& operator<<(Ref& cb_ref, const T& val) { - bool res = val.serialize(cb_ref.write()); - cb_ref->ensure_throw(res); - return cb_ref; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.cpp deleted file mode 100644 index 038e9a9a..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellHash.h" - -#include "td/utils/StringBuilder.h" -#include "td/utils/Slice.h" - -namespace vm { -td::StringBuilder &operator<<(td::StringBuilder &sb, const CellHash &hash) { - return sb << hash.to_hex(); -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.h deleted file mode 100644 index 2cbc0e8b..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellHash.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/CellTraits.h" -#include "common/bitstring.h" - -#include "td/utils/as.h" - -#include -namespace td { -class StringBuilder; -} - -namespace vm { -struct CellHash { - public: - td::Slice as_slice() const { - return td::Slice(hash_.data(), hash_.size()); - } - td::MutableSlice as_slice() { - return td::MutableSlice(hash_.data(), hash_.size()); - } - bool operator==(const CellHash& other) const { - return hash_ == other.hash_; - } - bool operator<(const CellHash& other) const { - return hash_ < other.hash_; - } - bool operator!=(const CellHash& other) const { - return hash_ != other.hash_; - } - std::string to_hex() const { - return td::ConstBitPtr{hash_.data()}.to_hex(hash_.size() * 8); - } - friend td::StringBuilder& operator<<(td::StringBuilder& sb, const CellHash& hash); - td::ConstBitPtr bits() const { - return td::ConstBitPtr{hash_.data()}; - } - td::BitPtr bits() { - return td::BitPtr{hash_.data()}; - } - td::BitSlice as_bitslice() const { - return td::BitSlice{hash_.data(), (unsigned int)hash_.size() * 8}; - } - const std::array& as_array() const { - return hash_; - } - - static CellHash from_slice(td::Slice slice) { - CellHash res; - CHECK(slice.size() == res.hash_.size()); - td::MutableSlice(res.hash_.data(), res.hash_.size()).copy_from(slice); - return res; - } - - private: - std::array hash_; -}; -} // namespace vm - -namespace std { -template <> -struct hash { - typedef vm::CellHash argument_type; - typedef std::size_t result_type; - result_type operator()(argument_type const& s) const noexcept { - return td::as(s.as_slice().ubegin()); - } -}; -} // namespace std -namespace vm { -template -H AbslHashValue(H h, const CellHash& cell_hash) { - return H::combine(std::move(h), std::hash()(cell_hash)); -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.cpp deleted file mode 100644 index 916fc023..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellSlice.h" -#include "vm/excno.hpp" -#include "td/utils/bits.h" -#include "td/utils/misc.h" - -namespace vm { - -/* -CellSlice::CellSlice(Ref&& ref) : cell(std::move(ref)), bits_st(0), refs_st(0), ptr(0), zd(0) { - init_bits_refs(); -} -*/ - -CellSlice::CellSlice(VirtualCell::LoadedCell loaded_cell) - : virt(loaded_cell.virt) - , cell(std::move(loaded_cell.data_cell)) - , tree_node(std::move(loaded_cell.tree_node)) - , bits_st(0) - , refs_st(0) - , ptr(0) - , zd(0) { - init_bits_refs(); -} - -CellSlice::CellSlice() : bits_st(0), refs_st(0), bits_en(0), refs_en(0), ptr(0), zd(0) { -} - -namespace { -Cell::LoadedCell load_cell_nothrow(const Ref& ref) { - auto res = ref->load_cell(); - if (res.is_ok()) { - auto ld = res.move_as_ok(); - CHECK(ld.virt.get_virtualization() == 0 || ld.data_cell->special_type() != Cell::SpecialType::PrunnedBranch); - return ld; - } - return {}; -} - -Cell::LoadedCell load_cell_nothrow(const Ref& ref, int mode) { - auto res = ref->load_cell(); - if (res.is_ok()) { - auto ld = res.move_as_ok(); - CHECK(ld.virt.get_virtualization() == 0 || ld.data_cell->special_type() != Cell::SpecialType::PrunnedBranch); - if ((mode >> (ld.data_cell->is_special() ? 1 : 0)) & 1) { - return ld; - } - } - return {}; -} - -} // namespace - -CellSlice::CellSlice(NoVm, Ref ref) : CellSlice(load_cell_nothrow(std::move(ref))) { -} -CellSlice::CellSlice(NoVmOrd, Ref ref) : CellSlice(load_cell_nothrow(std::move(ref), 1)) { -} -CellSlice::CellSlice(NoVmSpec, Ref ref) : CellSlice(load_cell_nothrow(std::move(ref), 2)) { -} -CellSlice::CellSlice(Ref ref) : CellSlice(VirtualCell::LoadedCell{std::move(ref), {}, {}}) { -} -CellSlice::CellSlice(const CellSlice& cs) = default; - -bool CellSlice::load(VirtualCell::LoadedCell loaded_cell) { - virt = loaded_cell.virt; - cell = std::move(loaded_cell.data_cell); - tree_node = std::move(loaded_cell.tree_node); - bits_st = 0; - refs_st = 0; - ptr = 0; - zd = 0; - init_bits_refs(); - return cell.not_null(); -} - -bool CellSlice::load(NoVm, Ref cell_ref) { - return load(load_cell_nothrow(std::move(cell_ref))); -} -bool CellSlice::load(NoVmOrd, Ref cell_ref) { - return load(load_cell_nothrow(std::move(cell_ref), 1)); -} -bool CellSlice::load(NoVmSpec, Ref cell_ref) { - return load(load_cell_nothrow(std::move(cell_ref), 2)); -} -bool CellSlice::load(Ref dc_ref) { - return load(VirtualCell::LoadedCell{std::move(dc_ref), {}, {}}); -} - -/* -CellSlice::CellSlice(Ref dc_ref, unsigned _bits_en, unsigned _refs_en, unsigned _bits_st, unsigned _refs_st) - : cell(std::move(dc_ref)) - , bits_st(_bits_st) - , refs_st(_refs_st) - , bits_en(_bits_en) - , refs_en(_refs_en) - , ptr(0) - , zd(0) { - assert(bits_st <= bits_en && refs_st <= refs_en); - if (cell.is_null()) { - assert(!bits_en && !refs_en); - } else { - assert(bits_en <= cell->get_bits() && refs_en <= cell->get_refs_cnt()); - if (bits_en) { - init_preload(); - } - } -} -*/ - -CellSlice::CellSlice(const CellSlice& cs, unsigned _bits_en, unsigned _refs_en, unsigned _bits_st, unsigned _refs_st) - : virt(cs.virt) - , cell(cs.cell) - , tree_node(cs.tree_node) - , bits_st(cs.bits_st + _bits_st) - , refs_st(cs.refs_st + _refs_st) - , bits_en(cs.bits_st + _bits_en) - , refs_en(cs.refs_st + _refs_en) - , ptr(0) - , zd(0) { - assert(_bits_st <= _bits_en && _refs_st <= _refs_en); - assert(_bits_en <= cs.size() && _refs_en <= cs.size_refs()); - if (_bits_en > _bits_st) { - init_preload(); - } -} - -CellSlice::CellSlice(const CellSlice& cs, unsigned _bits_en, unsigned _refs_en) - : virt(cs.virt) - , cell(cs.cell) - , tree_node(cs.tree_node) - , bits_st(cs.bits_st) - , refs_st(cs.refs_st) - , bits_en(cs.bits_st + _bits_en) - , refs_en(cs.refs_st + _refs_en) - , ptr(0) - , zd(0) { - assert(_bits_en <= cs.size() && _refs_en <= cs.size_refs()); - if (_bits_en) { - init_preload(); - } -} - -Cell::LoadedCell CellSlice::move_as_loaded_cell() { - Cell::LoadedCell res{std::move(cell), std::move(virt), std::move(tree_node)}; - clear(); - return res; -} - -void CellSlice::init_bits_refs() { - if (cell.is_null()) { - bits_en = 0; - refs_en = 0; - } else { - bits_en = cell->get_bits(); - refs_en = cell->get_refs_cnt(); - if (bits_en) { - init_preload(); - } - } -} - -void CellSlice::init_preload() const { - if (bits_st >= bits_en) { - zd = 0; - return; - } - ptr = cell->get_data() + (bits_st >> 3) + 1; - unsigned t = 8 - (bits_st & 7); - z = (((unsigned long long)ptr[-1]) << (64 - t)); - zd = std::min(t, size()); -} - -void CellSlice::clear() { - zd = 0; - bits_en = bits_st = 0; - refs_st = refs_en = 0; - ptr = 0; - cell.clear(); -} - -/* -void CellSlice::error() { - // maybe throw a different simple exception, and convert it at the upper level of the vm - throw VmError{Excno::cell_und, "cell deserialization error"}; -} -*/ - -unsigned CellSlice::get_cell_level() const { - return cell->get_level_mask().apply(virt.get_level()).get_level(); -} - -unsigned CellSlice::get_level() const { - unsigned l = 0; - for (unsigned i = refs_st; i < refs_en; i++) { - auto res = cell->get_ref(i)->virtualize(child_virt()); - unsigned l1 = res->get_level(); - // maybe l1 = cell->get_ref(i)->get_level_mask().apply(virt.get_level()).get_level(); - if (l1 > l) { - l = l1; - } - } - return l; -} - -Ref CellSlice::get_base_cell() const { - if (cell.is_null()) { - return {}; - } - auto res = cell->virtualize(virt); - if (!tree_node.empty()) { - res = UsageCell::create(std::move(res), tree_node); - } - return res; -} - -bool CellSlice::advance(unsigned bits) { - if (have(bits)) { - bits_st += bits; - if (zd <= bits) { // NB: if we write here zd < bits, we obtain bug with z <<= 64 - init_preload(); - } else { - zd -= bits; - z <<= bits; - } - return true; - } else { - return false; - } -} - -bool CellSlice::advance_refs(unsigned refs = 1) { - if (have_refs(refs)) { - refs_st += refs; - return true; - } else { - return false; - } -} - -bool CellSlice::advance_ext(unsigned bits, unsigned refs) { - if (have(bits) && have_refs(refs)) { - refs_st += refs; - return advance(bits); - } else { - return false; - } -} - -bool CellSlice::advance_ext(unsigned bits_refs) { - return advance_ext(bits_refs >> 16, bits_refs & 0xffff); -} - -// (PRIVATE) -// assume: at least `req_bits` bits can be preloaded -void CellSlice::preload_at_least(unsigned req_bits) const { - assert(req_bits <= 64 && have(req_bits) && ptr); - if (req_bits <= zd) { - return; - } - int remain = bits_en - bits_st - zd; - if (zd <= 32 && remain > 24) { - z |= (((unsigned long long)td::bswap32(td::as(ptr))) << (32 - zd)); - ptr += 4; - if (remain <= 32) { - zd += remain; - return; - } - zd += 32; - remain -= 32; - } - while (zd < req_bits && remain > 0) { - if (zd > 56) { - z |= (*ptr >> (zd - 56)); - return; - } - z |= (((unsigned long long)*ptr++) << (56 - zd)); - if (remain <= 8) { - zd += remain; - return; - } - zd += 8; - remain -= 8; - } -} - -int CellSlice::prefetch_octet() const { - if (!have(8)) { - return -1; - } else { - preload_at_least(8); - return (int)(z >> 56); - } -} - -int CellSlice::fetch_octet() { - if (!have(8)) { - return -1; - } else { - preload_at_least(8); - int res = (int)(z >> 56); - z <<= 8; - zd -= 8; - return res; - } -} - -unsigned long long CellSlice::fetch_ulong(unsigned bits) { - if (!have(bits) || bits > 64) { - return fetch_ulong_eof; - } else if (!bits) { - return 0; - } else if (bits <= 56) { - preload_at_least(bits); - unsigned long long res = (z >> (64 - bits)); - z <<= bits; - assert(zd >= bits); - zd -= bits; - bits_st += bits; - return res; - } else { - preload_at_least(bits); - unsigned long long res = (z >> (64 - bits)); - advance(bits); - return res; - } -} - -unsigned long long CellSlice::prefetch_ulong(unsigned bits) const { - if (!have(bits) || bits > 64) { - return fetch_ulong_eof; - } else if (!bits) { - return 0; - } else { - preload_at_least(bits); - return (z >> (64 - bits)); - } -} - -unsigned long long CellSlice::prefetch_ulong_top(unsigned& bits) const { - if (bits > size()) { - bits = size(); - } - if (!bits) { - return 0; - } - preload_at_least(bits); - return z; -} - -long long CellSlice::fetch_long(unsigned bits) { - if (!have(bits) || bits > 64) { - return fetch_long_eof; - } else if (!bits) { - return 0; - } else if (bits <= 56) { - preload_at_least(bits); - long long res = ((long long)z >> (64 - bits)); - z <<= bits; - assert(zd >= bits); - zd -= bits; - bits_st += bits; - return res; - } else { - preload_at_least(bits); - long long res = ((long long)z >> (64 - bits)); - advance(bits); - return res; - } -} - -long long CellSlice::prefetch_long(unsigned bits) const { - if (!have(bits) || bits > 64) { - return fetch_long_eof; - } else if (!bits) { - return 0; - } else { - preload_at_least(bits); - return ((long long)z >> (64 - bits)); - } -} - -bool CellSlice::fetch_long_bool(unsigned bits, long long& res) { - if (bits > 64 || !have(bits)) { - return false; - } - res = fetch_long(bits); - return true; -} - -bool CellSlice::prefetch_long_bool(unsigned bits, long long& res) const { - if (bits > 64 || !have(bits)) { - return false; - } - res = prefetch_long(bits); - return true; -} - -bool CellSlice::fetch_ulong_bool(unsigned bits, unsigned long long& res) { - if (bits > 64 || !have(bits)) { - return false; - } - res = fetch_ulong(bits); - return true; -} - -bool CellSlice::prefetch_ulong_bool(unsigned bits, unsigned long long& res) const { - if (bits > 64 || !have(bits)) { - return false; - } - res = prefetch_ulong(bits); - return true; -} - -bool CellSlice::fetch_bool_to(bool& res) { - if (!have(1)) { - return false; - } else { - res = (bool)fetch_ulong(1); - return true; - } -} - -bool CellSlice::fetch_bool_to(int& res) { - if (!have(1)) { - return false; - } else { - res = (int)fetch_ulong(1); - return true; - } -} - -bool CellSlice::fetch_bool_to(int& res, int mask) { - if (!have(1)) { - return false; - } else if (fetch_ulong(1)) { - res |= mask; - } else { - res &= ~mask; - } - return true; -} - -bool CellSlice::fetch_uint_to(unsigned bits, unsigned long long& res) { - if (bits > 64 || !have(bits)) { - return false; - } else { - res = fetch_ulong(bits); - return true; - } -} - -bool CellSlice::fetch_uint_to(unsigned bits, long long& res) { - if (bits > 64 || !have(bits)) { - return false; - } else { - res = (long long)fetch_ulong(bits); - return res >= 0; - } -} - -bool CellSlice::fetch_uint_to(unsigned bits, unsigned long& res) { - if (bits > 8 * sizeof(unsigned long) || !have(bits)) { - return false; - } else { - res = static_cast(fetch_ulong(bits)); - return true; - } -} - -bool CellSlice::fetch_uint_to(unsigned bits, long& res) { - if (bits > 8 * sizeof(long) || !have(bits)) { - return false; - } else { - res = static_cast(fetch_ulong(bits)); - return res >= 0; - } -} - -bool CellSlice::fetch_uint_to(unsigned bits, unsigned& res) { - if (bits > 32 || !have(bits)) { - return false; - } else { - res = (unsigned)fetch_ulong(bits); - return true; - } -} - -bool CellSlice::fetch_uint_to(unsigned bits, int& res) { - if (bits > 32 || !have(bits)) { - return false; - } else { - res = (int)fetch_ulong(bits); - return res >= 0; - } -} - -bool CellSlice::fetch_int_to(unsigned bits, long long& res) { - if (bits > 64 || !have(bits)) { - return false; - } else { - res = fetch_long(bits); - return true; - } -} - -bool CellSlice::fetch_int_to(unsigned bits, int& res) { - if (bits > 32 || !have(bits)) { - return false; - } else { - res = (int)fetch_long(bits); - return true; - } -} - -bool CellSlice::fetch_uint_less(unsigned upper_bound, int& res) { - unsigned bits = 32 - td::count_leading_zeroes32(upper_bound - 1); - if (!upper_bound || bits > 31 || !have(bits)) { - return false; - } else { - res = (int)fetch_ulong(bits); - return (unsigned)res < upper_bound; - } -} - -bool CellSlice::fetch_uint_less(unsigned upper_bound, unsigned& res) { - unsigned bits = 32 - td::count_leading_zeroes32(upper_bound - 1); - if (!upper_bound || bits > 32 || !have(bits)) { - return false; - } else { - res = (unsigned)fetch_ulong(bits); - return res < upper_bound; - } -} - -bool CellSlice::fetch_uint_leq(unsigned upper_bound, int& res) { - unsigned bits = 32 - td::count_leading_zeroes32(upper_bound); - if (bits > 31 || !have(bits)) { - return false; - } else { - res = (int)fetch_ulong(bits); - return (unsigned)res <= upper_bound; - } -} - -bool CellSlice::fetch_uint_leq(unsigned upper_bound, unsigned& res) { - unsigned bits = 32 - td::count_leading_zeroes32(upper_bound); - if (bits > 32 || !have(bits)) { - return false; - } else { - res = (unsigned)fetch_ulong(bits); - return res <= upper_bound; - } -} - -int CellSlice::bselect(unsigned bits, unsigned long long mask) const { - if (bits > 6 || !have(bits)) { - return -1; - } else { - int n = (int)prefetch_ulong(bits); - return td::count_bits64(mask & ((2ULL << n) - 1)) - 1; - } -} - -int CellSlice::bselect_ext(unsigned bits, unsigned long long mask) const { - if (bits > 6) { - return -1; - } - int n; - if (have(bits)) { - n = (int)prefetch_ulong(bits); - } else { - n = (int)prefetch_ulong(size()) << (bits - size()); - } - return td::count_bits64(mask & ((2ULL << n) - 1)) - 1; -} - -td::RefInt256 CellSlice::fetch_int256(unsigned bits, bool sgnd) { - if (!have(bits)) { - return {}; - } else if (bits < td::BigInt256::word_shift) { - return td::make_refint(sgnd ? fetch_long(bits) : fetch_ulong(bits)); - } else { - td::RefInt256 res{true}; - res.unique_write().import_bits(data_bits(), bits, sgnd); - advance(bits); - return res; - } -} - -td::RefInt256 CellSlice::prefetch_int256(unsigned bits, bool sgnd) const { - if (!have(bits)) { - return {}; - } else if (bits < td::BigInt256::word_shift) { - return td::make_refint(sgnd ? prefetch_long(bits) : prefetch_ulong(bits)); - } else { - td::RefInt256 res{true}; - res.unique_write().import_bits(data_bits(), bits, sgnd); - return res; - } -} - -td::RefInt256 CellSlice::prefetch_int256_zeroext(unsigned bits, bool sgnd) const { - if (bits > 256u + sgnd) { - return td::make_refint(); - } else { - unsigned ld_bits = std::min(bits, size()); - if (bits < td::BigInt256::word_shift) { - long long val = sgnd ? prefetch_long(ld_bits) : prefetch_ulong(ld_bits); - val <<= bits - ld_bits; - return td::make_refint(val); - } else { - auto res = td::make_refint(); - res.unique_write().import_bits(data_bits(), ld_bits, sgnd); - res <<= bits - ld_bits; - return res; - } - } -} - -td::BitSlice CellSlice::fetch_bits(unsigned bits) { - if (!have(bits)) { - return {}; - } else { - td::BitSlice res{cell, data(), (int)bits_st, bits}; - advance(bits); - return res; - } -} - -td::BitSlice CellSlice::prefetch_bits(unsigned bits) const { - if (!have(bits)) { - return {}; - } else { - return td::BitSlice{cell, data(), (int)bits_st, bits}; - } -} - -bool CellSlice::fetch_bits_to(td::BitPtr buffer, unsigned bits) { - if (!have(bits)) { - return false; - } - fetch_bits(bits).copy_to(buffer); - return true; -} - -bool CellSlice::prefetch_bits_to(td::BitPtr buffer, unsigned bits) const { - if (!have(bits)) { - return false; - } - prefetch_bits(bits).copy_to(buffer); - return true; -} - -td::Ref CellSlice::fetch_subslice(unsigned bits, unsigned refs) { - if (!have(bits, refs)) { - return {}; - } else { - td::Ref res{true, *this, bits, refs}; - advance(bits); - advance_refs(refs); - return res; - } -} - -td::Ref CellSlice::prefetch_subslice(unsigned bits, unsigned refs) const { - if (!have(bits, refs)) { - return {}; - } else { - return td::Ref{true, *this, bits, refs}; - } -} - -td::Ref CellSlice::fetch_subslice_ext(unsigned size) { - return fetch_subslice(size & 0xffff, size >> 16); -} - -td::Ref CellSlice::prefetch_subslice_ext(unsigned size) const { - return prefetch_subslice(size & 0xffff, size >> 16); -} - -td::Ref CellSlice::prefetch_bitstring(unsigned bits) const { - if (!have(bits)) { - return {}; - } else { - return td::Ref{true, prefetch_bits(bits)}; - } -} - -td::Ref CellSlice::fetch_bitstring(unsigned bits) { - if (!have(bits)) { - return {}; - } else { - return td::Ref{true, fetch_bits(bits)}; - } -} - -bool CellSlice::prefetch_bytes(unsigned char* buffer, unsigned bytes) const { - if (!have(bytes * 8)) { - return false; - } else { - td::BitSliceWrite{buffer, bytes* 8} = prefetch_bits(bytes * 8); - return true; - } -} - -bool CellSlice::fetch_bytes(td::MutableSlice slice) { - return fetch_bytes(slice.ubegin(), td::narrow_cast(slice.size())); -} - -bool CellSlice::fetch_bytes(unsigned char* buffer, unsigned bytes) { - if (prefetch_bytes(buffer, bytes)) { - advance(bytes * 8); - return true; - } else { - return false; - } -} - -bool CellSlice::prefetch_bytes(td::MutableSlice slice) const { - return prefetch_bytes(slice.ubegin(), td::narrow_cast(slice.size())); -} - -Ref CellSlice::prefetch_ref(unsigned offset) const { - if (offset < size_refs()) { - auto ref_id = refs_st + offset; - auto res = cell->get_ref(ref_id)->virtualize(child_virt()); - if (!tree_node.empty()) { - res = UsageCell::create(std::move(res), tree_node.create_child(ref_id)); - } - return res; - } else { - return Ref{}; - } -} - -Ref CellSlice::fetch_ref() { - if (have_refs()) { - auto ref_id = refs_st++; - auto res = cell->get_ref(ref_id)->virtualize(child_virt()); - if (!tree_node.empty()) { - res = UsageCell::create(std::move(res), tree_node.create_child(ref_id)); - } - return res; - } else { - return Ref{}; - } -} - -bool CellSlice::prefetch_maybe_ref(Ref& res) const { - auto z = prefetch_ulong(1); - if (!z) { - res.clear(); - return true; - } else { - return z == 1 && prefetch_ref_to(res); - } -} - -bool CellSlice::fetch_maybe_ref(Ref& res) { - auto z = prefetch_ulong(1); - if (!z) { - res.clear(); - return advance(1); - } else { - return z == 1 && prefetch_ref_to(res) && advance_ext(1, 1); - } -} - -td::uint16 CellSlice::get_depth() const { - int d = 0; - for (unsigned i = 0; i < size_refs(); ++i) { - d = std::max(d, prefetch_ref(i)->get_depth() + 1); - } - return static_cast(d); -} - -bool CellSlice::begins_with(unsigned bits, unsigned long long value) const { - return have(bits) && !((prefetch_ulong(bits) ^ value) & ((1ULL << bits) - 1)); -} - -bool CellSlice::begins_with(unsigned long long value) const { - return begins_with(63 - td::count_leading_zeroes_non_zero64(value), value); -} - -bool CellSlice::begins_with_skip(unsigned long long value) { - return begins_with_skip(63 - td::count_leading_zeroes_non_zero64(value), value); -} - -bool CellSlice::only_first(unsigned bits, unsigned refs) { - if (!have(bits, refs)) { - return false; - } - bits_en = bits_st + bits; - refs_en = refs_st + refs; - return true; -} - -bool CellSlice::only_ext(unsigned size) { - return only_first(size & 0xffff, size >> 16); -} - -bool CellSlice::skip_first(unsigned bits, unsigned refs) { - if (!have(bits, refs)) { - return false; - } - refs_st += refs; - return advance(bits); -} - -bool CellSlice::skip_ext(unsigned size) { - return skip_first(size & 0xffff, size >> 16); -} - -bool CellSlice::only_last(unsigned bits, unsigned refs) { - if (!have(bits, refs)) { - return false; - } - refs_st = refs_en - refs; - return advance(size() - bits); -} - -bool CellSlice::skip_last(unsigned bits, unsigned refs) { - if (!have(bits, refs)) { - return false; - } - bits_en -= bits; - refs_en -= refs; - return true; -} - -bool CellSlice::cut_tail(const CellSlice& tail_cs) { - return skip_last(tail_cs.size(), tail_cs.size_refs()); -} - -int CellSlice::lex_cmp(const CellSlice& cs2) const { - return td::bitstring::bits_lexcmp(data(), bits_st, size(), cs2.data(), cs2.bits_st, cs2.size()); -} - -bool CellSlice::contents_equal(const CellSlice& cs2) const { - if (size() != cs2.size() || size_refs() != cs2.size_refs()) { - return false; - } - if (td::bitstring::bits_memcmp(data_bits(), cs2.data_bits(), size())) { - return false; - } - for (unsigned i = 0; i < size_refs(); i++) { - if (prefetch_ref(i)->get_hash() != cs2.prefetch_ref(i)->get_hash()) { - return false; - } - } - return true; -} - -bool CellSlice::is_prefix_of(const CellSlice& cs2) const { - return size() <= cs2.size() && !td::bitstring::bits_memcmp(data_bits(), cs2.data_bits(), size(), 0); -} - -bool CellSlice::is_prefix_of(td::ConstBitPtr bs, unsigned len) const { - return size() <= len && !td::bitstring::bits_memcmp(data_bits(), bs, size(), 0); -} - -/* -bool CellSlice::is_prefix_of(const td::BitSlice& bs, unsigned offs, unsigned max_len) const { - max_len = std::min(max_len, size()); - return max_len + offs <= bs.size() && - !td::bitstring::bits_memcmp(data_bits(), bs.bits() + offs, max_len, 0); -} -*/ - -bool CellSlice::is_suffix_of(const CellSlice& cs2) const { - return size() <= cs2.size() && - !td::bitstring::bits_memcmp(data_bits(), cs2.data_bits() + (cs2.size() - size()), size(), 0); -} - -bool CellSlice::has_prefix(const CellSlice& cs2) const { - return size() >= cs2.size() && !td::bitstring::bits_memcmp(data_bits(), cs2.data_bits(), cs2.size(), 0); -} - -bool CellSlice::has_prefix(td::ConstBitPtr bs, unsigned len) const { - return size() >= len && !td::bitstring::bits_memcmp(data_bits(), bs, len, 0); -} - -bool CellSlice::has_suffix(const CellSlice& cs2) const { - return size() >= cs2.size() && - !td::bitstring::bits_memcmp(data_bits() + (size() - cs2.size()), cs2.data_bits(), cs2.size(), 0); -} - -bool CellSlice::is_proper_prefix_of(const CellSlice& cs2) const { - return size() < cs2.size() && !td::bitstring::bits_memcmp(data_bits(), cs2.data_bits(), size(), 0); -} - -bool CellSlice::is_proper_suffix_of(const CellSlice& cs2) const { - return size() < cs2.size() && - !td::bitstring::bits_memcmp(data_bits(), cs2.data_bits() + (cs2.size() - size()), size(), 0); -} - -int CellSlice::common_prefix_len(const CellSlice& cs2) const { - std::size_t same_upto = 0; - td::bitstring::bits_memcmp(data_bits(), cs2.data_bits(), std::min(size(), cs2.size()), &same_upto); - return (int)same_upto; -} - -/* -int CellSlice::common_prefix_len(const td::BitSlice& bs, unsigned offs, unsigned max_len) const { - return common_prefix_len(bs.bits() + offs, std::min(bs.size() - offs, max_len)); -} -*/ - -int CellSlice::common_prefix_len(td::ConstBitPtr bs, unsigned len) const { - std::size_t same_upto = 0; - td::bitstring::bits_memcmp(data_bits(), bs, std::min(size(), len), &same_upto); - return (int)same_upto; -} - -int CellSlice::count_leading(bool bit) const { - return (int)td::bitstring::bits_memscan(data_bits(), size(), bit); -} - -int CellSlice::count_trailing(bool bit) const { - return (int)td::bitstring::bits_memscan_rev(data_bits(), size(), bit); -} - -int CellSlice::remove_trailing() { - if (bits_st == bits_en) { - return 0; - } - unsigned bits = bits_en - bits_st; - unsigned trailing = (unsigned)td::bitstring::bits_memscan_rev(data(), bits_st, bits, 0); - assert(trailing <= bits); - if (trailing == bits) { - bits_en -= trailing; - } else { - bits_en -= ++trailing; - } - return trailing; -} - -bool cell_builder_add_slice_bool(CellBuilder& cb, const CellSlice& cs) { - if (!cb.can_extend_by(cs.size(), cs.size_refs())) { - return false; - } - for (unsigned cnt = 0; cnt < cs.size_refs(); cnt++) { - cb.store_ref(cs.prefetch_ref(cnt)); - } - cb.store_bits(cs.as_bitslice()); - return true; -} - -CellBuilder& cell_builder_add_slice(CellBuilder& cb, const CellSlice& cs) { - return cb.ensure_pass(cell_builder_add_slice_bool(cb, cs)); -} - -void CellSlice::dump(std::ostream& os, int level, bool endl) const { - os << "Cell"; - if (level > 0) { - os << "{" << cell->to_hex() << "}"; - } - os << " bits: " << bits_st << ".." << bits_en; - os << "; refs: " << refs_st << ".." << refs_en; - if (level > 2) { - char tmp[64]; - std::sprintf(tmp, "; ptr=data+%ld; z=%016llx", - static_cast(ptr && cell.not_null() ? ptr - cell->get_data() : -1), static_cast(z)); - os << tmp << " (have " << size() << " bits; " << zd << " preloaded)"; - } - if (endl) { - os << std::endl; - } -} - -void CellSlice::dump_hex(std::ostream& os, int mode, bool endl) const { - os << "x" << as_bitslice().to_hex(); - if (have_refs() && (mode & 1)) { - os << "," << size_refs(); - } - if (endl) { - os << std::endl; - } -} - -bool CellSlice::print_rec(std::ostream& os, int* limit, int indent) const { - for (int i = 0; i < indent; i++) { - os << ' '; - } - if (!limit || *limit <= 0) { - os << "" << std::endl; - return false; - } - --*limit; - if (cell.is_null()) { - os << "NULL" << std::endl; - return true; - } - if (is_special()) { - os << "SPECIAL "; - } - os << "x{" << as_bitslice().to_hex() << '}' << std::endl; - for (unsigned i = 0; i < size_refs(); i++) { - CellSlice cs{NoVm(), prefetch_ref(i)}; - if (!cs.print_rec(os, limit, indent + 1)) { - return false; - } - } - return true; -} - -bool CellSlice::print_rec(std::ostream& os, int indent) const { - int limit = default_recursive_print_limit; - return print_rec(os, &limit, indent); -} - -bool CellSlice::print_rec(int limit, std::ostream& os, int indent) const { - return print_rec(os, &limit, indent); -} - -td::StringBuilder& operator<<(td::StringBuilder& sb, const CellSlice& cs) { - std::ostringstream os; - cs.dump_hex(os, 1, false); - return sb << os.str(); -} - -std::ostream& operator<<(std::ostream& os, CellSlice cs) { - cs.dump_hex(os, 1, false); - return os; -} - -std::ostream& operator<<(std::ostream& os, Ref cs_ref) { - if (cs_ref.is_null()) { - os << "(null)"; - } else { - cs_ref->dump_hex(os, 1, false); - } - return os; -} - -// BEGIN (SLICE LOAD FUNCTIONS) -// (if these functions become more complicated, move them into a separate file) - -// If can_be_special is not null, then it is allowed to load special cell -// Flag whether loaded cell is actually special will be stored into can_be_special -VirtualCell::LoadedCell load_cell_slice_impl(const Ref& cell, bool* can_be_special) { - auto* vm_state_interface = VmStateInterface::get(); - if (vm_state_interface) { - vm_state_interface->register_cell_load(cell->get_hash()); - } - auto r_loaded_cell = cell->load_cell(); - if (r_loaded_cell.is_error()) { - throw VmError{Excno::cell_und, "failed to load cell"}; - } - auto loaded_cell = r_loaded_cell.move_as_ok(); - if (loaded_cell.data_cell->special_type() == DataCell::SpecialType::PrunnedBranch) { - auto virtualization = loaded_cell.virt.get_virtualization(); - if (virtualization != 0) { - throw VmVirtError{virtualization}; - } - } - if (can_be_special) { - *can_be_special = loaded_cell.data_cell->is_special(); - } else if (loaded_cell.data_cell->is_special()) { - if (loaded_cell.data_cell->special_type() == DataCell::SpecialType::Library) { - if (vm_state_interface) { - CellSlice cs(std::move(loaded_cell)); - DCHECK(cs.size() == Cell::hash_bits + 8); - auto library_cell = vm_state_interface->load_library(cs.data_bits() + 8); - if (library_cell.not_null()) { - //TODO: fix infinity loop - return load_cell_slice_impl(library_cell, nullptr); - } - throw VmError{Excno::cell_und, "failed to load library cell"}; - } - throw VmError{Excno::cell_und, "failed to load library cell (no vm_state_interface available)"}; - } else if (loaded_cell.data_cell->special_type() == DataCell::SpecialType::PrunnedBranch) { - CHECK(loaded_cell.virt.get_virtualization() == 0); - throw VmError{Excno::cell_und, "trying to load prunned cell"}; - } - throw VmError{Excno::cell_und, "unexpected special cell"}; - } - return loaded_cell; -} - -CellSlice load_cell_slice(const Ref& cell) { - return CellSlice{load_cell_slice_impl(cell, nullptr)}; -} - -CellSlice load_cell_slice_special(const Ref& cell, bool& special) { - return CellSlice{load_cell_slice_impl(cell, &special)}; -} - -Ref load_cell_slice_ref(const Ref& cell) { - return Ref{true, CellSlice(load_cell_slice_impl(cell, nullptr))}; -} - -Ref load_cell_slice_ref_special(const Ref& cell, bool& special) { - return Ref{true, CellSlice(load_cell_slice_impl(cell, &special))}; -} - -void print_load_cell(std::ostream& os, Ref cell, int indent) { - auto cs = load_cell_slice(cell); - cs.print_rec(os, indent); -} - -bool CellSlice::load(Ref cell) { - return load(load_cell_slice_impl(std::move(cell), nullptr)); -} - -bool CellSlice::load_ord(Ref cell) { - return load(load_cell_slice_impl(std::move(cell), nullptr)); -} - -// END (SLICE LOAD FUNCTIONS) - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.h deleted file mode 100644 index 33fad741..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellSlice.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "common/refcnt.hpp" -#include "common/refint.h" -#include "vm/cells.h" - -namespace td { -class StringBuilder; -} -namespace vm { - -struct NoVm {}; -struct NoVmOrd {}; -struct NoVmSpec {}; - -class CellSlice : public td::CntObject { - Cell::VirtualizationParameters virt; - Ref cell; - CellUsageTree::NodePtr tree_node; - unsigned bits_st, refs_st; - unsigned bits_en, refs_en; - mutable const unsigned char* ptr{nullptr}; - mutable unsigned long long z; - mutable unsigned zd; - - public: - static constexpr long long fetch_long_eof = (static_cast(-1LL) << 63); - static constexpr unsigned long long fetch_ulong_eof = (unsigned long long)-1LL; - enum { default_recursive_print_limit = 100 }; - struct CellReadError {}; - - CellSlice(NoVm, Ref cell_ref); - CellSlice(NoVmOrd, Ref cell_ref); - CellSlice(NoVmSpec, Ref cell_ref); - CellSlice(Ref dc_ref); - CellSlice(VirtualCell::LoadedCell loaded_cell); - /* - CellSlice(Ref dc_ref, unsigned _bits_en, unsigned _refs_en, unsigned _bits_st = 0, unsigned _refs_st = 0);*/ - CellSlice(const CellSlice& cs, unsigned _bits_en, unsigned _refs_en); - CellSlice(const CellSlice& cs, unsigned _bits_en, unsigned _refs_en, unsigned _bits_st, unsigned _refs_st); - CellSlice(const CellSlice&); - CellSlice& operator=(const CellSlice& other) = default; - CellSlice(); - Cell::LoadedCell move_as_loaded_cell(); - td::CntObject* make_copy() const override { - return new CellSlice{*this}; - } - void clear(); - bool load(VirtualCell::LoadedCell loaded_cell); - bool load(NoVm, Ref cell_ref); - bool load(NoVmOrd, Ref cell_ref); - bool load(NoVmSpec, Ref cell_ref); - bool load(Ref dc_ref); - bool load(Ref cell); - bool load_ord(Ref cell); - unsigned size() const { - return bits_en - bits_st; - } - bool is_special() const { - return cell->is_special(); - } - bool is_valid() const { - return cell.not_null(); - } - Cell::SpecialType special_type() const { - return cell->special_type(); - } - int child_merkle_depth(int merkle_depth) const { - if (merkle_depth == Cell::VirtualizationParameters::max_level()) { - return merkle_depth; - } - if (cell->special_type() == Cell::SpecialType::MerkleProof || - cell->special_type() == Cell::SpecialType::MerkleUpdate) { - merkle_depth++; - } - return merkle_depth; - } - unsigned size_refs() const { - return refs_en - refs_st; - } - unsigned size_ext() const { - return size() + (size_refs() << 16); - } - bool have(unsigned bits) const { - return bits <= size(); - } - bool have(unsigned bits, unsigned refs) const { - return bits <= size() && refs <= size_refs(); - } - bool have_ext(unsigned ext_size) const { - return have(ext_size & 0xffff, ext_size >> 16); - } - bool empty() const { - return !size(); - } - bool empty_ext() const { - return !size() && !size_refs(); - } - bool have_refs(unsigned refs = 1) const { - return refs <= size_refs(); - } - bool advance(unsigned bits); - bool advance_refs(unsigned refs); - bool advance_ext(unsigned bits_refs); - bool advance_ext(unsigned bits, unsigned refs); - unsigned cur_pos() const { - return bits_st; - } - unsigned cur_ref() const { - return refs_st; - } - const unsigned char* data() const { - return cell->get_data(); - } - td::uint16 get_depth() const; - td::ConstBitPtr data_bits() const { - return td::ConstBitPtr{data(), (int)cur_pos()}; - } - int subtract_base_ext(const CellSlice& base) { - return (bits_st - base.bits_st) | ((refs_st - base.refs_st) << 16); - } - unsigned get_cell_level() const; - unsigned get_level() const; - Ref get_base_cell() const; // be careful with this one! - int fetch_octet(); - int prefetch_octet() const; - unsigned long long prefetch_ulong_top(unsigned& bits) const; - unsigned long long fetch_ulong(unsigned bits); - unsigned long long prefetch_ulong(unsigned bits) const; - long long fetch_long(unsigned bits); - long long prefetch_long(unsigned bits) const; - bool fetch_long_bool(unsigned bits, long long& res); - bool prefetch_long_bool(unsigned bits, long long& res) const; - bool fetch_ulong_bool(unsigned bits, unsigned long long& res); - bool prefetch_ulong_bool(unsigned bits, unsigned long long& res) const; - bool fetch_bool_to(bool& res); - bool fetch_bool_to(int& res); - bool fetch_bool_to(int& res, int mask); - bool fetch_uint_to(unsigned bits, unsigned long long& res); - bool fetch_uint_to(unsigned bits, long long& res); - bool fetch_uint_to(unsigned bits, unsigned long& res); - bool fetch_uint_to(unsigned bits, long& res); - bool fetch_uint_to(unsigned bits, unsigned& res); - bool fetch_uint_to(unsigned bits, int& res); - bool fetch_uint_less(unsigned upper_bound, int& res); - bool fetch_uint_less(unsigned upper_bound, unsigned& res); - bool fetch_uint_leq(unsigned upper_bound, int& res); - bool fetch_uint_leq(unsigned upper_bound, unsigned& res); - bool fetch_int_to(unsigned bits, long long& res); - bool fetch_int_to(unsigned bits, int& res); - int bselect(unsigned bits, unsigned long long mask) const; - int bselect_ext(unsigned bits, unsigned long long mask) const; - int bit_at(unsigned i) const { - return have(i) ? data_bits()[i] : -1; - } - td::RefInt256 fetch_int256(unsigned bits, bool sgnd = true); - td::RefInt256 prefetch_int256(unsigned bits, bool sgnd = true) const; - td::RefInt256 prefetch_int256_zeroext(unsigned bits, bool sgnd = true) const; - bool fetch_int256_to(unsigned bits, td::RefInt256& res, bool sgnd = true) { - return (res = fetch_int256(bits, sgnd)).not_null(); - } - bool fetch_uint256_to(unsigned bits, td::RefInt256& res) { - return (res = fetch_int256(bits, false)).not_null(); - } - Ref prefetch_ref(unsigned offset = 0) const; - Ref fetch_ref(); - bool fetch_ref_to(Ref& ref) { - return (ref = fetch_ref()).not_null(); - } - bool prefetch_ref_to(Ref& ref, unsigned offset = 0) const { - return (ref = prefetch_ref(offset)).not_null(); - } - bool fetch_maybe_ref(Ref& ref); - bool prefetch_maybe_ref(Ref& ref) const; - td::BitSlice fetch_bits(unsigned bits); - td::BitSlice prefetch_bits(unsigned bits) const; - td::Ref fetch_subslice(unsigned bits, unsigned refs = 0); - td::Ref prefetch_subslice(unsigned bits, unsigned refs = 0) const; - td::Ref fetch_subslice_ext(unsigned size); - td::Ref prefetch_subslice_ext(unsigned size) const; - td::Ref fetch_bitstring(unsigned size); - td::Ref prefetch_bitstring(unsigned size) const; - bool fetch_subslice_to(unsigned bits, td::Ref& res) { - return (res = fetch_subslice(bits)).not_null(); - } - bool fetch_subslice_ext_to(unsigned bits, td::Ref& res) { - return (res = fetch_subslice_ext(bits)).not_null(); - } - bool fetch_bitstring_to(unsigned bits, td::Ref& res) { - return (res = fetch_bitstring(bits)).not_null(); - } - bool fetch_bits_to(td::BitPtr buffer, unsigned bits); - bool prefetch_bits_to(td::BitPtr buffer, unsigned bits) const; - template - bool fetch_bits_to(td::BitArray& buffer) { - return fetch_bits_to(buffer.bits(), n); - } - template - bool prefetch_bits_to(td::BitArray& buffer) const { - return prefetch_bits_to(buffer.bits(), n); - } - bool fetch_bytes(unsigned char* buffer, unsigned bytes); - bool fetch_bytes(td::MutableSlice slice); - bool prefetch_bytes(unsigned char* buffer, unsigned bytes) const; - bool prefetch_bytes(td::MutableSlice slice) const; - td::BitSlice as_bitslice() const { - return prefetch_bits(size()); - } - bool begins_with(unsigned bits, unsigned long long value) const; - bool begins_with(unsigned long long value) const; - bool begins_with_skip(unsigned bits, unsigned long long value) { - return begins_with(bits, value) && advance(bits); - } - bool begins_with_skip(unsigned long long value); - bool only_first(unsigned bits, unsigned refs = 0); - bool only_ext(unsigned size); - bool skip_first(unsigned bits, unsigned refs = 0); - bool skip_ext(unsigned size); - bool only_last(unsigned bits, unsigned refs = 0); - bool skip_last(unsigned bits, unsigned refs = 0); - bool cut_tail(const CellSlice& tail_cs); - int remove_trailing(); - int count_leading(bool bit) const; - int count_trailing(bool bit) const; - int lex_cmp(const CellSlice& cs2) const; - int common_prefix_len(const CellSlice& cs2) const; - bool is_prefix_of(const CellSlice& cs2) const; - bool is_prefix_of(td::ConstBitPtr bs, unsigned len) const; - bool is_suffix_of(const CellSlice& cs2) const; - bool has_prefix(const CellSlice& cs2) const; - bool has_prefix(td::ConstBitPtr bs, unsigned len) const; - bool has_suffix(const CellSlice& cs2) const; - bool is_proper_prefix_of(const CellSlice& cs2) const; - bool is_proper_suffix_of(const CellSlice& cs2) const; - // int common_prefix_len(const td::BitSlice& bs, unsigned offs = 0, unsigned max_len = 0xffffffffU) const; - int common_prefix_len(td::ConstBitPtr bs, unsigned len) const; - // bool is_prefix_of(const td::BitSlice& bs, unsigned offs = 0, unsigned max_len = 0xffffffffU) const; - bool contents_equal(const CellSlice& cs2) const; - void dump(std::ostream& os, int level = 0, bool endl = true) const; - void dump_hex(std::ostream& os, int mode = 0, bool endl = false) const; - bool print_rec(std::ostream& os, int indent = 0) const; - bool print_rec(std::ostream& os, int* limit, int indent = 0) const; - bool print_rec(int limit, std::ostream& os, int indent = 0) const; - void error() const { - throw CellReadError{}; - } - bool chk(bool cond) const { - if (!cond) { - error(); - } - return cond; - } - bool have_chk(unsigned bits) const { - return chk(have(bits)); - } - bool have_chk(unsigned bits, unsigned refs) const { - return chk(have(bits, refs)); - } - bool have_refs_chk(unsigned refs = 1) const { - return chk(have_refs(refs)); - } - CellSlice operator+(unsigned offs) const { - offs = std::min(offs, size()); - return CellSlice{*this, size() - offs, size_refs(), offs, 0}; - } - CellSlice clone() const; - - private: - void init_bits_refs(); - void init_preload() const; - void preload_at_least(unsigned req_bits) const; - Cell::VirtualizationParameters child_virt() const { - return Cell::VirtualizationParameters(static_cast(child_merkle_depth(virt.get_level())), - virt.get_virtualization()); - } -}; - -td::StringBuilder& operator<<(td::StringBuilder& sb, const CellSlice& cs); - -bool cell_builder_add_slice_bool(CellBuilder& cb, const CellSlice& cs); -CellBuilder& cell_builder_add_slice(CellBuilder& cb, const CellSlice& cs); - -std::ostream& operator<<(std::ostream& os, CellSlice cs); -std::ostream& operator<<(std::ostream& os, Ref cs_ref); - -template -CellSlice& operator>>(CellSlice& cs, T& val) { - cs.chk(val.deserialize(cs)); - return cs; -} - -template -Ref& operator>>(Ref& cs_ref, T& val) { - bool res = val.deserialize(cs_ref.write()); - cs_ref->chk(res); - return cs_ref; -} - -template -CellSlice& operator>>(CellSlice& cs, const T& val) { - cs.chk(val.deserialize(cs)); - return cs; -} - -template -Ref& operator>>(Ref& cs_ref, const T& val) { - bool res = val.deserialize(cs_ref.write()); - cs_ref->chk(res); - return cs_ref; -} - -// If can_be_special is not null, then it is allowed to load special cell -// Flag whether loaded cell is actually special will be stored into can_be_special -CellSlice load_cell_slice(const Ref& cell); -Ref load_cell_slice_ref(const Ref& cell); -CellSlice load_cell_slice_special(const Ref& cell, bool& is_special); -Ref load_cell_slice_ref_special(const Ref& cell, bool& is_special); -void print_load_cell(std::ostream& os, Ref cell, int indent = 0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp deleted file mode 100644 index 9889dc8e..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "CellString.h" -#include "td/utils/misc.h" - -#include "vm/cells/CellSlice.h" - -namespace vm { -td::Status CellString::store(CellBuilder &cb, td::Slice slice, unsigned int top_bits) { - td::uint32 size = td::narrow_cast(slice.size() * 8); - return store(cb, td::BitSlice(slice.ubegin(), size), top_bits); -} - -td::Status CellString::store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits) { - if (slice.size() > max_bytes * 8) { - return td::Status::Error("String is too long (1)"); - } - unsigned int head = td::min(slice.size(), td::min(cb.remaining_bits(), top_bits)) / 8 * 8; - auto max_bits = vm::Cell::max_bits / 8 * 8; - auto depth = 1 + (slice.size() - head + max_bits - 1) / max_bits; - if (depth > max_chain_length) { - return td::Status::Error("String is too long (2)"); - } - cb.append_bitslice(slice.subslice(0, head)); - slice.advance(head); - if (slice.size() == 0) { - return td::Status::OK(); - } - CellBuilder child_cb; - store(child_cb, std::move(slice)); - cb.store_ref(child_cb.finalize()); - return td::Status::OK(); -} - -template -void CellString::for_each(F &&f, CellSlice &cs, unsigned int top_bits) { - unsigned int head = td::min(cs.size(), top_bits); - f(cs.prefetch_bits(head)); - if (!cs.have_refs()) { - return; - } - auto ref = cs.prefetch_ref(); - while (true) { - auto cs = vm::load_cell_slice(ref); - f(cs.prefetch_bits(cs.size())); - if (!cs.have_refs()) { - return; - } - ref = cs.prefetch_ref(); - } -} - -td::Result CellString::load(CellSlice &cs, unsigned int top_bits) { - unsigned int size = 0; - for_each([&](auto slice) { size += slice.size(); }, cs, top_bits); - if (size % 8 != 0) { - return td::Status::Error("Size is not divisible by 8"); - } - std::string res(size / 8, 0); - - td::BitPtr to(td::MutableSlice(res).ubegin()); - for_each([&](auto slice) { to.concat(slice); }, cs, top_bits); - CHECK(to.offs == (int)size); - return res; -} - -td::Status CellText::store(CellBuilder &cb, td::Slice slice, unsigned int top_bits) { - td::uint32 size = td::narrow_cast(slice.size() * 8); - return store(cb, td::BitSlice(slice.ubegin(), size), top_bits); -} - -td::Status CellText::store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits) { - if (slice.size() > max_bytes * 8) { - return td::Status::Error("String is too long (1)"); - } - if (cb.remaining_bits() < 16) { - return td::Status::Error("Not enough space in a builder"); - } - if (top_bits < 16) { - return td::Status::Error("Need at least 16 top bits"); - } - if (slice.size() == 0) { - cb.store_long(0, 8); - return td::Status::OK(); - } - unsigned int head = td::min(slice.size(), td::min(cb.remaining_bits(), top_bits) - 16) / 8 * 8; - auto max_bits = vm::Cell::max_bits / 8 * 8; - auto depth = 1 + (slice.size() - head + max_bits - 8 - 1) / (max_bits - 8); - if (depth > max_chain_length) { - return td::Status::Error("String is too long (2)"); - } - cb.store_long(depth, 8); - cb.store_long(head / 8, 8); - cb.append_bitslice(slice.subslice(0, head)); - slice.advance(head); - if (slice.size() == 0) { - return td::Status::OK(); - } - cb.store_ref(do_store(std::move(slice))); - return td::Status::OK(); -} - -td::Ref CellText::do_store(td::BitSlice slice) { - vm::CellBuilder cb; - unsigned int head = td::min(slice.size(), cb.remaining_bits() - 8) / 8 * 8; - cb.store_long(head / 8, 8); - cb.append_bitslice(slice.subslice(0, head)); - slice.advance(head); - if (slice.size() != 0) { - cb.store_ref(do_store(std::move(slice))); - } - return cb.finalize(); -} - -template -void CellText::for_each(F &&f, CellSlice cs) { - auto depth = cs.fetch_ulong(8); - - for (td::uint32 i = 0; i < depth; i++) { - auto size = cs.fetch_ulong(8); - f(cs.fetch_bits(td::narrow_cast(size) * 8)); - if (i + 1 < depth) { - cs = vm::load_cell_slice(cs.prefetch_ref()); - } - } -} - -td::Result CellText::load(CellSlice &cs) { - unsigned int size = 0; - for_each([&](auto slice) { size += slice.size(); }, cs); - if (size % 8 != 0) { - return td::Status::Error("Size is not divisible by 8"); - } - std::string res(size / 8, 0); - - td::BitPtr to(td::MutableSlice(res).ubegin()); - for_each([&](auto slice) { to.concat(slice); }, cs); - CHECK(to.offs == (int)size); - return res; -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h deleted file mode 100644 index ab93203f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Status.h" - -#include "vm/cells/CellBuilder.h" - -namespace vm { -class CellString { - public: - static constexpr unsigned int max_bytes = 1024; - static constexpr unsigned int max_chain_length = 16; - - static td::Status store(CellBuilder &cb, td::Slice slice, unsigned int top_bits = Cell::max_bits); - static td::Status store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits = Cell::max_bits); - static td::Result load(CellSlice &cs, unsigned int top_bits = Cell::max_bits); - static td::Result> create(td::Slice slice, unsigned int top_bits = Cell::max_bits) { - vm::CellBuilder cb; - TRY_STATUS(store(cb, slice, top_bits)); - return cb.finalize(); - } - - private: - template - static void for_each(F &&f, CellSlice &cs, unsigned int top_bits = Cell::max_bits); -}; - -class CellText { - public: - static constexpr unsigned int max_bytes = 1024; - static constexpr unsigned int max_chain_length = 16; - - static td::Status store(CellBuilder &cb, td::Slice slice, unsigned int top_bits = Cell::max_bits); - static td::Status store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits = Cell::max_bits); - static td::Result load(CellSlice &cs); - static td::Result> create(td::Slice slice, unsigned int top_bits = Cell::max_bits) { - vm::CellBuilder cb; - TRY_STATUS(store(cb, slice, top_bits)); - return cb.finalize(); - } - - private: - template - static void for_each(F &&f, CellSlice cs); - static td::Ref do_store(td::BitSlice slice); -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.cpp deleted file mode 100644 index a619d86c..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellTraits.h" - -#include "td/utils/StringBuilder.h" -#include "td/utils/Slice.h" - -namespace vm { -td::StringBuilder& operator<<(td::StringBuilder& sb, CellTraits::SpecialType special_type) { - switch (special_type) { - case CellTraits::SpecialType::Ordinary: - sb << "Ordinary"; - break; - case CellTraits::SpecialType::MerkleProof: - sb << "MerkleProof"; - break; - case CellTraits::SpecialType::MerkleUpdate: - sb << "MerkleUpdate"; - break; - case CellTraits::SpecialType::PrunnedBranch: - sb << "PrunnedBranch"; - break; - case CellTraits::SpecialType::Library: - sb << "Library"; - break; - } - return sb; -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.h deleted file mode 100644 index c994e47e..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellTraits.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/int_types.h" -#include "common/refcnt.hpp" - -namespace td { -class StringBuilder; -} - -namespace vm { -class CellTraits : public td::CntObject { - public: - enum class SpecialType : td::uint8 { - Ordinary = 0, - PrunnedBranch = 1, - Library = 2, - MerkleProof = 3, - MerkleUpdate = 4 - }; - enum { - max_refs = 4, - max_bytes = 128, - max_bits = 1023, - hash_bytes = 32, - hash_bits = hash_bytes * 8, - depth_bytes = 2, - depth_bits = depth_bytes * 8, - max_level = 3, - max_depth = 1024, - max_virtualization = 7, - max_serialized_bytes = 2 + max_bytes + (max_level + 1) * (hash_bytes + depth_bytes) - }; -}; -td::StringBuilder& operator<<(td::StringBuilder& sb, CellTraits::SpecialType special_type); -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.cpp deleted file mode 100644 index 3f43ec6b..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellUsageTree.h" - -namespace vm { -// -// CellUsageTree::NodePtr -// -bool CellUsageTree::NodePtr::on_load() const { - auto tree = tree_weak_.lock(); - if (!tree) { - return false; - } - tree->on_load(node_id_); - return true; -} - -CellUsageTree::NodePtr CellUsageTree::NodePtr::create_child(unsigned ref_id) const { - auto tree = tree_weak_.lock(); - if (!tree) { - return {}; - } - return {tree_weak_, tree->create_child(node_id_, ref_id)}; -} - -bool CellUsageTree::NodePtr::is_from_tree(const CellUsageTree* master_tree) const { - DCHECK(master_tree); - auto tree = tree_weak_.lock(); - if (tree.get() != master_tree) { - return false; - } - return true; -} - -bool CellUsageTree::NodePtr::mark_path(CellUsageTree* master_tree) const { - DCHECK(master_tree); - auto tree = tree_weak_.lock(); - if (tree.get() != master_tree) { - return false; - } - master_tree->mark_path(node_id_); - return true; -} - -// -// CellUsageTree -// -CellUsageTree::NodePtr CellUsageTree::root_ptr() { - return {shared_from_this(), 1}; -} - -CellUsageTree::NodeId CellUsageTree::root_id() const { - return 1; -}; - -bool CellUsageTree::is_loaded(NodeId node_id) const { - if (use_mark_) { - return nodes_[node_id].has_mark; - } - return nodes_[node_id].is_loaded; -} - -bool CellUsageTree::has_mark(NodeId node_id) const { - return nodes_[node_id].has_mark; -} - -void CellUsageTree::set_mark(NodeId node_id, bool mark) { - if (node_id == 0) { - return; - } - nodes_[node_id].has_mark = mark; -} - -void CellUsageTree::mark_path(NodeId node_id) { - auto cur_node_id = get_parent(node_id); - while (cur_node_id != 0) { - if (has_mark(cur_node_id)) { - break; - } - set_mark(cur_node_id); - cur_node_id = get_parent(cur_node_id); - } -} - -CellUsageTree::NodeId CellUsageTree::get_parent(NodeId node_id) { - return nodes_[node_id].parent; -} - -CellUsageTree::NodeId CellUsageTree::get_child(NodeId node_id, unsigned ref_id) { - DCHECK(ref_id < CellTraits::max_refs); - return nodes_[node_id].children[ref_id]; -} - -void CellUsageTree::set_use_mark_for_is_loaded(bool use_mark) { - use_mark_ = use_mark; -} - -void CellUsageTree::on_load(NodeId node_id) { - nodes_[node_id].is_loaded = true; -} - -CellUsageTree::NodeId CellUsageTree::create_child(NodeId node_id, unsigned ref_id) { - DCHECK(ref_id < CellTraits::max_refs); - NodeId res = nodes_[node_id].children[ref_id]; - if (res) { - return res; - } - res = create_node(node_id); - nodes_[node_id].children[ref_id] = res; - return res; -} - -CellUsageTree::NodeId CellUsageTree::create_node(NodeId parent) { - NodeId res = static_cast(nodes_.size()); - nodes_.emplace_back(); - nodes_.back().parent = parent; - return res; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.h deleted file mode 100644 index 150dd2bd..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellUsageTree.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "vm/cells/CellTraits.h" - -#include "td/utils/int_types.h" -#include "td/utils/logging.h" - -namespace vm { -class CellUsageTree : public std::enable_shared_from_this { - public: - using NodeId = td::uint32; - - struct NodePtr { - public: - NodePtr() = default; - NodePtr(std::weak_ptr tree_weak, NodeId node_id) - : tree_weak_(std::move(tree_weak)), node_id_(node_id) { - } - bool empty() const { - return node_id_ == 0 || tree_weak_.expired(); - } - - bool on_load() const; - NodePtr create_child(unsigned ref_id) const; - bool mark_path(CellUsageTree* master_tree) const; - bool is_from_tree(const CellUsageTree* master_tree) const; - - private: - std::weak_ptr tree_weak_; - NodeId node_id_{0}; - }; - - NodePtr root_ptr(); - NodeId root_id() const; - bool is_loaded(NodeId node_id) const; - bool has_mark(NodeId node_id) const; - void set_mark(NodeId node_id, bool mark = true); - void mark_path(NodeId node_id); - NodeId get_parent(NodeId node_id); - NodeId get_child(NodeId node_id, unsigned ref_id); - void set_use_mark_for_is_loaded(bool use_mark = true); - NodeId create_child(NodeId node_id, unsigned ref_id); - - private: - struct Node { - bool is_loaded{false}; - bool has_mark{false}; - NodeId parent{0}; - std::array children{}; - }; - bool use_mark_{false}; - std::vector nodes_{2}; - - void on_load(NodeId node_id); - NodeId create_node(NodeId parent); -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellWithStorage.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellWithStorage.h deleted file mode 100644 index 1830c37d..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/CellWithStorage.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { -namespace detail { -template -class CellWithArrayStorage : public CellT { - public: - template - CellWithArrayStorage(ArgsT&&... args) : CellT(std::forward(args)...) { - } - ~CellWithArrayStorage() { - CellT::destroy_storage(get_storage()); - } - template - static std::unique_ptr create(size_t storage_size, ArgsT&&... args) { - static_assert(CellT::max_storage_size <= 40 * 8, ""); - //size = 128 + 32 + 8; - auto size = (storage_size + 7) / 8; -#define CASE(size) \ - case (size): \ - return std::make_unique>(std::forward(args)...); -#define CASE2(offset) CASE(offset) CASE(offset + 1) -#define CASE8(offset) CASE2(offset) CASE2(offset + 2) CASE2(offset + 4) CASE2(offset + 6) -#define CASE32(offset) CASE8(offset) CASE8(offset + 8) CASE8(offset + 16) CASE8(offset + 24) - switch (size) { CASE32(0) CASE8(32) } -#undef CASE -#undef CASE2 -#undef CASE8 -#undef CASE32 - LOG(FATAL) << "TOO BIG " << storage_size; - UNREACHABLE(); - } - - private: - alignas(alignof(void*)) char storage_[Size]; - - const char* get_storage() const final { - return storage_; - } - char* get_storage() final { - return storage_; - } -}; - -template -class CellWithUniquePtrStorage : public CellT { - public: - template - CellWithUniquePtrStorage(size_t storage_size, ArgsT&&... args) - : CellT(std::forward(args)...), storage_(std::make_unique(storage_size)) { - } - ~CellWithUniquePtrStorage() { - CellT::destroy_storage(get_storage()); - } - - template - static std::unique_ptr create(size_t storage_size, ArgsT&&... args) { - return std::make_unique(storage_size, std::forward(args)...); - } - - private: - std::unique_ptr storage_; - - const char* get_storage() const final { - CHECK(storage_); - return storage_.get(); - } - char* get_storage() final { - CHECK(storage_); - return storage_.get(); - } -}; -} // namespace detail -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.cpp deleted file mode 100644 index cccb11dc..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/DataCell.h" - -#include "openssl/digest.hpp" - -#include "td/utils/ScopeGuard.h" - -#include "vm/cells/CellWithStorage.h" - -namespace vm { -std::unique_ptr DataCell::create_empty_data_cell(Info info) { - return detail::CellWithUniquePtrStorage::create(info.get_storage_size(), info); -} - -DataCell::DataCell(Info info) : info_(std::move(info)) { - get_thread_safe_counter().add(1); -} -DataCell::~DataCell() { - get_thread_safe_counter().add(-1); -} - -void DataCell::destroy_storage(char* storage) { - auto* refs = info_.get_refs(storage); - for (size_t i = 0; i < get_refs_cnt(); i++) { - Ref(refs[i], Ref::acquire_t{}); // call destructor - } -} - -td::Result> DataCell::create(td::ConstBitPtr data, unsigned bits, td::Span> refs, - bool special) { - std::array, max_refs> copied_refs; - CHECK(refs.size() <= copied_refs.size()); - for (size_t i = 0; i < refs.size(); i++) { - copied_refs[i] = refs[i]; - } - return create(std::move(data), bits, td::MutableSpan>(copied_refs.data(), refs.size()), special); -} - -DataCell::SpecialType DataCell::special_type() const { - if (is_special()) { - return static_cast(td::bitstring::bits_load_ulong(get_data(), 8)); - } - return SpecialType::Ordinary; -} - -td::Result> DataCell::create(td::ConstBitPtr data, unsigned bits, td::MutableSpan> refs, - bool special) { - for (auto& ref : refs) { - if (ref.is_null()) { - return td::Status::Error("Has null cell reference"); - } - } - - SpecialType type = SpecialType::Ordinary; - if (special) { - if (bits < 8) { - return td::Status::Error("Not enough data for a special cell"); - } - type = static_cast(td::bitstring::bits_load_ulong(data, 8)); - if (type == SpecialType::Ordinary) { - return td::Status::Error("Special cell has Ordinary type"); - } - } - - LevelMask level_mask; - td::uint32 virtualization = 0; - switch (type) { - case SpecialType::Ordinary: { - for (auto& ref : refs) { - level_mask = level_mask.apply_or(ref->get_level_mask()); - virtualization = td::max(virtualization, ref->get_virtualization()); - } - break; - } - - case SpecialType::PrunnedBranch: { - if (refs.size() != 0) { - return td::Status::Error("PrunnedBranch special cell has a cell reference"); - } - if (bits < 16) { - return td::Status::Error("Not enough data for a PrunnedBranch special cell"); - } - level_mask = LevelMask((td::bitstring::bits_load_ulong(data + 8, 8)) & 0xff); - auto level = level_mask.get_level(); - if (level > max_level || level == 0) { - return td::Status::Error("Prunned Branch has an invalid level"); - } - if (bits != (2 + level_mask.apply(level - 1).get_hashes_count() * (hash_bytes + depth_bytes)) * 8) { - return td::Status::Error("Not enouch data for a PrunnedBranch special cell"); - } - // depth will be checked later! - break; - } - - case SpecialType::Library: { - if (bits != 8 + hash_bytes * 8) { - return td::Status::Error("Not enouch data for a Library special cell"); - } - break; - } - - case SpecialType::MerkleProof: { - if (bits != 8 + (hash_bytes + depth_bytes) * 8) { - return td::Status::Error("Not enouch data for a MerkleProof special cell"); - } - if (refs.size() != 1) { - return td::Status::Error("Wrong references count for a MerkleProof special cell"); - } - if (td::bitstring::bits_memcmp(data + 8, refs[0]->get_hash(0).as_bitslice().get_ptr(), hash_bits) != 0) { - return td::Status::Error("Hash mismatch in a MerkleProof special cell"); - } - if (td::bitstring::bits_load_ulong(data + 8 + hash_bits, depth_bytes * 8) != refs[0]->get_depth(0)) { - return td::Status::Error("Depth mismatch in a MerkleProof special cell"); - } - level_mask = refs[0]->get_level_mask().shift_right(); - virtualization = refs[0]->get_virtualization(); - break; - } - - case SpecialType::MerkleUpdate: { - if (bits != 8 + (hash_bytes + depth_bytes) * 8 * 2) { - return td::Status::Error("Not enouch data for a MerkleUpdate special cell"); - } - if (refs.size() != 2) { - return td::Status::Error("Wrong references count for a MerkleUpdate special cell"); - } - if (td::bitstring::bits_memcmp(data + 8, refs[0]->get_hash(0).as_bitslice().get_ptr(), hash_bits) != 0) { - return td::Status::Error("First hash mismatch in a MerkleProof special cell"); - } - if (td::bitstring::bits_memcmp(data + 8 + hash_bits, refs[1]->get_hash(0).as_bitslice().get_ptr(), hash_bits) != - 0) { - return td::Status::Error("Second hash mismatch in a MerkleProof special cell"); - } - if (td::bitstring::bits_load_ulong(data + 8 + 2 * hash_bits, depth_bytes * 8) != refs[0]->get_depth(0)) { - return td::Status::Error("First depth mismatch in a MerkleProof special cell"); - } - if (td::bitstring::bits_load_ulong(data + 8 + 2 * hash_bits + depth_bytes * 8, depth_bytes * 8) != - refs[1]->get_depth(0)) { - return td::Status::Error("Second depth mismatch in a MerkleProof special cell"); - } - - level_mask = refs[0]->get_level_mask().apply_or(refs[1]->get_level_mask()).shift_right(); - virtualization = td::max(refs[0]->get_virtualization(), refs[1]->get_virtualization()); - break; - } - - default: - return td::Status::Error("Unknown special cell type"); - } - - Info info; - if (td::unlikely(bits > max_bits)) { - return td::Status::Error("Too many bits"); - } - if (td::unlikely(refs.size() > max_refs)) { - return td::Status::Error("Too many cell references"); - } - if (td::unlikely(virtualization > max_virtualization)) { - return td::Status::Error("Too big virtualization"); - } - - CHECK(level_mask.get_level() <= max_level); - - auto hash_count = type == SpecialType::PrunnedBranch ? 1 : level_mask.get_hashes_count(); - DCHECK(hash_count <= max_level + 1); - - info.bits_ = bits; - info.refs_count_ = refs.size() & 7; - info.is_special_ = special; - info.level_mask_ = level_mask.get_mask() & 7; - info.hash_count_ = hash_count & 7; - info.virtualization_ = virtualization & 7; - - auto data_cell = create_empty_data_cell(info); - auto* storage = data_cell->get_storage(); - - // init data - auto* data_ptr = info.get_data(storage); - td::BitPtr{data_ptr}.copy_from(data, bits); - // prepare for serialization - if (bits & 7) { - int m = (0x80 >> (bits & 7)); - unsigned l = bits / 8; - data_ptr[l] = static_cast((data_ptr[l] & -m) | m); - } - - // init refs - auto refs_ptr = info.get_refs(storage); - for (size_t i = 0; i < refs.size(); i++) { - refs_ptr[i] = refs[i].release(); - } - - // init hashes and depth - auto* hashes_ptr = info.get_hashes(storage); - auto* depth_ptr = info.get_depth(storage); - - // NB: be careful with special cells - auto total_hash_count = level_mask.get_hashes_count(); - auto hash_i_offset = total_hash_count - hash_count; - for (td::uint32 level_i = 0, hash_i = 0, level = level_mask.get_level(); level_i <= level; level_i++) { - if (!level_mask.is_significant(level_i)) { - continue; - } - SCOPE_EXIT { - hash_i++; - }; - if (hash_i < hash_i_offset) { - continue; - } - unsigned char tmp[2]; - tmp[0] = info.d1(level_mask.apply(level_i)); - tmp[1] = info.d2(); - - static TD_THREAD_LOCAL digest::SHA256* hasher; - td::init_thread_local(hasher); - hasher->reset(); - - hasher->feed(td::Slice(tmp, 2)); - - if (hash_i == hash_i_offset) { - DCHECK(level_i == 0 || type == SpecialType::PrunnedBranch); - hasher->feed(td::Slice(data_ptr, (bits + 7) >> 3)); - } else { - DCHECK(level_i != 0 && type != SpecialType::PrunnedBranch); - hasher->feed(hashes_ptr[hash_i - hash_i_offset - 1].as_slice()); - } - - auto dest_i = hash_i - hash_i_offset; - - // calc depth - td::uint16 depth = 0; - for (int i = 0; i < info.refs_count_; i++) { - td::uint16 child_depth = 0; - if (type == SpecialType::MerkleProof || type == SpecialType::MerkleUpdate) { - child_depth = refs_ptr[i]->get_depth(level_i + 1); - } else { - child_depth = refs_ptr[i]->get_depth(level_i); - } - - // add depth into hash - td::uint8 child_depth_buf[depth_bytes]; - store_depth(child_depth_buf, child_depth); - hasher->feed(td::Slice(child_depth_buf, depth_bytes)); - - depth = std::max(depth, child_depth); - } - if (info.refs_count_ != 0) { - if (depth >= max_depth) { - return td::Status::Error("Depth is too big"); - } - depth++; - } - depth_ptr[dest_i] = depth; - - // children hash - for (int i = 0; i < info.refs_count_; i++) { - if (type == SpecialType::MerkleProof || type == SpecialType::MerkleUpdate) { - hasher->feed(refs_ptr[i]->get_hash(level_i + 1).as_slice()); - } else { - hasher->feed(refs_ptr[i]->get_hash(level_i).as_slice()); - } - } - auto extracted_size = hasher->extract(hashes_ptr[dest_i].as_slice()); - DCHECK(extracted_size == hash_bytes); - } - - return Ref(data_cell.release(), Ref::acquire_t{}); -} - -const DataCell::Hash DataCell::do_get_hash(td::uint32 level) const { - auto hash_i = get_level_mask().apply(level).get_hash_i(); - if (special_type() == SpecialType::PrunnedBranch) { - auto this_hash_i = get_level_mask().get_hash_i(); - if (hash_i != this_hash_i) { - return reinterpret_cast(info_.get_data(get_storage()) + 2)[hash_i]; - } - hash_i = 0; - } - return info_.get_hashes(get_storage())[hash_i]; -} - -td::uint16 DataCell::do_get_depth(td::uint32 level) const { - auto hash_i = get_level_mask().apply(level).get_hash_i(); - if (special_type() == SpecialType::PrunnedBranch) { - auto this_hash_i = get_level_mask().get_hash_i(); - if (hash_i != this_hash_i) { - return load_depth(info_.get_data(get_storage()) + 2 + hash_bytes * this_hash_i + hash_i * depth_bytes); - } - hash_i = 0; - } - return info_.get_depth(get_storage())[hash_i]; -} - -int DataCell::serialize(unsigned char* buff, int buff_size, bool with_hashes) const { - int len = get_serialized_size(with_hashes); - if (len > buff_size) { - return 0; - } - buff[0] = static_cast(info_.d1() | (with_hashes * 16)); - buff[1] = info_.d2(); - int hs = 0; - if (with_hashes) { - hs = (get_level_mask().get_hashes_count()) * (hash_bytes + depth_bytes); - assert(len >= 2 + hs); - std::memset(buff + 2, 0, hs); - auto dest = td::MutableSlice(buff + 2, hs); - auto level = get_level(); - // TODO: optimize for prunned brandh - for (unsigned i = 0; i <= level; i++) { - if (!get_level_mask().is_significant(i)) { - continue; - } - dest.copy_from(get_hash(i).as_slice()); - dest.remove_prefix(hash_bytes); - } - for (unsigned i = 0; i <= level; i++) { - if (!get_level_mask().is_significant(i)) { - continue; - } - store_depth(dest.ubegin(), get_depth(i)); - dest.remove_prefix(depth_bytes); - } - // buff[2] = 0; // for testing hash verification in deserialization - buff += hs; - len -= hs; - } - std::memcpy(buff + 2, get_data(), len - 2); - return len + hs; -} - -std::string DataCell::serialize() const { - unsigned char buff[max_serialized_bytes]; - int len = serialize(buff, sizeof(buff)); - return std::string(buff, buff + len); -} - -std::string DataCell::to_hex() const { - unsigned char buff[max_serialized_bytes]; - int len = serialize(buff, sizeof(buff)); - char hex_buff[max_serialized_bytes * 2 + 1]; - for (int i = 0; i < len; i++) { - sprintf(hex_buff + 2 * i, "%02x", buff[i]); - } - return hex_buff; -} - -std::ostream& operator<<(std::ostream& os, const DataCell& c) { - return os << c.to_hex(); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.h b/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.h deleted file mode 100644 index bec8b033..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/DataCell.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" - -#include "td/utils/Span.h" - -#include "td/utils/ThreadSafeCounter.h" - -namespace vm { - -class DataCell : public Cell { - public: - DataCell(const DataCell& other) = delete; - ~DataCell() override; - - static void store_depth(td::uint8* dest, td::uint16 depth) { - td::bitstring::bits_store_long(dest, depth, depth_bits); - } - static td::uint16 load_depth(const td::uint8* src) { - return td::bitstring::bits_load_ulong(src, depth_bits) & 0xff; - } - - protected: - struct Info { - unsigned bits_; - - // d1 - unsigned char refs_count_ : 3; - bool is_special_ : 1; - unsigned char level_mask_ : 3; - - unsigned char hash_count_ : 3; - - unsigned char virtualization_ : 3; - - unsigned char d1() const { - return d1(LevelMask{level_mask_}); - } - unsigned char d1(LevelMask level_mask) const { - // d1 = refs_count + 8 * is_special + 32 * level - // + 16 * with_hashes - for seriazlization - // d1 = 7 + 16 + 32 * l - for absent cells - return static_cast(refs_count_ + 8 * is_special_ + 32 * level_mask.get_mask()); - } - unsigned char d2() const { - auto res = static_cast((bits_ / 8) * 2); - if ((bits_ & 7) != 0) { - return static_cast(res + 1); - } - return res; - } - size_t get_hashes_offset() const { - return 0; - } - size_t get_refs_offset() const { - return get_hashes_offset() + hash_bytes * hash_count_; - } - size_t get_depth_offset() const { - return get_refs_offset() + refs_count_ * sizeof(Cell*); - } - size_t get_data_offset() const { - return get_depth_offset() + sizeof(td::uint16) * hash_count_; - } - size_t get_storage_size() const { - return get_data_offset() + (bits_ + 7) / 8; - } - - const Hash* get_hashes(const char* storage) const { - return reinterpret_cast(storage + get_hashes_offset()); - } - - Hash* get_hashes(char* storage) const { - return reinterpret_cast(storage + get_hashes_offset()); - } - - const td::uint16* get_depth(const char* storage) const { - return reinterpret_cast(storage + get_depth_offset()); - } - - td::uint16* get_depth(char* storage) const { - return reinterpret_cast(storage + get_depth_offset()); - } - - const unsigned char* get_data(const char* storage) const { - return reinterpret_cast(storage + get_data_offset()); - } - unsigned char* get_data(char* storage) const { - return reinterpret_cast(storage + get_data_offset()); - } - - Cell* const* get_refs(const char* storage) const { - return reinterpret_cast(storage + get_refs_offset()); - } - Cell** get_refs(char* storage) const { - return reinterpret_cast(storage + get_refs_offset()); - } - }; - - Info info_; - virtual char* get_storage() = 0; - virtual const char* get_storage() const = 0; - // TODO: we may also save three different pointers - - void destroy_storage(char* storage); - - explicit DataCell(Info info); - Cell* get_ref_raw_ptr(unsigned idx) const { - DCHECK(idx < get_refs_cnt()); - return info_.get_refs(get_storage())[idx]; - } - - public: - td::Result load_cell() const override { - return LoadedCell{Ref{this}, {}, {}}; - } - unsigned get_refs_cnt() const { - return info_.refs_count_; - } - unsigned get_bits() const { - return info_.bits_; - } - unsigned size_refs() const { - return info_.refs_count_; - } - unsigned size() const { - return info_.bits_; - } - const unsigned char* get_data() const { - return info_.get_data(get_storage()); - } - Ref get_ref(unsigned idx) const { - if (idx >= get_refs_cnt()) { - return Ref{}; - } - return Ref(get_ref_raw_ptr(idx)); - } - - td::uint32 get_virtualization() const override { - return info_.virtualization_; - } - CellUsageTree::NodePtr get_tree_node() const override { - return {}; - } - bool is_loaded() const override { - return true; - } - LevelMask get_level_mask() const override { - return LevelMask{info_.level_mask_}; - } - - bool is_special() const { - return info_.is_special_; - } - SpecialType special_type() const; - int get_serialized_size(bool with_hashes = false) const { - return ((get_bits() + 23) >> 3) + - (with_hashes ? get_level_mask().get_hashes_count() * (hash_bytes + depth_bytes) : 0); - } - int serialize(unsigned char* buff, int buff_size, bool with_hashes = false) const; - std::string serialize() const; - std::string to_hex() const; - static td::int64 get_total_data_cells() { - return get_thread_safe_counter().sum(); - } - - template - void store(StorerT& storer) const { - storer.template store_binary(info_.d1()); - storer.template store_binary(info_.d2()); - storer.store_slice(td::Slice(get_data(), (get_bits() + 7) / 8)); - } - - protected: - static constexpr auto max_storage_size = max_refs * sizeof(void*) + (max_level + 1) * hash_bytes + max_bytes; - - private: - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DataCell"); - return res; - } - static std::unique_ptr create_empty_data_cell(Info info); - - const Hash do_get_hash(td::uint32 level) const override; - td::uint16 do_get_depth(td::uint32 level) const override; - - friend class CellBuilder; - static td::Result> create(td::ConstBitPtr data, unsigned bits, td::Span> refs, bool special); - static td::Result> create(td::ConstBitPtr data, unsigned bits, td::MutableSpan> refs, - bool special); -}; - -std::ostream& operator<<(std::ostream& os, const DataCell& c); - -} // namespace vm - diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/ExtCell.h b/submodules/ton/tonlib-src/crypto/vm/cells/ExtCell.h deleted file mode 100644 index 401bb048..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/ExtCell.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" -#include "vm/cells/PrunnedCell.h" -#include "common/AtomicRef.h" - -#include -#include "td/utils/port/thread_local.h" -#include "td/utils/HazardPointers.h" -#include "td/utils/optional.h" - -namespace vm { - -template -class ExtCell : public Cell { - private: - struct PrivateTag {}; - - public: - static td::Result>> create(const PrunnedCellInfo& prunned_cell_info, ExtraT&& extra) { - TRY_RESULT(prunned_cell, PrunnedCell::create(prunned_cell_info, std::move(extra))); - return Ref>(true, std::move(prunned_cell), PrivateTag{}); - } - - ExtCell(Ref> prunned_cell, PrivateTag) : prunned_cell_(std::move(prunned_cell)) { - get_thread_safe_counter().add(1); - get_thread_safe_counter_unloaded().add(prunned_cell_.load_unsafe().not_null()); - } - ~ExtCell() { - get_thread_safe_counter().add(-1); - get_thread_safe_counter_unloaded().add(-static_cast(prunned_cell_.load_unsafe().not_null())); - } - - LevelMask get_level_mask() const override { - return CellView(this)->get_level_mask(); - } - - td::Result load_cell() const override { - TRY_RESULT(data_cell, load_data_cell()); - return LoadedCell{std::move(data_cell), {}, {}}; - } - td::uint32 get_virtualization() const override { - return 0; - } - CellUsageTree::NodePtr get_tree_node() const override { - return {}; - } - bool is_loaded() const override { - return CellView(this)->is_loaded(); - } - - private: - mutable td::AtomicRef data_cell_; - mutable td::AtomicRef> prunned_cell_; - - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("ExtCell"); - return res; - } - - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter_unloaded() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("ExtCell.unloaded"); - return res; - } - - struct CellView { - CellView(const ExtCell* cell) { - cell_ = cell->data_cell_.get_unsafe(); - if (cell_) { - return; - } - - prunned_cell_ = cell->prunned_cell_.load(); - if (!prunned_cell_.is_null()) { - cell_ = &*prunned_cell_; - return; - } - cell_ = cell->data_cell_.get_unsafe(); - DCHECK(cell_); - } - - const Cell* operator->() const { - return cell_; - } - - td::Ref> prunned_cell_; - const Cell* cell_; - }; - - const Hash do_get_hash(td::uint32 level) const override { - return CellView(this)->get_hash(level); - } - - td::uint16 do_get_depth(td::uint32 level) const override { - return CellView(this)->get_depth(level); - } - - td::Result> load_data_cell() const { - auto data_cell = data_cell_.get_unsafe(); - if (data_cell) { - return Ref(data_cell); - } - - auto prunned_cell = prunned_cell_.load(); - - if (prunned_cell.is_null()) { - data_cell = data_cell_.get_unsafe(); - DCHECK(data_cell); - return Ref(data_cell); - } - - TRY_RESULT(new_data_cell, Loader::load_data_cell(*this, prunned_cell->get_extra())); - TRY_STATUS(prunned_cell->check_equals_unloaded(new_data_cell)); - - if (data_cell_.store_if_empty(new_data_cell)) { - prunned_cell_.store({}); - get_thread_safe_counter_unloaded().add(-1); - } - - return data_cell_.load_unsafe(); - } -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.cpp deleted file mode 100644 index 46d73f0d..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "LevelMask.h" - -namespace vm { -namespace detail { -td::StringBuilder& operator<<(td::StringBuilder& sb, LevelMask level_mask) { - sb << "LevelMask{"; - for (int i = 0, level = level_mask.get_level(); i < level; i++) { - sb << "01"[(level_mask.get_mask() >> i) % 2]; - } - sb << "}"; - return sb; -} -} // namespace detail -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.h b/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.h deleted file mode 100644 index 35d03d93..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/LevelMask.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/bits.h" -#include "td/utils/int_types.h" -#include "td/utils/StringBuilder.h" - -namespace td { -class StringBuilder; -} - -namespace vm { -namespace detail { -class LevelMask { - public: - explicit LevelMask(td::uint32 new_mask = 0) : mask_(new_mask) { - } - td::uint32 get_mask() const { - return mask_; - } - td::uint32 get_level() const { - return 32 - td::count_leading_zeroes32(mask_); - } - td::uint32 get_hash_i() const { - return td::count_bits32(mask_); - } - td::uint32 get_hashes_count() const { - return get_hash_i() + 1; - } - LevelMask apply(td::uint32 level) const { - DCHECK(level < 32); - return LevelMask{mask_ & ((1u << level) - 1)}; - } - LevelMask apply_or(LevelMask other) const { - return LevelMask{mask_ | other.mask_}; - } - LevelMask shift_right() const { - return LevelMask{mask_ >> 1}; - } - bool is_significant(td::uint32 level) const { - DCHECK(level < 32); - bool res = level == 0 || ((mask_ >> (level - 1)) % 2 != 0); - CHECK(res == (apply(level).get_level() == level)); - return res; - } - - bool operator==(const LevelMask& other) const { - return mask_ == other.mask_; - } - bool operator!=(const LevelMask& other) const { - return !(*this == other); - } - - static LevelMask one_level(td::uint32 level) { - DCHECK(level < 32); - if (level == 0) { - return LevelMask(0); - } - return LevelMask(1 << (level - 1)); - } - - private: - td::uint32 mask_; -}; -td::StringBuilder& operator<<(td::StringBuilder& sb, LevelMask level_mask); -} // namespace detail -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.cpp deleted file mode 100644 index aee34367..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/MerkleProof.h" -#include "vm/cells/CellBuilder.h" -#include "vm/cells/CellSlice.h" -#include "vm/boc.h" - -#include "td/utils/HashMap.h" -#include "td/utils/HashSet.h" - -namespace vm { -namespace detail { -class MerkleProofImpl { - public: - explicit MerkleProofImpl(MerkleProof::IsPrunnedFunction is_prunned) : is_prunned_(std::move(is_prunned)) { - } - explicit MerkleProofImpl(CellUsageTree *usage_tree) : usage_tree_(usage_tree) { - } - - Ref create_from(Ref cell) { - if (!is_prunned_) { - CHECK(usage_tree_); - dfs_usage_tree(cell, usage_tree_->root_id()); - is_prunned_ = [this](const Ref &cell) { return visited_cells_.count(cell->get_hash()) == 0; }; - } - return dfs(cell, cell->get_level()); - } - - private: - using Key = std::pair; - td::HashMap> cells_; - td::HashSet visited_cells_; - CellUsageTree *usage_tree_{nullptr}; - MerkleProof::IsPrunnedFunction is_prunned_; - - void dfs_usage_tree(Ref cell, CellUsageTree::NodeId node_id) { - if (!usage_tree_->is_loaded(node_id)) { - return; - } - visited_cells_.insert(cell->get_hash()); - CellSlice cs(NoVm(), cell); - for (unsigned i = 0; i < cs.size_refs(); i++) { - dfs_usage_tree(cs.prefetch_ref(i), usage_tree_->get_child(node_id, i)); - } - } - - Ref dfs(Ref cell, int merkle_depth) { - CHECK(cell.not_null()); - Key key{cell->get_hash(), merkle_depth}; - { - auto it = cells_.find(key); - if (it != cells_.end()) { - CHECK(it->second.not_null()); - return it->second; - } - } - - if (is_prunned_(cell)) { - auto res = CellBuilder::create_pruned_branch(cell, merkle_depth + 1); - CHECK(res.not_null()); - cells_.emplace(key, res); - return res; - } - CellSlice cs(NoVm(), cell); - int children_merkle_depth = cs.child_merkle_depth(merkle_depth); - CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - for (unsigned i = 0; i < cs.size_refs(); i++) { - cb.store_ref(dfs(cs.prefetch_ref(i), children_merkle_depth)); - } - auto res = cb.finalize(cs.is_special()); - CHECK(res.not_null()); - cells_.emplace(key, res); - return res; - } -}; -} // namespace detail - -Ref MerkleProof::generate_raw(Ref cell, IsPrunnedFunction is_prunned) { - return detail::MerkleProofImpl(is_prunned).create_from(cell); -} - -Ref MerkleProof::generate_raw(Ref cell, CellUsageTree *usage_tree) { - return detail::MerkleProofImpl(usage_tree).create_from(cell); -} - -Ref MerkleProof::virtualize_raw(Ref cell, Cell::VirtualizationParameters virt) { - return cell->virtualize(virt); -} - -Ref MerkleProof::generate(Ref cell, IsPrunnedFunction is_prunned) { - int cell_level = cell->get_level(); - if (cell_level != 0) { - return {}; - } - auto raw = generate_raw(std::move(cell), is_prunned); - return CellBuilder::create_merkle_proof(std::move(raw)); -} - -Ref MerkleProof::generate(Ref cell, CellUsageTree *usage_tree) { - int cell_level = cell->get_level(); - if (cell_level != 0) { - return {}; - } - auto raw = generate_raw(std::move(cell), usage_tree); - return CellBuilder::create_merkle_proof(std::move(raw)); -} - -td::Result> unpack_proof(Ref cell) { - CHECK(cell.not_null()); - td::uint8 level = static_cast(cell->get_level()); - if (level != 0) { - return td::Status::Error("Level of MerkleProof must be zero"); - } - CellSlice cs(NoVm(), std::move(cell)); - if (cs.special_type() != Cell::SpecialType::MerkleProof) { - return td::Status::Error("Not a MekleProof cell"); - } - return cs.fetch_ref(); -} - -Ref MerkleProof::virtualize(Ref cell, int virtualization) { - auto r_raw = unpack_proof(std::move(cell)); - if (r_raw.is_error()) { - return {}; - } - return virtualize_raw(r_raw.move_as_ok(), {0 /*level*/, static_cast(virtualization)}); -} - -class MerkleProofCombineFast { - public: - MerkleProofCombineFast(Ref a, Ref b) : a_(std::move(a)), b_(std::move(b)) { - } - td::Result> run() { - if (a_.is_null()) { - return b_; - } else if (b_.is_null()) { - return a_; - } - TRY_RESULT_ASSIGN(a_, unpack_proof(a_)); - TRY_RESULT_ASSIGN(b_, unpack_proof(b_)); - TRY_RESULT(res, run_raw()); - return CellBuilder::create_merkle_proof(std::move(res)); - } - - td::Result> run_raw() { - if (a_->get_hash(0) != b_->get_hash(0)) { - return td::Status::Error("Can't combine MerkleProofs with different roots"); - } - return merge(a_, b_, 0); - } - - private: - Ref a_; - Ref b_; - - Ref merge(Ref a, Ref b, td::uint32 merkle_depth) { - if (a->get_hash() == b->get_hash()) { - return a; - } - if (a->get_level() == merkle_depth) { - return a; - } - if (b->get_level() == merkle_depth) { - return b; - } - - CellSlice csa(NoVm(), a); - CellSlice csb(NoVm(), b); - - if (csa.is_special() && csa.special_type() == vm::Cell::SpecialType::PrunnedBranch) { - return b; - } - if (csb.is_special() && csb.special_type() == vm::Cell::SpecialType::PrunnedBranch) { - return a; - } - - CHECK(csa.size_refs() != 0); - - auto child_merkle_depth = csa.child_merkle_depth(merkle_depth); - - CellBuilder cb; - cb.store_bits(csa.fetch_bits(csa.size())); - for (unsigned i = 0; i < csa.size_refs(); i++) { - cb.store_ref(merge(csa.prefetch_ref(i), csb.prefetch_ref(i), child_merkle_depth)); - } - return cb.finalize(csa.is_special()); - } -}; - -class MerkleProofCombine { - public: - MerkleProofCombine(Ref a, Ref b) : a_(std::move(a)), b_(std::move(b)) { - } - td::Result> run() { - if (a_.is_null()) { - return b_; - } else if (b_.is_null()) { - return a_; - } - TRY_RESULT_ASSIGN(a_, unpack_proof(a_)); - TRY_RESULT_ASSIGN(b_, unpack_proof(b_)); - TRY_RESULT(res, run_raw()); - return CellBuilder::create_merkle_proof(std::move(res)); - } - - td::Result> run_raw() { - if (a_->get_hash(0) != b_->get_hash(0)) { - return td::Status::Error("Can't combine MerkleProofs with different roots"); - } - dfs(a_, 0); - dfs(b_, 0); - return create_A(a_, 0, 0); - } - - private: - Ref a_; - Ref b_; - - struct Info { - Ref cell_; - Ref prunned_cells_[Cell::max_level]; // Cache prunned cells with different levels to reuse them - - Ref get_prunned_cell(int depth) { - if (depth < Cell::max_level) { - return prunned_cells_[depth]; - } - return {}; - } - Ref get_any_cell() const { - if (cell_.not_null()) { - return cell_; - } - for (auto &cell : prunned_cells_) { - if (cell.not_null()) { - return cell; - } - } - UNREACHABLE(); - } - }; - - using Key = std::pair; - td::HashMap cells_; - td::HashMap> create_A_res_; - td::HashSet visited_; - - void dfs(Ref cell, int merkle_depth) { - if (!visited_.emplace(cell->get_hash(), merkle_depth).second) { - return; - } - - auto &info = cells_[cell->get_hash(merkle_depth)]; - CellSlice cs(NoVm(), cell); - // check if prunned cell is bounded - if (cs.special_type() == Cell::SpecialType::PrunnedBranch && static_cast(cell->get_level()) > merkle_depth) { - info.prunned_cells_[cell->get_level() - 1] = std::move(cell); - return; - } - info.cell_ = std::move(cell); - - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - for (size_t i = 0, size = cs.size_refs(); i < size; i++) { - dfs(cs.fetch_ref(), child_merkle_depth); - } - } - - Ref create_A(Ref cell, int merkle_depth, int a_merkle_depth) { - merkle_depth = cell->get_level_mask().apply(merkle_depth).get_level(); - auto key = Key(cell->get_hash(merkle_depth), a_merkle_depth); - auto it = create_A_res_.find(key); - if (it != create_A_res_.end()) { - return it->second; - } - - auto res = do_create_A(std::move(cell), merkle_depth, a_merkle_depth); - create_A_res_.emplace(key, res); - return res; - } - - Ref do_create_A(Ref cell, int merkle_depth, int a_merkle_depth) { - auto &info = cells_[cell->get_hash(merkle_depth)]; - - if (info.cell_.is_null()) { - Ref res = info.get_prunned_cell(a_merkle_depth); - if (res.is_null()) { - res = CellBuilder::create_pruned_branch(info.get_any_cell(), a_merkle_depth + 1, merkle_depth); - } - return res; - } - - CHECK(info.cell_.not_null()); - CellSlice cs(NoVm(), info.cell_); - - //CHECK(cs.size_refs() != 0); - if (cs.size_refs() == 0) { - return info.cell_; - } - - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - auto child_a_merkle_depth = cs.child_merkle_depth(a_merkle_depth); - - CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - for (unsigned i = 0; i < cs.size_refs(); i++) { - cb.store_ref(create_A(cs.prefetch_ref(i), child_merkle_depth, child_a_merkle_depth)); - } - return cb.finalize(cs.is_special()); - } -}; - -Ref MerkleProof::combine(Ref a, Ref b) { - auto res = MerkleProofCombine(std::move(a), std::move(b)).run(); - if (res.is_error()) { - return {}; - } - return res.move_as_ok(); -} - -td::Result> MerkleProof::combine_status(Ref a, Ref b) { - return MerkleProofCombine(std::move(a), std::move(b)).run(); -} - -Ref MerkleProof::combine_fast(Ref a, Ref b) { - auto res = MerkleProofCombineFast(std::move(a), std::move(b)).run(); - if (res.is_error()) { - return {}; - } - return res.move_as_ok(); -} - -td::Result> MerkleProof::combine_fast_status(Ref a, Ref b) { - return MerkleProofCombineFast(std::move(a), std::move(b)).run(); -} - -Ref MerkleProof::combine_raw(Ref a, Ref b) { - auto res = MerkleProofCombine(std::move(a), std::move(b)).run_raw(); - if (res.is_error()) { - return {}; - } - return res.move_as_ok(); -} - -Ref MerkleProof::combine_fast_raw(Ref a, Ref b) { - auto res = MerkleProofCombineFast(std::move(a), std::move(b)).run_raw(); - if (res.is_error()) { - return {}; - } - return res.move_as_ok(); -} - -MerkleProofBuilder::MerkleProofBuilder(Ref root) - : usage_tree(std::make_shared()), orig_root(std::move(root)) { - usage_root = UsageCell::create(orig_root, usage_tree->root_ptr()); -} - -Ref MerkleProofBuilder::init(Ref root) { - usage_tree = std::make_shared(); - orig_root = std::move(root); - usage_root = UsageCell::create(orig_root, usage_tree->root_ptr()); - return usage_root; -} - -bool MerkleProofBuilder::clear() { - usage_tree.reset(); - orig_root.clear(); - usage_root.clear(); - return true; -} - -Ref MerkleProofBuilder::extract_proof() const { - return MerkleProof::generate(orig_root, usage_tree.get()); -} - -bool MerkleProofBuilder::extract_proof_to(Ref &proof_root) const { - return orig_root.not_null() && (proof_root = extract_proof()).not_null(); -} - -td::Result MerkleProofBuilder::extract_proof_boc() const { - Ref proof_root = extract_proof(); - if (proof_root.is_null()) { - return td::Status::Error("cannot create Merkle proof"); - } else { - return std_boc_serialize(std::move(proof_root)); - } -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.h b/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.h deleted file mode 100644 index 4f2add6c..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleProof.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" -#include "td/utils/buffer.h" - -#include -#include - -namespace vm { - -class MerkleProof { - public: - using IsPrunnedFunction = std::function &)>; - - // works with proofs wrapped in MerkleProof special cell - // cells must have zero level - static Ref generate(Ref cell, IsPrunnedFunction is_prunned); - static Ref generate(Ref cell, CellUsageTree *usage_tree); - - // cell must have zero level and must be a MerkleProof - static Ref virtualize(Ref cell, int virtualization); - - static Ref combine(Ref a, Ref b); - static td::Result> combine_status(Ref a, Ref b); - static Ref combine_fast(Ref a, Ref b); - static td::Result> combine_fast_status(Ref a, Ref b); - - // works with upwrapped proofs - // works fine with cell of non-zero level, but this is not supported (yet?) in MerkeProof special cell - static Ref generate_raw(Ref cell, IsPrunnedFunction is_prunned); - static Ref generate_raw(Ref cell, CellUsageTree *usage_tree); - static Ref virtualize_raw(Ref cell, Cell::VirtualizationParameters virt); - static Ref combine_raw(Ref a, Ref b); - static Ref combine_fast_raw(Ref a, Ref b); -}; - -class MerkleProofBuilder { - std::shared_ptr usage_tree; - Ref orig_root, usage_root; - - public: - MerkleProofBuilder() = default; - MerkleProofBuilder(Ref root); - Ref init(Ref root); - bool clear(); - Ref root() const { - return usage_root; - } - Ref extract_proof() const; - bool extract_proof_to(Ref &proof_root) const; - td::Result extract_proof_boc() const; -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.cpp deleted file mode 100644 index 3cc656c0..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/MerkleUpdate.h" -#include "vm/cells/MerkleProof.h" - -#include "td/utils/HashMap.h" -#include "td/utils/HashSet.h" - -namespace vm { -namespace detail { -class MerkleUpdateApply { - public: - Ref apply(Ref from, Ref update_from, Ref update_to, td::uint32 from_level, - td::uint32 to_level) { - if (from_level != from->get_level()) { - return {}; - } - dfs_both(from, update_from, from_level); - return dfs(update_to, to_level); - } - - private: - using Key = std::pair; - td::HashMap> known_cells_; - td::HashMap> ready_cells_; - - void dfs_both(Ref original, Ref update_from, int merkle_depth) { - CellSlice cs_update_from(NoVm(), update_from); - known_cells_.emplace(original->get_hash(merkle_depth), original); - if (cs_update_from.special_type() == Cell::SpecialType::PrunnedBranch) { - return; - } - int child_merkle_depth = cs_update_from.child_merkle_depth(merkle_depth); - - CellSlice cs_original(NoVm(), original); - for (unsigned i = 0; i < cs_original.size_refs(); i++) { - dfs_both(cs_original.prefetch_ref(i), cs_update_from.prefetch_ref(i), child_merkle_depth); - } - } - - Ref dfs(Ref cell, int merkle_depth) { - CellSlice cs(NoVm(), cell); - if (cs.special_type() == Cell::SpecialType::PrunnedBranch) { - if ((int)cell->get_level() == merkle_depth + 1) { - auto it = known_cells_.find(cell->get_hash(merkle_depth)); - if (it != known_cells_.end()) { - return it->second; - } - return {}; - } - return cell; - } - Key key{cell->get_hash(), merkle_depth}; - { - auto it = ready_cells_.find(key); - if (it != ready_cells_.end()) { - return it->second; - } - } - - int child_merkle_depth = cs.child_merkle_depth(merkle_depth); - - CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - for (unsigned i = 0; i < cs.size_refs(); i++) { - auto ref = dfs(cs.prefetch_ref(i), child_merkle_depth); - if (ref.is_null()) { - return {}; - } - cb.store_ref(std::move(ref)); - } - auto res = cb.finalize(cs.is_special()); - ready_cells_.emplace(key, res); - return res; - } -}; - -class MerkleUpdateValidator { - public: - td::Status validate(Ref update_from, Ref update_to, td::uint32 from_level, td::uint32 to_level) { - dfs_from(update_from, from_level); - return dfs_to(update_to, to_level); - } - - private: - td::HashSet known_cells_; - using Key = std::pair; - td::HashSet visited_from_; - td::HashSet visited_to_; - - void dfs_from(Ref cell, int merkle_depth) { - if (!visited_from_.emplace(cell->get_hash(), merkle_depth).second) { - return; - } - CellSlice cs(NoVm(), cell); - known_cells_.insert(cell->get_hash(merkle_depth)); - if (cs.special_type() == Cell::SpecialType::PrunnedBranch) { - return; - } - int child_merkle_depth = cs.child_merkle_depth(merkle_depth); - for (unsigned i = 0; i < cs.size_refs(); i++) { - dfs_from(cs.prefetch_ref(i), child_merkle_depth); - } - } - - td::Status dfs_to(Ref cell, int merkle_depth) { - if (!visited_to_.emplace(cell->get_hash(), merkle_depth).second) { - return td::Status::OK(); - } - CellSlice cs(NoVm(), cell); - if (cs.special_type() == Cell::SpecialType::PrunnedBranch) { - if ((int)cell->get_level() == merkle_depth + 1) { - if (known_cells_.count(cell->get_hash(merkle_depth)) == 0) { - return td::Status::Error(PSLICE() - << "Unknown prunned cell (validate): " << cell->get_hash(merkle_depth).to_hex()); - } - } - return td::Status::OK(); - } - int child_merkle_depth = cs.child_merkle_depth(merkle_depth); - - for (unsigned i = 0; i < cs.size_refs(); i++) { - TRY_STATUS(dfs_to(cs.prefetch_ref(i), child_merkle_depth)); - } - return td::Status::OK(); - } -}; -} // namespace detail - -td::Status MerkleUpdate::may_apply(Ref from, Ref update) { - if (update->get_level() != 0 || from->get_level() != 0) { - return td::Status::Error("Level of update of from is not zero"); - } - CellSlice cs(NoVm(), std::move(update)); - if (cs.special_type() != Cell::SpecialType::MerkleUpdate) { - return td::Status::Error("Update cell is not a MerkeUpdate"); - } - auto update_from = cs.fetch_ref(); - if (from->get_hash(0) != update_from->get_hash(0)) { - return td::Status::Error("Hash mismatch"); - } - return td::Status::OK(); -} - -Ref MerkleUpdate::apply(Ref from, Ref update) { - if (update->get_level() != 0 || from->get_level() != 0) { - return {}; - } - CellSlice cs(NoVm(), std::move(update)); - if (cs.special_type() != Cell::SpecialType::MerkleUpdate) { - return {}; - } - auto update_from = cs.fetch_ref(); - auto update_to = cs.fetch_ref(); - return apply_raw(std::move(from), std::move(update_from), std::move(update_to), 0, 0); -} - -Ref MerkleUpdate::apply_raw(Ref from, Ref update_from, Ref update_to, td::uint32 from_level, - td::uint32 to_level) { - if (from->get_hash(from_level) != update_from->get_hash(from_level)) { - LOG(DEBUG) << "invalid Merkle update: expected old value hash = " << update_from->get_hash(from_level).to_hex() - << ", applied to value with hash = " << from->get_hash(from_level).to_hex(); - return {}; - } - return detail::MerkleUpdateApply().apply(from, std::move(update_from), std::move(update_to), from_level, to_level); -} - -std::pair, Ref> MerkleUpdate::generate_raw(Ref from, Ref to, CellUsageTree *usage_tree) { - // create Merkle update cell->new_cell - auto update_to = MerkleProof::generate_raw(to, [tree = usage_tree](const Ref &cell) { - auto loaded_cell = cell->load_cell().move_as_ok(); // FIXME - if (loaded_cell.data_cell->size_refs() == 0) { - return false; - } - return !loaded_cell.tree_node.empty() && loaded_cell.tree_node.mark_path(tree); - }); - usage_tree->set_use_mark_for_is_loaded(true); - auto update_from = MerkleProof::generate_raw(from, usage_tree); - - return {std::move(update_from), std::move(update_to)}; -} - -td::Status MerkleUpdate::validate_raw(Ref update_from, Ref update_to, td::uint32 from_level, - td::uint32 to_level) { - return detail::MerkleUpdateValidator().validate(std::move(update_from), std::move(update_to), from_level, to_level); -} - -td::Status MerkleUpdate::validate(Ref update) { - if (update->get_level() != 0) { - return td::Status::Error("nonzero level"); - } - CellSlice cs(NoVm(), std::move(update)); - if (cs.special_type() != Cell::SpecialType::MerkleUpdate) { - return td::Status::Error("not a MerkleUpdate cell"); - } - auto update_from = cs.fetch_ref(); - auto update_to = cs.fetch_ref(); - return validate_raw(std::move(update_from), std::move(update_to), 0, 0); -} - -Ref MerkleUpdate::generate(Ref from, Ref to, CellUsageTree *usage_tree) { - auto from_level = from->get_level(); - auto to_level = to->get_level(); - if (from_level != 0 || to_level != 0) { - return {}; - } - auto res = generate_raw(std::move(from), std::move(to), usage_tree); - return CellBuilder::create_merkle_update(res.first, res.second); -} - -namespace detail { -class MerkleCombine { - public: - MerkleCombine(Ref AB, Ref CD) : AB_(std::move(AB)), CD_(std::move(CD)) { - } - - td::Result> run() { - TRY_RESULT(AB, unpack_update(std::move(AB_))); - TRY_RESULT(CD, unpack_update(std::move(CD_))); - std::tie(A_, B_) = AB; - std::tie(C_, D_) = CD; - if (B_->get_hash(0) != C_->get_hash(0)) { - return td::Status::Error("Impossible to combine merkle updates"); - } - - auto log = [](td::Slice name, auto cell) { - CellSlice cs(NoVm(), cell); - LOG(ERROR) << name << " " << cell->get_level(); - cs.print_rec(std::cerr); - }; - if (0) { - log("A", A_); - log("B", B_); - log("C", C_); - log("D", D_); - } - - // We have four bags of cells. A, B, C and D. - // X = Virtualize(A), A is subtree (merkle proof) of X - // Y = Virtualize(B) = Virtualize(C), B and C are subrees of Y - // Z = Virtualize(D), D is subtree of Z - // - // Prunned cells bounded by merkle proof P are essentially cells which are impossible to load during traversal of Virtualize(P) - // - // We want to create new_A and new_D - // Virtualize(new_A) = X - // Virtualize(new_D) = Z - // All prunned branches bounded by new_D must be in new_A - // i.e. if we have all cells reachable in Virtualize(new_A) we may construct Z from them (and from new_D) - // - // Main idea is following - // 1. Create maximum subtrees of X and Z with all cells in A, B, C and D - // Max(V) - such maximum subtree - // - // 2. Max(A) and Max(D) should be merkle update already. But we want to minimize it - // So we cut all branches of Max(D) which are in maxA - // When we cut branch q in Max(D) we mark some path to q in Max(A) - // Then we cut all branches of Max(A) which are not marked. - // - // How to create Max(A)? - // We just store all cells reachable from A, B, C and D in big cache. - // It we reach bounded prunned cell during traversion we may continue traversial with a cell from the cache. - // - // - // 1. load_cells(root) - caches all cell reachable in Virtualize(root); - visited_.clear(); - load_cells(A_, 0); - visited_.clear(); - load_cells(B_, 0); - visited_.clear(); - load_cells(C_, 0); - visited_.clear(); - load_cells(D_, 0); - - // 2. mark_A(A) - Traverse Max(A), but uses all cached cells from step 1. Mark all visited cells - A_usage_tree_ = std::make_shared(); - mark_A(A_, 0, A_usage_tree_->root_id()); - - // 3. create_D(D) - create new_D. Traverse Max(D), and stop at marked cells. Mark path in A to marked cells - auto new_D = create_D(D_, 0, 0); - if (new_D.is_null()) { - return td::Status::Error("Failed to combine updates. One of them is probably an invalid update"); - } - - // 4. create_A(A) - create new_A. Traverse Max(A), and stop at cells not marked at step 3. - auto new_A = create_A(A_, 0, 0); - if (0) { - log("NewD", new_D); - } - - return CellBuilder::create_merkle_update(new_A, new_D); - } - - private: - Ref AB_, CD_; - Ref A_, B_, C_, D_; - - std::shared_ptr A_usage_tree_; - - struct Info { - Ref cell_; - Ref prunned_cells_[Cell::max_level]; // Cache prunned cells with different levels to reuse them - CellUsageTree::NodeId A_node_id{0}; - - Ref get_prunned_cell(int depth) { - if (depth < Cell::max_level) { - return prunned_cells_[depth]; - } - return {}; - } - Ref get_any_cell() const { - if (cell_.not_null()) { - return cell_; - } - for (auto &cell : prunned_cells_) { - if (cell.not_null()) { - return cell; - } - } - UNREACHABLE(); - } - }; - using Key = std::pair; - td::HashMap cells_; - td::HashMap> create_A_res_; - td::HashMap> create_D_res_; - td::HashSet visited_; - - void load_cells(Ref cell, int merkle_depth) { - if (!visited_.emplace(cell->get_hash(), merkle_depth).second) { - return; - } - - auto &info = cells_[cell->get_hash(merkle_depth)]; - CellSlice cs(NoVm(), cell); - - // check if prunned cell is bounded - if (cs.special_type() == Cell::SpecialType::PrunnedBranch && static_cast(cell->get_level()) > merkle_depth) { - info.prunned_cells_[cell->get_level() - 1] = std::move(cell); - return; - } - - info.cell_ = std::move(cell); - - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - for (size_t i = 0, size = cs.size_refs(); i < size; i++) { - load_cells(cs.fetch_ref(), child_merkle_depth); - } - } - - void mark_A(Ref cell, int merkle_depth, CellUsageTree::NodeId node_id) { - CHECK(node_id != 0); - - // cell in cache may be virtualized with different level - // so we make merkle_depth as small as possible - merkle_depth = cell->get_level_mask().apply(merkle_depth).get_level(); - - auto &info = cells_[cell->get_hash(merkle_depth)]; - if (info.A_node_id != 0) { - return; - } - info.A_node_id = node_id; - if (info.cell_.is_null()) { - return; - } - - CellSlice cs(NoVm(), info.cell_); - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - for (int i = 0, size = cs.size_refs(); i < size; i++) { - mark_A(cs.fetch_ref(), child_merkle_depth, A_usage_tree_->create_child(node_id, i)); - } - } - - Ref create_D(Ref cell, int merkle_depth, int d_merkle_depth) { - merkle_depth = cell->get_level_mask().apply(merkle_depth).get_level(); - auto key = Key(cell->get_hash(merkle_depth), d_merkle_depth); - auto it = create_D_res_.find(key); - if (it != create_D_res_.end()) { - return it->second; - } - - auto res = do_create_D(std::move(cell), merkle_depth, d_merkle_depth); - if (res.is_null()) { - return {}; - } - create_D_res_.emplace(key, res); - return res; - } - - Ref do_create_D(Ref cell, int merkle_depth, int d_merkle_depth) { - auto &info = cells_[cell->get_hash(merkle_depth)]; - if (info.A_node_id != 0) { - A_usage_tree_->mark_path(info.A_node_id); - Ref res = info.get_prunned_cell(d_merkle_depth); - if (res.is_null()) { - res = CellBuilder::create_pruned_branch(info.get_any_cell(), d_merkle_depth + 1, merkle_depth); - } - return res; - } - - if (info.cell_.is_null()) { - return {}; - } - - CellSlice cs(NoVm(), info.cell_); - - if (cs.size_refs() == 0) { - return info.cell_; - } - - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - auto child_d_merkle_depth = cs.child_merkle_depth(d_merkle_depth); - - CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - for (unsigned i = 0; i < cs.size_refs(); i++) { - auto ref = create_D(cs.prefetch_ref(i), child_merkle_depth, child_d_merkle_depth); - if (ref.is_null()) { - return {}; - } - cb.store_ref(std::move(ref)); - } - return cb.finalize(cs.is_special()); - } - - Ref create_A(Ref cell, int merkle_depth, int a_merkle_depth) { - merkle_depth = cell->get_level_mask().apply(merkle_depth).get_level(); - auto key = Key(cell->get_hash(merkle_depth), a_merkle_depth); - auto it = create_A_res_.find(key); - if (it != create_A_res_.end()) { - return it->second; - } - - auto res = do_create_A(std::move(cell), merkle_depth, a_merkle_depth); - create_A_res_.emplace(key, res); - return res; - } - - Ref do_create_A(Ref cell, int merkle_depth, int a_merkle_depth) { - auto &info = cells_[cell->get_hash(merkle_depth)]; - - CHECK(info.A_node_id != 0); - if (!A_usage_tree_->has_mark(info.A_node_id)) { - Ref res = info.get_prunned_cell(a_merkle_depth); - if (res.is_null()) { - res = CellBuilder::create_pruned_branch(info.get_any_cell(), a_merkle_depth + 1, merkle_depth); - } - return res; - } - - CHECK(info.cell_.not_null()); - CellSlice cs(NoVm(), info.cell_); - - CHECK(cs.size_refs() != 0); - if (cs.size_refs() == 0) { - return info.cell_; - } - - auto child_merkle_depth = cs.child_merkle_depth(merkle_depth); - auto child_a_merkle_depth = cs.child_merkle_depth(a_merkle_depth); - - CellBuilder cb; - cb.store_bits(cs.fetch_bits(cs.size())); - for (unsigned i = 0; i < cs.size_refs(); i++) { - cb.store_ref(create_A(cs.prefetch_ref(i), child_merkle_depth, child_a_merkle_depth)); - } - return cb.finalize(cs.is_special()); - } - - td::Result, Ref>> unpack_update(Ref update) const { - if (update->get_level() != 0) { - return td::Status::Error("level is not zero"); - } - CellSlice cs(NoVm(), std::move(update)); - if (cs.special_type() != Cell::SpecialType::MerkleUpdate) { - return td::Status::Error("Not a Merkle Update cell"); - } - auto update_from = cs.fetch_ref(); - auto update_to = cs.fetch_ref(); - return std::make_pair(std::move(update_from), std::move(update_to)); - } -}; -} // namespace detail - -Ref MerkleUpdate::combine(Ref ab, Ref bc) { - detail::MerkleCombine combine(ab, bc); - auto res = combine.run(); - if (res.is_error()) { - return {}; - } - return res.move_as_ok(); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.h b/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.h deleted file mode 100644 index 41b4c138..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/MerkleUpdate.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" -#include "vm/cells/CellSlice.h" -#include "vm/cells/CellBuilder.h" - -#include "td/utils/Status.h" - -#include - -namespace vm { -class MerkleUpdate { - public: - // from + update == to - static Ref generate(Ref from, Ref to, CellUsageTree *usage_tree); - // Returns empty Ref if something go wrong. If validate(from).is_ok() and may_apply(from, to).is_ok(), then it - // must not fail. - static Ref apply(Ref from, Ref update); - - // check if update is valid - static TD_WARN_UNUSED_RESULT td::Status validate(Ref update); - // check that hash in from is same as hash stored in update. Do not validate update - static TD_WARN_UNUSED_RESULT td::Status may_apply(Ref from, Ref update); - - static Ref apply_raw(Ref from, Ref update_from, Ref update_to, td::uint32 from_level, - td::uint32 to_level); - static std::pair, Ref> generate_raw(Ref from, Ref to, CellUsageTree *usage_tree); - static td::Status validate_raw(Ref update_from, Ref update_to, td::uint32 from_level, - td::uint32 to_level); - - static Ref combine(Ref ab, Ref bc); -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/PrunnedCell.h b/submodules/ton/tonlib-src/crypto/vm/cells/PrunnedCell.h deleted file mode 100644 index e8434ae4..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/PrunnedCell.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/CellWithStorage.h" -#include "vm/cells/Cell.h" - -namespace vm { -struct PrunnedCellInfo { - Cell::LevelMask level_mask; - td::Slice hash; - td::Slice depth; -}; - -template -class PrunnedCell : public Cell { - public: - const ExtraT& get_extra() const { - return extra_; - } - - static td::Result>> create(const PrunnedCellInfo& prunned_cell_info, ExtraT&& extra) { - auto level_mask = prunned_cell_info.level_mask; - if (level_mask.get_level() > max_level) { - return td::Status::Error("Level is too big"); - } - Info info(level_mask); - auto prunned_cell = - detail::CellWithUniquePtrStorage>::create(info.get_storage_size(), info, std::move(extra)); - TRY_STATUS(prunned_cell->init(prunned_cell_info)); - return Ref>(prunned_cell.release(), typename Ref>::acquire_t{}); - } - - LevelMask get_level_mask() const override { - return LevelMask(info_.level_mask_); - } - - protected: - struct Info { - Info(LevelMask level_mask) { - level_mask_ = level_mask.get_mask() & 7; - hash_count_ = level_mask.get_hashes_count() & 7; - } - unsigned char level_mask_ : 3; - unsigned char hash_count_ : 3; - size_t get_hashes_offset() const { - return 0; - } - size_t get_depth_offset() const { - return get_hashes_offset() + hash_bytes * hash_count_; - } - size_t get_storage_size() const { - return get_depth_offset() + sizeof(td::uint16) * hash_count_; - } - const Hash* get_hashes(const char* storage) const { - return reinterpret_cast(storage + get_hashes_offset()); - } - Hash* get_hashes(char* storage) const { - return reinterpret_cast(storage + get_hashes_offset()); - } - const td::uint16* get_depth(const char* storage) const { - return reinterpret_cast(storage + get_depth_offset()); - } - td::uint16* get_depth(char* storage) const { - return reinterpret_cast(storage + get_depth_offset()); - } - }; - - Info info_; - ExtraT extra_; - virtual char* get_storage() = 0; - virtual const char* get_storage() const = 0; - void destroy_storage(char* storage) { - // noop - } - - td::Status init(const PrunnedCellInfo& prunned_cell_info) { - auto storage = get_storage(); - auto& new_hash = prunned_cell_info.hash; - auto* hash = info_.get_hashes(storage); - size_t n = prunned_cell_info.level_mask.get_hashes_count(); - CHECK(new_hash.size() == n * hash_bytes); - for (td::uint32 i = 0; i < n; i++) { - hash[i].as_slice().copy_from(new_hash.substr(i * Cell::hash_bytes, Cell::hash_bytes)); - } - - auto& new_depth = prunned_cell_info.depth; - CHECK(new_depth.size() == n * depth_bytes); - auto* depth = info_.get_depth(storage); - for (td::uint32 i = 0; i < n; i++) { - depth[i] = DataCell::load_depth(new_depth.substr(i * Cell::depth_bytes, Cell::depth_bytes).ubegin()); - if (depth[i] > max_depth) { - return td::Status::Error("Depth is too big"); - } - } - return td::Status::OK(); - } - - explicit PrunnedCell(Info info, ExtraT&& extra) : info_(info), extra_(std::move(extra)) { - } - td::uint32 get_virtualization() const override { - return 0; - } - CellUsageTree::NodePtr get_tree_node() const override { - return {}; - } - bool is_loaded() const override { - return false; - } - - private: - const Hash do_get_hash(td::uint32 level) const override { - return info_.get_hashes(get_storage())[get_level_mask().apply(level).get_hash_i()]; - } - - td::uint16 do_get_depth(td::uint32 level) const override { - return info_.get_depth(get_storage())[get_level_mask().apply(level).get_hash_i()]; - } - - td::Result load_cell() const override { - return td::Status::Error("Can't load prunned branch"); - } -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/UsageCell.h b/submodules/ton/tonlib-src/crypto/vm/cells/UsageCell.h deleted file mode 100644 index bf15bb56..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/UsageCell.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" -#include "vm/cells/CellUsageTree.h" - -namespace vm { -class UsageCell : public Cell { - private: - struct PrivateTag {}; - - public: - UsageCell(Ref cell, CellUsageTree::NodePtr tree_node, PrivateTag) - : cell_(std::move(cell)), tree_node_(std::move(tree_node)) { - } - static Ref create(Ref cell, CellUsageTree::NodePtr tree_node) { - if (tree_node.empty()) { - return cell; - } - return Ref{true, std::move(cell), std::move(tree_node), PrivateTag{}}; - } - - // load interface - td::Result load_cell() const override { - TRY_RESULT(loaded_cell, cell_->load_cell()); - if (tree_node_.on_load()) { - CHECK(loaded_cell.tree_node.empty()); - loaded_cell.tree_node = tree_node_; - } - return std::move(loaded_cell); - } - Ref virtualize(VirtualizationParameters virt) const override { - auto virtualized_cell = cell_->virtualize(virt); - if (tree_node_.empty()) { - return virtualized_cell; - } - if (virtualized_cell.get() == cell_.get()) { - return Ref(this); - } - return create(std::move(virtualized_cell), tree_node_); - } - - td::uint32 get_virtualization() const override { - return cell_->get_virtualization(); - } - - CellUsageTree::NodePtr get_tree_node() const override { - return tree_node_; - } - - bool is_loaded() const override { - return cell_->is_loaded(); - } - - // hash and level - LevelMask get_level_mask() const override { - return cell_->get_level_mask(); - } - - protected: - const Hash do_get_hash(td::uint32 level) const override { - return cell_->get_hash(level); - } - td::uint16 do_get_depth(td::uint32 level) const override { - return cell_->get_depth(level); - } - - private: - Ref cell_; - CellUsageTree::NodePtr tree_node_; -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/VirtualCell.h b/submodules/ton/tonlib-src/crypto/vm/cells/VirtualCell.h deleted file mode 100644 index 02abc1c8..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/VirtualCell.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells/Cell.h" - -namespace vm { -class VirtualCell : public Cell { - private: - struct PrivateTag {}; - - public: - static Ref create(VirtualizationParameters virt, Ref cell) { - if (cell->get_level() <= virt.get_level()) { - return cell; - } - return Ref{true, virt, std::move(cell), PrivateTag{}}; - } - - VirtualCell(VirtualizationParameters virt, Ref cell, PrivateTag) : virt_(virt), cell_(std::move(cell)) { - CHECK(cell_->get_virtualization() <= virt_.get_virtualization()); - } - - // load interface - td::Result load_cell() const override { - TRY_RESULT(loaded_cell, cell_->load_cell()); - loaded_cell.virt = loaded_cell.virt.apply(virt_); - return std::move(loaded_cell); - } - - Ref virtualize(VirtualizationParameters virt) const override { - auto new_virt = virt_.apply(virt); - if (new_virt == virt_) { - return Ref(this); - } - return create(new_virt, cell_); - } - - td::uint32 get_virtualization() const override { - return virt_.get_virtualization(); - } - - CellUsageTree::NodePtr get_tree_node() const override { - return cell_->get_tree_node(); - } - - bool is_loaded() const override { - return cell_->is_loaded(); - } - - // hash and level - LevelMask get_level_mask() const override { - return cell_->get_level_mask().apply(virt_.get_level()); - } - - protected: - const Hash do_get_hash(td::uint32 level) const override { - return cell_->get_hash(fix_level(level)); - } - td::uint16 do_get_depth(td::uint32 level) const override { - return cell_->get_depth(fix_level(level)); - } - - private: - VirtualizationParameters virt_; - Ref cell_; - - int fix_level(int level) const { - return get_level_mask().apply(level).get_level(); - } -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/VirtualizationParameters.h b/submodules/ton/tonlib-src/crypto/vm/cells/VirtualizationParameters.h deleted file mode 100644 index b83e87d2..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cells/VirtualizationParameters.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/int_types.h" -#include "td/utils/logging.h" - -#include - -namespace vm { -namespace detail { -class VirtualizationParameters { - public: - static constexpr td::uint8 max_level() { - return std::numeric_limits::max(); - } - - VirtualizationParameters() = default; - - VirtualizationParameters(td::uint8 level, td::uint8 virtualization) : level_(level), virtualization_(virtualization) { - CHECK(virtualization_ != 0 || empty()); - } - - bool empty() const { - return level_ == max_level() && virtualization_ == 0; - } - - VirtualizationParameters apply(VirtualizationParameters outer) const { - if (outer.level_ >= level_) { - return *this; - } - CHECK(virtualization_ <= outer.virtualization_); - return {outer.level_, outer.virtualization_}; - } - - td::uint8 get_level() const { - return level_; - } - - td::uint8 get_virtualization() const { - return virtualization_; - } - - bool operator==(const VirtualizationParameters &other) const { - return level_ == other.level_ && virtualization_ == other.virtualization_; - } - - private: - td::uint8 level_ = max_level(); - td::uint8 virtualization_ = 0; -}; -inline td::StringBuilder &operator<<(td::StringBuilder &sb, const VirtualizationParameters &virt) { - return sb << "{level: " << virt.get_level() << ", virtualization: " << virt.get_virtualization() << "}"; -} -} // namespace detail -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cellslice.h b/submodules/ton/tonlib-src/crypto/vm/cellslice.h deleted file mode 100644 index 8546e1ce..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cellslice.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/cells/CellSlice.h" diff --git a/submodules/ton/tonlib-src/crypto/vm/continuation.cpp b/submodules/ton/tonlib-src/crypto/vm/continuation.cpp deleted file mode 100644 index 94d20125..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/continuation.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/dispatch.h" -#include "vm/continuation.h" -#include "vm/dict.h" -#include "vm/log.h" -#include "vm/vm.h" -#include "vm/vmstate.h" - -namespace vm { - -int Continuation::jump_w(VmState* st) & { - return static_cast(this)->jump(st); -} - -bool Continuation::has_c0() const { - const ControlData* cont_data = get_cdata(); - return cont_data && cont_data->save.c[0].not_null(); -} - -bool ControlRegs::clear() { - for (unsigned i = 0; i < creg_num; i++) { - c[i].clear(); - } - for (unsigned i = 0; i < dreg_num; i++) { - d[i].clear(); - } - c7.clear(); - return true; -} - -StackEntry ControlRegs::get(unsigned idx) const { - if (idx < creg_num) { - return get_c(idx); - } else if (idx >= dreg_idx && idx < dreg_idx + dreg_num) { - return get_d(idx); - } else if (idx == 7) { - return c7; - } else { - return {}; - } -} - -bool ControlRegs::set(unsigned idx, StackEntry value) { - if (idx < creg_num) { - auto v = std::move(value).as_cont(); - return v.not_null() && set_c(idx, std::move(v)); - } else if (idx >= dreg_idx && idx < dreg_idx + dreg_num) { - auto v = std::move(value).as_cell(); - return v.not_null() && set_d(idx, std::move(v)); - } else if (idx == 7) { - auto v = std::move(value).as_tuple(); - return v.not_null() && set_c7(std::move(v)); - } else { - return false; - } -} - -bool ControlRegs::define(unsigned idx, StackEntry value) { - if (idx < creg_num) { - auto v = std::move(value).as_cont(); - return v.not_null() && define_c(idx, std::move(v)); - } else if (idx >= dreg_idx && idx < dreg_idx + dreg_num) { - auto v = std::move(value).as_cell(); - return v.not_null() && define_d(idx, std::move(v)); - } else if (idx == 7) { - auto v = std::move(value).as_tuple(); - return v.not_null() && define_c7(std::move(v)); - } else { - return false; - } -} - -ControlRegs& ControlRegs::operator^=(const ControlRegs& save) { - for (int i = 0; i < creg_num; i++) { - c[i] ^= save.c[i]; - } - for (int i = 0; i < dreg_num; i++) { - d[i] ^= save.d[i]; - } - c7 ^= save.c7; - return *this; -} - -ControlRegs& ControlRegs::operator^=(ControlRegs&& save) { - for (int i = 0; i < creg_num; i++) { - c[i] ^= std::move(save.c[i]); - } - for (int i = 0; i < dreg_num; i++) { - d[i] ^= std::move(save.d[i]); - } - c7 ^= std::move(save.c7); - return *this; -} - -ControlRegs& ControlRegs::operator&=(const ControlRegs& save) { - for (int i = 0; i < creg_num; i++) { - c[i] &= save.c[i].is_null(); - } - for (int i = 0; i < dreg_num; i++) { - d[i] &= save.d[i].is_null(); - } - c7 &= save.c7.is_null(); - return *this; -} - -bool ControlRegs::serialize(CellBuilder& cb) const { - // _ cregs:(HashmapE 4 VmStackValue) = VmSaveList; - Dictionary dict{4}; - CellBuilder cb2; - for (int i = 0; i < creg_num; i++) { - if (c[i].not_null() && - !(StackEntry{c[i]}.serialize(cb2) && dict.set_builder(td::BitArray<4>(i), cb2) && cb2.reset_bool())) { - return false; - } - } - for (int i = 0; i < dreg_num; i++) { - if (d[i].not_null() && !(StackEntry{d[i]}.serialize(cb2) && dict.set_builder(td::BitArray<4>(dreg_idx + i), cb2) && - cb2.reset_bool())) { - return false; - } - } - return (c7.is_null() || (StackEntry{c7}.serialize(cb2) && dict.set_builder(td::BitArray<4>(7), cb2))) && - std::move(dict).append_dict_to_bool(cb); -} - -bool ControlRegs::deserialize(CellSlice& cs, int mode) { - // _ cregs:(HashmapE 4 VmStackValue) = VmSaveList; - Ref root; - return cs.fetch_maybe_ref(root) && deserialize(std::move(root), mode); -} - -bool ControlRegs::deserialize(Ref root, int mode) { - try { - clear(); - Dictionary dict{std::move(root), 4}; - return dict.check_for_each([this, mode](Ref val, td::ConstBitPtr key, int n) { - StackEntry value; - return value.deserialize(val.write(), mode) && val->empty_ext() && set((int)key.get_uint(4), std::move(value)); - }); - } catch (VmError&) { - return false; - } -} - -bool ControlData::clear() { - stack.clear(); - save.clear(); - nargs = cp = -1; - return true; -} - -bool ControlData::serialize(CellBuilder& cb) const { - // vm_ctl_data$_ nargs:(Maybe uint13) stack:(Maybe VmStack) save:VmSaveList - // cp:(Maybe int16) = VmControlData; - return cb.store_bool_bool(nargs >= 0) // vm_ctl_data$_ nargs:(Maybe ... - && (nargs < 0 || cb.store_long_bool(nargs, 13)) // ... int13) - && cb.store_bool_bool(stack.not_null()) // stack:(Maybe ... - && (stack.is_null() || stack->serialize(cb)) // ... VmStack) - && save.serialize(cb) // save:VmSaveList - && cb.store_bool_bool(cp != -1) // cp:(Maybe ... - && (cp == -1 || cb.store_long_bool(cp, 16)); // ... int16) -} - -bool ControlData::deserialize(CellSlice& cs, int mode) { - // vm_ctl_data$_ nargs:(Maybe uint13) stack:(Maybe VmStack) save:VmSaveList - // cp:(Maybe int16) = VmControlData; - nargs = cp = -1; - stack.clear(); - bool f; - return cs.fetch_bool_to(f) && (!f || cs.fetch_uint_to(13, nargs)) // nargs:(Maybe uint13) - && cs.fetch_bool_to(f) && (!f || Stack::deserialize_to(cs, stack, mode)) // stack:(Maybe VmStack) - && save.deserialize(cs, mode) // save:VmSaveList - && cs.fetch_bool_to(f) && (!f || (cs.fetch_int_to(16, cp) && cp != -1)); // cp:(Maybe int16) -} - -bool Continuation::serialize_ref(CellBuilder& cb) const { - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return false; - } - vm::CellBuilder cb2; - return serialize(cb2) && cb.store_ref_bool(cb2.finalize()); -} - -Ref Continuation::deserialize(CellSlice& cs, int mode) { - if (mode & 0x1002) { - return {}; - } - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return {}; - } - - mode |= 0x1000; - switch (cs.bselect_ext(6, 0x100f011100010001ULL)) { - case 0: - // vmc_std$00 cdata:VmControlData code:VmCellSlice = VmCont; - return OrdCont::deserialize(cs, mode); - case 1: - // vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont; - return ArgContExt::deserialize(cs, mode); - case 2: - // vmc_quit$1000 exit_code:int32 = VmCont; - return QuitCont::deserialize(cs, mode); - case 3: - // vmc_quit_exc$1001 = VmCont; - return ExcQuitCont::deserialize(cs, mode); - case 4: - // vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont; - return RepeatCont::deserialize(cs, mode); - case 5: - // vmc_until$110000 body:^VmCont after:^VmCont = VmCont; - return UntilCont::deserialize(cs, mode); - case 6: - // vmc_again$110001 body:^VmCont = VmCont; - return AgainCont::deserialize(cs, mode); - case 7: - // vmc_while_cond$110010 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - return WhileCont::deserialize(cs, mode | 0x2000); - case 8: - // vmc_while_body$110011 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - return WhileCont::deserialize(cs, mode & ~0x2000); - case 9: - // vmc_pushint$1111 value:int32 next:^VmCont = VmCont; - return PushIntCont::deserialize(cs, mode); - default: - return {}; - } -} - -bool Continuation::deserialize_to(Ref cell, Ref& cont, int mode) { - if (cell.is_null()) { - cont.clear(); - return false; - } - CellSlice cs = load_cell_slice(std::move(cell)); - return deserialize_to(cs, cont, mode & ~0x1000) && cs.empty_ext(); -} - -bool QuitCont::serialize(CellBuilder& cb) const { - // vmc_quit$1000 exit_code:int32 = VmCont; - return cb.store_long_bool(8, 4) && cb.store_long_bool(exit_code, 32); -} - -Ref QuitCont::deserialize(CellSlice& cs, int mode) { - // vmc_quit$1000 exit_code:int32 = VmCont; - int exit_code; - if (cs.fetch_ulong(4) == 8 && cs.fetch_int_to(32, exit_code)) { - return Ref{true, exit_code}; - } else { - return {}; - } -} - -int ExcQuitCont::jump(VmState* st) const & { - int n = 0; - try { - n = st->get_stack().pop_smallint_range(0xffff); - } catch (const VmError& vme) { - n = vme.get_errno(); - } - VM_LOG(st) << "default exception handler, terminating vm with exit code " << n; - return ~n; -} - -bool ExcQuitCont::serialize(CellBuilder& cb) const { - // vmc_quit_exc$1001 = VmCont; - return cb.store_long_bool(9, 4); -} - -Ref ExcQuitCont::deserialize(CellSlice& cs, int mode) { - // vmc_quit_exc$1001 = VmCont; - return cs.fetch_ulong(4) == 9 ? Ref{true} : Ref{}; -} - -int PushIntCont::jump(VmState* st) const & { - VM_LOG(st) << "execute implicit PUSH " << push_val << " (slow)"; - st->get_stack().push_smallint(push_val); - return st->jump(next); -} - -int PushIntCont::jump_w(VmState* st) & { - VM_LOG(st) << "execute implicit PUSH " << push_val; - st->get_stack().push_smallint(push_val); - return st->jump(std::move(next)); -} - -bool PushIntCont::serialize(CellBuilder& cb) const { - // vmc_pushint$1111 value:int32 next:^VmCont = VmCont; - return cb.store_long_bool(15, 4) && cb.store_long_bool(push_val, 32) && next->serialize_ref(cb); -} - -Ref PushIntCont::deserialize(CellSlice& cs, int mode) { - // vmc_pushint$1111 value:int32 next:^VmCont = VmCont; - int value; - Ref ref; - Ref next; - if (cs.fetch_ulong(4) == 15 && cs.fetch_int_to(32, value) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), next, mode)) { - return Ref{true, value, std::move(next)}; - } else { - return {}; - } -} - -int ArgContExt::jump(VmState* st) const & { - st->adjust_cr(data.save); - if (data.cp != -1) { - st->force_cp(data.cp); - } - return ext->jump(st); -} - -int ArgContExt::jump_w(VmState* st) & { - st->adjust_cr(std::move(data.save)); - if (data.cp != -1) { - st->force_cp(data.cp); - } - return st->jump_to(std::move(ext)); -} - -bool ArgContExt::serialize(CellBuilder& cb) const { - // vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont; - return cb.store_long_bool(1, 2) && data.serialize(cb) && ext->serialize_ref(cb); -} - -Ref ArgContExt::deserialize(CellSlice& cs, int mode) { - // vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont; - ControlData cdata; - Ref ref; - Ref next; - mode &= ~0x1000; - return cs.fetch_ulong(2) == 1 && cdata.deserialize(cs, mode) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), next, mode) - ? Ref{true, std::move(next), std::move(cdata)} - : Ref{}; -} - -int RepeatCont::jump(VmState* st) const & { - VM_LOG(st) << "repeat " << count << " more times (slow)\n"; - if (count <= 0) { - return st->jump(after); - } - if (body->has_c0()) { - return st->jump(body); - } - st->set_c0(Ref{true, body, after, count - 1}); - return st->jump(body); -} - -int RepeatCont::jump_w(VmState* st) & { - VM_LOG(st) << "repeat " << count << " more times\n"; - if (count <= 0) { - body.clear(); - return st->jump(std::move(after)); - } - if (body->has_c0()) { - after.clear(); - return st->jump(std::move(body)); - } - // optimization: since this is unique, reuse *this instead of creating new object - --count; - st->set_c0(Ref{this}); - return st->jump(body); -} - -bool RepeatCont::serialize(CellBuilder& cb) const { - // vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont; - return cb.store_long_bool(0x14, 5) && cb.store_long_bool(count, 63) && body->serialize_ref(cb) && - after->serialize_ref(cb); -} - -Ref RepeatCont::deserialize(CellSlice& cs, int mode) { - // vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont; - long long count; - Ref ref; - Ref body, after; - if (cs.fetch_ulong(5) == 0x14 && cs.fetch_uint_to(63, count) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), body, mode) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), after, mode)) { - return Ref{true, std::move(body), std::move(after), count}; - } else { - return {}; - } -} - -int VmState::repeat(Ref body, Ref after, long long count) { - if (count <= 0) { - body.clear(); - return jump(std::move(after)); - } else { - return jump(Ref{true, std::move(body), std::move(after), count}); - } -} - -int AgainCont::jump(VmState* st) const & { - VM_LOG(st) << "again an infinite loop iteration (slow)\n"; - if (!body->has_c0()) { - st->set_c0(Ref{this}); - } - return st->jump(body); -} - -int AgainCont::jump_w(VmState* st) & { - VM_LOG(st) << "again an infinite loop iteration\n"; - if (!body->has_c0()) { - st->set_c0(Ref{this}); - return st->jump(body); - } else { - return st->jump(std::move(body)); - } -} - -bool AgainCont::serialize(CellBuilder& cb) const { - // vmc_again$110001 body:^VmCont = VmCont; - return cb.store_long_bool(0x31, 6) && body->serialize_ref(cb); -} - -Ref AgainCont::deserialize(CellSlice& cs, int mode) { - // vmc_again$110001 body:^VmCont = VmCont; - Ref ref; - Ref body; - if (cs.fetch_ulong(6) == 0x31 && cs.fetch_ref_to(ref) && deserialize_to(std::move(ref), body, mode)) { - return Ref{true, std::move(body)}; - } else { - return {}; - } -} - -int VmState::again(Ref body) { - return jump(Ref{true, std::move(body)}); -} - -int UntilCont::jump(VmState* st) const & { - VM_LOG(st) << "until loop body end (slow)\n"; - if (st->get_stack().pop_bool()) { - VM_LOG(st) << "until loop terminated\n"; - return st->jump(after); - } - if (!body->has_c0()) { - st->set_c0(Ref{this}); - } - return st->jump(body); -} - -int UntilCont::jump_w(VmState* st) & { - VM_LOG(st) << "until loop body end\n"; - if (st->get_stack().pop_bool()) { - VM_LOG(st) << "until loop terminated\n"; - body.clear(); - return st->jump(std::move(after)); - } - if (!body->has_c0()) { - st->set_c0(Ref{this}); - return st->jump(body); - } else { - after.clear(); - return st->jump(std::move(body)); - } -} - -bool UntilCont::serialize(CellBuilder& cb) const { - // vmc_until$110000 body:^VmCont after:^VmCont = VmCont; - return cb.store_long_bool(0x30, 6) && body->serialize_ref(cb) && after->serialize_ref(cb); -} - -Ref UntilCont::deserialize(CellSlice& cs, int mode) { - // vmc_until$110000 body:^VmCont after:^VmCont = VmCont; - Ref ref; - Ref body, after; - if (cs.fetch_ulong(6) == 0x30 && cs.fetch_ref_to(ref) && deserialize_to(std::move(ref), body, mode) && - cs.fetch_ref_to(ref) && deserialize_to(std::move(ref), after, mode)) { - return Ref{true, std::move(body), std::move(after)}; - } else { - return {}; - } -} - -int VmState::until(Ref body, Ref after) { - if (!body->has_c0()) { - set_c0(Ref{true, body, std::move(after)}); - } - return jump(std::move(body)); -} - -int WhileCont::jump(VmState* st) const & { - if (chkcond) { - VM_LOG(st) << "while loop condition end (slow)\n"; - if (!st->get_stack().pop_bool()) { - VM_LOG(st) << "while loop terminated\n"; - return st->jump(after); - } - if (!body->has_c0()) { - st->set_c0(Ref{true, cond, body, after, false}); - } - return st->jump(body); - } else { - VM_LOG(st) << "while loop body end (slow)\n"; - if (!cond->has_c0()) { - st->set_c0(Ref{true, cond, body, after, true}); - } - return st->jump(cond); - } -} - -int WhileCont::jump_w(VmState* st) & { - if (chkcond) { - VM_LOG(st) << "while loop condition end\n"; - if (!st->get_stack().pop_bool()) { - VM_LOG(st) << "while loop terminated\n"; - cond.clear(); - body.clear(); - return st->jump(std::move(after)); - } - if (!body->has_c0()) { - chkcond = false; // re-use current object since we hold the unique pointer to it - st->set_c0(Ref{this}); - return st->jump(body); - } else { - cond.clear(); - after.clear(); - return st->jump(std::move(body)); - } - } else { - VM_LOG(st) << "while loop body end\n"; - if (!cond->has_c0()) { - chkcond = true; // re-use current object - st->set_c0(Ref{this}); - return st->jump(cond); - } else { - body.clear(); - after.clear(); - return st->jump(std::move(cond)); - } - } -} - -bool WhileCont::serialize(CellBuilder& cb) const { - // vmc_while_cond$110010 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - // vmc_while_body$110011 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - return cb.store_long_bool(0x19, 5) && cb.store_bool_bool(!chkcond) && cond->serialize_ref(cb) && - body->serialize_ref(cb) && after->serialize_ref(cb); -} - -Ref WhileCont::deserialize(CellSlice& cs, int mode) { - // vmc_while_cond$110010 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - // vmc_while_body$110011 cond:^VmCont body:^VmCont after:^VmCont = VmCont; - bool at_body; - Ref ref; - Ref cond, body, after; - if (cs.fetch_ulong(5) == 0x19 && cs.fetch_bool_to(at_body) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), cond, mode) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), body, mode) && cs.fetch_ref_to(ref) && - deserialize_to(std::move(ref), after, mode)) { - return Ref{true, std::move(cond), std::move(body), std::move(after), !at_body}; - } else { - return {}; - } -} - -int VmState::loop_while(Ref cond, Ref body, Ref after) { - if (!cond->has_c0()) { - set_c0(Ref{true, cond, std::move(body), std::move(after), true}); - } - return jump(std::move(cond)); -} - -int OrdCont::jump(VmState* st) const & { - st->adjust_cr(data.save); - st->set_code(code, data.cp); - return 0; -} - -int OrdCont::jump_w(VmState* st) & { - st->adjust_cr(std::move(data.save)); - st->set_code(std::move(code), data.cp); - return 0; -} - -bool OrdCont::serialize(CellBuilder& cb) const { - // vmc_std$00 cdata:VmControlData code:VmCellSlice = VmCont; - return cb.store_long_bool(0, 2) && data.serialize(cb) && StackEntry{code}.serialize(cb, 0x1000); -} - -Ref OrdCont::deserialize(CellSlice& cs, int mode) { - // vmc_std$00 cdata:VmControlData code:VmCellSlice = VmCont; - ControlData cdata; - StackEntry val; - mode &= ~0x1000; - return cs.fetch_ulong(2) == 0 && cdata.deserialize(cs, mode) && val.deserialize(cs, 0x4000) && - val.is(StackEntry::t_slice) - ? Ref{true, std::move(val).as_slice(), std::move(cdata)} - : Ref{}; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/continuation.h b/submodules/ton/tonlib-src/crypto/vm/continuation.h deleted file mode 100644 index 37abe869..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/continuation.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "common/refcnt.hpp" -#include "vm/cellslice.h" -#include "vm/stack.hpp" -#include "vm/vmstate.h" -#include "vm/log.h" - -namespace vm { - -using td::Ref; - -class VmState; -class Continuation; -class DispatchTable; - -struct ControlRegs { - static constexpr int creg_num = 4, dreg_num = 2, dreg_idx = 4; - Ref c[creg_num]; // c0..c3 - Ref d[dreg_num]; // c4..c5 - Ref c7; // c7 - bool clear(); - Ref get_c(unsigned idx) const { - return idx < creg_num ? c[idx] : Ref{}; - } - Ref get_d(unsigned idx) const { - idx -= dreg_idx; - return idx < dreg_num ? d[idx] : Ref{}; - } - Ref get_c7() const { - return c7; - } - StackEntry get(unsigned idx) const; - static bool valid_idx(unsigned idx) { - return idx < creg_num || (idx >= dreg_idx && idx < dreg_idx + dreg_num) || idx == 7; - } - void set_c0(Ref cont) { - c[0] = std::move(cont); - } - void set_c1(Ref cont) { - c[1] = std::move(cont); - } - void set_c2(Ref cont) { - c[2] = std::move(cont); - } - void set_c3(Ref cont) { - c[3] = std::move(cont); - } - void set_c4(Ref cell) { - d[0] = std::move(cell); - } - bool set_c(unsigned idx, Ref cont) { - if (idx < creg_num) { - c[idx] = std::move(cont); - return true; - } else { - return false; - } - } - bool set_d(unsigned idx, Ref cell) { - idx -= dreg_idx; - if (idx < dreg_num) { - d[idx] = std::move(cell); - return true; - } else { - return false; - } - } - bool set_c7(Ref tuple) { - c7 = std::move(tuple); - return true; - } - bool set(unsigned idx, StackEntry value); - void define_c0(Ref cont) { - if (c[0].is_null()) { - c[0] = std::move(cont); - } - } - void define_c1(Ref cont) { - if (c[1].is_null()) { - c[1] = std::move(cont); - } - } - void define_c2(Ref cont) { - if (c[2].is_null()) { - c[2] = std::move(cont); - } - } - bool define_c(unsigned idx, Ref cont) { - if (idx < creg_num && c[idx].is_null()) { - c[idx] = std::move(cont); - return true; - } else { - return false; - } - } - bool define_d(unsigned idx, Ref cell) { - idx -= dreg_idx; - if (idx < dreg_num && d[idx].is_null()) { - d[idx] = std::move(cell); - return true; - } else { - return false; - } - } - void define_c4(Ref cell) { - if (d[0].is_null()) { - d[0] = std::move(cell); - } - } - bool define_c7(Ref tuple) { - if (c7.is_null()) { - c7 = std::move(tuple); - } - return true; - } - bool define(unsigned idx, StackEntry value); - ControlRegs& operator&=(const ControlRegs& save); // clears all c[i]'s which are present in save - ControlRegs& operator^=(const ControlRegs& save); // sets c[i]=save.c[i] for all save.c[i] != 0 - ControlRegs& operator^=(ControlRegs&& save); - bool serialize(CellBuilder& cb) const; - bool deserialize(CellSlice& cs, int mode = 0); - bool deserialize(Ref root, int mode = 0); -}; - -struct ControlData { - Ref stack; - ControlRegs save; - int nargs; - int cp; - ControlData() : nargs(-1), cp(-1) { - } - ControlData(int _cp) : nargs(-1), cp(_cp) { - } - ControlData(Ref _stack) : stack(std::move(_stack)), nargs(-1), cp(-1) { - } - ControlData(int _cp, Ref _stack, int _nargs = -1) : stack(std::move(_stack)), nargs(_nargs), cp(_cp) { - } - bool clear(); - bool serialize(CellBuilder& cb) const; - bool deserialize(CellSlice& cs, int mode = 0); -}; - -class Continuation : public td::CntObject { - public: - virtual int jump(VmState* st) const & = 0; - virtual int jump_w(VmState* st) &; - virtual ControlData* get_cdata() { - return 0; - } - virtual const ControlData* get_cdata() const { - return 0; - } - bool has_c0() const; - Continuation() { - } - Continuation(const Continuation&) = default; - Continuation(Continuation&&) { - } - Continuation& operator=(const Continuation&) { - return *this; - } - Continuation& operator=(Continuation&&) { - return *this; - } - ~Continuation() override = default; - virtual bool serialize(CellBuilder& cb) const { - return false; - } - bool serialize_ref(CellBuilder& cb) const; - static Ref deserialize(CellSlice& cs, int mode = 0); - static bool deserialize_to(CellSlice& cs, Ref& cont, int mode = 0) { - return (cont = deserialize(cs, mode)).not_null(); - } - static bool deserialize_to(Ref cell, Ref& cont, int mode = 0); -}; - -class QuitCont : public Continuation { - int exit_code; - - public: - QuitCont(int _code = 0) : exit_code(_code) { - } - ~QuitCont() override = default; - int jump(VmState* st) const & override { - return ~exit_code; - } - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class ExcQuitCont : public Continuation { - public: - ExcQuitCont() = default; - ~ExcQuitCont() override = default; - int jump(VmState* st) const & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class PushIntCont : public Continuation { - int push_val; - Ref next; - - public: - PushIntCont(int val, Ref _next) : push_val(val), next(_next) { - } - ~PushIntCont() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class RepeatCont : public Continuation { - Ref body, after; - long long count; - - public: - RepeatCont(Ref _body, Ref _after, long long _count) - : body(std::move(_body)), after(std::move(_after)), count(_count) { - } - ~RepeatCont() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class AgainCont : public Continuation { - Ref body; - - public: - AgainCont(Ref _body) : body(std::move(_body)) { - } - ~AgainCont() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class UntilCont : public Continuation { - Ref body, after; - - public: - UntilCont(Ref _body, Ref _after) : body(std::move(_body)), after(std::move(_after)) { - } - ~UntilCont() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class WhileCont : public Continuation { - Ref cond, body, after; - bool chkcond; - - public: - WhileCont(Ref _cond, Ref _body, Ref _after, bool _chk = true) - : cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)), chkcond(_chk) { - } - ~WhileCont() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class ArgContExt : public Continuation { - ControlData data; - Ref ext; - - public: - ArgContExt(Ref _ext) : data(), ext(std::move(_ext)) { - } - ArgContExt(Ref _ext, Ref _stack) : data(std::move(_stack)), ext(std::move(_ext)) { - } - ArgContExt(Ref _ext, const ControlData& _cdata) : data(_cdata), ext(std::move(_ext)) { - } - ArgContExt(Ref _ext, ControlData&& _cdata) : data(std::move(_cdata)), ext(std::move(_ext)) { - } - ArgContExt(const ArgContExt&) = default; - ArgContExt(ArgContExt&&) = default; - ~ArgContExt() override = default; - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - ControlData* get_cdata() override { - return &data; - } - const ControlData* get_cdata() const override { - return &data; - } - td::CntObject* make_copy() const override { - return new ArgContExt{*this}; - } - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -class OrdCont : public Continuation { - ControlData data; - Ref code; - friend class VmState; - - public: - OrdCont() : data(), code() { - } - //OrdCont(Ref _code) : data(), code(std::move(_code)) {} - OrdCont(Ref _code, int _cp) : data(_cp), code(std::move(_code)) { - } - //OrdCont(Ref _code, Ref _stack) : data(std::move(_stack)), code(std::move(_code)) {} - OrdCont(Ref _code, int _cp, Ref _stack, int nargs = -1) - : data(_cp, std::move(_stack), nargs), code(std::move(_code)) { - } - OrdCont(Ref _code, const ControlData& _cdata) : data(_cdata), code(std::move(_code)) { - } - OrdCont(Ref _code, ControlData&& _cdata) : data(std::move(_cdata)), code(std::move(_code)) { - } - OrdCont(const OrdCont&) = default; - OrdCont(OrdCont&&) = default; - ~OrdCont() override = default; - - td::CntObject* make_copy() const override { - return new OrdCont{*this}; - } - int jump(VmState* st) const & override; - int jump_w(VmState* st) & override; - - ControlData* get_cdata() override { - return &data; - } - const ControlData* get_cdata() const override { - return &data; - } - Stack& get_stack() { - return data.stack.write(); - } - const Stack& get_stack_const() const { - return *(data.stack); - } - Ref get_stack_ref() const { - return data.stack; - } - Ref copy_ord() const & { - return Ref{true, *this}; - } - Ref copy_ord() && { - return Ref{true, *this}; - } - bool serialize(CellBuilder& cb) const override; - static Ref deserialize(CellSlice& cs, int mode = 0); -}; - -ControlData* force_cdata(Ref& cont); -ControlRegs* force_cregs(Ref& cont); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/contops.cpp b/submodules/ton/tonlib-src/crypto/vm/contops.cpp deleted file mode 100644 index c3cb36bb..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/contops.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/contops.h" -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/continuation.h" -#include "vm/cellops.h" -#include "vm/excno.hpp" -#include "vm/vm.h" - -using namespace std::literals::string_literals; - -namespace vm { - -int exec_execute(VmState* st) { - VM_LOG(st) << "execute EXECUTE"; - auto cont = st->get_stack().pop_cont(); - return st->call(std::move(cont)); -} - -int exec_callx_args(VmState* st, unsigned args) { - unsigned params = (args >> 4) & 15, retvals = (args & 15); - VM_LOG(st) << "execute CALLXARGS " << params << ',' << retvals; - auto cont = st->get_stack().pop_cont(); - return st->call(std::move(cont), params, retvals); -} - -int exec_callx_args_p(VmState* st, unsigned args) { - unsigned params = (args & 15); - VM_LOG(st) << "execute CALLXARGS " << params << ",-1\n"; - auto cont = st->get_stack().pop_cont(); - return st->call(std::move(cont), params, -1); -} - -int exec_jmpx(VmState* st) { - VM_LOG(st) << "execute JMPX\n"; - auto cont = st->get_stack().pop_cont(); - return st->jump(std::move(cont)); -} - -int exec_jmpx_args(VmState* st, unsigned args) { - unsigned params = args & 15; - VM_LOG(st) << "execute JMPXARGS " << params; - auto cont = st->get_stack().pop_cont(); - return st->jump(std::move(cont), params); -} - -int exec_ret(VmState* st) { - VM_LOG(st) << "execute RET\n"; - return st->ret(); -} - -int exec_ret_args(VmState* st, unsigned args) { - unsigned params = args & 15; - VM_LOG(st) << "execute RETARGS " << params; - return st->ret(params); -} - -int exec_ret_alt(VmState* st) { - VM_LOG(st) << "execute RETALT\n"; - return st->ret_alt(); -} - -int exec_ret_bool(VmState* st) { - VM_LOG(st) << "execute RETBOOL\n"; - return st->get_stack().pop_bool() ? st->ret() : st->ret_alt(); -} - -int exec_callcc(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CALLCC\n"; - auto cont = stack.pop_cont(); - auto cc = st->extract_cc(3); - st->get_stack().push_cont(std::move(cc)); - return st->jump(std::move(cont)); -} - -int exec_jmpx_data(VmState* st) { - VM_LOG(st) << "execute JMPXDATA\n"; - auto cont = st->get_stack().pop_cont(); - st->push_code(); - return st->jump(std::move(cont)); -} - -int exec_callcc_args(VmState* st, unsigned args) { - int params = (args >> 4) & 15, retvals = ((args + 1) & 15) - 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CALLCCARGS " << params << ',' << retvals; - stack.check_underflow(params + 1); - auto cont = stack.pop_cont(); - auto cc = st->extract_cc(3, params, retvals); - st->get_stack().push_cont(std::move(cc)); - return st->jump(std::move(cont)); -} - -int exec_callx_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CALLXVARARGS\n"; - stack.check_underflow(3); - int retvals = stack.pop_smallint_range(254, -1); - int params = stack.pop_smallint_range(254, -1); - return st->call(stack.pop_cont(), params, retvals); -} - -int exec_ret_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute RETVARARGS\n"; - int retvals = stack.pop_smallint_range(254, -1); - return st->ret(retvals); -} - -int exec_jmpx_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute JMPXVARARGS\n"; - stack.check_underflow(2); - int params = stack.pop_smallint_range(254, -1); - stack.check_underflow(params + 1); - return st->jump(stack.pop_cont(), params); -} - -int exec_callcc_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CALLCCVARARGS\n"; - stack.check_underflow(3); - int retvals = stack.pop_smallint_range(254, -1); - int params = stack.pop_smallint_range(254, -1); - stack.check_underflow(params + 1); - auto cont = stack.pop_cont(); - auto cc = st->extract_cc(3, params, retvals); - st->get_stack().push_cont(std::move(cc)); - return st->jump(std::move(cont)); -} - -int exec_do_with_ref(VmState* st, CellSlice& cs, int pfx_bits, const std::function)>& func, - const char* name) { - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"}; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")"; - return func(st, st->ref_to_cont(std::move(cell))); -} - -int exec_do_with_cell(VmState* st, CellSlice& cs, int pfx_bits, const std::function)>& func, - const char* name) { - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"}; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")"; - return func(st, std::move(cell)); -} - -int exec_ifelse_ref(VmState* st, CellSlice& cs, int pfx_bits, bool mode) { - const char* name = mode ? "IFREFELSE" : "IFELSEREF"; - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"}; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")"; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - if (stack.pop_bool() == mode) { - cont = st->ref_to_cont(std::move(cell)); - } else { - cell.clear(); - } - return st->call(std::move(cont)); -} - -int exec_ifref_elseref(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have_refs(2)) { - throw VmError{Excno::inv_opcode, "no references left for a IFREFELSEREF instruction"}; - } - cs.advance(pfx_bits); - auto cell1 = cs.fetch_ref(), cell2 = cs.fetch_ref(); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IFREFELSEREF (" << cell1->get_hash().to_hex() << ") (" << cell2->get_hash().to_hex() << ")"; - if (!stack.pop_bool()) { - cell1 = std::move(cell2); - } else { - cell2.clear(); - } - return st->call(st->ref_to_cont(std::move(cell1))); -} - -int exec_ret_data(VmState* st) { - VM_LOG(st) << "execute RETDATA\n"; - st->push_code(); - return st->ret(); -} - -void register_continuation_jump_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xd8, 8, "EXECUTE", exec_execute)) - .insert(OpcodeInstr::mksimple(0xd9, 8, "JMPX", exec_jmpx)) - .insert(OpcodeInstr::mkfixed(0xda, 8, 8, instr::dump_2c("CALLXARGS ", ","), exec_callx_args)) - .insert(OpcodeInstr::mkfixed(0xdb0, 12, 4, instr::dump_1c("CALLXARGS ", ",-1"), exec_callx_args_p)) - .insert(OpcodeInstr::mkfixed(0xdb1, 12, 4, instr::dump_1c("JMPXARGS "), exec_jmpx_args)) - .insert(OpcodeInstr::mkfixed(0xdb2, 12, 4, instr::dump_1c("RETARGS "), exec_ret_args)) - .insert(OpcodeInstr::mksimple(0xdb30, 16, "RET", exec_ret)) - .insert(OpcodeInstr::mksimple(0xdb31, 16, "RETALT", exec_ret_alt)) - .insert(OpcodeInstr::mksimple(0xdb32, 16, "RETBOOL", exec_ret_bool)) - .insert(OpcodeInstr::mksimple(0xdb34, 16, "CALLCC", exec_callcc)) - .insert(OpcodeInstr::mksimple(0xdb35, 16, "JMPXDATA", exec_jmpx_data)) - .insert(OpcodeInstr::mkfixed(0xdb36, 16, 8, instr::dump_2c("CALLCCARGS ", ","), exec_callcc_args)) - .insert(OpcodeInstr::mksimple(0xdb38, 16, "CALLXVARARGS", exec_callx_varargs)) - .insert(OpcodeInstr::mksimple(0xdb39, 16, "RETVARARGS", exec_ret_varargs)) - .insert(OpcodeInstr::mksimple(0xdb3a, 16, "JMPXVARARGS", exec_jmpx_varargs)) - .insert(OpcodeInstr::mksimple(0xdb3b, 16, "CALLCCVARARGS", exec_callcc_varargs)) - .insert(OpcodeInstr::mkext(0xdb3c, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "CALLREF"), - std::bind(exec_do_with_ref, _1, _2, _4, - [](auto st, auto cont) { return st->call(std::move(cont)); }, "CALLREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xdb3d, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "JMPREF"), - std::bind(exec_do_with_ref, _1, _2, _4, - [](auto st, auto cont) { return st->jump(std::move(cont)); }, "JMPREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xdb3e, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "JMPREFDATA"), - std::bind(exec_do_with_ref, _1, _2, _4, - [](auto st, auto cont) { - st->push_code(); - return st->jump(std::move(cont)); - }, - "JMPREFDATA"), - compute_len_push_ref)) - .insert(OpcodeInstr::mksimple(0xdb3f, 16, "RETDATA", exec_ret_data)); -} - -int exec_if(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IF\n"; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - if (stack.pop_bool()) { - return st->call(std::move(cont)); - } - return 0; -} - -int exec_ifnot(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IFNOT\n"; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - if (!stack.pop_bool()) { - return st->call(std::move(cont)); - } - return 0; -} - -int exec_if_jmp(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IFJMP\n"; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - if (stack.pop_bool()) { - return st->jump(std::move(cont)); - } - return 0; -} - -int exec_ifnot_jmp(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IFNOTJMP\n"; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - if (!stack.pop_bool()) { - return st->jump(std::move(cont)); - } - return 0; -} - -int exec_ifret(VmState* st) { - VM_LOG(st) << "execute IFRET\n"; - if (st->get_stack().pop_bool()) { - return st->ret(); - } - return 0; -} - -int exec_ifnotret(VmState* st) { - VM_LOG(st) << "execute IFNOTRET\n"; - if (!st->get_stack().pop_bool()) { - return st->ret(); - } - return 0; -} - -int exec_if_else(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IFELSE\n"; - stack.check_underflow(3); - auto cont0 = stack.pop_cont(); - auto cont1 = stack.pop_cont(); - if (stack.pop_bool()) { - std::swap(cont0, cont1); - } - cont1.clear(); - return st->call(std::move(cont0)); -} - -int exec_condsel(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CONDSEL\n"; - stack.check_underflow(3); - auto y = stack.pop(); - auto x = stack.pop(); - stack.push(stack.pop_bool() ? std::move(x) : std::move(y)); - return 0; -} - -int exec_condsel_chk(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CONDSELCHK\n"; - stack.check_underflow(3); - auto y = stack.pop(); - auto x = stack.pop(); - if (x.type() != y.type()) { - throw VmError{Excno::type_chk, "two arguments of CONDSELCHK have different type"}; - } - stack.push(stack.pop_bool() ? std::move(x) : std::move(y)); - return 0; -} - -int exec_ifretalt(VmState* st) { - VM_LOG(st) << "execute IFRETALT\n"; - if (st->get_stack().pop_bool()) { - return st->ret_alt(); - } - return 0; -} - -int exec_ifnotretalt(VmState* st) { - VM_LOG(st) << "execute IFNOTRETALT\n"; - if (!st->get_stack().pop_bool()) { - return st->ret_alt(); - } - return 0; -} - -int exec_if_bit_jmp(VmState* st, unsigned args) { - bool negate = args & 0x20; - unsigned bit = args & 0x1f; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IF" << (negate ? "NBITJMP " : "BITJMP ") << bit; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - auto x = stack.pop_int_finite(); - bool val = x->get_bit(bit); - stack.push_int(std::move(x)); - if (val ^ negate) { - return st->jump(std::move(cont)); - } - return 0; -} - -std::string dump_if_bit_jmp(CellSlice& cs, unsigned args) { - std::ostringstream os{args & 0x20 ? "IFN" : " IF"}; - os << "BITJMP " << (args & 0x1f); - return os.str(); -} - -int exec_if_bit_jmpref(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have_refs()) { - throw VmError{Excno::inv_opcode, "no references left for a IFBITJMPREF instruction"}; - } - cs.advance(pfx_bits); - auto cell = cs.fetch_ref(); - bool negate = args & 0x20; - unsigned bit = args & 0x1f; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute IF" << (negate ? "N" : "") << "BITJMPREF " << bit << " (" << cell->get_hash().to_hex() << ")"; - auto x = stack.pop_int_finite(); - bool val = x->get_bit(bit); - stack.push_int(std::move(x)); - if (val ^ negate) { - return st->jump(st->ref_to_cont(std::move(cell))); - } - return 0; -} - -std::string dump_if_bit_jmpref(CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have_refs()) { - return ""; - } - cs.advance(pfx_bits); - cs.advance_refs(1); - std::ostringstream os{args & 0x20 ? "IFN" : " IF"}; - os << "BITJMPREF " << (args & 0x1f); - return os.str(); -} - -int exec_repeat(VmState* st, bool brk) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute REPEAT" << (brk ? "BRK" : ""); - stack.check_underflow(2); - auto cont = stack.pop_cont(); - int c = stack.pop_smallint_range(0x7fffffff, 0x80000000); - if (c <= 0) { - return 0; - } - return st->repeat(std::move(cont), st->c1_envelope_if(brk, st->extract_cc(1)), c); -} - -int exec_repeat_end(VmState* st, bool brk) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute REPEATEND" << (brk ? "BRK" : ""); - stack.check_underflow(1); - int c = stack.pop_smallint_range(0x7fffffff, 0x80000000); - if (c <= 0) { - return st->ret(); - } - auto cont = st->extract_cc(0); - return st->repeat(std::move(cont), st->c1_envelope_if(brk, st->get_c0()), c); -} - -int exec_until(VmState* st, bool brk) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute UNTIL" << (brk ? "BRK" : ""); - auto cont = stack.pop_cont(); - return st->until(std::move(cont), st->c1_envelope_if(brk, st->extract_cc(1))); -} - -int exec_until_end(VmState* st, bool brk) { - VM_LOG(st) << "execute UNTILEND" << (brk ? "BRK" : ""); - auto cont = st->extract_cc(0); - return st->until(std::move(cont), st->c1_envelope_if(brk, st->get_c0())); -} - -int exec_while(VmState* st, bool brk) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute WHILE" << (brk ? "BRK" : ""); - stack.check_underflow(2); - auto body = stack.pop_cont(); - auto cond = stack.pop_cont(); - return st->loop_while(std::move(cond), std::move(body), st->c1_envelope_if(brk, st->extract_cc(1))); -} - -int exec_while_end(VmState* st, bool brk) { - VM_LOG(st) << "execute WHILEEND" << (brk ? "BRK" : ""); - auto cond = st->get_stack().pop_cont(); - auto body = st->extract_cc(0); - return st->loop_while(std::move(cond), std::move(body), st->c1_envelope_if(brk, st->get_c0())); -} - -int exec_again(VmState* st, bool brk) { - VM_LOG(st) << "execute AGAIN" << (brk ? "BRK" : ""); - if (brk) { - st->set_c1(st->extract_cc(3)); - } - return st->again(st->get_stack().pop_cont()); -} - -int exec_again_end(VmState* st, bool brk) { - VM_LOG(st) << "execute AGAINEND" << (brk ? "BRK" : ""); - if (brk) { - st->c1_save_set(); - } - return st->again(st->extract_cc(0)); -} - -void register_continuation_cond_loop_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xdc, 8, "IFRET", exec_ifret)) - .insert(OpcodeInstr::mksimple(0xdd, 8, "IFNOTRET", exec_ifnotret)) - .insert(OpcodeInstr::mksimple(0xde, 8, "IF", exec_if)) - .insert(OpcodeInstr::mksimple(0xdf, 8, "IFNOT", exec_ifnot)) - .insert(OpcodeInstr::mksimple(0xe0, 8, "IFJMP", exec_if_jmp)) - .insert(OpcodeInstr::mksimple(0xe1, 8, "IFNOTJMP", exec_ifnot_jmp)) - .insert(OpcodeInstr::mksimple(0xe2, 8, "IFELSE", exec_if_else)) - .insert(OpcodeInstr::mkext(0xe300, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFREF"), - std::bind(exec_do_with_cell, _1, _2, _4, - [](auto st, auto cell) { - return st->get_stack().pop_bool() - ? st->call(st->ref_to_cont(std::move(cell))) - : 0; - }, - "IFREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xe301, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTREF"), - std::bind(exec_do_with_cell, _1, _2, _4, - [](auto st, auto cell) { - return st->get_stack().pop_bool() - ? 0 - : st->call(st->ref_to_cont(std::move(cell))); - }, - "IFNOTREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xe302, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFJMPREF"), - std::bind(exec_do_with_cell, _1, _2, _4, - [](auto st, auto cell) { - return st->get_stack().pop_bool() - ? st->jump(st->ref_to_cont(std::move(cell))) - : 0; - }, - "IFJMPREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xe303, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTJMPREF"), - std::bind(exec_do_with_cell, _1, _2, _4, - [](auto st, auto cell) { - return st->get_stack().pop_bool() - ? 0 - : st->jump(st->ref_to_cont(std::move(cell))); - }, - "IFNOTJMPREF"), - compute_len_push_ref)) - .insert(OpcodeInstr::mksimple(0xe304, 16, "CONDSEL", exec_condsel)) - .insert(OpcodeInstr::mksimple(0xe305, 16, "CONDSELCHK", exec_condsel_chk)) - .insert(OpcodeInstr::mksimple(0xe308, 16, "IFRETALT", exec_ifretalt)) - .insert(OpcodeInstr::mksimple(0xe309, 16, "IFNOTRETALT", exec_ifnotretalt)) - .insert(OpcodeInstr::mkext(0xe30d, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFREFELSE"), - std::bind(exec_ifelse_ref, _1, _2, _4, true), compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xe30e, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFELSEREF"), - std::bind(exec_ifelse_ref, _1, _2, _4, false), compute_len_push_ref)) - .insert(OpcodeInstr::mkext(0xe30f, 16, 0, std::bind(dump_push_ref2, _1, _2, _3, "IFREFELSEREF"), - exec_ifref_elseref, compute_len_push_ref2)) - .insert(OpcodeInstr::mkfixed(0xe380 >> 6, 10, 6, dump_if_bit_jmp, exec_if_bit_jmp)) - .insert(OpcodeInstr::mkext(0xe3c0 >> 6, 10, 6, dump_if_bit_jmpref, exec_if_bit_jmpref, compute_len_push_ref)) - .insert(OpcodeInstr::mksimple(0xe4, 8, "REPEAT", std::bind(exec_repeat, _1, false))) - .insert(OpcodeInstr::mksimple(0xe5, 8, "REPEATEND", std::bind(exec_repeat_end, _1, false))) - .insert(OpcodeInstr::mksimple(0xe6, 8, "UNTIL", std::bind(exec_until, _1, false))) - .insert(OpcodeInstr::mksimple(0xe7, 8, "UNTILEND", std::bind(exec_until_end, _1, false))) - .insert(OpcodeInstr::mksimple(0xe8, 8, "WHILE", std::bind(exec_while, _1, false))) - .insert(OpcodeInstr::mksimple(0xe9, 8, "WHILEEND", std::bind(exec_while_end, _1, false))) - .insert(OpcodeInstr::mksimple(0xea, 8, "AGAIN", std::bind(exec_again, _1, false))) - .insert(OpcodeInstr::mksimple(0xeb, 8, "AGAINEND", std::bind(exec_again_end, _1, false))) - .insert(OpcodeInstr::mksimple(0xe314, 16, "REPEATBRK", std::bind(exec_repeat, _1, true))) - .insert(OpcodeInstr::mksimple(0xe315, 16, "REPEATENDBRK", std::bind(exec_repeat_end, _1, true))) - .insert(OpcodeInstr::mksimple(0xe316, 16, "UNTILBRK", std::bind(exec_until, _1, true))) - .insert(OpcodeInstr::mksimple(0xe317, 16, "UNTILENDBRK", std::bind(exec_until_end, _1, true))) - .insert(OpcodeInstr::mksimple(0xe318, 16, "WHILEBRK", std::bind(exec_while, _1, true))) - .insert(OpcodeInstr::mksimple(0xe319, 16, "WHILEENDBRK", std::bind(exec_while_end, _1, true))) - .insert(OpcodeInstr::mksimple(0xe31a, 16, "AGAINBRK", std::bind(exec_again, _1, true))) - .insert(OpcodeInstr::mksimple(0xe31b, 16, "AGAINENDBRK", std::bind(exec_again_end, _1, true))); -} - -int exec_setcontargs_common(VmState* st, int copy, int more) { - Stack& stack = st->get_stack(); - stack.check_underflow(copy + 1); - auto cont = stack.pop_cont(); - if (copy || more >= 0) { - ControlData* cdata = force_cdata(cont); - if (copy > 0) { - if (cdata->nargs >= 0 && cdata->nargs < copy) { - throw VmError{Excno::stk_ov, "too many arguments copied into a closure continuation"}; - } - if (cdata->stack.is_null()) { - cdata->stack = stack.split_top(copy); - } else { - cdata->stack.write().move_from_stack(stack, copy); - } - st->consume_stack_gas(cdata->stack); - if (cdata->nargs >= 0) { - cdata->nargs -= copy; - } - } - if (more >= 0) { - if (cdata->nargs > more) { - cdata->nargs = 0x40000000; // will throw an exception if run - } else if (cdata->nargs < 0) { - cdata->nargs = more; - } - } - } - st->get_stack().push_cont(std::move(cont)); - return 0; -} - -int exec_setcontargs(VmState* st, unsigned args) { - int copy = (args >> 4) & 15, more = ((args + 1) & 15) - 1; - VM_LOG(st) << "execute SETCONTARGS " << copy << ',' << more; - return exec_setcontargs_common(st, copy, more); -} - -std::string dump_setcontargs(CellSlice& cs, unsigned args, const char* name) { - int copy = (args >> 4) & 15, more = ((args + 1) & 15) - 1; - std::ostringstream os{name}; - os << ' ' << copy << ',' << more; - return os.str(); -} - -int exec_setcont_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SETCONTVARARGS\n"; - stack.check_underflow(2); - int more = stack.pop_smallint_range(255, -1); - int copy = stack.pop_smallint_range(255); - return exec_setcontargs_common(st, copy, more); -} - -int exec_setnum_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SETNUMVARARGS\n"; - stack.check_underflow(2); - int more = stack.pop_smallint_range(255, -1); - return exec_setcontargs_common(st, 0, more); -} - -int exec_return_args_common(VmState* st, int count) { - Stack& stack = st->get_stack(); - stack.check_underflow(count); - if (stack.depth() == count) { - return 0; - } - int copy = stack.depth() - count; - Ref alt_stk = st->swap_stack(stack.split_top(count)); - auto cont = st->get_c0(); - ControlData* cdata = force_cdata(cont); - if (cdata->nargs >= 0 && cdata->nargs < copy) { - throw VmError{Excno::stk_ov, "too many arguments copied into a closure continuation"}; - } - if (cdata->stack.is_null()) { - cdata->stack = std::move(alt_stk); - } else { - cdata->stack.write().move_from_stack(alt_stk.write(), copy); - alt_stk.clear(); - } - st->consume_stack_gas(cdata->stack); - if (cdata->nargs >= 0) { - cdata->nargs -= copy; - } - st->set_c0(std::move(cont)); - return 0; -} - -int exec_return_args(VmState* st, unsigned args) { - int count = args & 15; - VM_LOG(st) << "execute RETURNARGS " << count; - return exec_return_args_common(st, count); -} - -int exec_return_varargs(VmState* st) { - VM_LOG(st) << "execute RETURNVARARGS\n"; - return exec_return_args_common(st, st->get_stack().pop_smallint_range(255)); -} - -int exec_bless(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLESS\n"; - stack.push_cont(Ref{true, stack.pop_cellslice(), st->get_cp()}); - return 0; -} - -int exec_bless_args_common(VmState* st, int copy, int more) { - Stack& stack = st->get_stack(); - stack.check_underflow(copy + 1); - auto cs = stack.pop_cellslice(); - auto new_stk = stack.split_top(copy); - st->consume_stack_gas(new_stk); - stack.push_cont(Ref{true, std::move(cs), st->get_cp(), std::move(new_stk), more}); - return 0; -} - -int exec_bless_varargs(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLESSVARARGS\n"; - stack.check_underflow(2); - int more = stack.pop_smallint_range(255, -1); - int copy = stack.pop_smallint_range(255); - return exec_bless_args_common(st, copy, more); -} - -int exec_bless_args(VmState* st, unsigned args) { - int copy = (args >> 4) & 15, more = ((args + 1) & 15) - 1; - VM_LOG(st) << "execute BLESSARGS " << copy << ',' << more; - return exec_bless_args_common(st, copy, more); -} - -int exec_push_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute PUSH c" << idx; - st->get_stack().push(st->get(idx)); - return 0; -} - -namespace { -inline void throw_typechk(bool ok) { - if (!ok) { - throw VmError{Excno::type_chk, "invalid value type for control register"}; - } -} - -inline void throw_rangechk(bool ok) { - if (!ok) { - throw VmError{Excno::range_chk, "control register index out of range"}; - } -} -} // namespace - -int exec_bless_pop_c3(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CTOSBLESSPOPc3"; - stack.check_underflow(1); - throw_typechk(st->set_c(3, Ref{true, vm::load_cell_slice_ref(stack.pop_cell()), st->get_cp()})); - return 0; -} - -int exec_pop_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute POP c" << idx; - /* - if (idx == 3 && st->get_stack().depth() > 0 && st->get_stack().tos().is(StackEntry::t_cell)) { - // temp hack: accept cell argument for POP c3 and do auto-BLESSing - return exec_bless_pop_c3(st); - } - */ - throw_typechk(st->set(idx, st->get_stack().pop_chk())); - return 0; -} - -int exec_setcont_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SETCONTCTR c" << idx; - stack.check_underflow(2); - auto cont = stack.pop_cont(); - throw_typechk(force_cregs(cont)->define(idx, stack.pop_chk())); - st->get_stack().push_cont(std::move(cont)); - return 0; -} - -int exec_setret_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute SETRETCTR c" << idx; - auto cont = st->get_c0(); - throw_typechk(force_cregs(cont)->define(idx, st->get_stack().pop_chk())); - st->set_c0(std::move(cont)); - return 0; -} - -int exec_setalt_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute SETALTCTR c" << idx; - auto cont = st->get_c1(); - throw_typechk(force_cregs(cont)->define(idx, st->get_stack().pop_chk())); - st->set_c1(std::move(cont)); - return 0; -} - -int exec_popsave_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute POPSAVE c" << idx; - auto val = st->get_stack().pop_chk(); - auto c0 = st->get_c0(); - throw_typechk(idx || val.is(StackEntry::t_vmcont)); - force_cregs(c0)->define(idx, st->get(idx)); - if (!idx) { - st->set_c0(std::move(c0)); - throw_typechk(st->set(idx, std::move(val))); - } else { - throw_typechk(st->set(idx, std::move(val))); - st->set_c0(std::move(c0)); - } - return 0; -} - -int exec_save_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute SAVECTR c" << idx; - auto c0 = st->get_c0(); - throw_typechk(force_cregs(c0)->define(idx, st->get(idx))); - st->set_c0(std::move(c0)); - return 0; -} - -int exec_samealt(VmState* st, bool save) { - VM_LOG(st) << "execute SAMEALT" << (save ? "SAVE" : ""); - auto c0 = st->get_c0(); - if (save) { - force_cregs(c0)->define_c1(st->get_c1()); - st->set_c0(c0); - } - st->set_c1(std::move(c0)); - return 0; -} - -int exec_savealt_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute SAVEALTCTR c" << idx; - auto c1 = st->get_c1(); - throw_typechk(force_cregs(c1)->define(idx, st->get(idx))); - st->set_c1(std::move(c1)); - return 0; -} - -int exec_saveboth_ctr(VmState* st, unsigned args) { - unsigned idx = args & 15; - VM_LOG(st) << "execute SAVEBOTHCTR c" << idx; - auto c0 = st->get_c0(), c1 = st->get_c1(); - auto val = st->get(idx); - force_cregs(c0)->define(idx, val); - force_cregs(c1)->define(idx, std::move(val)); - st->set_c0(std::move(c0)); - st->set_c1(std::move(c1)); - return 0; -} - -int exec_push_ctr_var(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSHCTRX\n"; - unsigned idx = stack.pop_smallint_range(16); - auto val = st->get(idx); - throw_rangechk(!val.empty()); - stack.push(std::move(val)); - return 0; -} - -int exec_pop_ctr_var(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute POPCTRX\n"; - stack.check_underflow(2); - unsigned idx = stack.pop_smallint_range(16); - throw_rangechk(ControlRegs::valid_idx(idx)); - throw_typechk(st->set(idx, stack.pop_chk())); - return 0; -} - -int exec_setcont_ctr_var(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SETCONTCTRX\n"; - stack.check_underflow(3); - unsigned idx = stack.pop_smallint_range(16); - throw_rangechk(ControlRegs::valid_idx(idx)); - auto cont = stack.pop_cont(); - throw_typechk(force_cregs(cont)->define(idx, stack.pop_chk())); - st->get_stack().push_cont(std::move(cont)); - return 0; -} - -int exec_compos(VmState* st, unsigned mask, const char* name) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << name; - stack.check_underflow(2); - auto val = stack.pop_cont(); - auto cont = stack.pop_cont(); - ControlRegs* regs = force_cregs(cont); - switch (mask) { - case 1: - regs->define_c0(std::move(val)); - break; - case 3: - regs->define_c0(val); - // fallthrough - case 2: - regs->define_c1(std::move(val)); - break; - } - st->get_stack().push_cont(std::move(cont)); - return 0; -} - -int exec_atexit(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ATEXIT\n"; - auto cont = stack.pop_cont(); - force_cregs(cont)->define_c0(st->get_c0()); - st->set_c0(std::move(cont)); - return 0; -} - -int exec_atexit_alt(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ATEXITALT\n"; - auto cont = stack.pop_cont(); - force_cregs(cont)->define_c1(st->get_c1()); - st->set_c1(std::move(cont)); - return 0; -} - -int exec_setexit_alt(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SETEXITALT\n"; - auto cont = stack.pop_cont(); - force_cregs(cont)->define_c0(st->get_c0()); - force_cregs(cont)->define_c1(st->get_c1()); - st->set_c1(std::move(cont)); - return 0; -} - -int exec_thenret(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute THENRET\n"; - auto cont = stack.pop_cont(); - force_cregs(cont)->define_c0(st->get_c0()); - stack.push_cont(std::move(cont)); - return 0; -} - -int exec_thenret_alt(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute THENRETALT\n"; - auto cont = stack.pop_cont(); - force_cregs(cont)->define_c0(st->get_c1()); - stack.push_cont(std::move(cont)); - return 0; -} - -int exec_invert(VmState* st) { - VM_LOG(st) << "execute INVERT\n"; - auto c0 = st->get_c0(), c1 = st->get_c1(); - st->set_c0(std::move(c1)); - st->set_c1(std::move(c0)); - return 0; -} - -int exec_booleval(VmState* st) { - VM_LOG(st) << "execute BOOLEVAL\n"; - auto cont = st->get_stack().pop_cont(); - auto cc = st->extract_cc(3); - st->set_c0(Ref{true, -1, cc}); - st->set_c1(Ref{true, 0, std::move(cc)}); - return st->jump(std::move(cont)); -} - -void reg_ctr_oprange(OpcodeTable& cp, unsigned opcode, std::string name, exec_arg_instr_func_t exec_ctr) { - cp.insert(OpcodeInstr::mkfixedrange(opcode, opcode + 4, 16, 4, instr::dump_1c(name + " c"), exec_ctr)) - .insert(OpcodeInstr::mkfixedrange(opcode + 4, opcode + 6, 16, 4, instr::dump_1c(name + " c"), exec_ctr)) - .insert(OpcodeInstr::mkfixedrange(opcode + 7, opcode + 8, 16, 4, instr::dump_1c(name + " c"), exec_ctr)); -} - -void register_continuation_change_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0xec, 8, 8, std::bind(dump_setcontargs, _1, _2, "SETCONTARGS"), exec_setcontargs)) - .insert(OpcodeInstr::mkfixed(0xed0, 12, 4, instr::dump_1c("RETURNARGS "), exec_return_args)) - .insert(OpcodeInstr::mksimple(0xed10, 16, "RETURNVARARGS", exec_return_varargs)) - .insert(OpcodeInstr::mksimple(0xed11, 16, "SETCONTVARARGS", exec_setcont_varargs)) - .insert(OpcodeInstr::mksimple(0xed12, 16, "SETNUMVARARGS", exec_setnum_varargs)) - .insert(OpcodeInstr::mksimple(0xed1e, 16, "BLESS", exec_bless)) - .insert(OpcodeInstr::mksimple(0xed1f, 16, "BLESSVARARGS", exec_bless_varargs)); - - reg_ctr_oprange(cp0, 0xed40, "PUSH", exec_push_ctr); - reg_ctr_oprange(cp0, 0xed50, "POP", exec_pop_ctr); - reg_ctr_oprange(cp0, 0xed60, "SETCONTCTR", exec_setcont_ctr); - reg_ctr_oprange(cp0, 0xed70, "SETRETCTR", exec_setret_ctr); - reg_ctr_oprange(cp0, 0xed80, "SETALTCTR", exec_setalt_ctr); - reg_ctr_oprange(cp0, 0xed90, "POPSAVE", exec_popsave_ctr); - reg_ctr_oprange(cp0, 0xeda0, "SAVECTR", exec_save_ctr); - reg_ctr_oprange(cp0, 0xedb0, "SAVEALTCTR", exec_savealt_ctr); - reg_ctr_oprange(cp0, 0xedc0, "SAVEBOTHCTR", exec_saveboth_ctr); - - cp0.insert(OpcodeInstr::mksimple(0xede0, 16, "PUSHCTRX", exec_push_ctr_var)) - .insert(OpcodeInstr::mksimple(0xede1, 16, "POPCTRX", exec_pop_ctr_var)) - .insert(OpcodeInstr::mksimple(0xede2, 16, "SETCONTCTRX", exec_setcont_ctr_var)) - .insert(OpcodeInstr::mksimple(0xedf0, 16, "BOOLAND", std::bind(exec_compos, _1, 1, "BOOLAND"))) - .insert(OpcodeInstr::mksimple(0xedf1, 16, "BOOLOR", std::bind(exec_compos, _1, 2, "BOOLOR"))) - .insert(OpcodeInstr::mksimple(0xedf2, 16, "COMPOSBOTH", std::bind(exec_compos, _1, 3, "COMPOSBOTH"))) - .insert(OpcodeInstr::mksimple(0xedf3, 16, "ATEXIT", exec_atexit)) - .insert(OpcodeInstr::mksimple(0xedf4, 16, "ATEXITALT", exec_atexit_alt)) - .insert(OpcodeInstr::mksimple(0xedf5, 16, "SETEXITALT", exec_setexit_alt)) - .insert(OpcodeInstr::mksimple(0xedf6, 16, "THENRET", exec_thenret)) - .insert(OpcodeInstr::mksimple(0xedf7, 16, "THENRETALT", exec_thenret_alt)) - .insert(OpcodeInstr::mksimple(0xedf8, 16, "INVERT", exec_invert)) - .insert(OpcodeInstr::mksimple(0xedf9, 16, "BOOLEVAL", exec_booleval)) - .insert(OpcodeInstr::mksimple(0xedfa, 16, "SAMEALT", std::bind(exec_samealt, _1, false))) - .insert(OpcodeInstr::mksimple(0xedfb, 16, "SAMEALTSAVE", std::bind(exec_samealt, _1, true))) - .insert(OpcodeInstr::mkfixed(0xee, 8, 8, std::bind(dump_setcontargs, _1, _2, "BLESSARGS"), exec_bless_args)); -} - -int exec_calldict_short(VmState* st, unsigned args) { - args &= 0xff; - VM_LOG(st) << "execute CALLDICT " << args; - st->get_stack().push_smallint(args); - return st->call(st->get_c3()); -} - -int exec_calldict(VmState* st, unsigned args) { - args &= 0x3fff; - VM_LOG(st) << "execute CALLDICT " << args; - st->get_stack().push_smallint(args); - return st->call(st->get_c3()); -} - -int exec_jmpdict(VmState* st, unsigned args) { - args &= 0x3fff; - VM_LOG(st) << "execute JMPDICT " << args; - st->get_stack().push_smallint(args); - return st->jump(st->get_c3()); -} - -int exec_preparedict(VmState* st, unsigned args) { - args &= 0x3fff; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PREPAREDICT " << args; - stack.push_smallint(args); - stack.push_cont(st->get_c3()); - return 0; -} - -void register_continuation_dict_jump_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0xf0, 8, 8, instr::dump_1c_and(255, "CALLDICT "), exec_calldict_short)) - .insert(OpcodeInstr::mkfixed(0xf100 >> 6, 10, 14, instr::dump_1c_and(0x3fff, "CALLDICT "), exec_calldict)) - .insert(OpcodeInstr::mkfixed(0xf140 >> 6, 10, 14, instr::dump_1c_and(0x3fff, "JMPDICT "), exec_jmpdict)) - .insert(OpcodeInstr::mkfixed(0xf180 >> 6, 10, 14, instr::dump_1c_and(0x3fff, "PREPAREDICT "), exec_preparedict)); -} - -int exec_throw_fixed(VmState* st, unsigned args, unsigned mask, int mode) { - unsigned excno = args & mask; - VM_LOG(st) << "execute THROW" << (mode ? "IF" : "") << (mode == 2 ? "NOT " : " ") << excno; - if (mode && st->get_stack().pop_bool() != (bool)(mode & 1)) { - return 0; - } else { - return st->throw_exception(excno); - } -} - -int exec_throw_arg_fixed(VmState* st, unsigned args, unsigned mask, int mode) { - unsigned excno = args & mask; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute THROWARG" << (mode ? "IF" : "") << (mode == 2 ? "NOT " : " ") << excno; - stack.check_underflow(mode ? 2 : 1); - if (mode && stack.pop_bool() != (bool)(mode & 1)) { - stack.pop(); - return 0; - } else { - return st->throw_exception(excno, stack.pop()); - } -} - -int exec_throw_any(VmState* st, unsigned args) { - bool has_param = args & 1; - bool has_cond = args & 6; - bool throw_cond = args & 2; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute THROW" << (has_param ? "ARG" : "") << "ANY" << (has_cond ? (throw_cond ? "IF" : "IFNOT") : ""); - stack.check_underflow(1 + (int)has_cond + (int)has_param); - bool flag = has_cond ? stack.pop_bool() : throw_cond; - int excno = stack.pop_smallint_range(0xffff); - if (flag != throw_cond) { - if (has_param) { - stack.pop(); - } - return 0; - } else if (has_param) { - return st->throw_exception(excno, stack.pop()); - } else { - return st->throw_exception(excno); - } -} - -std::string dump_throw_any(CellSlice& cs, unsigned args) { - bool has_param = args & 1; - bool has_cond = args & 6; - bool throw_cond = args & 2; - std::ostringstream os{has_param ? "THROWARG" : "THROW"}; - os << "ANY"; - if (has_cond) { - os << (throw_cond ? "IF" : "IFNOT"); - } - return os.str(); -} - -int exec_try(VmState* st, int args) { - int params = (args >> 4) & 15, retvals = args & 15; - Stack& stack = st->get_stack(); - if (args < 0) { - VM_LOG(st) << "execute TRY"; - } else { - VM_LOG(st) << "execute TRYARGS " << params << "," << retvals; - } - stack.check_underflow(args >= 0 ? params + 2 : 2); - auto handler_cont = stack.pop_cont(); - auto cont = stack.pop_cont(); - auto old_c2 = st->get_c2(); - auto cc = (args >= 0 ? st->extract_cc(7, params, retvals) : st->extract_cc(7)); - ControlRegs* handler_cr = force_cregs(handler_cont); - handler_cr->define_c2(std::move(old_c2)); - handler_cr->define_c0(cc); - st->set_c0(std::move(cc)); - st->set_c2(std::move(handler_cont)); - return st->jump(std::move(cont)); -} - -void register_exception_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixed(0xf200 >> 6, 10, 6, instr::dump_1c_and(0x3f, "THROW "), - std::bind(exec_throw_fixed, _1, _2, 63, 0))) - .insert(OpcodeInstr::mkfixed(0xf240 >> 6, 10, 6, instr::dump_1c_and(0x3f, "THROWIF "), - std::bind(exec_throw_fixed, _1, _2, 63, 3))) - .insert(OpcodeInstr::mkfixed(0xf280 >> 6, 10, 6, instr::dump_1c_and(0x3f, "THROWIFNOT "), - std::bind(exec_throw_fixed, _1, _2, 63, 2))) - .insert(OpcodeInstr::mkfixed(0xf2c0 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROW "), - std::bind(exec_throw_fixed, _1, _2, 0x7ff, 0))) - .insert(OpcodeInstr::mkfixed(0xf2c8 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROWARG "), - std::bind(exec_throw_arg_fixed, _1, _2, 0x7ff, 0))) - .insert(OpcodeInstr::mkfixed(0xf2d0 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROWIF "), - std::bind(exec_throw_fixed, _1, _2, 0x7ff, 3))) - .insert(OpcodeInstr::mkfixed(0xf2d8 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROWARGIF "), - std::bind(exec_throw_arg_fixed, _1, _2, 0x7ff, 3))) - .insert(OpcodeInstr::mkfixed(0xf2e0 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROWIFNOT "), - std::bind(exec_throw_fixed, _1, _2, 0x7ff, 2))) - .insert(OpcodeInstr::mkfixed(0xf2e8 >> 3, 13, 11, instr::dump_1c_and(0x7ff, "THROWARGIFNOT "), - std::bind(exec_throw_arg_fixed, _1, _2, 0x7ff, 2))) - .insert(OpcodeInstr::mkfixedrange(0xf2f0, 0xf2f6, 16, 3, dump_throw_any, exec_throw_any)) - .insert(OpcodeInstr::mksimple(0xf2ff, 16, "TRY", std::bind(exec_try, _1, -1))) - .insert(OpcodeInstr::mkfixed(0xf3, 8, 8, instr::dump_2c("TRYARGS ", ","), exec_try)); -} - -int exec_set_cp_generic(VmState* st, int new_codepage) { - st->force_cp(new_codepage); - return 0; -} - -int exec_set_cp(VmState* st, int args) { - int cp = ((args + 0x10) & 0xff) - 0x10; - VM_LOG(st) << "execute SETCP " << cp; - return exec_set_cp_generic(st, cp); -} - -int exec_set_cp_any(VmState* st) { - VM_LOG(st) << "execute SETCPX"; - int cp = st->get_stack().pop_smallint_range(0x7fff, -0x8000); - return exec_set_cp_generic(st, cp); -} - -void register_codepage_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixedrange(0xff00, 0xfff0, 16, 8, instr::dump_1c_and(0xff, "SETCP "), exec_set_cp)) - .insert(OpcodeInstr::mkfixedrange(0xfff1, 0x10000, 16, 8, instr::dump_1c_l_add(-256, "SETCP "), exec_set_cp)) - .insert(OpcodeInstr::mksimple(0xfff0, 16, "SETCPX", exec_set_cp_any)); -} - -void register_continuation_ops(OpcodeTable& cp0) { - register_continuation_jump_ops(cp0); - register_continuation_cond_loop_ops(cp0); - register_continuation_change_ops(cp0); - register_continuation_dict_jump_ops(cp0); - register_exception_ops(cp0); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/contops.h b/submodules/ton/tonlib-src/crypto/vm/contops.h deleted file mode 100644 index e86a303c..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/contops.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_continuation_ops(OpcodeTable& cp0); -void register_codepage_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cp0.cpp b/submodules/ton/tonlib-src/crypto/vm/cp0.cpp deleted file mode 100644 index fe5dd8ef..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cp0.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "cp0.h" -#include "opctable.h" -#include "stackops.h" -#include "tupleops.h" -#include "arithops.h" -#include "cellops.h" -#include "contops.h" -#include "dictops.h" -#include "debugops.h" -#include "tonops.h" - -namespace vm { - -const OpcodeTable* init_op_cp0(bool enable_debug) { - set_debug_enabled(enable_debug); - static const OpcodeTable* static_op_cp0 = [] { - auto op_cp0 = new OpcodeTable("TEST CODEPAGE", Codepage::test_cp); - register_stack_ops(*op_cp0); // stackops.cpp - register_tuple_ops(*op_cp0); // tupleops.cpp - register_arith_ops(*op_cp0); // arithops.cpp - register_cell_ops(*op_cp0); // cellops.cpp - register_continuation_ops(*op_cp0); // contops.cpp - register_dictionary_ops(*op_cp0); // dictops.cpp - register_ton_ops(*op_cp0); // tonops.cpp - register_debug_ops(*op_cp0); // debugops.cpp - register_codepage_ops(*op_cp0); // contops.cpp - op_cp0->finalize()->register_table(Codepage::test_cp); - return op_cp0; - }(); - return static_op_cp0; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cp0.h b/submodules/ton/tonlib-src/crypto/vm/cp0.h deleted file mode 100644 index 9a657969..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/cp0.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/dispatch.h" - -namespace vm { - -class OpcodeTable; - -const OpcodeTable* init_op_cp0(bool debug_enabled = false); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/BlobView.cpp b/submodules/ton/tonlib-src/crypto/vm/db/BlobView.cpp deleted file mode 100644 index 1a879d00..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/BlobView.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/db/BlobView.h" - -#include "td/utils/port/FileFd.h" -#include "td/utils/HashMap.h" - -#include "td/utils/format.h" -#include "td/utils/port/RwMutex.h" -#include "td/utils/port/MemoryMapping.h" - -#include -#include - -namespace vm { -td::Result BlobView::view(td::MutableSlice slice, td::uint64 offset) { - if (offset > size() || slice.size() > size() - offset) { - return td::Status::Error(PSLICE() << "BlobView: invalid range requested " << td::tag("slice offset", offset) - << td::tag("slice size", slice.size()) << td::tag("blob size", size())); - } - return view_impl(slice, offset); -} -namespace { -class BufferSliceBlobViewImpl : public BlobView { - public: - BufferSliceBlobViewImpl(td::BufferSlice slice) : slice_(std::move(slice)) { - } - td::Result view_impl(td::MutableSlice slice, td::uint64 offset) override { - // optimize anyway - if (offset > std::numeric_limits::max()) { - return td::Slice(); - } - return slice_.as_slice().substr(static_cast(offset), slice.size()); - } - td::uint64 size() override { - return slice_.size(); - } - - private: - td::BufferSlice slice_; -}; -} // namespace - -std::unique_ptr BufferSliceBlobView::create(td::BufferSlice slice) { - return std::make_unique(std::move(slice)); -} - -class FileBlobViewImpl : public BlobView { - public: - FileBlobViewImpl(td::FileFd fd, td::uint64 file_size) : fd_(std::move(fd)), file_size_(file_size) { - } - - td::uint64 size() override { - return file_size_; - } - td::Result view_impl(td::MutableSlice slice, td::uint64 offset) override { - CHECK(offset < size()); - CHECK(size() - offset >= slice.size()); - slice.truncate(file_size_ - offset); - auto first_page = offset / page_size; - auto last_page = (offset + slice.size() - 1) / page_size; - td::uint64 res_offset = 0; - for (auto page_i = first_page; page_i <= last_page; page_i++) { - auto page_offset = page_i * page_size; - auto from = td::max(page_offset, offset); - auto till = td::min(page_offset + page_size, offset + slice.size()); - CHECK(from < till); - TRY_RESULT(page, load_page(page_i)); - auto len = till - from; - slice.substr(res_offset, len).copy_from(page.substr(from - page_offset, len)); - res_offset += len; - } - CHECK(slice.size() == res_offset); - total_view_size_ += slice.size(); - return slice; - } - ~FileBlobViewImpl() { - //LOG(ERROR) << "LOADED " << pages_.size() << " " << total_view_size_; - } - - private: - td::FileFd fd_; - td::uint64 file_size_; - const td::uint64 page_size = 4096; - td::uint64 total_view_size_{0}; - - td::RwMutex pages_rw_mutex_; - td::HashMap pages_; - - std::mutex fd_mutex_; - - td::Result load_page(td::uint64 page_i) { - { - auto pages_guard = pages_rw_mutex_.lock_read(); - auto it = pages_.find(page_i); - if (it != pages_.end()) { - return it->second.as_slice(); - } - } - - std::lock_guard fd_guard(fd_mutex_); - { - auto pages_guard = pages_rw_mutex_.lock_read(); - auto it = pages_.find(page_i); - if (it != pages_.end()) { - return it->second.as_slice(); - } - } - auto offset = page_i * page_size; - - auto size = td::min(file_size_ - offset, page_size); - auto buffer_slice = td::BufferSlice(size); - TRY_RESULT(read_size, fd_.pread(buffer_slice.as_slice(), offset)); - if (read_size != buffer_slice.size()) { - return td::Status::Error("not enough data in file"); - } - - auto pages_guard = pages_rw_mutex_.lock_write(); - auto &res = pages_[page_i]; - res = std::move(buffer_slice); - return res.as_slice(); - } -}; -td::Result> FileBlobView::create(td::CSlice file_path, td::uint64 file_size) { - TRY_RESULT(fd, td::FileFd::open(file_path, td::FileFd::Flags::Read)); - TRY_RESULT(stat, fd.stat()); - if (file_size == 0) { - file_size = stat.size_; - } else if (file_size != (td::uint64)stat.size_) { - return td::Status::Error("Wrong file size"); - } - return std::make_unique(std::move(fd), file_size); -} - -class FileMemoryMappingBlobViewImpl : public BlobView { - public: - FileMemoryMappingBlobViewImpl(td::MemoryMapping mapping) : mapping_(std::move(mapping)) { - } - td::Result view_impl(td::MutableSlice slice, td::uint64 offset) override { - // optimize anyway - return mapping_.as_slice().substr(offset, slice.size()); - } - td::uint64 size() override { - return mapping_.as_slice().size(); - } - - private: - td::MemoryMapping mapping_; -}; - -td::Result> FileMemoryMappingBlobView::create(td::CSlice file_path, td::uint64 file_size) { - TRY_RESULT(fd, td::FileFd::open(file_path, td::FileFd::Flags::Read)); - TRY_RESULT(stat, fd.stat()); - if (file_size == 0) { - file_size = stat.size_; - } else if (file_size != (td::uint64)stat.size_) { - return td::Status::Error("Wrong file size"); - } - - TRY_RESULT(mapping, td::MemoryMapping::create_from_file(fd)); - - return std::make_unique(std::move(mapping)); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/BlobView.h b/submodules/ton/tonlib-src/crypto/vm/db/BlobView.h deleted file mode 100644 index 113ccf2e..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/BlobView.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/buffer.h" - -namespace vm { -class BlobView { - public: - virtual ~BlobView() = default; - td::Result view(td::MutableSlice slice, td::uint64 offset); - virtual td::uint64 size() = 0; - - private: - virtual td::Result view_impl(td::MutableSlice slice, td::uint64 offset) = 0; -}; - -class BufferSliceBlobView { - public: - static std::unique_ptr create(td::BufferSlice slice); -}; -class FileBlobView { - public: - static td::Result> create(td::CSlice file_path, td::uint64 file_size = 0); -}; -class FileMemoryMappingBlobView { - public: - static td::Result> create(td::CSlice file_path, td::uint64 file_size = 0); -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/CellHashTable.h b/submodules/ton/tonlib-src/crypto/vm/db/CellHashTable.h deleted file mode 100644 index acb3b3fc..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/CellHashTable.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Slice.h" - -#include - -namespace vm { -template -class CellHashTable { - public: - template - InfoT &apply(td::Slice hash, F &&f) { - auto it = set_.find(hash); - if (it != set_.end()) { - auto &res = const_cast(*it); - f(res); - return res; - } - InfoT info; - f(info); - auto &res = const_cast(*(set_.insert(std::move(info)).first)); - return res; - } - - template - void for_each(F &&f) { - for (auto &info : set_) { - f(info); - } - } - template - void filter(F &&f) { - for (auto it = set_.begin(); it != set_.end();) { - if (f(*it)) { - it++; - } else { - it = set_.erase(it); - } - } - } - void erase(td::Slice hash) { - auto it = set_.find(hash); - CHECK(it != set_.end()); - set_.erase(it); - } - size_t size() const { - return set_.size(); - } - - private: - std::set> set_; -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.cpp b/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.cpp deleted file mode 100644 index a1b7365b..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/db/CellStorage.h" -#include "vm/db/DynamicBagOfCellsDb.h" -#include "vm/boc.h" -#include "td/utils/base64.h" -#include "td/utils/tl_parsers.h" -#include "td/utils/tl_helpers.h" - -namespace vm { -namespace { -class RefcntCellStorer { - public: - RefcntCellStorer(td::int32 refcnt, const DataCell &cell) : refcnt_(refcnt), cell_(cell) { - } - - template - void store(StorerT &storer) const { - using td::store; - store(refcnt_, storer); - store(cell_, storer); - for (unsigned i = 0; i < cell_.size_refs(); i++) { - auto cell = cell_.get_ref(i); - auto level_mask = cell->get_level_mask(); - auto level = level_mask.get_level(); - td::uint8 x = static_cast(level_mask.get_mask()); - storer.store_slice(td::Slice(&x, 1)); - for (unsigned level_i = 0; level_i <= level; level_i++) { - if (!level_mask.is_significant(level_i)) { - continue; - } - storer.store_slice(cell->get_hash(level_i).as_slice()); - } - for (unsigned level_i = 0; level_i <= level; level_i++) { - if (!level_mask.is_significant(level_i)) { - continue; - } - td::uint8 depth_buf[Cell::depth_bytes]; - DataCell::store_depth(depth_buf, cell->get_depth(level_i)); - storer.store_slice(td::Slice(depth_buf, Cell::depth_bytes)); - } - } - } - - private: - td::int32 refcnt_; - const DataCell &cell_; -}; - -class RefcntCellParser { - public: - RefcntCellParser(bool need_data) : need_data_(need_data) { - } - td::int32 refcnt; - Ref cell; - - template - void parse(ParserT &parser, ExtCellCreator &ext_cell_creator) { - using ::td::parse; - parse(refcnt, parser); - if (!need_data_) { - return; - } - auto status = [&]() -> td::Status { - TRY_STATUS(parser.get_status()); - auto size = parser.get_left_len(); - td::Slice data = parser.template fetch_string_raw(size); - CellSerializationInfo info; - auto cell_data = data; - TRY_STATUS(info.init(cell_data, 0 /*ref_byte_size*/)); - data = data.substr(info.end_offset); - - Ref refs[Cell::max_refs]; - for (int i = 0; i < info.refs_cnt; i++) { - if (data.size() < 1) { - return td::Status::Error("Not enought data"); - } - Cell::LevelMask level_mask(data[0]); - auto n = level_mask.get_hashes_count(); - auto end_offset = 1 + n * (Cell::hash_bytes + Cell::depth_bytes); - if (data.size() < end_offset) { - return td::Status::Error("Not enought data"); - } - - TRY_RESULT(ext_cell, ext_cell_creator.ext_cell(level_mask, data.substr(1, n * Cell::hash_bytes), - data.substr(1 + n * Cell::hash_bytes, n * Cell::depth_bytes))); - refs[i] = std::move(ext_cell); - CHECK(refs[i]->get_level() == level_mask.get_level()); - data = data.substr(end_offset); - } - if (!data.empty()) { - return td::Status::Error("Too much data"); - } - TRY_RESULT(data_cell, info.create_data_cell(cell_data, td::Span>(refs, info.refs_cnt))); - cell = std::move(data_cell); - return td::Status::OK(); - }(); - if (status.is_error()) { - parser.set_error(status.message().str()); - return; - } - } - - private: - bool need_data_; -}; -} // namespace - -CellLoader::CellLoader(std::shared_ptr reader) : reader_(std::move(reader)) { - CHECK(reader_); -} - -td::Result CellLoader::load(td::Slice hash, bool need_data, ExtCellCreator &ext_cell_creator) { - //LOG(ERROR) << "Storage: load cell " << hash.size() << " " << td::base64_encode(hash); - LoadResult res; - std::string serialized; - TRY_RESULT(get_status, reader_->get(hash, serialized)); - if (get_status != KeyValue::GetStatus::Ok) { - DCHECK(get_status == KeyValue::GetStatus::NotFound); - return res; - } - - res.status = LoadResult::Ok; - - RefcntCellParser refcnt_cell(need_data); - td::TlParser parser(serialized); - refcnt_cell.parse(parser, ext_cell_creator); - TRY_STATUS(parser.get_status()); - - res.refcnt_ = refcnt_cell.refcnt; - res.cell_ = std::move(refcnt_cell.cell); - //CHECK(res.cell_->get_hash() == hash); - - return res; -} - -CellStorer::CellStorer(KeyValue &kv) : kv_(kv) { -} - -td::Status CellStorer::erase(td::Slice hash) { - return kv_.erase(hash); -} - -td::Status CellStorer::set(td::int32 refcnt, const DataCell &cell) { - return kv_.set(cell.get_hash().as_slice(), td::serialize(RefcntCellStorer(refcnt, cell))); -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.h b/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.h deleted file mode 100644 index b705b531..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/CellStorage.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/db/KeyValue.h" -#include "vm/db/DynamicBagOfCellsDb.h" -#include "vm/cells.h" - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace vm { -using KeyValue = td::KeyValue; -using KeyValueReader = td::KeyValueReader; - -class CellLoader { - public: - struct LoadResult { - public: - enum { Ok, NotFound } status{NotFound}; - - Ref &cell() { - DCHECK(status == Ok); - return cell_; - } - - td::int32 refcnt() const { - return refcnt_; - } - - Ref cell_; - td::int32 refcnt_{0}; - }; - CellLoader(std::shared_ptr reader); - td::Result load(td::Slice hash, bool need_data, ExtCellCreator &ext_cell_creator); - - private: - std::shared_ptr reader_; -}; - -class CellStorer { - public: - CellStorer(KeyValue &kv); - td::Status erase(td::Slice hash); - td::Status set(td::int32 refcnt, const DataCell &cell); - - private: - KeyValue &kv_; -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.cpp b/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.cpp deleted file mode 100644 index 5fcc3923..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/db/DynamicBagOfCellsDb.h" -#include "vm/db/CellStorage.h" -#include "vm/db/CellHashTable.h" - -#include "vm/cells/ExtCell.h" - -#include "td/utils/base64.h" -#include "td/utils/format.h" -#include "td/utils/ThreadSafeCounter.h" - -#include "vm/cellslice.h" - -namespace vm { -namespace { - -class CellDbReader { - public: - virtual ~CellDbReader() = default; - virtual td::Result> load_cell(td::Slice hash) = 0; -}; - -struct DynamicBocExtCellExtra { - std::shared_ptr reader; -}; - -class DynamicBocCellLoader { - public: - static td::Result> load_data_cell(const Cell &cell, const DynamicBocExtCellExtra &extra) { - return extra.reader->load_cell(cell.get_hash().as_slice()); - } -}; - -using DynamicBocExtCell = ExtCell; - -struct CellInfo { - bool sync_with_db{false}; - bool in_db{false}; - - bool was_dfs_new_cells{false}; - bool was{false}; - - td::int32 db_refcnt{0}; - td::int32 refcnt_diff{0}; - Ref cell; - Cell::Hash key() const { - return cell->get_hash(); - } - bool operator<(const CellInfo &other) const { - return key() < other.key(); - } -}; - -bool operator<(const CellInfo &a, td::Slice b) { - return a.key().as_slice() < b; -} - -bool operator<(td::Slice a, const CellInfo &b) { - return a < b.key().as_slice(); -} - -class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreator { - public: - DynamicBagOfCellsDbImpl() { - get_thread_safe_counter().add(1); - } - ~DynamicBagOfCellsDbImpl() { - get_thread_safe_counter().add(-1); - reset_cell_db_reader(); - } - td::Result> ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) override { - return get_cell_info_lazy(level_mask, hash, depth).cell; - } - td::Result> load_cell(td::Slice hash) override { - TRY_RESULT(loaded_cell, get_cell_info_force(hash).cell->load_cell()); - return std::move(loaded_cell.data_cell); - } - CellInfo &get_cell_info_force(td::Slice hash) { - return hash_table_.apply(hash, [&](CellInfo &info) { update_cell_info_force(info, hash); }); - } - CellInfo &get_cell_info_lazy(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) { - return hash_table_.apply(hash.substr(hash.size() - Cell::hash_bytes), - [&](CellInfo &info) { update_cell_info_lazy(info, level_mask, hash, depth); }); - } - CellInfo &get_cell_info(const Ref &cell) { - return hash_table_.apply(cell->get_hash().as_slice(), [&](CellInfo &info) { update_cell_info(info, cell); }); - } - - void inc(const Ref &cell) override { - if (cell.is_null()) { - return; - } - if (cell->get_virtualization() != 0) { - return; - } - //LOG(ERROR) << "INC"; - //CellSlice(cell, nullptr).print_rec(std::cout); - to_inc_.push_back(cell); - } - void dec(const Ref &cell) override { - if (cell.is_null()) { - return; - } - if (cell->get_virtualization() != 0) { - return; - } - //LOG(ERROR) << "DEC"; - //CellSlice(cell, nullptr).print_rec(std::cout); - to_dec_.push_back(cell); - } - - bool is_prepared_for_commit() { - return to_inc_.empty() && to_dec_.empty(); - } - - Stats get_stats_diff() override { - CHECK(is_prepared_for_commit()); - return stats_diff_; - } - - td::Status prepare_commit() override { - if (is_prepared_for_commit()) { - return td::Status::OK(); - } - //LOG(ERROR) << "dfs_new_cells_in_db"; - for (auto &new_cell : to_inc_) { - auto &new_cell_info = get_cell_info(new_cell); - dfs_new_cells_in_db(new_cell_info); - } - //return td::Status::OK(); - //LOG(ERROR) << "dfs_new_cells"; - for (auto &new_cell : to_inc_) { - auto &new_cell_info = get_cell_info(new_cell); - dfs_new_cells(new_cell_info); - } - - //LOG(ERROR) << "dfs_old_cells"; - for (auto &old_cell : to_dec_) { - auto &old_cell_info = get_cell_info(old_cell); - dfs_old_cells(old_cell_info); - } - - //LOG(ERROR) << "save_diff_prepare"; - save_diff_prepare(); - - to_inc_.clear(); - to_dec_.clear(); - - return td::Status::OK(); - } - - td::Status commit(CellStorer &storer) override { - prepare_commit(); - save_diff(storer); - // Some elements are erased from hash table, to keep it small. - // Hash table is no longer represents the difference between the loader and - // the current bag of cells. - reset_cell_db_reader(); - return td::Status::OK(); - } - - td::Status set_loader(std::unique_ptr loader) override { - reset_cell_db_reader(); - loader_ = std::move(loader); - //cell_db_reader_ = std::make_shared(this); - // Temporary(?) fix to make ExtCell thread safe. - // Downside(?) - loaded cells won't be cached - cell_db_reader_ = std::make_shared(std::make_unique(*loader_)); - stats_diff_ = {}; - return td::Status::OK(); - } - - private: - std::unique_ptr loader_; - std::vector> to_inc_; - std::vector> to_dec_; - CellHashTable hash_table_; - std::vector visited_; - Stats stats_diff_; - - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DynamicBagOfCellsDb"); - return res; - } - - class CellDbReaderImpl : public CellDbReader, - private ExtCellCreator, - public std::enable_shared_from_this { - public: - CellDbReaderImpl(std::unique_ptr cell_loader) : db_(nullptr), cell_loader_(std::move(cell_loader)) { - if (cell_loader_) { - get_thread_safe_counter().add(1); - } - } - CellDbReaderImpl(DynamicBagOfCellsDb *db) : db_(db) { - } - ~CellDbReaderImpl() { - if (cell_loader_) { - get_thread_safe_counter().add(-1); - } - } - void set_loader(std::unique_ptr cell_loader) { - if (cell_loader_) { - // avoid race - return; - } - cell_loader_ = std::move(cell_loader); - db_ = nullptr; - if (cell_loader_) { - get_thread_safe_counter().add(1); - } - } - - td::Result> ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) override { - CHECK(!db_); - TRY_RESULT(ext_cell, DynamicBocExtCell::create(PrunnedCellInfo{level_mask, hash, depth}, - DynamicBocExtCellExtra{shared_from_this()})); - return std::move(ext_cell); - } - - td::Result> load_cell(td::Slice hash) override { - if (db_) { - return db_->load_cell(hash); - } - TRY_RESULT(load_result, cell_loader_->load(hash, true, *this)); - CHECK(load_result.status == CellLoader::LoadResult::Ok); - return std::move(load_result.cell()); - } - - private: - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DynamicBagOfCellsDbLoader"); - return res; - } - DynamicBagOfCellsDb *db_; - std::unique_ptr cell_loader_; - }; - - std::shared_ptr cell_db_reader_; - - void reset_cell_db_reader() { - if (!cell_db_reader_) { - return; - } - cell_db_reader_->set_loader(std::move(loader_)); - cell_db_reader_.reset(); - //EXPERIMENTAL: clear cache to drop all references to old reader. - hash_table_ = {}; - } - - bool is_in_db(CellInfo &info) { - if (info.in_db) { - return true; - } - load_cell(info); - return info.in_db; - } - bool is_loaded(CellInfo &info) { - return info.sync_with_db; - } - - void load_cell(CellInfo &info) { - if (is_loaded(info)) { - return; - } - do_load_cell(info); - } - - bool dfs_new_cells_in_db(CellInfo &info) { - if (info.sync_with_db) { - return is_in_db(info); - } - if (info.in_db) { - return true; - } - - bool not_in_db = false; - for_each( - info, [¬_in_db, this](auto &child_info) { not_in_db |= !dfs_new_cells_in_db(child_info); }, false); - - if (not_in_db) { - CHECK(!info.in_db); - info.sync_with_db = true; - } - return is_in_db(info); - } - - void dfs_new_cells(CellInfo &info) { - info.refcnt_diff++; - if (!info.was) { - info.was = true; - visited_.push_back(&info); - } - //LOG(ERROR) << "dfs new " << td::format::escaped(info.cell->hash()); - - if (info.was_dfs_new_cells) { - return; - } - info.was_dfs_new_cells = true; - - if (is_in_db(info)) { - return; - } - - CHECK(is_loaded(info)); - for_each(info, [this](auto &child_info) { dfs_new_cells(child_info); }); - } - - void dfs_old_cells(CellInfo &info) { - info.refcnt_diff--; - if (!info.was) { - info.was = true; - visited_.push_back(&info); - } - //LOG(ERROR) << "dfs old " << td::format::escaped(info.cell->hash()); - - load_cell(info); - - auto new_refcnt = info.refcnt_diff + info.db_refcnt; - CHECK(new_refcnt >= 0); - if (new_refcnt != 0) { - return; - } - - for_each(info, [this](auto &child_info) { dfs_old_cells(child_info); }); - } - - void save_diff_prepare() { - stats_diff_ = {}; - for (auto info_ptr : visited_) { - save_cell_prepare(*info_ptr); - } - } - - void save_diff(CellStorer &storer) { - //LOG(ERROR) << hash_table_.size(); - for (auto info_ptr : visited_) { - save_cell(*info_ptr, storer); - } - visited_.clear(); - } - - void save_cell_prepare(CellInfo &info) { - if (info.refcnt_diff == 0) { - //CellSlice(info.cell, nullptr).print_rec(std::cout); - return; - } - load_cell(info); - - auto loaded_cell = info.cell->load_cell().move_as_ok(); - if (info.db_refcnt + info.refcnt_diff == 0) { - CHECK(info.in_db); - // erase - stats_diff_.cells_total_count--; - stats_diff_.cells_total_size -= loaded_cell.data_cell->get_serialized_size(true); - } else { - //save - if (info.in_db == false) { - stats_diff_.cells_total_count++; - stats_diff_.cells_total_size += loaded_cell.data_cell->get_serialized_size(true); - } - } - } - - void save_cell(CellInfo &info, CellStorer &storer) { - auto guard = td::ScopeExit{} + [&] { - info.was_dfs_new_cells = false; - info.was = false; - }; - if (info.refcnt_diff == 0) { - //CellSlice(info.cell, nullptr).print_rec(std::cout); - return; - } - CHECK(info.sync_with_db); - - info.db_refcnt += info.refcnt_diff; - info.refcnt_diff = 0; - - if (info.db_refcnt == 0) { - CHECK(info.in_db); - //LOG(ERROR) << "ERASE"; - //CellSlice(NoVm(), info.cell).print_rec(std::cout); - storer.erase(info.cell->get_hash().as_slice()); - info.in_db = false; - hash_table_.erase(info.cell->get_hash().as_slice()); - guard.dismiss(); - } else { - //LOG(ERROR) << "SAVE " << info.db_refcnt; - //CellSlice(NoVm(), info.cell).print_rec(std::cout); - auto loaded_cell = info.cell->load_cell().move_as_ok(); - storer.set(info.db_refcnt, *loaded_cell.data_cell); - info.in_db = true; - } - } - - template - void for_each(CellInfo &info, F &&f, bool force = true) { - auto cell = info.cell; - - if (!cell->is_loaded()) { - if (!force) { - return; - } - load_cell(info); - cell = info.cell; - } - if (!cell->is_loaded()) { - cell->load_cell().ensure(); - } - CHECK(cell->is_loaded()); - vm::CellSlice cs(vm::NoVm{}, cell); // FIXME - for (unsigned i = 0; i < cs.size_refs(); i++) { - //LOG(ERROR) << "---> " << td::format::escaped(cell->ref(i)->hash()); - f(get_cell_info(cs.prefetch_ref(i))); - } - } - - void do_load_cell(CellInfo &info) { - update_cell_info_force(info, info.cell->get_hash().as_slice()); - } - - void update_cell_info(CellInfo &info, const Ref &cell) { - CHECK(!cell.is_null()); - if (info.sync_with_db) { - return; - } - info.cell = cell; - } - - void update_cell_info_lazy(CellInfo &info, Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) { - if (info.sync_with_db) { - CHECK(info.cell.not_null()); - CHECK(info.cell->get_level_mask() == level_mask); - return; - } - if (info.cell.is_null()) { - auto ext_cell_r = create_empty_ext_cell(level_mask, hash, depth); - if (ext_cell_r.is_error()) { - //FIXME - LOG(ERROR) << "Failed to create ext_cell" << ext_cell_r.error(); - return; - } - info.cell = ext_cell_r.move_as_ok(); - info.in_db = true; // TODO - } - } - void update_cell_info_force(CellInfo &info, td::Slice hash) { - if (info.sync_with_db) { - return; - } - - do { - CHECK(loader_); - auto r_res = loader_->load(hash, true, *this); - if (r_res.is_error()) { - //FIXME - LOG(ERROR) << "Failed to load cell from db" << r_res.error(); - break; - } - auto res = r_res.move_as_ok(); - if (res.status != CellLoader::LoadResult::Ok) { - break; - } - info.cell = std::move(res.cell()); - CHECK(info.cell->get_hash().as_slice() == hash); - info.in_db = true; - info.db_refcnt = res.refcnt(); - } while (false); - info.sync_with_db = true; - } - - td::Result> create_empty_ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) { - TRY_RESULT(res, DynamicBocExtCell::create(PrunnedCellInfo{level_mask, hash, depth}, - DynamicBocExtCellExtra{cell_db_reader_})); - return std::move(res); - } -}; -} // namespace - -std::unique_ptr DynamicBagOfCellsDb::create() { - return std::make_unique(); -} -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.h b/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.h deleted file mode 100644 index 67d92ecf..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/DynamicBagOfCellsDb.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cells.h" - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace vm { -class CellLoader; -class CellStorer; -} // namespace vm - -namespace vm { -class ExtCellCreator { - public: - virtual ~ExtCellCreator() = default; - virtual td::Result> ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) = 0; -}; - -class DynamicBagOfCellsDb { - public: - virtual ~DynamicBagOfCellsDb() = default; - virtual td::Result> load_cell(td::Slice hash) = 0; - struct Stats { - td::int64 cells_total_count{0}; - td::int64 cells_total_size{0}; - void apply_diff(Stats diff) { - cells_total_count += diff.cells_total_count; - cells_total_size += diff.cells_total_size; - } - }; - virtual void inc(const Ref &old_root) = 0; - virtual void dec(const Ref &old_root) = 0; - - virtual td::Status prepare_commit() = 0; - virtual Stats get_stats_diff() = 0; - virtual td::Status commit(CellStorer &) = 0; - - // restart with new loader will also reset stats_diff - virtual td::Status set_loader(std::unique_ptr loader) = 0; - - static std::unique_ptr create(); -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.cpp b/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.cpp deleted file mode 100644 index 88291575..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/db/StaticBagOfCellsDb.h" - -#include "vm/cells/CellWithStorage.h" -#include "vm/boc.h" - -#include "vm/cells/ExtCell.h" - -#include "td/utils/crypto.h" -#include "td/utils/format.h" -#include "td/utils/misc.h" -#include "td/utils/port/RwMutex.h" -#include "td/utils/ConcurrentHashTable.h" - -#include - -namespace vm { -// -// Common interface -// -template -class RootCell : public Cell { - struct PrivateTag {}; - - public: - td::Result load_cell() const override { - return cell_->load_cell(); - } - Ref virtualize(VirtualizationParameters virt) const override { - return cell_->virtualize(virt); - } - td::uint32 get_virtualization() const override { - return cell_->get_virtualization(); - } - CellUsageTree::NodePtr get_tree_node() const override { - return cell_->get_tree_node(); - } - bool is_loaded() const override { - return cell_->is_loaded(); - } - - // hash and level - LevelMask get_level_mask() const override { - return cell_->get_level_mask(); - } - - template - static Ref create(Ref cell, T&& extra) { - return Ref(true, std::move(cell), std::forward(extra), PrivateTag{}); - } - template - RootCell(Ref cell, T&& extra, PrivateTag) : cell_(std::move(cell)), extra_(std::forward(extra)) { - } - - private: - Ref cell_; - ExtraT extra_; - td::uint16 do_get_depth(td::uint32 level) const override { - return cell_->get_depth(level); - } - const Hash do_get_hash(td::uint32 level) const override { - return cell_->get_hash(level); - } -}; - -class DataCellCacheNoop { - public: - Ref store(int idx, Ref cell) { - return cell; - } - Ref load(int idx) { - return {}; - } - void clear() { - } -}; -class DataCellCacheMutex { - public: - Ref store(int idx, Ref cell) { - auto lock = cells_rw_mutex_.lock_write(); - return cells_.emplace(idx, std::move(cell)).first->second; - } - Ref load(int idx) { - auto lock = cells_rw_mutex_.lock_read(); - auto it = cells_.find(idx); - if (it != cells_.end()) { - return it->second; - } - return {}; - } - void clear() { - auto guard = cells_rw_mutex_.lock_write(); - cells_.clear(); - } - - private: - td::RwMutex cells_rw_mutex_; - td::HashMap> cells_; -}; - -class DataCellCacheTdlib { - public: - Ref store(int idx, Ref cell) { - return Ref(cells_.insert(as_key(idx), cell.get())); - } - Ref load(int idx) { - return Ref(cells_.find(as_key(idx), nullptr)); - } - - void clear() { - cells_.for_each([](auto key, auto value) { Ref{value}; }); - } - - private: - td::ConcurrentHashMap cells_; - td::uint32 as_key(int idx) { - td::uint32 key = static_cast(idx + 1); - key *= 1000000007; - return key; - } -}; - -struct StaticBocExtCellExtra { - int idx; - std::weak_ptr deserializer; -}; - -class StaticBocLoader { - public: - static td::Result> load_data_cell(const Cell& cell, const StaticBocExtCellExtra& extra) { - auto deserializer = extra.deserializer.lock(); - if (!deserializer) { - return td::Status::Error("StaticBocDb is already destroyed, cannot fetch cell"); - } - return deserializer->load_by_idx(extra.idx); - } -}; -using StaticBocExtCell = ExtCell; -using StaticBocRootCell = RootCell>; - -td::Result> StaticBagOfCellsDb::create_ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth, - int idx) { - TRY_RESULT(res, StaticBocExtCell::create(PrunnedCellInfo{level_mask, hash, depth}, - StaticBocExtCellExtra{idx, shared_from_this()})); - return std::move(res); -} - -// -// Baseline implementation -// -class StaticBagOfCellsDbBaselineImpl : public StaticBagOfCellsDb { - public: - StaticBagOfCellsDbBaselineImpl(std::vector> roots) : roots_(std::move(roots)) { - } - td::Result get_root_count() override { - return roots_.size(); - }; - td::Result> get_root_cell(size_t idx) override { - if (idx >= roots_.size()) { - return td::Status::Error(PSLICE() << "invalid root_cell index: " << idx); - } - return roots_[idx]; - }; - - private: - std::vector> roots_; - - td::Result> load_by_idx(int idx) override { - UNREACHABLE(); - } -}; - -td::Result> StaticBagOfCellsDbBaseline::create(std::unique_ptr data) { - std::string buf(data->size(), '\0'); - TRY_RESULT(slice, data->view(buf, 0)); - return create(slice); -} - -td::Result> StaticBagOfCellsDbBaseline::create(td::Slice data) { - BagOfCells boc; - TRY_RESULT(x, boc.deserialize(data)); - if (x <= 0) { - return td::Status::Error("failed to deserialize"); - } - std::vector> roots(boc.get_root_count()); - for (int i = 0; i < boc.get_root_count(); i++) { - roots[i] = boc.get_root_cell(i); - } - return std::make_shared(std::move(roots)); -} - -// -// Main implementation -// -class StaticBagOfCellsDbLazyImpl : public StaticBagOfCellsDb { - public: - explicit StaticBagOfCellsDbLazyImpl(std::unique_ptr data, StaticBagOfCellsDbLazy::Options options) - : data_(std::move(data)), options_(std::move(options)) { - get_thread_safe_counter().add(1); - } - td::Result get_root_count() override { - TRY_STATUS(check_status()); - TRY_STATUS(check_result(load_header())); - return info_.root_count; - }; - td::Result> get_root_cell(size_t idx) override { - TRY_STATUS(check_status()); - TRY_RESULT(root_count, get_root_count()); - if (idx >= root_count) { - return td::Status::Error(PSLICE() << "invalid root_cell index: " << idx); - } - TRY_RESULT(cell_idx, load_root_idx(td::narrow_cast(idx))); - // Load DataCell in order to ensure lower hashes correctness - // They will be valid for all non-root cell automaically - TRY_RESULT(data_cell, check_result(load_data_cell(td::narrow_cast(cell_idx)))); - return create_root_cell(std::move(data_cell)); - }; - - ~StaticBagOfCellsDbLazyImpl() { - //LOG(ERROR) << deserialize_cell_cnt_ << " " << deserialize_cell_hash_cnt_; - get_thread_safe_counter().add(-1); - } - - private: - std::atomic should_cache_cells_{true}; - std::unique_ptr data_; - StaticBagOfCellsDbLazy::Options options_; - bool has_info_{false}; - BagOfCells::Info info_; - - std::mutex index_i_mutex_; - td::RwMutex index_data_rw_mutex_; - std::string index_data_; - std::atomic index_i_{0}; - size_t index_offset_{0}; - DataCellCacheMutex cells_; - //DataCellCacheNoop cells_; - //DataCellCacheTdlib cells_; - int next_idx_{0}; - Ref empty_cell_; - - //stats - td::ThreadSafeCounter deserialize_cell_cnt_; - td::ThreadSafeCounter deserialize_cell_hash_cnt_; - - std::atomic has_error_{false}; - std::mutex status_mutex_; - td::Status status_; - - static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { - static auto res = td::NamedThreadSafeCounter::get_default().get_counter("StaticBagOfCellsDbLazy"); - return res; - } - - td::Status check_status() TD_WARN_UNUSED_RESULT { - if (has_error_.load(std::memory_order_relaxed)) { - std::lock_guard guard(status_mutex_); - return status_.clone(); - } - return td::Status::OK(); - } - template - T check_result(T&& to_check) { - CHECK(status_.is_ok()); - if (to_check.is_error()) { - std::lock_guard guard(status_mutex_); - has_error_.store(true); - status_ = to_check.error().clone(); - } - return std::forward(to_check); - } - - td::Result> load_by_idx(int idx) override { - TRY_STATUS(check_status()); - return check_result(load_data_cell(idx)); - } - - struct Ptr { - td::MutableSlice as_slice() { - return data; - } - td::string data; - }; - // May be optimized - auto alloc(size_t size) { - //return td::StackAllocator::alloc(size); - return Ptr{std::string(size, '\0')}; - } - - td::Result load_idx_offset(int idx) { - if (idx < 0) { - return 0; - } - td::Slice offset_view; - CHECK(info_.offset_byte_size <= 8); - char arr[8]; - td::RwMutex::ReadLock guard; - if (info_.has_index) { - TRY_RESULT(new_offset_view, data_->view(td::MutableSlice(arr, info_.offset_byte_size), - info_.index_offset + idx * info_.offset_byte_size)); - offset_view = new_offset_view; - } else { - guard = index_data_rw_mutex_.lock_read().move_as_ok(); - offset_view = td::Slice(index_data_).substr(idx * info_.offset_byte_size, info_.offset_byte_size); - } - - CHECK(offset_view.size() == (size_t)info_.offset_byte_size); - return td::narrow_cast(info_.read_offset(offset_view.ubegin())); - } - - td::Result load_root_idx(int root_i) { - CHECK(root_i >= 0 && root_i < info_.root_count); - if (!info_.has_roots) { - return 0; - } - char arr[8]; - TRY_RESULT(idx_view, data_->view(td::MutableSlice(arr, info_.ref_byte_size), - info_.roots_offset + root_i * info_.ref_byte_size)); - CHECK(idx_view.size() == (size_t)info_.ref_byte_size); - return info_.read_ref(idx_view.ubegin()); - } - - struct CellLocation { - std::size_t begin; - std::size_t end; - bool should_cache; - }; - td::Result get_cell_location(int idx) { - CHECK(idx >= 0); - CHECK(idx < info_.cell_count); - TRY_STATUS(preload_index(idx)); - TRY_RESULT(from, load_idx_offset(idx - 1)); - TRY_RESULT(till, load_idx_offset(idx)); - CellLocation res; - res.begin = from; - res.end = till; - res.should_cache = true; - if (info_.has_cache_bits) { - res.begin /= 2; - res.should_cache = res.end % 2 == 1; - res.end /= 2; - } - CHECK(std::numeric_limits::max() - res.begin >= info_.data_offset); - CHECK(std::numeric_limits::max() - res.end >= info_.data_offset); - res.begin += static_cast(info_.data_offset); - res.end += static_cast(info_.data_offset); - return res; - } - - td::Status load_header() { - if (has_info_) { - return td::Status::OK(); - } - std::string header(1000, '\0'); - TRY_RESULT(header_view, data_->view(td::MutableSlice(header).truncate(data_->size()), 0)) - auto parse_res = info_.parse_serialized_header(header_view); - if (parse_res <= 0) { - return td::Status::Error("bag-of-cell error: failed to read header"); - } - if (info_.total_size < data_->size()) { - return td::Status::Error("bag-of-cell error: not enough data"); - } - if (options_.check_crc32c && info_.has_crc32c) { - std::string buf(td::narrow_cast(info_.total_size), '\0'); - TRY_RESULT(data, data_->view(td::MutableSlice(buf), 0)); - unsigned crc_computed = td::crc32c(td::Slice{data.ubegin(), data.uend() - 4}); - unsigned crc_stored = td::as(data.uend() - 4); - if (crc_computed != crc_stored) { - return td::Status::Error(PSLICE() - << "bag-of-cells CRC32C mismatch: expected " << td::format::as_hex(crc_computed) - << ", found " << td::format::as_hex(crc_stored)); - } - } - has_info_ = true; - return td::Status::OK(); - } - - td::Status preload_index(int idx) { - if (info_.has_index) { - return td::Status::OK(); - } - - CHECK(idx < info_.cell_count); - if (index_i_.load(std::memory_order_relaxed) > idx) { - return td::Status::OK(); - } - - std::lock_guard index_i_guard(index_i_mutex_); - std::array buf; - auto buf_slice = td::MutableSlice(buf.data(), buf.size()); - for (; index_i_ <= idx; index_i_++) { - auto offset = td::narrow_cast(info_.data_offset + index_offset_); - CHECK(data_->size() >= offset); - TRY_RESULT(cell, data_->view(buf_slice.copy().truncate(data_->size() - offset), offset)); - CellSerializationInfo cell_info; - TRY_STATUS(cell_info.init(cell, info_.ref_byte_size)); - index_offset_ += cell_info.end_offset; - LOG_CHECK((unsigned)info_.offset_byte_size <= 8) << info_.offset_byte_size; - td::uint8 tmp[8]; - info_.write_offset(tmp, index_offset_); - auto guard = index_data_rw_mutex_.lock_write(); - index_data_.append(reinterpret_cast(tmp), info_.offset_byte_size); - } - return td::Status::OK(); - } - - Ref get_any_cell(int idx) { - return get_data_cell(idx); - } - - Ref get_data_cell(int idx) { - return cells_.load(idx); - } - - Ref set_data_cell(int idx, Ref cell) { - if (/*idx >= info_.root_count || */ !should_cache_cells_.load(std::memory_order_relaxed)) { - return cell; - } - CHECK(cell.not_null()); - return cells_.store(idx, std::move(cell)); - } - - Ref set_any_cell(int idx, Ref cell) { - auto data_cell = Ref(cell); - if (data_cell.is_null()) { - return cell; - } - return set_data_cell(idx, std::move(data_cell)); - } - - td::Result> load_any_cell(int idx) { - { - auto cell = get_any_cell(idx); - if (cell.not_null()) { - return std::move(cell); - } - } - - TRY_RESULT(cell_location, get_cell_location(idx)); - auto buf = alloc(cell_location.end - cell_location.begin); - TRY_RESULT(cell_slice, data_->view(buf.as_slice(), cell_location.begin)); - TRY_RESULT(res, deserialize_any_cell(idx, cell_slice, cell_location.should_cache)); - return std::move(res); - } - - td::Result> load_data_cell(int idx) { - { - auto cell = get_data_cell(idx); - if (cell.not_null()) { - return std::move(cell); - } - } - - TRY_RESULT(cell_location, get_cell_location(idx)); - auto buf = alloc(cell_location.end - cell_location.begin); - TRY_RESULT(cell_slice, data_->view(buf.as_slice(), cell_location.begin)); - TRY_RESULT(res, deserialize_data_cell(idx, cell_slice, cell_location.should_cache)); - return std::move(res); - } - - td::Result> deserialize_data_cell(int idx, td::Slice cell_slice, bool should_cache) { - CellSerializationInfo cell_info; - TRY_STATUS(cell_info.init(cell_slice, info_.ref_byte_size)); - if (cell_slice.size() != cell_info.end_offset) { - return td::Status::Error(PSLICE() << "unused space in cell #" << idx << " serialization"); - } - return deserialize_data_cell(idx, cell_slice, cell_info, should_cache); - } - - td::Result> deserialize_data_cell(int idx, td::Slice cell_slice, const CellSerializationInfo& cell_info, - bool should_cache) { - deserialize_cell_cnt_.add(1); - Ref refs[4]; - CHECK(cell_info.refs_cnt <= 4); - auto* ref_ptr = cell_slice.ubegin() + cell_info.refs_offset; - for (int k = 0; k < cell_info.refs_cnt; k++, ref_ptr += info_.ref_byte_size) { - int ref_idx = td::narrow_cast(info_.read_ref(ref_ptr)); - if (ref_idx >= info_.cell_count) { - return td::Status::Error(PSLICE() << "invalid bag-of-cells cell #" << idx << " refers to cell #" << ref_idx - << " which is too big " << td::tag("cell_count", info_.cell_count)); - } - if (idx >= ref_idx) { - return td::Status::Error(PSLICE() << "invalid bag-of-cells cell #" << idx << " refers to cell #" << ref_idx - << " which is a backward reference"); - } - TRY_RESULT(ref, load_any_cell(ref_idx)); - refs[k] = std::move(ref); - } - - TRY_RESULT(data_cell, cell_info.create_data_cell(cell_slice, td::Span>(refs, cell_info.refs_cnt))); - if (!should_cache) { - return std::move(data_cell); - } - return set_data_cell(idx, std::move(data_cell)); - } - - td::Result> deserialize_any_cell(int idx, td::Slice cell_slice, bool should_cache) { - CellSerializationInfo cell_info; - TRY_STATUS(cell_info.init(cell_slice, info_.ref_byte_size)); - if (cell_info.with_hashes) { - deserialize_cell_hash_cnt_.add(1); - int n = cell_info.level_mask.get_hashes_count(); - return create_ext_cell(cell_info.level_mask, cell_slice.substr(cell_info.hashes_offset, n * Cell::hash_bytes), - cell_slice.substr(cell_info.depth_offset, n * Cell::depth_bytes), idx); - } - TRY_RESULT(data_cell, deserialize_data_cell(idx, cell_slice, cell_info, should_cache)); - return std::move(data_cell); - } - td::Result> create_root_cell(Ref data_cell) { - return StaticBocRootCell::create(std::move(data_cell), shared_from_this()); - } -}; - -td::Result> StaticBagOfCellsDbLazy::create(std::unique_ptr data, - Options options) { - return std::make_shared(std::move(data), std::move(options)); -} - -td::Result> StaticBagOfCellsDbLazy::create(td::BufferSlice data, Options options) { - return std::make_shared(vm::BufferSliceBlobView::create(std::move(data)), - std::move(options)); -} - -td::Result> StaticBagOfCellsDbLazy::create(std::string data, Options options) { - return create(BufferSliceBlobView::create(td::BufferSlice(data)), std::move(options)); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.h b/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.h deleted file mode 100644 index 124c868a..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/StaticBagOfCellsDb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "vm/cells.h" -#include "vm/db/BlobView.h" - -#include "td/utils/Status.h" - -namespace vm { -class StaticBagOfCellsDb : public std::enable_shared_from_this { - public: - virtual ~StaticBagOfCellsDb() = default; - // TODO: handle errors - virtual td::Result get_root_count() = 0; - virtual td::Result> get_root_cell(size_t idx) = 0; - - protected: - virtual td::Result> load_by_idx(int idx) = 0; - friend class StaticBocLoader; - friend class StaticBocRootLoader; - td::Result> create_ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth, int idx); - td::Result> create_root_ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth, int idx); -}; - -class StaticBagOfCellsDbBaseline { - public: - static td::Result> create(std::unique_ptr data); - static td::Result> create(td::Slice data); -}; - -class StaticBagOfCellsDbLazy { - public: - struct Options { - Options() { - } - bool check_crc32c{false}; - }; - static td::Result> create(std::unique_ptr data, Options options = {}); - static td::Result> create(td::BufferSlice data, Options options = {}); - static td::Result> create(std::string data, Options options = {}); -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/TonDb.cpp b/submodules/ton/tonlib-src/crypto/vm/db/TonDb.cpp deleted file mode 100644 index ac69973f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/TonDb.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/db/TonDb.h" - -#include "td/utils/tl_helpers.h" -#include "td/utils/Random.h" - -#if TDDB_USE_ROCKSDB -#include "td/db/RocksDb.h" -#endif - -namespace vm { - -template -void SmartContractMeta::store(StorerT &storer) const { - using td::store; - store(stats.cells_total_count, storer); - store(stats.cells_total_size, storer); - store(type, storer); -} -template -void SmartContractMeta::parse(ParserT &parser) { - using td::parse; - parse(stats.cells_total_count, parser); - parse(stats.cells_total_size, parser); - parse(type, parser); -} - -// -// SmartContractDbImpl -// -Ref SmartContractDbImpl::get_root() { - if (sync_root_with_db_ || !new_root_.is_null()) { - return new_root_; - } - - sync_root_with_db(); - return new_root_; -} - -void SmartContractDbImpl::set_root(Ref new_root) { - CHECK(new_root.not_null()); - sync_root_with_db(); - if (is_dynamic()) { - cell_db_->dec(new_root_); - } - new_root_ = std::move(new_root); - if (is_dynamic()) { - cell_db_->inc(new_root_); - } -} - -SmartContractDbImpl::SmartContractDbImpl(td::Slice hash, std::shared_ptr kv) - : hash_(hash.str()), kv_(std::move(kv)) { - cell_db_ = DynamicBagOfCellsDb::create(); -} - -SmartContractMeta SmartContractDbImpl::get_meta() { - sync_root_with_db(); - return meta_; -} -td::Status SmartContractDbImpl::validate_meta() { - if (!is_dynamic()) { - return td::Status::OK(); - } - sync_root_with_db(); - TRY_RESULT(in_db, kv_->count({})); - if (static_cast(in_db) != meta_.stats.cells_total_count + 2) { - return td::Status::Error(PSLICE() << "Invalid meta " << td::tag("expected_count", in_db) - << td::tag("meta_count", meta_.stats.cells_total_count + 2)); - } - return td::Status::OK(); -} - -bool SmartContractDbImpl::is_dynamic() const { - return meta_.type == SmartContractMeta::Dynamic; -} - -bool SmartContractDbImpl::is_root_changed() const { - return !new_root_.is_null() && (db_root_.is_null() || db_root_->get_hash() != new_root_->get_hash()); -} - -void SmartContractDbImpl::sync_root_with_db() { - if (sync_root_with_db_) { - return; - } - std::string root_hash; - kv_->get("root", root_hash); - std::string meta_serialized; - kv_->get("meta", meta_serialized); - // TODO: proper serialization - td::unserialize(meta_, meta_serialized).ignore(); - sync_root_with_db_ = true; - - if (root_hash.empty()) { - meta_.type = SmartContractMeta::Static; - //meta_.type = SmartContractMeta::Dynamic; - } else { - if (is_dynamic()) { - //FIXME: error handling - db_root_ = cell_db_->load_cell(root_hash).move_as_ok(); - } else { - std::string boc_serialized; - kv_->get("boc", boc_serialized); - BagOfCells boc; - //TODO: check error - boc.deserialize(boc_serialized); - db_root_ = boc.get_root_cell(); - } - CHECK(db_root_->get_hash().as_slice() == root_hash); - new_root_ = db_root_; - } -} - -enum { boc_size = 2000 }; -void SmartContractDbImpl::prepare_commit_dynamic(bool force) { - if (!is_dynamic()) { - CHECK(force); - meta_.stats = {}; - cell_db_->inc(new_root_); - } - cell_db_->prepare_commit(); - meta_.stats.apply_diff(cell_db_->get_stats_diff()); - - if (!force && meta_.stats.cells_total_size < boc_size) { - //LOG(ERROR) << "DYNAMIC -> BOC"; - return prepare_commit_static(true); - } - is_dynamic_commit_ = true; -}; - -void SmartContractDbImpl::prepare_commit_static(bool force) { - BagOfCells boc; - boc.add_root(new_root_); - boc.import_cells().ensure(); // FIXME - if (!force && boc.estimate_serialized_size(15) > boc_size) { - //LOG(ERROR) << "BOC -> DYNAMIC "; - return prepare_commit_dynamic(true); - } - if (is_dynamic()) { - cell_db_->dec(new_root_); - cell_db_->prepare_commit(); - // stats is invalid now - } - is_dynamic_commit_ = false; - boc_to_commit_ = boc.serialize_to_string(15); - meta_.stats = {}; -} - -void SmartContractDbImpl::prepare_transaction() { - sync_root_with_db(); - if (!is_root_changed()) { - return; - } - - if (is_dynamic()) { - prepare_commit_dynamic(false); - } else { - prepare_commit_static(false); - } -} - -void SmartContractDbImpl::commit_transaction(KeyValue &kv) { - if (!is_root_changed()) { - return; - } - - if (is_dynamic_commit_) { - //LOG(ERROR) << "STORE DYNAMIC"; - if (!is_dynamic() && db_root_.not_null()) { - kv.erase("boc"); - } - CellStorer storer(kv); - cell_db_->commit(storer); - meta_.type = SmartContractMeta::Dynamic; - } else { - //LOG(ERROR) << "STORE BOC"; - if (is_dynamic() && db_root_.not_null()) { - //LOG(ERROR) << "Clear Dynamic db"; - CellStorer storer(kv); - cell_db_->commit(storer); - cell_db_ = DynamicBagOfCellsDb::create(); - } - meta_.type = SmartContractMeta::Static; - kv.set("boc", boc_to_commit_); - boc_to_commit_ = {}; - } - - kv.set("root", new_root_->get_hash().as_slice()); - kv.set("meta", td::serialize(meta_)); - db_root_ = new_root_; -} - -void SmartContractDbImpl::set_reader(std::shared_ptr reader) { - kv_ = std::move(reader); - cell_db_->set_loader(std::make_unique(kv_)); -} - -// -// TonDbTransactionImpl -// -SmartContractDb TonDbTransactionImpl::begin_smartcontract(td::Slice hash) { - SmartContractDb res; - contracts_.apply(hash, [&](auto &info) { - if (!info.is_inited) { - info.is_inited = true; - info.hash = hash.str(); - info.smart_contract_db = std::make_unique(hash, nullptr); - } - LOG_CHECK(info.generation_ != generation_) << "Cannot begin one smartcontract twice during the same transaction"; - CHECK(info.smart_contract_db); - info.smart_contract_db->set_reader(std::make_shared(reader_, hash)); - res = std::move(info.smart_contract_db); - }); - return res; -} - -void TonDbTransactionImpl::commit_smartcontract(SmartContractDb txn) { - commit_smartcontract(SmartContractDiff(std::move(txn))); -} -void TonDbTransactionImpl::commit_smartcontract(SmartContractDiff txn) { - { - td::PrefixedKeyValue kv(kv_, txn.hash()); - txn.commit_transaction(kv); - } - end_smartcontract(txn.extract_smartcontract()); -} - -void TonDbTransactionImpl::abort_smartcontract(SmartContractDb txn) { - end_smartcontract(std::move(txn)); -} -void TonDbTransactionImpl::abort_smartcontract(SmartContractDiff txn) { - end_smartcontract(txn.extract_smartcontract()); -} - -TonDbTransactionImpl::TonDbTransactionImpl(std::shared_ptr kv) : kv_(std::move(kv)) { - CHECK(kv_ != nullptr); - reader_.reset(kv_->snapshot().release()); -} - -void TonDbTransactionImpl::begin() { - kv_->begin_write_batch(); - generation_++; -} -void TonDbTransactionImpl::commit() { - kv_->commit_write_batch(); - reader_.reset(kv_->snapshot().release()); -} -void TonDbTransactionImpl::abort() { - kv_->abort_write_batch(); -} -void TonDbTransactionImpl::clear_cache() { - contracts_ = {}; -} - -void TonDbTransactionImpl::end_smartcontract(SmartContractDb smart_contract) { - contracts_.apply(smart_contract->hash(), [&](auto &info) { - CHECK(info.hash == smart_contract->hash()); - CHECK(!info.smart_contract_db); - info.smart_contract_db = std::move(smart_contract); - }); -} - -// -// TonDbImpl -// -TonDbImpl::TonDbImpl(std::unique_ptr kv) - : kv_(std::move(kv)), transaction_(std::make_unique(kv_)) { -} -TonDbImpl::~TonDbImpl() { - CHECK(transaction_); - kv_->flush(); -} -TonDbTransaction TonDbImpl::begin_transaction() { - CHECK(transaction_); - transaction_->begin(); - return std::move(transaction_); -} -void TonDbImpl::commit_transaction(TonDbTransaction transaction) { - CHECK(!transaction_); - CHECK(&transaction->kv() == kv_.get()); - transaction_ = std::move(transaction); - transaction_->commit(); -} -void TonDbImpl::abort_transaction(TonDbTransaction transaction) { - CHECK(!transaction_); - CHECK(&transaction->kv() == kv_.get()); - transaction_ = std::move(transaction); - transaction_->abort(); -} -void TonDbImpl::clear_cache() { - CHECK(transaction_); - transaction_->clear_cache(); -} - -std::string TonDbImpl::stats() const { - return kv_->stats(); -} - -td::Result TonDbImpl::open(td::Slice path) { -#if TDDB_USE_ROCKSDB - TRY_RESULT(rocksdb, td::RocksDb::open(path.str())); - return std::make_unique(std::make_unique(std::move(rocksdb))); -#else - return td::Status::Error("TonDb is not supported in this build"); -#endif -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/db/TonDb.h b/submodules/ton/tonlib-src/crypto/vm/db/TonDb.h deleted file mode 100644 index dfce3110..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/db/TonDb.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/cellslice.h" -#include "vm/cells.h" -#include "vm/boc.h" -#include "td/db/KeyValue.h" -#include "vm/db/CellStorage.h" -#include "vm/db/CellHashTable.h" - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace vm { -class SmartContractDbImpl; -using SmartContractDb = std::unique_ptr; -using KeyValue = td::KeyValue; -using KeyValueReader = td::KeyValueReader; - -struct SmartContractMeta { - DynamicBagOfCellsDb::Stats stats; - enum BagOfCellsType { Dynamic, Static } type{Static}; - - template - void store(StorerT &storer) const; - template - void parse(ParserT &parser); -}; - -class SmartContractDbImpl { - public: - Ref get_root(); - SmartContractMeta get_meta(); - td::Status validate_meta(); - - void set_root(Ref new_root); - - SmartContractDbImpl(td::Slice hash, std::shared_ptr kv); - - private: - std::string hash_; - std::shared_ptr kv_; - - bool sync_root_with_db_{false}; - Ref db_root_; - Ref new_root_; - SmartContractMeta meta_; - bool is_dynamic_commit_; - std::string boc_to_commit_; - - std::unique_ptr cell_db_; - std::unique_ptr bag_of_cells_; - - friend class SmartContractDiff; - friend class TonDbTransactionImpl; - - void sync_root_with_db(); - - td::Slice hash() const { - return hash_; - } - - void prepare_transaction(); - void commit_transaction(KeyValue &kv); - - void set_reader(std::shared_ptr reader); - - bool is_dynamic() const; - void prepare_commit_dynamic(bool force); - void prepare_commit_static(bool force); - bool is_root_changed() const; -}; - -class SmartContractDiff { - public: - explicit SmartContractDiff(SmartContractDb db) : db_(std::move(db)) { - db_->prepare_transaction(); - } - - SmartContractDb extract_smartcontract() { - return std::move(db_); - } - - td::Slice hash() const { - return db_->hash(); - } - - void commit_transaction(KeyValue &kv) { - db_->commit_transaction(kv); - } - - private: - SmartContractDb db_; -}; - -class TonDbTransactionImpl; -using TonDbTransaction = std::unique_ptr; -class TonDbTransactionImpl { - public: - SmartContractDb begin_smartcontract(td::Slice hash = {}); - - void commit_smartcontract(SmartContractDb txn); - void commit_smartcontract(SmartContractDiff txn); - - void abort_smartcontract(SmartContractDb txn); - void abort_smartcontract(SmartContractDiff txn); - - TonDbTransactionImpl(std::shared_ptr kv); - - private: - std::shared_ptr kv_; - std::shared_ptr reader_; - td::uint64 generation_{0}; - - struct SmartContractInfo { - bool is_inited{false}; - td::uint64 generation_{0}; - std::string hash; - SmartContractDb smart_contract_db; - bool operator<(const SmartContractInfo &other) const { - return hash < other.hash; - } - friend bool operator<(const SmartContractInfo &info, td::Slice hash) { - return info.hash < hash; - } - friend bool operator<(td::Slice hash, const SmartContractInfo &info) { - return hash < info.hash; - } - }; - - CellHashTable contracts_; - - KeyValue &kv() { - return *kv_; - } - friend class TonDbImpl; - - void begin(); - void commit(); - void abort(); - void clear_cache(); - - void end_smartcontract(SmartContractDb smart_contract); -}; - -class TonDbImpl; -using TonDb = std::unique_ptr; -class TonDbImpl { - public: - TonDbImpl(std::unique_ptr kv); - ~TonDbImpl(); - TonDbTransaction begin_transaction(); - void commit_transaction(TonDbTransaction transaction); - void abort_transaction(TonDbTransaction transaction); - void clear_cache(); - static td::Result open(td::Slice path); - std::string stats() const; - - private: - std::shared_ptr kv_; - TonDbTransaction transaction_; -}; -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/debugops.cpp b/submodules/ton/tonlib-src/crypto/vm/debugops.cpp deleted file mode 100644 index 0ec205a3..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/debugops.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/debugops.h" -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" - -namespace vm { - -bool vm_debug_enabled = false; - -void set_debug_enabled(bool enable_debug) { - vm_debug_enabled = enable_debug; -} - -int exec_dummy_debug(VmState* st, int args) { - VM_LOG(st) << "execute DEBUG " << (args & 0xff); - return 0; -} - -// similar to PUSHSLICE instruction in cellops.cpp -int exec_dummy_debug_str(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - int data_bits = ((args & 15) + 1) * 8; - if (!cs.have(pfx_bits + data_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a DEBUGSTR instruction"}; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits); - VM_LOG(st) << "execute DEBUGSTR " << slice->as_bitslice().to_hex(); - return 0; -} - -std::string dump_dummy_debug_str(CellSlice& cs, unsigned args, int pfx_bits) { - int data_bits = ((args & 15) + 1) * 8; - if (!cs.have(pfx_bits + data_bits)) { - return ""; - } - cs.advance(pfx_bits); - auto slice = cs.fetch_subslice(data_bits); - slice.unique_write().remove_trailing(); - std::ostringstream os; - os << "DEBUGSTR "; - slice->dump_hex(os, 1, false); - return os.str(); -} - -int compute_len_debug_str(const CellSlice& cs, unsigned args, int pfx_bits) { - unsigned bits = pfx_bits + ((args & 15) + 1) * 8; - return cs.have(bits) ? bits : 0; -} - -int exec_dump_stack(VmState* st) { - VM_LOG(st) << "execute DUMPSTK"; - if (!vm_debug_enabled) { - return 0; - } - Stack& stack = st->get_stack(); - int d = stack.depth(); - std::cerr << "#DEBUG#: stack(" << d << " values) : "; - if (d > 255) { - std::cerr << "... "; - d = 255; - } - for (int i = d; i > 0; i--) { - stack[i - 1].print_list(std::cerr); - std::cerr << ' '; - } - std::cerr << std::endl; - return 0; -} - -int exec_dump_value(VmState* st, unsigned arg) { - arg &= 15; - VM_LOG(st) << "execute DUMP s" << arg; - if (!vm_debug_enabled) { - return 0; - } - Stack& stack = st->get_stack(); - if ((int)arg < stack.depth()) { - std::cerr << "#DEBUG#: s" << arg << " = "; - stack[arg].print_list(std::cerr); - std::cerr << std::endl; - } else { - std::cerr << "#DEBUG#: s" << arg << " is absent" << std::endl; - } - return 0; -} - -void register_debug_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - if (!vm_debug_enabled) { - cp0.insert(OpcodeInstr::mkfixedrange(0xfe00, 0xfef0, 16, 8, instr::dump_1c_and(0xff, "DEBUG "), exec_dummy_debug)) - .insert(OpcodeInstr::mkext(0xfef, 12, 4, dump_dummy_debug_str, exec_dummy_debug_str, compute_len_debug_str)); - } else { - // NB: all non-redefined opcodes in fe00..feff should be redirected to dummy debug definitions - cp0.insert(OpcodeInstr::mksimple(0xfe00, 16, "DUMPSTK", exec_dump_stack)) - .insert(OpcodeInstr::mkfixedrange(0xfe01, 0xfe20, 16, 8, instr::dump_1c_and(0xff, "DEBUG "), exec_dummy_debug)) - .insert(OpcodeInstr::mkfixed(0xfe2, 12, 4, instr::dump_1sr("DUMP"), exec_dump_value)) - .insert(OpcodeInstr::mkfixedrange(0xfe30, 0xfef0, 16, 8, instr::dump_1c_and(0xff, "DEBUG "), exec_dummy_debug)) - .insert(OpcodeInstr::mkext(0xfef, 12, 4, dump_dummy_debug_str, exec_dummy_debug_str, compute_len_debug_str)); - } -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/debugops.h b/submodules/ton/tonlib-src/crypto/vm/debugops.h deleted file mode 100644 index ba3d673f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/debugops.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -extern bool vm_debug_enabled; - -void register_debug_ops(OpcodeTable& cp0); -void set_debug_enabled(bool enable_debug); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dict.cpp b/submodules/ton/tonlib-src/crypto/vm/dict.cpp deleted file mode 100644 index ac32b38f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dict.cpp +++ /dev/null @@ -1,2954 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/dict.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/stack.hpp" -#include "common/bitstring.h" - -#include "td/utils/bits.h" - -namespace vm { - -/* - * - * DictionaryBase : basic (common) dictionary manipulation - * - */ - -DictionaryBase::DictionaryBase(Ref _root, int _n, bool validate) - : root(std::move(_root)), root_cell(), key_bits(_n), flags(f_root_cached) { - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(const CellSlice& root_cs, int _n, bool validate) - : root(), root_cell(), key_bits(_n), flags(0) { - int f = (int)root_cs.prefetch_ulong(1); - if (f < 0) { - flags |= f_invalid; - } else if (f > 0) { - if (root_cs.size_refs()) { - root_cell = root_cs.prefetch_ref(); - } else { - flags |= f_invalid; - } - } - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(DictAdvance, CellSlice& root_cs, int _n, bool validate) - : root(), root_cell(), key_bits(_n), flags(0) { - int f = (int)root_cs.prefetch_ulong(1); - if (!f) { - root_cs.advance(1); - } else if (f > 0 && root_cs.size_refs()) { - root_cs.advance(1); - root_cell = root_cs.fetch_ref(); - } else { - flags |= f_invalid; - } - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(Ref cell, int _n, bool validate) - : root(), root_cell(std::move(cell)), key_bits(_n), flags(0) { - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(int _n, bool validate) : root(), root_cell(), key_bits(_n), flags(0) { - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(DictNonEmpty, Ref _root, int _n, bool validate) - : root(), root_cell(), key_bits(_n), flags(0) { - if (_root.is_null() || !init_root_for_nonempty(*_root)) { // empty ? - invalidate(); // invalidate - } - if (validate) { - force_validate(); - } -} - -DictionaryBase::DictionaryBase(DictNonEmpty, const CellSlice& _root, int _n, bool validate) - : root(), root_cell(), key_bits(_n), flags(0) { - if (!init_root_for_nonempty(_root)) { - invalidate(); - } - if (validate) { - force_validate(); - } -} - -bool DictionaryBase::init_root_for_nonempty(const CellSlice& cs) { - vm::CellBuilder cb; - return cb.append_cellslice_bool(cs) && cb.finalize_to(root_cell); -} - -Ref DictionaryBase::construct_root_from(const CellSlice& root_node_cs) { - vm::CellBuilder cb; - if (cb.append_cellslice_bool(root_node_cs)) { - return cb.finalize(); - } else { - return {}; - } -} - -void DictionaryBase::force_validate() { - if (!is_valid() && !validate()) { - throw VmError{Excno::dict_err, "invalid dictionary"}; - } -} - -bool DictionaryBase::validate() { - if (is_valid()) { - return true; - } - if (flags & f_invalid) { - return false; - } - if (key_bits < 0 || key_bits > max_key_bits) { - return invalidate(); - } - if (flags & f_root_cached) { - if (root.is_null() || root->size() != 1) { - return invalidate(); - } - bool non_empty = root->prefetch_ulong(1); - if (root->size_refs() != (non_empty ? 1u : 0u)) { - return invalidate(); - } - if (root_cell.not_null()) { - return invalidate(); - } - if (non_empty) { - root_cell = root->prefetch_ref(); - } - } else if (root.not_null()) { - return invalidate(); - } - flags |= f_valid; - return true; -} - -Ref DictionaryBase::get_root() const { - if (!(flags & f_root_cached) && !compute_root()) { - return {}; - } - return root; -} - -Ref DictionaryBase::extract_root() && { - if (!(flags & f_root_cached) && !compute_root()) { - return {}; - } - flags = f_invalid; - return std::move(root); -} - -bool DictionaryBase::append_dict_to_bool(CellBuilder& cb) && { - if (!is_valid()) { - return false; - } - flags = f_invalid; - return cb.store_maybe_ref(std::move(root_cell)); -} - -bool DictionaryBase::append_dict_to_bool(CellBuilder& cb) const & { - return is_valid() && cb.store_maybe_ref(root_cell); -} - -bool DictionaryBase::compute_root() const { - if (!is_valid()) { - return false; - } - if (root_cell.is_null()) { - root = get_empty_dictionary(); - flags |= f_root_cached; - return true; - } - CellBuilder cb; - cb.store_long(1, 1); - cb.store_ref(root_cell); - root = Ref{true, cb.finalize()}; - flags |= f_root_cached; - return true; -} - -Ref DictionaryBase::get_empty_dictionary() { - static Ref empty_dict{new_empty_dictionary()}; - return empty_dict; -} - -Ref DictionaryBase::new_empty_dictionary() { - CellBuilder cb; // Builder - cb.store_long(0, 1); - return Ref{true, cb.finalize()}; -} - -Ref DictionaryFixed::finish_create_leaf(CellBuilder& cb, const CellSlice& value) const { - if (!cb.append_cellslice_bool(value)) { - throw VmError{Excno::dict_err, "cannot store new value into a dictionary leaf cell"}; - } - return cb.finalize(); -} - -Ref DictionaryFixed::finish_create_fork(CellBuilder& cb, Ref c1, Ref c2, int n) const { - assert(n > 0); - if (!(cb.store_ref_bool(std::move(c1)) && cb.store_ref_bool(std::move(c2)))) { - throw VmError{Excno::dict_err, "cannot store branch references into a dictionary fork cell"}; - } - return cb.finalize(); -} - -bool DictionaryFixed::check_fork_raw(Ref cs_ref, int n) const { - if (cs_ref.is_null()) { - return false; - } - Ref c1, c2; - CellSlice& cs = cs_ref.write(); - return cs.fetch_ref_to(c1) && cs.fetch_ref_to(c2) && check_fork(cs, std::move(c1), std::move(c2), n); -} - -/* - * - * Label parser (HmLabel n ~l) for all dictionary types - * - */ - -namespace dict { - -LabelParser::LabelParser(Ref cs, int max_label_len, int auto_validate) : remainder(), l_offs(0), l_same(0) { - if (!parse_label(cs.write(), max_label_len)) { - l_offs = 0; - } else { - s_bits = (l_same ? 0 : l_bits); - remainder = std::move(cs); - } - if (auto_validate) { - if (auto_validate > 2) { - validate_ext(max_label_len); - } else if (auto_validate == 2) { - validate_simple(max_label_len); - } else { - validate(); - } - } -} - -LabelParser::LabelParser(Ref cell, int max_label_len, int auto_validate) : remainder(), l_offs(0), l_same(0) { - Ref cs = load_cell_slice_ref(std::move(cell)); - if (!parse_label(cs.unique_write(), max_label_len)) { - l_offs = 0; - } else { - s_bits = (l_same ? 0 : l_bits); - remainder = std::move(cs); - } - if (auto_validate) { - if (auto_validate > 2) { - validate_ext(max_label_len); - } else if (auto_validate == 2) { - validate_simple(max_label_len); - } else { - validate(); - } - } -} - -bool LabelParser::parse_label(CellSlice& cs, int max_label_len) { - int ltype = (int)cs.prefetch_ulong(2); - // std::cerr << "parse_label of type " << ltype << " and maximal length " << max_label_len << " in "; - // cs.dump_hex(std::cerr, 0, true); - switch (ltype) { - case 0: { - l_bits = 0; - l_offs = 2; - cs.advance(2); - return true; - } - case 1: { - cs.advance(1); - l_bits = cs.count_leading(1); - // std::cerr << "unary-encoded l_bits = " << l_bits << ", have " << cs.size() << std::endl; - if (l_bits > max_label_len || !cs.have(2 * l_bits + 1)) { - return false; - } - l_offs = l_bits + 2; - cs.advance(l_bits + 1); - return true; - } - case 2: { - int len_bits = 32 - td::count_leading_zeroes32(max_label_len); - cs.advance(2); - l_bits = (int)cs.fetch_ulong(len_bits); - if (l_bits < 0 || l_bits > max_label_len) { - return false; - } - l_offs = len_bits + 2; - return cs.have(l_bits); - } - case 3: { - int len_bits = 32 - td::count_leading_zeroes32(max_label_len); - // std::cerr << "len_bits = " << len_bits << ", have " << cs.size() << std::endl; - if (!cs.have(3 + len_bits)) { - return false; - } - l_same = (int)cs.fetch_ulong(3); - l_bits = (int)cs.fetch_ulong(len_bits); - // std::cerr << "l_bits = " << l_bits << ", l_same = " << l_same << std::endl; - if (l_bits < 0 || l_bits > max_label_len) { - return false; - } - l_offs = -1; - return true; - } - default: - return false; - } -} - -void LabelParser::validate() const { - if (!is_valid()) { - throw VmError{Excno::cell_und, "error while parsing a dictionary node label"}; - } -} - -void LabelParser::validate_ext(int n) const { - validate(); - if (l_bits > n) { - throw VmError{Excno::dict_err, "invalid dictionary node"}; - } else if (l_bits < n && (remainder->size() != s_bits || remainder->size_refs() != 2)) { - throw VmError{Excno::dict_err, "invalid dictionary fork node"}; - } -} - -void LabelParser::validate_simple(int n) const { - validate(); - if (l_bits > n) { - throw VmError{Excno::dict_err, "invalid dictionary node"}; - } else if (l_bits < n && (remainder->size() < s_bits || remainder->size_refs() < 2)) { - throw VmError{Excno::dict_err, "invalid dictionary fork node"}; - } -} - -bool LabelParser::is_prefix_of(td::ConstBitPtr key, int len) const { - if (l_bits > len) { - return false; - } else if (!l_same) { - //std::cerr << "key is " << key.to_hex(len) << "; len = " << len << "; label_bits = " << l_bits << "; remainder = "; - //remainder->dump_hex(std::cerr, 0, true); - return remainder->has_prefix(key, l_bits); - } else { - return td::bitstring::bits_memscan(key, l_bits, l_same & 1) == (unsigned)l_bits; - } -} - -bool LabelParser::has_prefix(td::ConstBitPtr key, int len) const { - return len >= 0 && len <= l_bits && common_prefix_len(key, len) == len; -} - -int LabelParser::common_prefix_len(td::ConstBitPtr key, int len) const { - if (!l_same) { - //std::cerr << "key is " << key.to_hex(len) << "; len = " << len << "; label_bits = " << l_bits << "; remainder = "; - //remainder->dump_hex(std::cerr, 0, true); - return remainder->common_prefix_len(key, std::min(l_bits, len)); - } else { - return (int)td::bitstring::bits_memscan(key, std::min(l_bits, len), l_same & 1); - } -} - -int LabelParser::extract_label_to(td::BitPtr to) { - if (!l_same) { - to.copy_from(remainder->data_bits(), l_bits); - remainder.write().advance(l_bits); - } else { - to.fill(l_same & 1, l_bits); - } - return l_bits; -} - -int LabelParser::copy_label_prefix_to(td::BitPtr to, int max_len) const { - if (max_len <= 0) { - return max_len; - } - int sz = std::min(max_len, l_bits); - if (!l_same) { - to.copy_from(remainder->data_bits(), sz); - } else { - to.fill(l_same & 1, sz); - } - return sz; -} - -} // namespace dict - -/* - * - * Usual Dictionary - * - */ - -using dict::LabelParser; - -BitSlice DictionaryFixed::integer_key(td::RefInt256 x, unsigned n, bool sgnd, unsigned char buffer[128], bool quiet) { - if (x.not_null() && x->fits_bits(n, sgnd)) { - if (buffer) { - if (x->export_bits(buffer, 0, n, sgnd)) { - return BitSlice{{}, buffer, 0, n}; - } - } else { - Ref bs{true, n}; - if (x->export_bits(bs.unique_write().reserve_bitslice(n), sgnd)) { - return static_cast(*bs); - } - } - } - if (!quiet) { - throw VmError{Excno::range_chk, "dictionary index out of bounds"}; - } - return {}; -} - -bool DictionaryFixed::integer_key_simple(td::RefInt256 x, unsigned n, bool sgnd, td::BitPtr buffer, bool quiet) { - if (x.not_null() && x->fits_bits(n, sgnd) && x->export_bits(buffer, n, sgnd)) { - return true; - } - if (!quiet) { - throw VmError{Excno::range_chk, "dictionary index out of bounds"}; - } - return false; -} - -Ref Dictionary::extract_value_ref(Ref cs) { - if (cs.is_null()) { - return {}; - } else if (!cs->size() && cs->size_refs() == 1) { - return cs->prefetch_ref(); - } else { - throw VmError{Excno::dict_err, "dictionary value does not consist of exactly one reference"}; - } -} - -Ref DictionaryFixed::lookup(td::ConstBitPtr key, int key_len) { - force_validate(); - if (key_len != get_key_bits() || is_empty()) { - return {}; - } - //std::cerr << "dictionary lookup for key = " << key.to_hex(key_len) << std::endl; - Ref cell = get_root_cell(); - int n = key_len; - while (true) { - LabelParser label{std::move(cell), n, label_mode()}; - if (!label.is_prefix_of(key, n)) { - //std::cerr << "(not a prefix)\n"; - return {}; - } - n -= label.l_bits; - if (n <= 0) { - assert(!n); - label.skip_label(); - return std::move(label.remainder); - } - key += label.l_bits; - bool sw = *key++; - //std::cerr << "key bit at position " << key_bits - n << " equals " << sw << std::endl; - --n; - cell = label.remainder->prefetch_ref(sw); - } -} - -Ref Dictionary::lookup_ref(td::ConstBitPtr key, int key_len) { - return extract_value_ref(lookup(key, key_len)); -} - -bool DictionaryFixed::has_common_prefix(td::ConstBitPtr prefix, int prefix_len) { - force_validate(); - if (is_empty() || prefix_len <= 0) { - return true; - } - if (prefix_len > get_key_bits()) { - return false; - } - LabelParser label{get_root_cell(), get_key_bits(), label_mode()}; - return label.has_prefix(prefix, prefix_len); -} - -int DictionaryFixed::get_common_prefix(td::BitPtr buffer, unsigned buffer_len) { - force_validate(); - if (is_empty()) { - return 0; - } - LabelParser label{get_root_cell(), get_key_bits(), label_mode()}; - return label.copy_label_prefix_to(buffer, (int)buffer_len); -} - -bool DictionaryFixed::key_exists(td::ConstBitPtr key, int key_len) { - return lookup(key, key_len).not_null(); -} - -bool DictionaryFixed::int_key_exists(long long key) { - force_validate(); - int l = get_key_bits(); - if (is_empty() || l > 64) { - return false; - } - if (l < 64) { - long long m = (1LL << (l - 1)); - if (key < -m || key >= m) { - return false; - } - } - td::BitArray<64> a; - a.bits().store_int(key, l); - return key_exists(a.cbits(), l); -} - -bool DictionaryFixed::uint_key_exists(unsigned long long key) { - force_validate(); - int l = get_key_bits(); - if (is_empty() || l > 64) { - return false; - } - if (l < 64 && key >= (1ULL << l)) { - return false; - } - td::BitArray<64> a; - a.bits().store_uint(key, l); - return key_exists(a.cbits(), l); -} - -namespace { - -void append_dict_label_same(CellBuilder& cb, bool same, int len, int max_len) { - int k = 32 - td::count_leading_zeroes32(max_len); - assert(len >= 0 && len <= max_len && max_len <= 1023); - // options: mode '0', requires 2n+2 bits (always for n=0) - // mode '10', requires 2+k+n bits (only for n<=1) - // mode '11', requires 3+k bits (for n>=2, k<2n-1) - if (len > 1 && k < 2 * len - 1) { - // mode '11' - cb.store_long(6 + same, 3).store_long(len, k); - } else if (k < len) { - // mode '10' - cb.store_long(2, 2).store_long(len, k).store_long(-static_cast(same), len); - } else { - // mode '0' - cb.store_long(0, 1).store_long(-2, len + 1).store_long(-static_cast(same), len); - } -} - -void append_dict_label(CellBuilder& cb, td::ConstBitPtr label, int len, int max_len) { - assert(len <= max_len && max_len <= 1023); - if (len > 0 && (int)td::bitstring::bits_memscan(label, len, *label) == len) { - return append_dict_label_same(cb, *label, len, max_len); - } - int k = 32 - td::count_leading_zeroes32(max_len); - // two options: mode '0', requires 2n+2 bits - // mode '10', requires 2+k+n bits - if (k < len) { - cb.store_long(2, 2).store_long(len, k); - } else { - cb.store_long(0, 1).store_long(-2, len + 1); - } - if ((int)cb.remaining_bits() < len) { - throw VmError{Excno::cell_ov, "cannot store a label into a dictionary cell"}; - } - cb.store_bits(label, len); -} - -std::pair, bool> dict_set(Ref dict, td::ConstBitPtr key, int n, - const Dictionary::store_value_func_t& store_val, Dictionary::SetMode mode) { - //std::cerr << "dictionary modification for " << n << "-bit key = " << key.to_hex(n) << std::endl; - if (dict.is_null()) { - // the dictionary is very empty - if (mode == Dictionary::SetMode::Replace) { - return std::make_pair, bool>({}, false); - } - // create an one-element dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_pair(cb.finalize(), true); - } - LabelParser label{std::move(dict), n}; - label.validate(); - int pfx_len = label.common_prefix_len(key, n); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len < label.l_bits) { - // have to insert a new node (fork) inside the current edge - if (mode == Dictionary::SetMode::Replace) { - // key not found, return unchanged dictionary - return std::make_pair(Ref{}, false); - } - // first, create the edge + new leaf cell - int m = n - pfx_len - 1; - CellBuilder cb; - append_dict_label(cb, key + (pfx_len + 1), m, m); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - Ref c1 = cb.finalize(); // new leaf cell corresponding to `key` - //cb.reset(); - // create the lower portion of the old edge - int t = label.l_bits - pfx_len - 1; - auto cs = std::move(label.remainder); - if (label.l_same) { - append_dict_label_same(cb, label.l_same & 1, t, m); - } else { - cs.write().advance(pfx_len + 1); - append_dict_label(cb, cs->data_bits(), t, m); - cs.unique_write().advance(t); - } - // now cs is the old payload of the edge, either a value or two subdictionary references - if (!cell_builder_add_slice_bool(cb, *cs)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell (?)"}; - } - Ref c2 = cb.finalize(); // the other child of the new fork - // cb.reset(); - append_dict_label(cb, key, pfx_len, n); - bool sw_bit = key[pfx_len]; - if (sw_bit) { - c1.swap(c2); - } - cb.store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_pair(cb.finalize(), true); - } - if (label.l_bits == n) { - // the edge leads to a leaf node - // this leaf node already contains a value for the key wanted - if (mode == Dictionary::SetMode::Add) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - // replace the value of the only element of the dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_pair(cb.finalize(), true); - } - // main case: the edge leads to a fork, have to insert new value either in the right or in the left subtree - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - label.remainder.clear(); - if (key[label.l_bits]) { - // insert key into the right child (c2) - auto res = dict_set(std::move(c2), key + (label.l_bits + 1), n - label.l_bits - 1, store_val, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c2 = std::move(res.first); - } else { - // insert key into the left child (c1) - auto res = dict_set(std::move(c1), key + (label.l_bits + 1), n - label.l_bits - 1, store_val, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c1 = std::move(res.first); - } - // create a new label with the same content - CellBuilder cb; - append_dict_label(cb, key, label.l_bits, n); - cb.store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_pair(cb.finalize(), true); -} - -std::tuple, Ref, bool> dict_lookup_set(Ref dict, td::ConstBitPtr key, int n, - const Dictionary::store_value_func_t& store_val, - Dictionary::SetMode mode) { - //std::cerr << "dictionary lookup/modification for " << n << "-bit key = " << key.to_hex(n) << std::endl; - if (dict.is_null()) { - // the dictionary is very empty - if (mode == Dictionary::SetMode::Replace) { - return std::make_tuple, Ref, bool>({}, {}, false); - } - // create an one-element dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_tuple, Ref, bool>({}, cb.finalize(), true); - } - LabelParser label{std::move(dict), n}; - int pfx_len = label.common_prefix_len(key, n); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len < label.l_bits) { - // have to insert a new node (fork) inside the current edge - if (mode == Dictionary::SetMode::Replace) { - // key not found, return unchanged dictionary - return std::make_tuple, Ref, bool>({}, {}, false); - } - // first, create the edge + new leaf cell - int m = n - pfx_len - 1; - CellBuilder cb; - append_dict_label(cb, key + (pfx_len + 1), m, m); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - Ref c1 = cb.finalize(); // new leaf cell corresponding to `key` - //cb.reset(); - // create the lower portion of the old edge - int t = label.l_bits - pfx_len - 1; - auto cs = std::move(label.remainder); - if (label.l_same) { - append_dict_label_same(cb, label.l_same & 1, t, m); - } else { - cs.write().advance(pfx_len + 1); - append_dict_label(cb, cs->data_bits(), t, m); - cs.unique_write().fetch_bits(t); - } - // now cs is the old payload of the edge, either a value or two subdictionary references - if (!cell_builder_add_slice_bool(cb, *cs)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell (?)"}; - } - Ref c2 = cb.finalize(); // the other child of the new fork - //cb.reset(); - append_dict_label(cb, key, pfx_len, n); - bool sw_bit = key[pfx_len]; - if (sw_bit) { - c1.swap(c2); - } - cb.store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_tuple, Ref, bool>({}, cb.finalize(), true); - } - if (label.l_bits == n) { - // the edge leads to a leaf node - // this leaf node already contains a value for the key wanted - auto old_val = std::move(label.remainder); - old_val.write().advance(label.s_bits); - if (mode == Dictionary::SetMode::Add) { - // return unchanged dictionary - return std::make_tuple, Ref, bool>(std::move(old_val), {}, false); - } - // replace the value of the only element of the dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_tuple(std::move(old_val), cb.finalize(), true); - } - // main case: the edge leads to a fork, have to insert new value either in the right or in the left subtree - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - Ref old_val; - label.remainder.clear(); - if (key[label.l_bits]) { - // insert key into the right child (c2) - auto res = dict_lookup_set(std::move(c2), key + (label.l_bits + 1), n - label.l_bits - 1, store_val, mode); - old_val = std::get>(res); - if (!std::get(res)) { - // return unchanged dictionary - return std::make_tuple, Ref, bool>(std::move(old_val), {}, false); - } - c2 = std::get>(std::move(res)); - } else { - // insert key into the left child (c1) - auto res = dict_lookup_set(std::move(c1), key + (label.l_bits + 1), n - label.l_bits - 1, store_val, mode); - old_val = std::get>(res); - if (!std::get(res)) { - // return unchanged dictionary - return std::make_tuple(std::move(old_val), Ref{}, false); - } - c1 = std::get>(std::move(res)); - } - // create a new label with the same content - CellBuilder cb; - append_dict_label(cb, key, label.l_bits, n); - cb.store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_tuple, Ref, bool>(std::move(old_val), cb.finalize(), true); -} - -std::pair, bool> pfx_dict_set(Ref dict, td::ConstBitPtr key, int m, int n, - const PrefixDictionary::store_value_func_t& store_val, - Dictionary::SetMode mode) { - // std::cerr << "up to " << n << "-bit prefix code dictionary modification for " << m << "-bit key = " << key.to_hex(m) << std::endl; - if (m > n) { - return std::make_pair(Ref{}, false); - } - if (dict.is_null()) { - // the dictionary is very empty - if (mode == Dictionary::SetMode::Replace) { - return std::make_pair(Ref{}, false); - } - // create an one-element dictionary - CellBuilder cb; - append_dict_label(cb, key, m, n); - cb.store_long(0, 1); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_pair(cb.finalize(), true); - } - LabelParser label{std::move(dict), n, 1}; - int l = label.common_prefix_len(key, m); - assert(l >= 0 && l <= label.l_bits && label.l_bits <= n && l <= m && m <= n); - if (l < label.l_bits) { - // have to insert a new node (fork) inside the current edge - if (l == m || mode == Dictionary::SetMode::Replace) { - // key not found, return unchanged dictionary - return std::make_pair(Ref{}, false); - } - // first, create the edge + new leaf cell - int q = l + 1; - CellBuilder cb; - append_dict_label(cb, key + q, m - q, n - q); - cb.store_long(0, 1); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a prefix dictionary cell"}; - } - Ref c1 = cb.finalize(); // new leaf cell corresponding to `key` - // cb.reset(); // contained in finalize() - // create the lower portion of the old edge - int t = label.l_bits - q; - auto cs = std::move(label.remainder); - if (label.l_same) { - append_dict_label_same(cb, label.l_same & 1, t, n - q); - } else { - cs.write().advance(l + 1); - append_dict_label(cb, cs->data_bits(), t, n - q); - cs.unique_write().advance(t); - } - // now cs is the old payload of the edge, either a value or two subdictionary references - if (!cell_builder_add_slice_bool(cb, *cs)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell (?)"}; - } - Ref c2 = cb.finalize(); // the other child of the new fork - //cb.reset(); - append_dict_label(cb, key, l, n); - bool sw_bit = key[l]; - if (sw_bit) { - c1.swap(c2); - } - cb.store_long(1, 1).store_ref(c1).store_ref(c2); - return std::make_pair, bool>(cb.finalize(), true); - } - assert(label.l_bits == l); - label.skip_label(); - if (!label.remainder->have(1)) { - throw VmError{Excno::dict_err, "no node constructor in a prefix code dictionary"}; - } - if (!label.remainder.unique_write().fetch_ulong(1)) { - // the edge leads to a leaf node - if (l != m || mode == Dictionary::SetMode::Add) { - // return unchanged dictionary - return std::make_pair, bool>({}, false); - } - // this leaf node already contains a value for the key wanted - // replace the value of the only element of the dictionary - CellBuilder cb; - append_dict_label(cb, key, m, n); - cb.store_long(0, 1); - if (!store_val(cb)) { - throw VmError{Excno::cell_ov, "cannot store new value into a dictionary cell"}; - } - return std::make_pair, bool>(cb.finalize(), true); - } - // main case: the edge leads to a fork, have to insert new value either in the right or in the left subtree - if (label.remainder->size() || label.remainder->size_refs() != 2) { - throw VmError{Excno::dict_err, "invalid fork node in a prefix code dictionary"}; - } - if (m == l) { - // cannot insert a value into a fork - return std::make_pair(Ref{}, false); - } - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - label.remainder.clear(); - if (key[l++]) { - // insert key into the right child (c2) - auto res = pfx_dict_set(std::move(c2), key + l, m - l, n - l, store_val, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c2 = std::move(res.first); - } else { - // insert key into the left child (c1) - auto res = pfx_dict_set(std::move(c1), key + l, m - l, n - l, store_val, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c1 = std::move(res.first); - } - // create a new label with the same content - CellBuilder cb; - append_dict_label(cb, key, l - 1, n); - cb.store_long(1, 1).store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_pair(cb.finalize(), true); -} - -std::pair, Ref> pfx_dict_lookup_delete(Ref dict, td::ConstBitPtr key, int m, int n) { - //std::cerr << "up to " << n << "-bit prefix dictionary delete for " << m << "-bit key = " << key.to_hex(m) << std::endl; - if (dict.is_null()) { - // the dictionary is very empty - return std::make_pair(Ref{}, Ref{}); - } - LabelParser label{std::move(dict), n, 1}; - int l = label.common_prefix_len(key, m); - assert(l >= 0 && l <= label.l_bits && l <= m && m <= n && label.l_bits <= n); - if (l < label.l_bits) { - // key not found - return std::make_pair(Ref{}, Ref{}); - } - assert(label.l_bits == l); - label.skip_label(); - if (!label.remainder->have(1)) { - throw VmError{Excno::dict_err, "no node constructor in a prefix code dictionary"}; - } - if (!label.remainder.unique_write().fetch_ulong(1)) { - // the edge leads to a leaf node - if (l < m) { - // key not found - return std::make_pair(Ref{}, Ref{}); - } - // this leaf node contains the value for the key wanted - return std::make_pair(std::move(label.remainder), Ref{}); - } - // main case: the edge leads to a fork, have to delete the key either from the right or from the left subtree - if (label.remainder->size() || label.remainder->size_refs() != 2) { - throw VmError{Excno::dict_err, "invalid fork node in a prefix code dictionary"}; - } - if (l == m) { - // the fork itself cannot correspond to a key, key not found - return std::make_pair(Ref{}, Ref{}); - } - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - Ref old_val; - label.remainder.clear(); - bool sw_bit = key[l++]; - if (sw_bit) { - // delete key from the right child (c2) - auto res = pfx_dict_lookup_delete(std::move(c2), key + l, m - l, n - l); - if (res.first.is_null()) { - // return unchanged dictionary - return std::make_pair(Ref{}, Ref{}); - } - old_val = std::move(res.first); - c2 = std::move(res.second); - } else { - // delete key from the left child (c1) - auto res = pfx_dict_lookup_delete(std::move(c1), key + l, m - l, n - l); - if (res.first.is_null()) { - // return unchanged dictionary - return std::make_pair(Ref{}, Ref{}); - } - old_val = std::move(res.first); - c1 = std::move(res.second); - } - if (c1.not_null() && c2.not_null()) { - // create a new label with the same content leading to a fork with modified children - CellBuilder cb; - append_dict_label(cb, key, label.l_bits, n); - cb.store_long(1, 1).store_ref(std::move(c1)).store_ref(std::move(c2)); - return std::make_pair(std::move(old_val), cb.finalize()); - } - // have to merge current edge with the edge leading to c1 or c2 - if (!sw_bit) { - c1.swap(c2); - } - assert(c1.not_null() && c2.is_null()); - unsigned char buffer[Dictionary::max_key_bytes]; - td::BitPtr bw{buffer}; - bw.concat(key, label.l_bits); - bw.concat_same(!sw_bit, 1); - LabelParser label2{std::move(c1), n - l, 1}; - bw += label2.extract_label_to(bw); - assert(bw.offs >= 0 && bw.offs <= Dictionary::max_key_bits); - CellBuilder cb; - append_dict_label(cb, td::ConstBitPtr{buffer}, bw.offs, n); - if (!cell_builder_add_slice_bool(cb, *label2.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old prefix code dictionary cell while merging edges"}; - } - label2.remainder.clear(); - return std::make_pair(std::move(old_val), cb.finalize()); -} - -Ref dict_map(Ref dict, td::BitPtr key_buffer, int n, int total_key_len, - const Dictionary::map_func_t& map_func) { - if (dict.is_null()) { - // dictionary is empty - return dict; - } - LabelParser label{std::move(dict), n}; - int l = label.l_bits; - label.extract_label_to(key_buffer); - if (l == n) { - // leaf node, value left in label.remainder - CellBuilder cb; - append_dict_label(cb, key_buffer, l, n); - if (!map_func(cb, std::move(label.remainder), key_buffer + n - total_key_len, total_key_len)) { - return {}; // leaf to be omitted from the result altogether - } - return cb.finalize(); - } - assert(l >= 0 && l < n); - // a fork with two children, c1 and c2 - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - key_buffer += l + 1; - key_buffer[-1] = 0; - // recursive map applied to both children - c1 = dict_map(std::move(c1), key_buffer, n - l - 1, total_key_len, map_func); - key_buffer[-1] = 1; - c2 = dict_map(std::move(c2), key_buffer, n - l - 1, total_key_len, map_func); - if (c1.is_null() && c2.is_null()) { - return {}; // both children have become empty - } - if (c1.is_null() || c2.is_null()) { - if (c1.is_null()) { - c1 = std::move(c2); - // notice that the label of c2 is still in key_buffer - } else { - // recover label of c1 - key_buffer[-1] = 0; - } - // one of children is empty, have to combine current edge with the root edge of c1 - LabelParser label1{std::move(c1), n - l - 1}; - label1.extract_label_to(key_buffer); - CellBuilder cb; - key_buffer -= l + 1; - // store combined label for the new edge - append_dict_label(cb, key_buffer, l + 1 + label1.l_bits, n); - // store payload - if (!cell_builder_add_slice_bool(cb, *label1.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - return cb.finalize(); - } - // main case: both children c1 and c2 remain non-empty - key_buffer -= l + 1; - CellBuilder cb; - append_dict_label(cb, key_buffer, l, n); - return cb.store_ref(std::move(c1)).store_ref(std::move(c2)).finalize(); -} - -} // namespace - -bool Dictionary::set_gen(td::ConstBitPtr key, int key_len, const std::function& store_val, - SetMode mode) { - force_validate(); - if (key_len != get_key_bits()) { - return false; - } - auto res = dict_set(get_root_cell(), key, key_len, store_val, mode); - if (res.second) { - set_root_cell(std::move(res.first)); - } - return res.second; -} - -bool Dictionary::set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode) { - return set_gen(key, key_len, [value](CellBuilder& cb) { return cell_builder_add_slice_bool(cb, *value); }, mode); -} - -bool Dictionary::set_ref(td::ConstBitPtr key, int key_len, Ref val_ref, SetMode mode) { - return set_gen(key, key_len, [val_ref](CellBuilder& cb) { return cb.store_ref_bool(val_ref); }, mode); -} - -bool Dictionary::set_builder(td::ConstBitPtr key, int key_len, Ref val_b, SetMode mode) { - return set_gen(key, key_len, [val_b](CellBuilder& cb) { return cb.append_builder_bool(val_b); }, mode); -} - -bool Dictionary::set_builder(td::ConstBitPtr key, int key_len, const CellBuilder& val_b, SetMode mode) { - return set_gen(key, key_len, [&val_b](CellBuilder& cb) { return cb.append_builder_bool(val_b); }, mode); -} - -Ref Dictionary::lookup_set_gen(td::ConstBitPtr key, int key_len, const store_value_func_t& store_val, - SetMode mode) { - force_validate(); - if (key_len != get_key_bits()) { - return {}; - } - auto res = dict_lookup_set(get_root_cell(), key, key_len, store_val, mode); - if (std::get(res)) { - set_root_cell(std::get>(res)); - } - return std::get>(std::move(res)); -} - -Ref Dictionary::lookup_set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode) { - return lookup_set_gen(key, key_len, [value](CellBuilder& cb) { return cell_builder_add_slice_bool(cb, *value); }, - mode); -} - -Ref Dictionary::lookup_set_ref(td::ConstBitPtr key, int key_len, Ref val_ref, SetMode mode) { - return extract_value_ref( - lookup_set_gen(key, key_len, [val_ref](CellBuilder& cb) { return cb.store_ref_bool(val_ref); }, mode)); -} - -Ref Dictionary::lookup_set_builder(td::ConstBitPtr key, int key_len, Ref val_b, SetMode mode) { - return lookup_set_gen(key, key_len, [val_b](CellBuilder& cb) { return cb.append_builder_bool(val_b); }, mode); -} - -std::pair, Ref> DictionaryFixed::dict_lookup_delete(Ref dict, td::ConstBitPtr key, - int n) const { - // std::cerr << "dictionary delete for " << n << "-bit key = " << key.to_hex(n) << std::endl; - if (dict.is_null()) { - // the dictionary is very empty - return std::make_pair(Ref{}, Ref{}); - } - LabelParser label{std::move(dict), n, label_mode()}; - int pfx_len = label.common_prefix_len(key, n); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len < label.l_bits) { - // key not found - return std::make_pair(Ref{}, Ref{}); - } - if (label.l_bits == n) { - // the edge leads to a leaf node - // this leaf node contains the value for the key wanted - label.skip_label(); - return std::make_pair(std::move(label.remainder), Ref{}); - } - // main case: the edge leads to a fork, have to delete the key either from the right or from the left subtree - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - Ref old_val; - label.remainder.clear(); - bool sw_bit = key[label.l_bits]; - if (sw_bit) { - // delete key from the right child (c2) - auto res = dict_lookup_delete(std::move(c2), key + (label.l_bits + 1), n - label.l_bits - 1); - if (res.first.is_null()) { - // return unchanged dictionary - return std::make_pair(Ref{}, Ref{}); - } - old_val = std::move(res.first); - c2 = std::move(res.second); - } else { - // delete key from the left child (c1) - auto res = dict_lookup_delete(std::move(c1), key + (label.l_bits + 1), n - label.l_bits - 1); - if (res.first.is_null()) { - // return unchanged dictionary - return std::make_pair(Ref{}, Ref{}); - } - old_val = std::move(res.first); - c1 = std::move(res.second); - } - if (c1.not_null() && c2.not_null()) { - // create a new label with the same content leading to a fork with modified children - CellBuilder cb; - append_dict_label(cb, key, label.l_bits, n); - return std::make_pair(std::move(old_val), finish_create_fork(cb, std::move(c1), std::move(c2), n - label.l_bits)); - } - // have to merge current edge with the edge leading to c1 or c2 - if (!sw_bit) { - c1.swap(c2); - } - assert(c1.not_null() && c2.is_null()); - unsigned char buffer[Dictionary::max_key_bytes]; - td::BitPtr bw{buffer}; - bw.concat(key, label.l_bits); - bw.concat_same(!sw_bit, 1); - LabelParser label2{std::move(c1), n - label.l_bits - 1, label_mode()}; - bw += label2.extract_label_to(bw); - assert(bw.offs >= 0 && bw.offs <= Dictionary::max_key_bits); - CellBuilder cb; - append_dict_label(cb, td::ConstBitPtr{buffer}, bw.offs, n); - if (!cell_builder_add_slice_bool(cb, *label2.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - label2.remainder.clear(); - return std::make_pair(std::move(old_val), cb.finalize()); -} - -Ref DictionaryFixed::lookup_delete(td::ConstBitPtr key, int key_len) { - force_validate(); - if (key_len != get_key_bits()) { - return {}; - } - auto res = dict_lookup_delete(get_root_cell(), key, key_len); - if (res.first.not_null()) { - set_root_cell(std::move(res.second)); - } - return std::move(res.first); -} - -Ref Dictionary::lookup_delete_ref(td::ConstBitPtr key, int key_len) { - return extract_value_ref(lookup_delete(key, key_len)); -} - -Ref DictionaryFixed::dict_lookup_minmax(Ref dict, td::BitPtr key_buffer, int n, int mode) const { - if (dict.is_null()) { - return {}; - } - while (1) { - LabelParser label{std::move(dict), n, label_mode()}; - int l = label.extract_label_to(key_buffer); - assert(l >= 0 && l <= n); - key_buffer += l; - n -= l; - if (!n) { - return std::move(label.remainder); - } - if (l) { - mode >>= 1; - } - bool bit = mode & 1; - dict = label.remainder->prefetch_ref(bit); - *key_buffer++ = bit; - --n; - mode >>= 1; - } -} - -Ref DictionaryFixed::dict_lookup_nearest(Ref dict, td::BitPtr key_buffer, int n, bool allow_eq, - int mode) const { - if (dict.is_null()) { - return {}; - } - LabelParser label{dict, n, label_mode()}; - int pfx_len = label.common_prefix_len(key_buffer, n); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len < label.l_bits) { - if (key_buffer[pfx_len] == ((mode >> static_cast(pfx_len != 0)) & 1)) { - return {}; - } else { - return dict_lookup_minmax(std::move(dict), key_buffer, n, ~mode); - } - } - dict.clear(); - if (label.l_bits) { - mode >>= 1; - } - key_buffer += label.l_bits; - n -= label.l_bits; - if (!n) { - if (!allow_eq) { - return {}; - } - label.skip_label(); - return std::move(label.remainder); - } - bool bit = *key_buffer++; - auto res = dict_lookup_nearest(label.remainder->prefetch_ref(bit), key_buffer, n - 1, allow_eq, mode >> 1); - if (res.not_null() || bit == (mode & 1)) { - return res; - } - key_buffer[-1] = mode & 1; - dict = label.remainder->prefetch_ref(mode & 1); - label.remainder.clear(); - return dict_lookup_minmax(std::move(dict), key_buffer, n - 1, ~mode >> 1); -} - -Ref DictionaryFixed::lookup_nearest_key(td::BitPtr key_buffer, int key_len, bool fetch_next, bool allow_eq, - bool invert_first) { - force_validate(); - if (key_len != get_key_bits()) { - return {}; - } - return dict_lookup_nearest(get_root_cell(), key_buffer, key_len, allow_eq, - (-static_cast(fetch_next)) ^ static_cast(invert_first)); -} - -Ref DictionaryFixed::get_minmax_key(td::BitPtr key_buffer, int key_len, bool fetch_max, bool invert_first) { - force_validate(); - if (key_len != get_key_bits()) { - return {}; - } - return dict_lookup_minmax(get_root_cell(), key_buffer, key_len, - (-static_cast(fetch_max)) ^ static_cast(invert_first)); -} - -Ref Dictionary::get_minmax_key_ref(td::BitPtr key_buffer, int key_len, bool fetch_max, bool invert_first) { - return extract_value_ref(get_minmax_key(key_buffer, key_len, fetch_max, invert_first)); -} - -Ref DictionaryFixed::extract_minmax_key(td::BitPtr key_buffer, int key_len, bool fetch_max, - bool invert_first) { - force_validate(); - if (key_len != get_key_bits()) { - return {}; - } - auto val = dict_lookup_minmax(get_root_cell(), key_buffer, key_len, -(fetch_max ? 1 : 0) ^ (invert_first ? 1 : 0)); - if (val.is_null()) { - return {}; - } - auto res = dict_lookup_delete(get_root_cell(), key_buffer, key_len); - assert(res.first.not_null()); - set_root_cell(std::move(res.second)); - return val; -} - -Ref Dictionary::extract_minmax_key_ref(td::BitPtr key_buffer, int key_len, bool fetch_max, bool invert_first) { - return extract_value_ref(extract_minmax_key(key_buffer, key_len, fetch_max, invert_first)); -} - -/* - * - * ITERATORS (to be moved into a separate file) - * - */ - -bool DictIterator::prevalidate(int mode) { - if (key_bits_ <= 0 || key_bits_ > Dictionary::max_key_bits) { - reset(); - flags_ &= ~f_valid; - key_bits_ = 0; - return false; - } else { - if (mode >= 0) { - order_ = -(mode & 1) ^ ((mode >> 1) & 1); - } - flags_ |= f_valid; - return true; - } -} - -bool DictIterator::bind(const DictionaryFixed& dict, int do_rewind) { - if (!is_valid() || !is_bound_to(dict)) { - return false; - } - dict_ = &dict; - label_mode_ = dict.label_mode(); - return !do_rewind || rewind(do_rewind < 0); -} - -bool DictIterator::rebind_to(const DictionaryFixed& dict, int do_rewind) { - reset(); - dict_ = &dict; - label_mode_ = dict.label_mode(); - root_ = dict.get_root_cell(); - key_bits_ = dict.get_key_bits(); - flags_ &= 3; - return prevalidate() && (!do_rewind || rewind(do_rewind < 0)); -} - -int DictIterator::compare_keys(td::ConstBitPtr a, td::ConstBitPtr b) const { - if (!key_bits_) { - return 0; - } - int c = (int)*a - (int)*b; - if (c) { - return (order_ & 1) ? -c : c; - } - c = a.compare(b, key_bits_); - return order_ >= 0 ? c : -c; -} - -bool DictIterator::dive(int mode) { - int n = key_bits_, m = 0; - Ref node = path_.empty() ? root_ : path_.back().next; - if (!path_.empty()) { - m = path_.back().pos + 1; - n -= m; - mode >>= 1; - } - // similar to dict_lookup_minmax: create new path down until the leaf - while (1) { - LabelParser label{std::move(node), n, label_mode_}; - int l = label.extract_label_to(key(m)); - assert(l >= 0 && l <= n); - m += l; - n -= l; - if (!n) { - leaf_ = std::move(label.remainder); - return true; - } - if (l) { - mode >>= 1; - } - int bit = mode & 1; - node = label.remainder->prefetch_ref(bit); - auto alt = label.remainder->prefetch_ref(1 - bit); - path_.emplace_back(node, std::move(alt), m, bit); - *key(m++) = (bool)bit; - --n; - mode >>= 1; - } -} - -bool DictIterator::rewind(bool to_end) { - if (!is_valid()) { - return false; - } - if (root_.is_null()) { - return true; - } - auto node = root_; - int k = 0, mode = order_ ^ -(int)to_end; - // NB: can optimize by reusing several first entries of current path_ - while (k < (int)path_.size()) { - auto& pe = path_[k++]; - assert(pe.pos >= 0 && pe.pos < key_bits_); - if (pe.pos) { - mode >>= 1; - } - if (pe.v != (bool)(mode & 1)) { - // went different way at this node before, rotate and stop going down - pe.rotate(key()); - leaf_.clear(); - path_.resize(k); // drop the remainder of the original path after first incorrect branch - return dive(mode); - } - mode >>= 1; - } - return !eof() || dive(mode); -} - -bool DictIterator::next(bool go_back) { - if (!is_valid() || root_.is_null() || eof()) { - return false; - } - leaf_.clear(); - int mode = order_ ^ -(int)go_back; - while (!path_.empty()) { - auto& pe = path_.back(); - int bit = (mode >> (pe.pos > 0)) & 1; - if (pe.v == bit) { - pe.rotate(key()); - return dive(mode); - } - path_.pop_back(); - } - return false; -} - -bool DictIterator::lookup(td::ConstBitPtr pos, int pos_bits, bool strict_after, bool backw) { - if (!is_valid() || root_.is_null() || pos_bits < 0 || pos_bits > key_bits_) { - return false; - } - int fill_mode = -(strict_after ^ backw) ^ order_; - if (!eof()) { - // reuse part of current path - std::size_t bp0 = 0; - int bp; - if (!key().compare(pos, pos_bits, &bp0)) { - bp = pos_bits; - if (bp >= key_bits_) { - // already at the desired element - return !strict_after || next(backw); - } - } else { - bp = (int)bp0; - } - int k = 0; - while (k < (int)path_.size() && path_[k].pos <= bp) { - auto& pe = path_[k]; - if (pe.pos == bp) { - if (bp < pos_bits || pe.v != ((fill_mode >> (bp > 0)) & 1)) { - // rotate the last path element if it branched in incorrect direction - path_[k++].rotate(key()); - } - break; - } - ++k; - } - path_.resize(k); // drop the remainder of the path - } - int m = 0, n = key_bits_; - auto node = path_.empty() ? root_ : path_.back().next; - if (!path_.empty()) { - m = path_.back().pos + 1; // m <= pos_bits + 1 - n -= m; - } - int mode = -backw ^ order_, action = 0; - while (m < pos_bits && !action) { - LabelParser label{std::move(node), n, label_mode_}; - int pfx_len = label.common_prefix_len(pos + m, pos_bits - m); - int l = label.extract_label_to(key() + m); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len == pos_bits - m) { - // end of given position prefix - if (strict_after) { - // have to backtrace - action = 2; - break; - } else { - // label has correct prefix, register and dive down - action = 1; - } - } else if (pfx_len < l) { - // all subtree is either smaller or larger than required - if (pos[m + pfx_len] != ((mode >> (int)(m + pfx_len > 0)) & 1)) { - // label smaller than required, have to backtrace - action = 2; - break; - } else { - // label larger than required, register node and dive down - action = 1; - } - } - // if we are here, then either action=1 (dive down activated) - // ... or l = pfx_len < pos_bits - m - // continue going down - m += l; - n -= l; - if (!n) { - // key found in a leaf - leaf_ = std::move(label.remainder); - return true; - } - bool bit = action ? ((mode >> (m > 0)) & 1) : pos[m]; - node = label.remainder->prefetch_ref(bit); - auto alt = label.remainder->prefetch_ref(1 - bit); - path_.emplace_back(node, std::move(alt), m, bit); - *key(m++) = (bool)bit; - --n; - } - if (!action) { - action = (strict_after ? 2 : 1); - } - if (action == 2) { - // have to backtrace to the "next" larger branch - // similar to next() - leaf_.clear(); - while (!path_.empty()) { - auto& pe = path_.back(); - int bit = (mode >> (pe.pos > 0)) & 1; - if (pe.v == bit) { - pe.rotate(key()); - return dive(mode); - } - path_.pop_back(); - } - return false; // eof: no suitable element - } - // action=1, dive down - return dive(mode); -} - -DictIterator DictionaryFixed::null_iterator() { - force_validate(); - return DictIterator{*this}; -} - -DictIterator DictionaryFixed::make_iterator(int mode) { - force_validate(); - DictIterator it{*this, mode}; - it.rewind(); - return it; -} - -DictIterator DictionaryFixed::init_iterator(bool backw, bool invert_first) { - return make_iterator((int)backw + 2 * (int)invert_first); -} - -DictIterator DictionaryFixed::begin() { - return init_iterator(); -} - -DictIterator DictionaryFixed::end() { - return null_iterator(); -} - -DictIterator DictionaryFixed::cbegin() { - return begin(); -} - -DictIterator DictionaryFixed::cend() { - return end(); -} - -DictIterator DictionaryFixed::rbegin() { - return init_iterator(true); -} - -DictIterator DictionaryFixed::rend() { - return null_iterator(); -} - -DictIterator DictionaryFixed::crbegin() { - return rbegin(); -} - -DictIterator DictionaryFixed::crend() { - return rend(); -} - -/* - * - * END (ITERATORS) - * - */ - -std::pair, bool> DictionaryFixed::extract_prefix_subdict_internal(Ref dict, td::ConstBitPtr prefix, - int prefix_len, bool remove_prefix) const { - if (is_empty() || prefix_len <= 0) { - return {{}, false}; // unchanged - } - if (prefix_len > get_key_bits()) { - return {{}, true}; // empty dict - } - int n = get_key_bits(), m = 0; - while (true) { - LabelParser label{std::move(dict), n - m, label_mode()}; - int l = std::min(prefix_len - m, label.l_bits); - if (label.common_prefix_len(prefix + m, l) < l) { - return {{}, true}; // empty dict - } - if (m + label.l_bits < prefix_len) { - m += label.l_bits; - dict = label.remainder->prefetch_ref(prefix[m++]); - continue; - } - // end, have consumed all of prefix - vm::CellBuilder cb; - if (!remove_prefix) { - if (!m) { - // dictionary unchanged: all keys already begin with prefix - return {{}, false}; - } - // concatenate prefix with a suffix of the label - assert(m <= prefix_len); - unsigned char buffer[max_key_bytes]; - auto p = td::BitPtr{buffer}; - p.copy_from(prefix, m); - label.extract_label_to(p + m); - append_dict_label(cb, p, m + label.l_bits, key_bits); - } else if (!label.l_same) { - m += label.l_bits - prefix_len; // leave that many last bits of the label - append_dict_label(cb, label.bits_end() - m, m, key_bits - prefix_len); - label.skip_label(); - } else { - m += label.l_bits - prefix_len; // leave that many last bits of the label - append_dict_label_same(cb, label.l_same & 1, m, key_bits - prefix_len); - } - if (!cb.append_cellslice_bool(*label.remainder)) { - throw VmError{Excno::cell_ov, "cannot create new dictionary root while constructing prefix subdictionary"}; - } - return {Ref{cb.finalize()}, true}; - } -} - -bool DictionaryFixed::cut_prefix_subdict(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix) { - force_validate(); - if (prefix_len < 0) { - return false; - } - if (prefix_len > key_bits && remove_prefix) { - return false; - } - auto res = extract_prefix_subdict_internal(get_root_cell(), prefix, prefix_len, remove_prefix); - if (remove_prefix) { - key_bits -= prefix_len; - } - if (res.second) { - set_root_cell(std::move(res.first)); - } - return true; -} - -Ref DictionaryFixed::extract_prefix_subdict_root(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix) { - force_validate(); - auto res = extract_prefix_subdict_internal(get_root_cell(), prefix, prefix_len, remove_prefix); - return res.second ? res.first : root_cell; -} - -std::pair, int> DictionaryFixed::dict_filter(Ref dict, td::BitPtr key, int n, - const DictionaryFixed::filter_func_t& check_leaf, - int& skip_rest) const { - // std::cerr << "dictionary filter for " << n << "-bit key = " << (key + n - key_bits).to_hex(key_bits - n) - // << std::endl; - if (dict.is_null()) { - // empty dictionary, return unchanged - return {{}, 0}; - } - if (skip_rest >= 0) { - // either drop subtree completely (if skip_rest>0), or retain it completely (if skip_rest=0) - return {{}, skip_rest}; - } - LabelParser label{std::move(dict), n, label_mode()}; - assert(label.l_bits >= 0 && label.l_bits <= n); - label.extract_label_to(key); - key += label.l_bits; - if (label.l_bits == n) { - // leaf - int res = check_leaf(label.remainder.write(), key - key_bits, key_bits); - if (res >= (1 << 30)) { - // skip all, or retain all - res &= (1 << 30) - 1; - skip_rest = (res ? 0 : (1 << 30)); - } - return {{}, res < 0 ? res : !res}; - } - // fork, process left and right subtrees - ++key; - key[-1] = false; - int delta = label.l_bits + 1; - n -= delta; - auto left_res = dict_filter(label.remainder->prefetch_ref(0), key, n, check_leaf, skip_rest); - if (left_res.second < 0) { - return left_res; - } - key[-1] = true; - auto right_res = dict_filter(label.remainder->prefetch_ref(1), key, n, check_leaf, skip_rest); - if ((left_res.second | right_res.second) <= 0) { - // error in right, or both left and right unchanged - return right_res; - } - auto left = left_res.second ? std::move(left_res.first) : label.remainder->prefetch_ref(0); - auto right = right_res.second ? std::move(right_res.first) : label.remainder->prefetch_ref(1); - // 2^30 is effectively infinity, meaning that we dropped whole branches with unknown # of nodes - auto changes = ((left_res.second | right_res.second) & (1 << 30)) ? (1 << 30) : left_res.second + right_res.second; - label.clear(); - if (left.is_null()) { - if (right.is_null()) { - // both branches are empty => the result is an empty tree - return {{}, changes}; - } - std::swap(left, right); - } else if (right.is_null()) { - key[-1] = false; - } else { - // both new branches are non-empty => create new fork - CellBuilder cb; - append_dict_label(cb, key - delta, label.l_bits, n + delta); - return {finish_create_fork(cb, std::move(left), std::move(right), n + 1), changes}; - } - // only one child (in `left`) remains, collapse an edge - // NB: similar to code in lookup_delete() - assert(left.not_null() && right.is_null()); - LabelParser label2{std::move(left), n, label_mode()}; - label2.extract_label_to(key); - CellBuilder cb; - append_dict_label(cb, key - delta, delta + label2.l_bits, n + delta); - if (!cell_builder_add_slice_bool(cb, *label2.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - label2.remainder.clear(); - return {cb.finalize(), changes}; -} - -int DictionaryFixed::filter(DictionaryFixed::filter_func_t check_leaf) { - force_validate(); - int skip_rest = -1; - unsigned char buffer[DictionaryFixed::max_key_bytes]; - auto res = dict_filter(get_root_cell(), td::BitPtr{buffer}, key_bits, check_leaf, skip_rest); - if (res.second > 0) { - // std::cerr << "after filter (" << res.second << " changes): new augmented dictionary root is:\n"; - // vm::load_cell_slice(res.first).print_rec(std::cerr); - set_root_cell(std::move(res.first)); - } - return res.second; -} - -void Dictionary::map(const map_func_t& map_func) { - force_validate(); - int key_len = get_key_bits(); - unsigned char key_buffer[max_key_bytes]; - auto res = dict_map(get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, map_func); - set_root_cell(std::move(res)); -} - -void Dictionary::map(const simple_map_func_t& simple_map_func) { - using namespace std::placeholders; - map_func_t map_func = std::bind(simple_map_func, _1, _2); - map(map_func); -} - -// mode: +1 = forbid empty dict1 with non-empty dict2 -// +2 = forbid empty dict2 with non-empty dict1 -Ref DictionaryFixed::dict_combine_with(Ref dict1, Ref dict2, td::BitPtr key_buffer, int n, - int total_key_len, const DictionaryFixed::combine_func_t& combine_func, - int mode, int skip1, int skip2) const { - if (dict1.is_null()) { - assert(!skip2); - if ((mode & 1) && dict2.is_null()) { - throw CombineError{}; - } - return dict2; - } else if (dict2.is_null()) { - assert(!skip1); - if ((mode & 2)) { - throw CombineError{}; - } - return dict1; - } - // both dictionaries non-empty - // skip1: remove that much first bits from all keys in dictionary dict1 (its keys are actually n + skip1 bits long) - // skip2: similar for dict2 - // resulting dictionary will have n-bit keys - LabelParser label1{dict1, n + skip1, label_mode()}, label2{dict2, n + skip2, label_mode()}; - int l1 = label1.l_bits - skip1, l2 = label2.l_bits - skip2; - assert(l1 >= 0 && l2 >= 0); - assert(!skip1 || label1.common_prefix_len(key_buffer - skip1, skip1) == skip1); - assert(!skip2 || label2.common_prefix_len(key_buffer - skip2, skip2) == skip2); - label1.extract_label_to(key_buffer - skip1); - int c = label2.common_prefix_len(key_buffer - skip2, skip2 + l1) - skip2; - assert(c >= 0 && c <= l1 && c <= l2); - if (c < l1 && c < l2) { - // the two dictionaries have disjoint keys - dict1.clear(); - dict2.clear(); - if ((mode & 3)) { - throw CombineError{}; - } - CellBuilder cb; - append_dict_label(cb, key_buffer + c + 1, l1 - c - 1, n - c - 1); - if (!cell_builder_add_slice_bool(cb, *label1.remainder)) { - throw VmError{Excno::cell_ov, "cannot prune label of an old dictionary cell while merging dictionaries"}; - } - label1.remainder.clear(); - dict1 = cb.finalize(); - // cb.reset(); // included into finalize(); - // now dict1 has been "pruned" -- first skip1+c+1 bits removed from its root egde label - label2.extract_label_to(key_buffer - skip2); - append_dict_label(cb, key_buffer + c + 1, l2 - c - 1, n - c - 1); - if (!cell_builder_add_slice_bool(cb, *label2.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - label2.remainder.clear(); - dict2 = cb.finalize(); - // now dict2 has also been pruned - if (!key_buffer[c]) { - std::swap(dict1, dict2); - } - // put dict1 into the left tree (with smaller labels), dict2 into the right tree - append_dict_label(cb, key_buffer, c, n); - return finish_create_fork(cb, std::move(dict1), std::move(dict2), n - c); - } - if (c == l1 && c == l2) { - // funny enough, the non-skipped parts of labels of l1 and l2 match - dict1.clear(); - dict2.clear(); - label2.skip_label(); - CellBuilder cb; - append_dict_label(cb, key_buffer, c, n); - if (c == n) { - // our two dictionaries are in fact leafs with matching edge labels (keys) - if (!combine_func(cb, std::move(label1.remainder), std::move(label2.remainder), key_buffer + n - total_key_len, - total_key_len)) { - // alas, the two values did not combine, this key will be absent from resulting dictionary - return {}; - } - return cb.finalize(); - } - assert(c < n); - key_buffer += c + 1; - key_buffer[-1] = 0; - // combine left subtrees - auto c1 = dict_combine_with(label1.remainder->prefetch_ref(0), label2.remainder->prefetch_ref(0), key_buffer, - n - c - 1, total_key_len, combine_func); - key_buffer[-1] = 1; - // combine right subtrees - auto c2 = dict_combine_with(label1.remainder->prefetch_ref(1), label2.remainder->prefetch_ref(1), key_buffer, - n - c - 1, total_key_len, combine_func); - label1.remainder.clear(); - label2.remainder.clear(); - // c1 and c2 are merged left and right children of dict1 and dict2 - if (!c1.is_null() && !c2.is_null()) { - // both children non-empty, simply put them into the new node - return finish_create_fork(cb, std::move(c1), std::move(c2), n - c); - } - if (c1.is_null() && c2.is_null()) { - return {}; // both children empty, resulting dictionary also empty - } - // exactly one of c1 and c2 is non-empty, have to merge labels - bool sw = c1.is_null(); - key_buffer[-1] = sw; - if (sw) { - c1 = std::move(c2); - } - LabelParser label3{std::move(c1), n - c - 1, label_mode()}; - label3.extract_label_to(key_buffer); - key_buffer -= c + 1; - // store combined label for the new edge - cb.reset(); - append_dict_label(cb, key_buffer, c + 1 + label3.l_bits, n); - // store payload - if (!cell_builder_add_slice_bool(cb, *label3.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - return cb.finalize(); - } - if (c == l1) { - assert(c < l2); - dict1.clear(); - if ((mode & 2)) { - throw CombineError{}; - } - // children of root node of dict1 - auto c1 = label1.remainder->prefetch_ref(0); - auto c2 = label1.remainder->prefetch_ref(1); - label1.remainder.clear(); - // have to merge dict2 with one of the children of dict1 - label2.extract_label_to(key_buffer - skip2); // dict2 has longer label, extract it - bool sw = key_buffer[c]; - if (!sw) { - // merge c1 with dict2 - c1 = dict_combine_with(std::move(c1), std::move(dict2), key_buffer + c + 1, n - c - 1, total_key_len, - combine_func, mode, 0, skip2 + c + 1); - } else { - // merge c2 with dict2 - c2 = dict_combine_with(std::move(c2), std::move(dict2), key_buffer + c + 1, n - c - 1, total_key_len, - combine_func, mode, 0, skip2 + c + 1); - } - if (!c1.is_null() && !c2.is_null()) { - CellBuilder cb; - append_dict_label(cb, key_buffer, c, n); - return finish_create_fork(cb, std::move(c1), std::move(c2), n - c); - } - // one of children is empty, have to merge root edges - key_buffer[c] = !sw; - if (!sw) { - std::swap(c1, c2); - } - assert(!c1.is_null() && c2.is_null()); - LabelParser label3{std::move(c1), n - c - 1, label_mode()}; - label3.extract_label_to(key_buffer + c + 1); - CellBuilder cb; - append_dict_label(cb, key_buffer, c + 1 + label3.l_bits, n); - // store payload - if (!cell_builder_add_slice_bool(cb, *label3.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - return cb.finalize(); - } else { - assert(c == l2 && c < l1); - dict2.clear(); - if ((mode & 1)) { - throw CombineError{}; - } - // children of root node of dict2 - label2.skip_label(); // dict2 had shorter label anyway, label1 is already unpacked - auto c1 = label2.remainder->prefetch_ref(0); - auto c2 = label2.remainder->prefetch_ref(1); - label2.remainder.clear(); - // have to merge dict1 with one of the children of dict2 - bool sw = key_buffer[c]; - if (!sw) { - // merge dict1 with c1 - c1 = dict_combine_with(std::move(dict1), std::move(c1), key_buffer + c + 1, n - c - 1, total_key_len, - combine_func, mode, skip1 + c + 1, 0); - } else { - // merge dict1 with c2 - c2 = dict_combine_with(std::move(dict1), std::move(c2), key_buffer + c + 1, n - c - 1, total_key_len, - combine_func, mode, skip1 + c + 1, 0); - } - if (!c1.is_null() && !c2.is_null()) { - CellBuilder cb; - append_dict_label(cb, key_buffer, c, n); - return finish_create_fork(cb, std::move(c1), std::move(c2), n - c); - } - // one of children is empty, have to merge root edges - key_buffer[c] = !sw; - if (!sw) { - std::swap(c1, c2); - } - assert(!c1.is_null() && c2.is_null()); - LabelParser label3{std::move(c1), n - c - 1, label_mode()}; - label3.extract_label_to(key_buffer + c + 1); - CellBuilder cb; - append_dict_label(cb, key_buffer, c + 1 + label3.l_bits, n); - // store payload - if (!cell_builder_add_slice_bool(cb, *label3.remainder)) { - throw VmError{Excno::cell_ov, "cannot change label of an old dictionary cell while merging edges"}; - } - return cb.finalize(); - } -} - -bool DictionaryFixed::combine_with(DictionaryFixed& dict2, const combine_func_t& combine_func, int mode) { - force_validate(); - dict2.force_validate(); - int key_len = get_key_bits(); - if (key_len != dict2.get_key_bits()) { - throw VmError{Excno::dict_err, "cannot combine dictionaries with different key lengths"}; - } - unsigned char key_buffer[max_key_bytes]; - try { - auto res = dict_combine_with(get_root_cell(), dict2.get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, - combine_func, mode); - set_root_cell(std::move(res)); - return true; - } catch (CombineError) { - return false; - } -} - -bool DictionaryFixed::combine_with(DictionaryFixed& dict2, const simple_combine_func_t& simple_combine_func, int mode) { - using namespace std::placeholders; - combine_func_t combine_func = std::bind(simple_combine_func, _1, _2, _3); - return combine_with(dict2, combine_func, mode); -} - -bool DictionaryFixed::combine_with(DictionaryFixed& dict2) { - return combine_with(dict2, - [](CellBuilder&, Ref, Ref, td::ConstBitPtr key, int key_len) -> bool { - LOG(WARNING) << "dictionary merge conflict for key " << key.to_hex(key_len); - throw CombineError{}; - }); -} - -bool DictionaryFixed::dict_check_for_each(Ref dict, td::BitPtr key_buffer, int n, int total_key_len, - const DictionaryFixed::foreach_func_t& foreach_func, - bool invert_first) const { - if (dict.is_null()) { - return true; - } - LabelParser label{std::move(dict), n, label_mode()}; - int l = label.l_bits; - label.extract_label_to(key_buffer); - if (l == n) { - // leaf node, value left in label.remainder - return foreach_func(std::move(label.remainder), key_buffer + n - total_key_len, total_key_len); - } - assert(l >= 0 && l < n); - // a fork with two children, c1 and c2 - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - label.remainder.clear(); - key_buffer += l + 1; - if (l) { - invert_first = false; - } else if (invert_first) { - std::swap(c1, c2); - } - key_buffer[-1] = invert_first; - // recursive check_foreach applied to both children - if (!dict_check_for_each(std::move(c1), key_buffer, n - l - 1, total_key_len, foreach_func)) { - return false; - } - key_buffer[-1] = !invert_first; - return dict_check_for_each(std::move(c2), key_buffer, n - l - 1, total_key_len, foreach_func); -} - -bool DictionaryFixed::check_for_each(const foreach_func_t& foreach_func, bool invert_first) { - force_validate(); - if (is_empty()) { - return true; - } - int key_len = get_key_bits(); - unsigned char key_buffer[max_key_bytes]; - return dict_check_for_each(get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, foreach_func, invert_first); -} - -static inline bool set_bit(td::BitPtr ptr, bool value = true) { - *ptr = value; - return true; -} - -// mode: +1 = check augmentation of dict1, +2 = ... of dict2 -bool DictionaryFixed::dict_scan_diff(Ref dict1, Ref dict2, td::BitPtr key_buffer, int n, int total_key_len, - const scan_diff_func_t& diff_func, int mode, int skip1, int skip2) const { - // skip1: remove that much first bits from all keys in dictionary dict1 (its keys are actually n + skip1 bits long) - // skip2: similar for dict2 - // pretending to compare subdictionaries with n-bit keys - if (dict1.is_null()) { - if (dict2.is_null()) { - return true; // both dictionaries are empty - } - assert(!skip2); - // dict1 empty, dict2 non-empty -> parse label of dict2 - LabelParser label{dict2, n, label_mode()}; - label.extract_label_to(key_buffer); - if (label.l_bits >= n) { - assert(label.l_bits == n); - // leaf in dict2, empty dict1 - auto key = key_buffer + label.l_bits - total_key_len; - if ((mode & 2) && !check_leaf(label.remainder, key, total_key_len)) { - throw VmError{Excno::dict_err, "invalid leaf in the second dictionary being compared"}; - } - return diff_func(key, total_key_len, {}, std::move(label.remainder)); - } - n -= label.l_bits + 1; - key_buffer += label.l_bits + 1; - if ((mode & 2) && !check_fork_raw(label.remainder, n + 1)) { - throw VmError{Excno::dict_err, "invalid fork in the second dictionary being compared"}; - } - // compare {} with each of children of dict2 - for (unsigned sw = 0; sw < 2; sw++) { - key_buffer[-1] = (bool)sw; - if (!dict_scan_diff({}, label.remainder->prefetch_ref(sw), key_buffer, n, total_key_len, diff_func, mode)) { - return false; - } - } - return true; - } else if (dict2.is_null()) { - assert(!skip1); - // dict2 empty, dict1 non-empty -> parse label of dict1 - LabelParser label{dict1, n, label_mode()}; - label.extract_label_to(key_buffer); - if (label.l_bits >= n) { - assert(label.l_bits == n); - // leaf in dict1, empty dict2 - auto key = key_buffer + label.l_bits - total_key_len; - if ((mode & 1) && !check_leaf(label.remainder, key, total_key_len)) { - throw VmError{Excno::dict_err, "invalid leaf in the first dictionary being compared"}; - } - return diff_func(key, total_key_len, std::move(label.remainder), {}); - } - n -= label.l_bits + 1; - key_buffer += label.l_bits + 1; - if ((mode & 1) && !check_fork_raw(label.remainder, n + 1)) { - throw VmError{Excno::dict_err, "invalid fork in the first dictionary being compared"}; - } - // compare each of children of dict1 with {} - for (unsigned sw = 0; sw < 2; sw++) { - key_buffer[-1] = (bool)sw; - if (!dict_scan_diff(label.remainder->prefetch_ref(sw), {}, key_buffer, n, total_key_len, diff_func, mode)) { - return false; - } - } - return true; - } - // both dictionaries non-empty - if (skip1 == skip2 && (dict1 == dict2 || dict1->get_hash() == dict2->get_hash())) { - // dictionaries match, subtree comparison not necessary - return true; - } - LabelParser label1{dict1, n + skip1, label_mode()}, label2{dict2, n + skip2, label_mode()}; - int l1 = label1.l_bits - skip1, l2 = label2.l_bits - skip2; - assert(l1 >= 0 && l2 >= 0); - assert(!skip1 || label1.common_prefix_len(key_buffer - skip1, skip1) == skip1); - assert(!skip2 || label2.common_prefix_len(key_buffer - skip2, skip2) == skip2); - label1.extract_label_to(key_buffer - skip1); - int c = label2.common_prefix_len(key_buffer - skip2, skip2 + l1) - skip2; - assert(c >= 0 && c <= l1 && c <= l2); - if (c < l1 && c < l2) { - // the two dictionaries have disjoint keys - if (!key_buffer[c]) { - // all keys of dict1 are before dict2 - return dict_scan_diff(std::move(dict1), {}, key_buffer - skip1, n + skip1, total_key_len, diff_func, mode) && - dict_scan_diff({}, std::move(dict2), key_buffer - skip2, n + skip2, total_key_len, diff_func, mode); - } else { - // all keys of dict2 are before dict1 - return dict_scan_diff({}, std::move(dict2), key_buffer - skip2, n + skip2, total_key_len, diff_func, mode) && - dict_scan_diff(std::move(dict1), {}, key_buffer - skip1, n + skip1, total_key_len, diff_func, mode); - } - } - if (c == l1 && c == l2) { - // funny enough, the non-skipped parts of labels of l1 and l2 match - dict1.clear(); - dict2.clear(); - label2.skip_label(); - if (c == n) { - // our two dictionaries are in fact leafs with matching edge labels (keys) - auto key = key_buffer + n - total_key_len; - if ((mode & 1) && !check_leaf(label1.remainder, key, total_key_len)) { - throw VmError{Excno::dict_err, "invalid leaf in the first dictionary being compared"}; - } - if ((mode & 2) && !check_leaf(label2.remainder, key, total_key_len)) { - throw VmError{Excno::dict_err, "invalid leaf in the second dictionary being compared"}; - } - return label1.remainder->contents_equal(*label2.remainder) || - diff_func(key, total_key_len, std::move(label1.remainder), std::move(label2.remainder)); - } - assert(c < n); - key_buffer += c + 1; - n -= c + 1; - if ((mode & 1) && !check_fork_raw(label1.remainder, n + 1)) { - throw VmError{Excno::dict_err, "invalid fork in the first dictionary being compared"}; - } - if ((mode & 2) && !check_fork_raw(label2.remainder, n + 1)) { - throw VmError{Excno::dict_err, "invalid fork in the second dictionary being compared"}; - } - for (unsigned sw = 0; sw <= 1; sw++) { - key_buffer[-1] = (bool)sw; - // compare left and then right subtrees - if (!dict_scan_diff(label1.remainder->prefetch_ref(sw), label2.remainder->prefetch_ref(sw), key_buffer, n, - total_key_len, diff_func, mode)) { - return false; - } - } - return true; - } - if (c == l1) { - assert(c < l2); - dict1.clear(); - if ((mode & 1) && !check_fork_raw(label1.remainder, n - c)) { - throw VmError{Excno::dict_err, "invalid fork in the first dictionary being compared"}; - } - // children of root node of dict1 - auto c1 = label1.remainder->prefetch_ref(0); - auto c2 = label1.remainder->prefetch_ref(1); - label1.remainder.clear(); - // have to compare dict2 with one of the children of dict1 - label2.extract_label_to(key_buffer - skip2); // dict2 has longer label, extract it - key_buffer += c + 1; - n -= c + 1; - bool sw = key_buffer[-1]; - key_buffer[-1] = false; - if (!sw) { - // compare c1 with dict2, then c2 with {} - return dict_scan_diff(std::move(c1), std::move(dict2), key_buffer, n, total_key_len, diff_func, mode, 0, - skip2 + c + 1) && - set_bit(key_buffer - 1) && - dict_scan_diff(std::move(c2), {}, key_buffer, n, total_key_len, diff_func, mode); - } else { - // compare c1 with {}, then c2 with dict2 - return dict_scan_diff(std::move(c1), {}, key_buffer, n, total_key_len, diff_func, mode) && - set_bit(key_buffer - 1) && - dict_scan_diff(std::move(c2), std::move(dict2), key_buffer, n, total_key_len, diff_func, mode, 0, - skip2 + c + 1); - } - } else { - assert(c == l2 && c < l1); - dict2.clear(); - label2.skip_label(); // dict2 had shorter label anyway, label1 is already unpacked - if ((mode & 2) && !check_fork_raw(label2.remainder, n - c)) { - throw VmError{Excno::dict_err, "invalid fork in the second dictionary being compared"}; - } - // children of root node of dict2 - auto c1 = label2.remainder->prefetch_ref(0); - auto c2 = label2.remainder->prefetch_ref(1); - label2.remainder.clear(); - // have to compare dict1 with one of the children of dict2 - key_buffer += c + 1; - n -= c + 1; - bool sw = key_buffer[-1]; - key_buffer[-1] = false; - if (!sw) { - // compare dict1 with c1, then {} with c2 - return dict_scan_diff(std::move(dict1), std::move(c1), key_buffer, n, total_key_len, diff_func, mode, - skip1 + c + 1, 0) && - set_bit(key_buffer - 1) && - dict_scan_diff({}, std::move(c2), key_buffer, n, total_key_len, diff_func, mode); - } else { - // compare {} with c1, then dict1 with c2 - return dict_scan_diff({}, std::move(c1), key_buffer, n, total_key_len, diff_func, mode) && - set_bit(key_buffer - 1) && - dict_scan_diff(std::move(dict1), std::move(c2), key_buffer, n, total_key_len, diff_func, mode, - skip1 + c + 1, 0); - } - } -} - -bool DictionaryFixed::scan_diff(DictionaryFixed& dict2, const scan_diff_func_t& diff_func, int check_augm) { - force_validate(); - dict2.force_validate(); - int key_len = get_key_bits(); - if (key_len != dict2.get_key_bits()) { - throw VmError{Excno::dict_err, "cannot compare dictionaries with different key lengths"}; - } - unsigned char key_buffer[max_key_bytes]; - try { - return dict_scan_diff(get_root_cell(), dict2.get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, diff_func, - check_augm); - } catch (CombineError) { - return false; - } -} - -bool DictionaryFixed::dict_validate_check(Ref dict, td::BitPtr key_buffer, int n, int total_key_len, - const DictionaryFixed::foreach_func_t& foreach_func, - bool invert_first) const { - //LOG(DEBUG) << "dict_validate_check for " << total_key_len - n << "-bit key prefix " << (key_buffer - n + total_key_len).to_hex(total_key_len - n); - if (dict.is_null()) { - return true; - } - LabelParser label{std::move(dict), n, label_mode()}; - int l = label.l_bits; - label.extract_label_to(key_buffer); - if (l == n) { - // leaf node, value left in label.remainder - vm::CellSlice cs{*label.remainder}; - auto key = key_buffer + n - total_key_len; - if (!(check_leaf(cs, key, total_key_len) && foreach_func(std::move(label.remainder), key, total_key_len))) { - LOG(DEBUG) << "invalid dictionary leaf node with " << total_key_len << "-bit key " << key.to_hex(total_key_len); - return false; - } - return true; - } - assert(l >= 0 && l < n); - // a fork with two children, c1 and c2 - auto c1 = label.remainder.write().fetch_ref(); - auto c2 = label.remainder.unique_write().fetch_ref(); - key_buffer += l + 1; - n -= l + 1; - if (!check_fork(label.remainder.write(), c1, c2, n + 1)) { - LOG(DEBUG) << "invalid dictionary fork augmentation for fork node with " << total_key_len - n - 1 - << "-bit key prefix " << (key_buffer + n - total_key_len).to_hex(total_key_len - n - 1); - return false; - } - label.remainder.clear(); - if (l) { - invert_first = false; - } else if (invert_first) { - std::swap(c1, c2); - } - key_buffer[-1] = invert_first; - // recursive check_foreach applied to both children - if (!dict_validate_check(std::move(c1), key_buffer, n, total_key_len, foreach_func)) { - return false; - } - key_buffer[-1] = !invert_first; - return dict_validate_check(std::move(c2), key_buffer, n, total_key_len, foreach_func); -} - -bool DictionaryFixed::validate_check(const DictionaryFixed::foreach_func_t& foreach_func, bool invert_first) { - if (!validate()) { - return false; - } - if (is_empty()) { - return true; - } - int key_len = get_key_bits(); - unsigned char key_buffer[max_key_bytes]; - return dict_validate_check(get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, foreach_func, invert_first); -} - -bool DictionaryFixed::validate_all() { - return validate_check([](Ref value, td::ConstBitPtr key, int n) { return true; }) || invalidate(); -} - -/* - * - * PREFIX DICTIONARIES - * - */ - -std::pair, int> PrefixDictionary::lookup_prefix(td::ConstBitPtr key, int key_len) { - force_validate(); - int n = get_key_bits(); - if (is_empty()) { - return std::make_pair(Ref{}, 0); - } - //std::cerr << "dictionary lookup for key = " << key.to_hex(key_len) << std::endl; - Ref cell = get_root_cell(); - int m = key_len; - while (true) { - LabelParser label{std::move(cell), n, 1}; - int l = label.common_prefix_len(key, m); - if (l < label.l_bits) { - //std::cerr << "(not a prefix)\n"; - return std::make_pair(Ref{}, key_len - m + l); - } - n -= label.l_bits; - m -= label.l_bits; - assert(m >= 0); - label.skip_label(); - Ref cs = std::move(label.remainder); - if (!cs->have(1)) { - throw VmError{Excno::dict_err, "no node constructor in a prefix code dictionary"}; - } - if (!cs.unique_write().fetch_ulong(1)) { - return std::make_pair(std::move(cs), key_len - m); - } - if (!n) { - throw VmError{Excno::dict_err, "a fork node in a prefix code dictionary with zero remaining key length"}; - } - if (cs->size() != 0 || cs->size_refs() != 2) { - throw VmError{Excno::dict_err, "invalid fork node in a prefix code dictionary"}; - } - if (!m) { - return std::make_pair(Ref{}, key_len); - } - key += label.l_bits; - bool sw = *key++; - //std::cerr << "key bit at position " << key_bits - n << " equals " << sw << std::endl; - --n; - --m; - cell = cs->prefetch_ref(sw); - } -} - -Ref PrefixDictionary::lookup(td::ConstBitPtr key, int key_len) { - force_validate(); - if (key_len > get_key_bits()) { - return {}; - } - auto res = lookup_prefix(key, key_len); - return res.second == key_len ? std::move(res.first) : Ref{}; -} - -bool PrefixDictionary::set_gen(td::ConstBitPtr key, int key_len, const std::function& store_val, - SetMode mode) { - force_validate(); - if (key_len > get_key_bits() || key_len < 0) { - return false; - } - auto res = pfx_dict_set(get_root_cell(), key, key_len, get_key_bits(), store_val, mode); - if (res.second) { - set_root_cell(std::move(res.first)); - } - return res.second; -} - -bool PrefixDictionary::set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode) { - return set_gen(key, key_len, [value](CellBuilder& cb) { return cell_builder_add_slice_bool(cb, *value); }, mode); -} - -bool PrefixDictionary::set_builder(td::ConstBitPtr key, int key_len, Ref val_b, SetMode mode) { - return set_gen(key, key_len, [val_b](CellBuilder& cb) { return cb.append_builder_bool(val_b); }, mode); -} - -Ref PrefixDictionary::lookup_delete(td::ConstBitPtr key, int key_len) { - force_validate(); - if (key_len > get_key_bits() || key_len < 0) { - return {}; - } - auto res = pfx_dict_lookup_delete(get_root_cell(), key, key_len, get_key_bits()); - if (res.first.not_null()) { - set_root_cell(std::move(res.second)); - } - return std::move(res.first); -} - -/* - * - * AUGMENTED DICTIONARIES - * - */ - -namespace dict { - -bool AugmentationData::check_empty(vm::CellSlice& cs) const { - vm::CellBuilder cb; - return eval_empty(cb) && cb.contents_equal(cs); -} - -bool AugmentationData::check_leaf(vm::CellSlice& cs, vm::CellSlice& val_cs) const { - vm::CellBuilder cb; - return eval_leaf(cb, val_cs) && cb.contents_equal(cs); -} - -bool AugmentationData::check_fork(vm::CellSlice& cs, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const { - vm::CellBuilder cb; - return eval_fork(cb, left_cs, right_cs) && cb.contents_equal(cs); -} - -Ref AugmentationData::extract_extra(vm::CellSlice& cs) const { - Ref res{true, cs}; - return skip_extra(cs) && res.write().cut_tail(cs) ? std::move(res) : Ref{}; -} - -Ref AugmentationData::extract_extra(Ref cs_ref) const { - CellSlice cs{*cs_ref}; - return skip_extra(cs) && cs_ref.write().cut_tail(cs) ? std::move(cs_ref) : Ref{}; -} - -bool AugmentationData::extract_extra_to(vm::CellSlice& cs, vm::CellSlice& extra) const { - extra = cs; - return cs.is_valid() && skip_extra(cs) && extra.cut_tail(cs); -} - -} // namespace dict - -using dict::AugmentationData; -using dict::LabelParser; - -AugmentedDictionary::AugmentedDictionary(int _n, const AugmentationData& _aug, bool validate) - : DictionaryFixed(_n, false), aug(_aug) { - if (validate) { - force_validate(); - } -} - -AugmentedDictionary::AugmentedDictionary(Ref _root, int _n, const AugmentationData& _aug, bool validate) - : DictionaryFixed(std::move(_root), _n, false), aug(_aug) { - if (validate) { - force_validate(); - } -} - -AugmentedDictionary::AugmentedDictionary(Ref cell, int _n, const AugmentationData& _aug, bool validate) - : DictionaryFixed(std::move(cell), _n, false), aug(_aug) { - if (validate) { - force_validate(); - } -} - -AugmentedDictionary::AugmentedDictionary(DictNonEmpty, Ref _root, int _n, const AugmentationData& _aug, - bool validate) - : DictionaryFixed(DictNonEmpty{}, std::move(_root), _n, false), aug(_aug) { - if (validate) { - force_validate(); - } -} - -bool AugmentedDictionary::validate() { - if (is_valid()) { - return true; - } - if (flags & f_invalid) { - return false; - } - if (key_bits < 0 || key_bits > max_key_bits) { - return invalidate(); - } - if (flags & f_root_cached) { - if (root.is_null() || !root->size()) { - return invalidate(); - } - bool non_empty = root->prefetch_ulong(1); - if (non_empty && !root->size_refs()) { - return invalidate(); - } - if (root_cell.not_null()) { - return invalidate(); - } - vm::CellSlice cs{*root}; - if (!cs.advance(1)) { - return invalidate(); - } - if (non_empty) { - root_cell = cs.fetch_ref(); - auto root_extra = get_root_extra(); - if (!(root_extra.not_null() && root_extra->contents_equal(cs))) { - return invalidate(); - } - } else { - if (!aug.check_empty(cs)) { - return invalidate(); - } - } - } else if (root.not_null()) { - return invalidate(); - } - flags |= f_valid; - return true; -} - -Ref AugmentedDictionary::get_root() const { - if (!(flags & f_root_cached) && !compute_root()) { - return {}; - } - return root; -} - -Ref AugmentedDictionary::extract_root() && { - if (!(flags & f_root_cached) && !compute_root()) { - return {}; - } - flags = f_invalid; - return std::move(root); -} - -bool AugmentedDictionary::append_dict_to_bool(CellBuilder& cb) const & { - if (!is_valid()) { - return false; - } - if (root_cell.is_null()) { - return cb.store_zeroes_bool(1) && aug.eval_empty(cb); - } else { - return cb.store_ones_bool(1) && cb.store_ref_bool(root_cell) && cb.append_cellslice_bool(get_root_extra()); - } -} - -bool AugmentedDictionary::append_dict_to_bool(CellBuilder& cb) && { - if (!is_valid()) { - return false; - } - flags = f_invalid; - if (root_cell.is_null()) { - return cb.store_zeroes_bool(1) && aug.eval_empty(cb); - } else { - return cb.store_ones_bool(1) && cb.store_ref_bool(root_cell) && cb.append_cellslice_bool(get_root_extra()); - } -} - -bool AugmentedDictionary::compute_root() const { - if (!is_valid()) { - return false; - } - if (root_cell.is_null()) { - root = get_empty_dictionary(); - flags |= f_root_cached; - return true; - } - CellBuilder cb; - if (cb.store_long_bool(1, 1) && cb.store_ref_bool(root_cell) && cb.append_cellslice_bool(get_root_extra())) { - root = Ref{true, cb.finalize()}; - flags |= f_root_cached; - return true; - } else { - return false; - } -} - -Ref AugmentedDictionary::get_empty_dictionary() const { - CellBuilder cb; - cb.store_long(0, 1); - return aug.eval_empty(cb) ? Ref{true, cb.finalize()} : Ref{}; -} - -Ref AugmentedDictionary::get_node_extra(Ref cell_ref, int n) const { - if (cell_ref.is_null()) { - CellBuilder cb; - if (!aug.eval_empty(cb)) { - return {}; - } - return Ref{true, cb.finalize()}; - } - LabelParser label{std::move(cell_ref), n, 2}; - label.skip_label(); - if (label.l_bits == n) { - return aug.extract_extra(std::move(label.remainder)); - } else if (label.remainder.write().advance_refs(2)) { - vm::CellSlice cs{*label.remainder}; - if (aug.skip_extra(cs) && cs.empty_ext()) { - return std::move(label.remainder); - } - } - return {}; -} - -Ref AugmentedDictionary::extract_leaf_value(Ref leaf) const { - if (leaf.not_null() && aug.skip_extra(leaf.write())) { - return std::move(leaf); - } else { - return Ref{}; - } -} - -Ref AugmentedDictionary::get_root_extra() const { - return get_node_extra(root_cell, key_bits); -} - -Ref AugmentedDictionary::extract_value(Ref value_extra) const { - if (value_extra.not_null() && aug.skip_extra(value_extra.write())) { - return value_extra; - } else { - return {}; - } -} - -Ref AugmentedDictionary::extract_value_ref(Ref value_extra) const { - if (value_extra.not_null() && aug.skip_extra(value_extra.write()) && value_extra->size_ext() == 0x10000) { - return value_extra->prefetch_ref(); - } else { - return {}; - } -} - -std::pair, Ref> AugmentedDictionary::decompose_value_extra(Ref value_extra) const { - if (value_extra.is_null()) { - return {}; - } - auto extra = aug.extract_extra(value_extra.write()); - if (extra.is_null()) { - return {}; - } else { - return {std::move(value_extra), std::move(extra)}; - } -} - -std::pair, Ref> AugmentedDictionary::decompose_value_ref_extra(Ref value_extra) const { - if (value_extra.is_null()) { - return {}; - } - auto extra = aug.extract_extra(value_extra.write()); - if (extra.is_null() || value_extra->size_ext() != 0x10000) { - return {}; - } else { - return {value_extra->prefetch_ref(), std::move(extra)}; - } -} - -Ref AugmentedDictionary::lookup_with_extra(td::ConstBitPtr key, int key_len) { - return DictionaryFixed::lookup(key, key_len); -} - -Ref AugmentedDictionary::lookup(td::ConstBitPtr key, int key_len) { - return extract_value(lookup_with_extra(key, key_len)); -} - -Ref AugmentedDictionary::lookup_ref(td::ConstBitPtr key, int key_len) { - return extract_value_ref(lookup_with_extra(key, key_len)); -} - -std::pair, Ref> AugmentedDictionary::lookup_extra(td::ConstBitPtr key, int key_len) { - return decompose_value_extra(lookup_with_extra(key, key_len)); -} - -std::pair, Ref> AugmentedDictionary::lookup_ref_extra(td::ConstBitPtr key, int key_len) { - return decompose_value_ref_extra(lookup_with_extra(key, key_len)); -} - -Ref AugmentedDictionary::lookup_delete_with_extra(td::ConstBitPtr key, int key_len) { - return DictionaryFixed::lookup_delete(key, key_len); -} - -Ref AugmentedDictionary::lookup_delete(td::ConstBitPtr key, int key_len) { - return extract_value(lookup_delete_with_extra(key, key_len)); -} - -Ref AugmentedDictionary::lookup_delete_ref(td::ConstBitPtr key, int key_len) { - return extract_value_ref(lookup_delete_with_extra(key, key_len)); -} - -std::pair, Ref> AugmentedDictionary::lookup_delete_extra(td::ConstBitPtr key, int key_len) { - return decompose_value_extra(lookup_delete_with_extra(key, key_len)); -} - -bool AugmentedDictionary::check_leaf(CellSlice& cs, td::ConstBitPtr key, int key_len) const { - vm::CellSlice extra; - return aug.extract_extra_to(cs, extra) && aug.check_leaf_key_extra(cs, extra, key, key_len); -} - -bool AugmentedDictionary::check_fork(CellSlice& cs, Ref c1, Ref c2, int n) const { - if (n <= 0) { - return false; - } - auto extra1 = get_node_extra(std::move(c1), n - 1); - auto extra2 = get_node_extra(std::move(c2), n - 1); - return extra1.not_null() && extra2.not_null() && aug.check_fork(cs, extra1.write(), extra2.write()); -} - -Ref AugmentedDictionary::finish_create_leaf(CellBuilder& cb, const CellSlice& value) const { - CellSlice value_copy{value}; - if (!aug.eval_leaf(cb, value_copy)) { - throw VmError{Excno::dict_err, "cannot compute and store extra value into an augmented dictionary cell"}; - } - if (!cb.append_cellslice_bool(value)) { - throw VmError{Excno::dict_err, "cannot store new value into an augmented dictionary cell"}; - } - return cb.finalize(); -} - -Ref AugmentedDictionary::finish_create_fork(CellBuilder& cb, Ref c1, Ref c2, int n) const { - assert(n > 0); - if (!(cb.store_ref_bool(c1) && cb.store_ref_bool(c2))) { - throw VmError{Excno::dict_err, "cannot store branch references into an augmented dictionary cell"}; - } - auto extra1 = get_node_extra(std::move(c1), n - 1); - auto extra2 = get_node_extra(std::move(c2), n - 1); - if (extra1.is_null()) { - throw VmError{Excno::dict_err, "cannot extract extra value from left branch of an augmented dictionary fork node"}; - } - if (extra2.is_null()) { - throw VmError{Excno::dict_err, "cannot extract extra value from left branch of an augmented dictionary fork node"}; - } - if (!aug.eval_fork(cb, extra1.write(), extra2.write())) { - throw VmError{Excno::dict_err, "cannot compute extra value for an augmented dictionary fork node"}; - } - return cb.finalize(); -} - -std::pair, bool> AugmentedDictionary::dict_set(Ref dict, td::ConstBitPtr key, int n, - const CellSlice& value, Dictionary::SetMode mode) const { - //std::cerr << "augmented dictionary modification for " << n << "-bit key = " << key.to_hex(n) << std::endl; - if (dict.is_null()) { - // the dictionary is very empty - if (mode == Dictionary::SetMode::Replace) { - return std::make_pair, bool>({}, false); - } - // create an one-element dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - return std::make_pair(finish_create_leaf(cb, value), true); - } - LabelParser label{std::move(dict), n, 2}; - label.validate(); - int pfx_len = label.common_prefix_len(key, n); - assert(pfx_len >= 0 && pfx_len <= label.l_bits && label.l_bits <= n); - if (pfx_len < label.l_bits) { - // have to insert a new node (fork) inside the current edge - if (mode == Dictionary::SetMode::Replace) { - // key not found, return unchanged dictionary - return std::make_pair(Ref{}, false); - } - // first, create the edge + new leaf cell - int m = n - pfx_len - 1; - CellBuilder cb; - append_dict_label(cb, key + (pfx_len + 1), m, m); - Ref c1 = finish_create_leaf(cb, value); // new leaf cell corresponding to `key` - //cb.reset(); - // create the lower portion of the old edge - int t = label.l_bits - pfx_len - 1; - auto cs = std::move(label.remainder); - if (label.l_same) { - append_dict_label_same(cb, label.l_same & 1, t, m); - } else { - cs.write().advance(pfx_len + 1); - append_dict_label(cb, cs->data_bits(), t, m); - cs.unique_write().advance(t); - } - // now cs is the old payload of the edge, either a value or two subdictionary references - if (!cell_builder_add_slice_bool(cb, *cs)) { - throw VmError{Excno::cell_ov, "cannot change label of an old augmented dictionary cell (?)"}; - } - Ref c2 = cb.finalize(); // the other child of the new fork - // cb.reset(); - append_dict_label(cb, key, pfx_len, n); - bool sw_bit = key[pfx_len]; - if (sw_bit) { - c1.swap(c2); - } - return std::make_pair(finish_create_fork(cb, std::move(c1), std::move(c2), n - pfx_len), true); - } - if (label.l_bits == n) { - // the edge leads to a leaf node - // this leaf node already contains a value for the key wanted - if (mode == Dictionary::SetMode::Add) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - // replace the value of the only element of the dictionary - CellBuilder cb; - append_dict_label(cb, key, n, n); - return std::make_pair(finish_create_leaf(cb, value), true); - } - // main case: the edge leads to a fork, have to insert new value either in the right or in the left subtree - auto c1 = label.remainder->prefetch_ref(0); - auto c2 = label.remainder->prefetch_ref(1); - label.remainder.clear(); - if (key[label.l_bits]) { - // insert key into the right child (c2) - auto res = dict_set(std::move(c2), key + (label.l_bits + 1), n - label.l_bits - 1, value, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c2 = std::move(res.first); - } else { - // insert key into the left child (c1) - auto res = dict_set(std::move(c1), key + (label.l_bits + 1), n - label.l_bits - 1, value, mode); - if (!res.second) { - // return unchanged dictionary - return std::make_pair(Ref{}, false); - } - c1 = std::move(res.first); - } - // create a new label with the same content - CellBuilder cb; - append_dict_label(cb, key, label.l_bits, n); - return std::make_pair(finish_create_fork(cb, std::move(c1), std::move(c2), n - label.l_bits), true); -} - -bool AugmentedDictionary::set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode) { - return value.not_null() && set(key, key_len, *value, mode); -} - -bool AugmentedDictionary::set(td::ConstBitPtr key, int key_len, const CellSlice& value, SetMode mode) { - force_validate(); - if (key_len != get_key_bits()) { - return false; - } - auto res = dict_set(get_root_cell(), key, key_len, value, mode); - if (res.second) { - //vm::CellSlice cs{vm::NoVmOrd(), res.first}; - //std::cerr << "new augmented dictionary root is:\n"; - //cs.print_rec(std::cerr); - set_root_cell(std::move(res.first)); - } - return res.second; -} - -bool AugmentedDictionary::set_ref(td::ConstBitPtr key, int key_len, Ref value_ref, SetMode mode) { - if (value_ref.not_null()) { - CellBuilder cb; - cb.store_ref(std::move(value_ref)); - return set(key, key_len, load_cell_slice(cb.finalize())); - } else { - return false; - } -} - -bool AugmentedDictionary::set_builder(td::ConstBitPtr key, int key_len, const CellBuilder& value, SetMode mode) { - return set(key, key_len, load_cell_slice(value.finalize_copy())); -} - -bool AugmentedDictionary::check_for_each_extra(const foreach_extra_func_t& foreach_extra_func, bool invert_first) { - force_validate(); - const auto& augm = aug; - foreach_func_t foreach_func = [&foreach_extra_func, &augm](Ref value_extra, td::ConstBitPtr key, - int key_len) { - auto extra = augm.extract_extra(value_extra.write()); - return extra.not_null() && foreach_extra_func(std::move(value_extra), std::move(extra), key, key_len); - }; - return DictionaryFixed::check_for_each(foreach_func, invert_first); -} - -std::pair, Ref> AugmentedDictionary::dict_traverse_extra( - Ref dict, td::BitPtr key_buffer, int n, const traverse_func_t& traverse_node) const { - int m = get_key_bits(); - while (true) { - CHECK(dict.not_null()); - LabelParser label{std::move(dict), n, 2}; - label.extract_label_to(key_buffer); - key_buffer += label.l_bits; - n -= label.l_bits; - if (n <= 0) { - // reached a leaf, check it - assert(!n); - auto pair = decompose_value_extra(std::move(label.remainder)); - if (pair.first.is_null()) { - throw VmError{Excno::dict_err, "invalid leaf value/extra in an augmented dictionary"}; - } - int r = traverse_node(key_buffer - m, m, pair.second /* extra */, pair.first /* value */); - if (r < 0) { - throw CombineErrorValue{r}; - } else if (r > 0) { - return pair; - } else { - return {}; - } - } - // visit (traverse) fork - auto c1 = label.remainder.write().fetch_ref(), c2 = label.remainder.write().fetch_ref(); - int r = traverse_node(key_buffer + n - m, m - n, std::move(label.remainder) /* extra */, {}); - if (r < 0 || (r & 3) == 3) { - throw CombineErrorValue{r}; - } else if (!(r & 3)) { - return {}; - } - // r = 1 : visit only left, 2 = visit only right, 5 = visit right, then left, 6 = visit left, then right - ++key_buffer; - --n; - bool sw = r & 1; - if (sw) { - std::swap(c1, c2); - } - if (r & 4) { - // have to visit both children in some order; do a recursive call to visit the first child - key_buffer[-1] = sw; - auto tmp = dict_traverse_extra(std::move(c1), key_buffer, n, traverse_node); - if (tmp.first.not_null()) { - return tmp; - } - } - // visit the remaining child - key_buffer[-1] = !sw; - dict = std::move(c2); - } -} - -std::pair, Ref> AugmentedDictionary::traverse_extra(td::BitPtr key_buffer, int key_len, - const traverse_func_t& traverse_node) { - force_validate(); - if (key_len != get_key_bits() || is_empty()) { - return {}; - } - return dict_traverse_extra(get_root_cell(), key_buffer, key_len, traverse_node); -} - -bool AugmentedDictionary::validate_check_extra(const AugmentedDictionary::foreach_extra_func_t& foreach_extra_func, - bool invert_first) { - const AugmentationData& augm = aug; - int key_len = get_key_bits(); - return validate_check( - [&foreach_extra_func, &augm, key_len](Ref value_extra, td::ConstBitPtr key, int value) { - auto extra = augm.extract_extra(value_extra.write()); - return extra.not_null() && foreach_extra_func(std::move(value_extra), std::move(extra), key, key_len); - }, - invert_first); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dict.h b/submodules/ton/tonlib-src/crypto/vm/dict.h deleted file mode 100644 index 978f4d53..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dict.h +++ /dev/null @@ -1,654 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/bitstring.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/stack.hpp" -#include - -namespace vm { -using td::BitSlice; -using td::Ref; - -namespace dict { - -struct LabelParser { - enum { chk_none = 0, chk_min = 1, chk_size = 2, chk_all = 3 }; - Ref remainder; - int l_offs; - int l_same; - int l_bits; - unsigned s_bits; - LabelParser(Ref cs, int max_label_len, int auto_validate = chk_all); - LabelParser(Ref cell, int max_label_len, int auto_validate = chk_all); - int is_valid() const { - return l_offs; - } - void validate() const; - void validate_simple(int n) const; - void validate_ext(int n) const; - bool is_prefix_of(td::ConstBitPtr key, int len) const; - bool has_prefix(td::ConstBitPtr key, int len) const; - int common_prefix_len(td::ConstBitPtr key, int len) const; - int extract_label_to(td::BitPtr to); - int copy_label_prefix_to(td::BitPtr to, int max_len) const; - td::ConstBitPtr bits() const { - return remainder->data_bits(); - } - td::ConstBitPtr bits_end() const { - return bits() + l_bits; - } - void skip_label() { - remainder.write().advance(s_bits); - } - void clear() { - remainder.clear(); - } - - private: - bool parse_label(CellSlice& cs, int max_label_len); -}; - -struct AugmentationData { - virtual ~AugmentationData() = default; - virtual bool skip_extra(vm::CellSlice& cs) const = 0; - virtual bool eval_leaf(vm::CellBuilder& cb, vm::CellSlice& val_cs) const = 0; - virtual bool eval_fork(vm::CellBuilder& cb, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const = 0; - virtual bool eval_empty(vm::CellBuilder& cb) const = 0; - virtual bool check_leaf(vm::CellSlice& cs, vm::CellSlice& val_cs) const; - virtual bool check_fork(vm::CellSlice& cs, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const; - virtual bool check_empty(vm::CellSlice& cs) const; - virtual bool check_leaf_key_extra(vm::CellSlice& val_cs, vm::CellSlice& extra_cs, td::ConstBitPtr key, - int key_len) const { - return check_leaf(extra_cs, val_cs); - } - Ref extract_extra(vm::CellSlice& cs) const; - Ref extract_extra(Ref cs_ref) const; - bool extract_extra_to(vm::CellSlice& cs, Ref& extra_csr) const { - return (extra_csr = extract_extra(cs)).not_null(); - } - bool extract_extra_to(Ref cs_ref, Ref& extra_csr) const { - return (extra_csr = extract_extra(std::move(cs_ref))).not_null(); - } - bool extract_extra_to(vm::CellSlice& cs, vm::CellSlice& extra) const; -}; - -static inline bool store_cell_dict(vm::CellBuilder& cb, Ref dict_root) { - return dict_root.not_null() ? cb.store_long_bool(1, 1) && cb.store_ref_bool(std::move(dict_root)) - : cb.store_long_bool(0, 1); -} - -} // namespace dict - -struct CombineError {}; // thrown by Dictionary::combine_with -struct CombineErrorValue { - int arg_; -}; - -struct DictNonEmpty {}; -struct DictAdvance {}; - -class DictionaryBase { - protected: - mutable Ref root; - Ref root_cell; - int key_bits; - mutable int flags; - enum { f_valid = 1, f_root_cached = 2, f_invalid = 0x80 }; - - public: - enum class SetMode : int { Set = 3, Replace = 1, Add = 2 }; - enum { max_key_bits = 1023, max_key_bytes = (max_key_bits + 7) / 8 }; - - typedef std::function store_value_func_t; - - DictionaryBase(int _n, bool validate = true); - DictionaryBase(Ref _root, int _n, bool validate = true); - DictionaryBase(const CellSlice& root_cs, int _n, bool validate = true); - DictionaryBase(DictAdvance, CellSlice& root_cs, int _n, bool validate = true); - DictionaryBase(Ref cell, int _n, bool validate = true); - DictionaryBase(DictNonEmpty, Ref _root, int _n, bool validate = true); - DictionaryBase(DictNonEmpty, const CellSlice& root_cs, int _n, bool validate = true); - virtual ~DictionaryBase() = default; - - static Ref construct_root_from(const CellSlice& root_node_cs); - Ref get_root() const; - Ref extract_root() &&; - Ref get_root_cell() const { - return root_cell; - } - Ref extract_root_cell() && { - return std::move(root_cell); - } - bool append_dict_to_bool(CellBuilder& cb) &&; - bool append_dict_to_bool(CellBuilder& cb) const &; - int get_key_bits() const { - return key_bits; - } - bool is_valid() const { - return flags & f_valid; - } - void reset() { - root.clear(); - root_cell.clear(); - flags = f_valid; - } - virtual bool validate(); - void force_validate(); - bool is_empty() const { - return root_cell.is_null(); - } - static Ref get_empty_dictionary(); - - protected: - bool init_root_for_nonempty(const CellSlice& cs); - bool invalidate() { - flags |= f_invalid; - return false; - } - bool compute_root() const; - static Ref new_empty_dictionary(); - void set_root_cell(Ref cell) { - root_cell = std::move(cell); - flags &= ~f_root_cached; - } -}; - -class DictIterator; - -template -std::pair dict_range(T&& dict, bool rev = false, bool sgnd = false) { - return std::pair{std::forward(dict), (int)rev + 2 * (int)sgnd}; -} - -class DictionaryFixed : public DictionaryBase { - public: - typedef std::function filter_func_t; - typedef std::function, Ref)> simple_combine_func_t; - typedef std::function, Ref, td::ConstBitPtr, int)> combine_func_t; - typedef std::function, td::ConstBitPtr, int)> foreach_func_t; - typedef std::function, Ref)> scan_diff_func_t; - - DictionaryFixed(int _n, bool validate = true) : DictionaryBase(_n, validate) { - } - DictionaryFixed(Ref _root, int _n, bool validate = true) : DictionaryBase(std::move(_root), _n, validate) { - } - DictionaryFixed(const CellSlice& root_cs, int _n, bool validate = true) : DictionaryBase(root_cs, _n, validate) { - } - DictionaryFixed(DictAdvance, CellSlice& root_cs, int _n, bool validate = true) - : DictionaryBase(DictAdvance(), root_cs, _n, validate) { - } - DictionaryFixed(Ref cell, int _n, bool validate = true) : DictionaryBase(std::move(cell), _n, validate) { - } - DictionaryFixed(DictNonEmpty, Ref _root, int _n, bool validate = true) - : DictionaryBase(DictNonEmpty(), std::move(_root), _n, validate) { - } - DictionaryFixed(DictNonEmpty, const CellSlice& root_cs, int _n, bool validate = true) - : DictionaryBase(DictNonEmpty(), root_cs, _n, validate) { - } - static BitSlice integer_key(td::RefInt256 x, unsigned n, bool sgnd = true, unsigned char buffer[128] = 0, - bool quiet = false); - static bool integer_key_simple(td::RefInt256 x, unsigned n, bool sgnd, td::BitPtr buffer, bool quiet = false); - td::RefInt256 key_as_integer(td::ConstBitPtr key, bool sgnd = false) const { - return td::bits_to_refint(key, key_bits, sgnd); - } - bool key_exists(td::ConstBitPtr key, int key_len); - bool int_key_exists(long long key); - bool uint_key_exists(unsigned long long key); - Ref lookup(td::ConstBitPtr key, int key_len); - Ref lookup_delete(td::ConstBitPtr key, int key_len); - Ref get_minmax_key(td::BitPtr key_buffer, int key_len, bool fetch_max = false, bool invert_first = false); - Ref extract_minmax_key(td::BitPtr key_buffer, int key_len, bool fetch_max = false, - bool invert_first = false); - Ref lookup_nearest_key(td::BitPtr key_buffer, int key_len, bool fetch_next = false, bool allow_eq = false, - bool invert_first = false); - bool has_common_prefix(td::ConstBitPtr prefix, int prefix_len); - int get_common_prefix(td::BitPtr buffer, unsigned buffer_len); - bool cut_prefix_subdict(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false); - Ref extract_prefix_subdict_root(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false); - bool check_for_each(const foreach_func_t& foreach_func, bool invert_first = false); - int filter(filter_func_t check); - bool combine_with(DictionaryFixed& dict2, const combine_func_t& combine_func, int mode = 0); - bool combine_with(DictionaryFixed& dict2, const simple_combine_func_t& simple_combine_func, int mode = 0); - bool combine_with(DictionaryFixed& dict2); - bool scan_diff(DictionaryFixed& dict2, const scan_diff_func_t& diff_func, int check_augm = 0); - bool validate_check(const foreach_func_t& foreach_func, bool invert_first = false); - bool validate_all(); - DictIterator null_iterator(); - DictIterator init_iterator(bool backw = false, bool invert_first = false); - DictIterator make_iterator(int mode); - DictIterator begin(); - DictIterator end(); - DictIterator cbegin(); - DictIterator cend(); - DictIterator rbegin(); - DictIterator rend(); - DictIterator crbegin(); - DictIterator crend(); - template - bool key_exists(const T& key) { - return key_exists(key.bits(), key.size()); - } - template - Ref lookup(const T& key) { - return lookup(key.bits(), key.size()); - } - template - Ref lookup_delete(const T& key) { - return lookup_delete(key.bits(), key.size()); - } - template - Ref get_minmax_key(T& key_buffer, bool fetch_max = false, bool invert_first = false) { - return get_minmax_key(key_buffer.bits(), key_buffer.size(), fetch_max, invert_first); - } - template - Ref lookup_nearest_key(T& key_buffer, bool fetch_next = false, bool allow_eq = false, - bool invert_first = false) { - return lookup_nearest_key(key_buffer.bits(), key_buffer.size(), fetch_next, allow_eq, invert_first); - } - - protected: - virtual int label_mode() const { - return dict::LabelParser::chk_all; - } - virtual Ref extract_leaf_value(Ref leaf) const { - return leaf; - } - virtual Ref finish_create_leaf(CellBuilder& cb, const CellSlice& value) const; - virtual Ref finish_create_fork(CellBuilder& cb, Ref c1, Ref c2, int n) const; - virtual bool check_fork(CellSlice& cs, Ref c1, Ref c2, int n) const { - return true; - } - virtual bool check_leaf(CellSlice& cs, td::ConstBitPtr key, int key_len) const { - return true; - } - bool check_leaf(Ref cs_ref, td::ConstBitPtr key, int key_len) const { - return check_leaf(cs_ref.write(), key, key_len); - } - bool check_fork_raw(Ref cs_ref, int n) const; - friend class DictIterator; - - private: - std::pair, Ref> dict_lookup_delete(Ref dict, td::ConstBitPtr key, int n) const; - Ref dict_lookup_minmax(Ref dict, td::BitPtr key_buffer, int n, int mode) const; - Ref dict_lookup_nearest(Ref dict, td::BitPtr key_buffer, int n, bool allow_eq, int mode) const; - std::pair, bool> extract_prefix_subdict_internal(Ref dict, td::ConstBitPtr prefix, int prefix_len, - bool remove_prefix = false) const; - bool dict_check_for_each(Ref dict, td::BitPtr key_buffer, int n, int total_key_len, - const foreach_func_t& foreach_func, bool invert_first = false) const; - std::pair, int> dict_filter(Ref dict, td::BitPtr key, int n, const filter_func_t& check_leaf, - int& skip_rest) const; - Ref dict_combine_with(Ref dict1, Ref dict2, td::BitPtr key_buffer, int n, int total_key_len, - const combine_func_t& combine_func, int mode = 0, int skip1 = 0, int skip2 = 0) const; - bool dict_scan_diff(Ref dict1, Ref dict2, td::BitPtr key_buffer, int n, int total_key_len, - const scan_diff_func_t& diff_func, int mode = 0, int skip1 = 0, int skip2 = 0) const; - bool dict_validate_check(Ref dict, td::BitPtr key_buffer, int n, int total_key_len, - const foreach_func_t& foreach_func, bool invert_first = false) const; -}; - -class DictIterator { - const DictionaryFixed* dict_{nullptr}; - Ref root_; - int label_mode_{dict::LabelParser::chk_size}; - int key_bits_; - int flags_; - int order_; - unsigned char key_buffer[DictionaryBase::max_key_bytes]; - bool prevalidate(int mode = -1); - enum { f_valid = 4 }; - - protected: - struct Fork { - Ref next, alt; - int pos; - bool v; - Fork() : pos(-1) { - } - Fork(Ref _next, Ref _alt, int _pos, bool _v) - : next(std::move(_next)), alt(std::move(_alt)), pos(_pos), v(_v) { - } - void rotate(td::BitPtr key) { - std::swap(next, alt); - key[pos] = (v ^= true); - } - }; - std::vector path_; - Ref leaf_; - - td::BitPtr key(int offs = 0) { - return td::BitPtr{key_buffer, offs}; - } - td::ConstBitPtr key(int offs = 0) const { - return td::ConstBitPtr{key_buffer, offs}; - } - td::ConstBitPtr ckey(int offs = 0) const { - return td::ConstBitPtr{key_buffer, offs}; - } - - public: - DictIterator() : key_bits_(0), flags_(0), order_(0) { - } - // mode: 0 = bidir, +4 = fwd only, +8 = back only; +1 = reverse directions, +2 = signed int keys - enum { it_reverse = 1, it_signed = 2 }; - DictIterator(Ref root_cell, int key_bits, int mode = 0) - : root_(std::move(root_cell)), key_bits_(key_bits), flags_(mode >> 2) { - prevalidate(mode & 3); - } - DictIterator(const DictionaryFixed& dict, int mode = 0) - : DictIterator(dict.get_root_cell(), dict.get_key_bits(), mode) { - dict_ = &dict; - label_mode_ = dict.label_mode(); - } - bool is_valid() const { - return flags_ & f_valid; - } - bool eof() const { - return leaf_.is_null(); - } - bool reset() { - dict_ = nullptr; - root_.clear(); - path_.clear(); - leaf_.clear(); - return true; - } - td::ConstBitPtr cur_pos() const { - return eof() ? td::ConstBitPtr{nullptr} : key(); - } - Ref get_root_cell() const { - return root_; - } - int get_key_bits() const { - return key_bits_; - } - bool is_bound() const { - return dict_; - } - bool is_bound_to(const DictionaryFixed& dict) const { - return root_.not_null() == dict.get_root_cell().not_null() && - (root_.not_null() ? root_.get() == dict.get_root_cell().get() : key_bits_ == dict.get_key_bits()); - } - bool bind(const DictionaryFixed& dict, int do_rewind = 0); - bool rebind_to(const DictionaryFixed& dict, int do_rewind = 0); - bool rewind(bool to_end = false); - bool next(bool backw = false); - bool prev() { - return next(true); - } - bool lookup(td::ConstBitPtr pos, int pos_bits, bool strict_after = false, bool backw = false); - template - bool lookup(const T& key, bool strict_after = false, bool backw = false) { - return lookup(key.bits(), key.size(), strict_after, backw); - } - Ref cur_value() const { - return dict_ ? dict_->extract_leaf_value(leaf_) : Ref{}; - } - Ref cur_value_raw() const { - return leaf_; - } - std::pair> operator*() const { - return std::make_pair(cur_pos(), cur_value()); - } - bool bound_to_same(const DictIterator& other) const { - return dict_ && dict_ == other.dict_; - } - bool operator==(const DictIterator& other) const { - return bound_to_same(other) && eof() == other.eof() && (eof() || key().equals(other.key(), key_bits_)); - } - int compare_keys(td::ConstBitPtr a, td::ConstBitPtr b) const; - bool operator<(const DictIterator& other) const { - return bound_to_same(other) && !eof() && (other.eof() || compare_keys(key(), other.key()) < 0); - } - bool operator!=(const DictIterator& other) const { - return !(operator==(other)); - } - bool operator>(const DictIterator& other) const { - return other < *this; - } - DictIterator& operator++() { - next(); - return *this; - } - DictIterator& operator--() { - next(true); - return *this; - } - - private: - bool dive(int mode); -}; - -template -DictIterator begin(std::pair dictm) { - return dictm.first.make_iterator(dictm.second); -} - -template -DictIterator end(std::pair dictm) { - return dictm.first.null_iterator(); -} - -class Dictionary final : public DictionaryFixed { - public: - typedef std::function)> simple_map_func_t; - typedef std::function, td::ConstBitPtr, int)> map_func_t; - Dictionary(int _n, bool validate = true) : DictionaryFixed(_n, validate) { - } - Dictionary(Ref _root, int _n, bool validate = true) : DictionaryFixed(std::move(_root), _n, validate) { - } - Dictionary(const CellSlice& root_cs, int _n, bool validate = true) : DictionaryFixed(root_cs, _n, validate) { - } - Dictionary(DictAdvance, CellSlice& root_cs, int _n, bool validate = true) - : DictionaryFixed(DictAdvance(), root_cs, _n, validate) { - } - Dictionary(Ref cell, int _n, bool validate = true) : DictionaryFixed(std::move(cell), _n, validate) { - } - Dictionary(DictNonEmpty, Ref _root, int _n, bool validate = true) - : DictionaryFixed(DictNonEmpty(), std::move(_root), _n, validate) { - } - Dictionary(DictNonEmpty, const CellSlice& root_cs, int _n, bool validate = true) - : DictionaryFixed(DictNonEmpty(), root_cs, _n, validate) { - } - Ref lookup_ref(td::ConstBitPtr key, int key_len); - Ref lookup_delete_ref(td::ConstBitPtr key, int key_len); - bool set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode = SetMode::Set); - bool set_ref(td::ConstBitPtr key, int key_len, Ref val_ref, SetMode mode = SetMode::Set); - bool set_builder(td::ConstBitPtr key, int key_len, Ref val_b, SetMode mode = SetMode::Set); - bool set_builder(td::ConstBitPtr key, int key_len, const CellBuilder& val_b, SetMode mode = SetMode::Set); - bool set_gen(td::ConstBitPtr key, int key_len, const store_value_func_t& store_val, SetMode mode = SetMode::Set); - Ref lookup_set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode = SetMode::Set); - Ref lookup_set_ref(td::ConstBitPtr key, int key_len, Ref val_ref, SetMode mode = SetMode::Set); - Ref lookup_set_builder(td::ConstBitPtr key, int key_len, Ref val_b, - SetMode mode = SetMode::Set); - Ref lookup_set_gen(td::ConstBitPtr key, int key_len, const store_value_func_t& store_val, - SetMode mode = SetMode::Set); - Ref get_minmax_key_ref(td::BitPtr key_buffer, int key_len, bool fetch_max = false, bool invert_first = false); - Ref extract_minmax_key_ref(td::BitPtr key_buffer, int key_len, bool fetch_max = false, - bool invert_first = false); - void map(const map_func_t& map_func); - void map(const simple_map_func_t& simple_map_func); - template - Ref lookup_ref(const T& key) { - return lookup_ref(key.bits(), key.size()); - } - template - Ref lookup_delete_ref(const T& key) { - return lookup_delete_ref(key.bits(), key.size()); - } - template - bool set(const T& key, Ref value, SetMode mode = SetMode::Set) { - return set(key.bits(), key.size(), std::move(value), mode); - } - template - bool set_ref(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return set_ref(key.bits(), key.size(), std::move(val_ref), mode); - } - template - bool set_builder(const T& key, const CellBuilder& val_b, SetMode mode = SetMode::Set) { - return set_builder(key.bits(), key.size(), val_b, mode); - } - template - bool set_builder(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return set_builder(key.bits(), key.size(), std::move(val_ref), mode); - } - template - Ref lookup_set(const T& key, Ref value, SetMode mode = SetMode::Set) { - return lookup_set(key.bits(), key.size(), std::move(value), mode); - } - template - Ref lookup_set_ref(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return lookup_set_ref(key.bits(), key.size(), std::move(val_ref), mode); - } - template - Ref lookup_set_builder(const T& key, const CellBuilder& val_b, SetMode mode = SetMode::Set) { - return lookup_set_builder(key.bits(), key.size(), val_b, mode); - } - template - Ref lookup_set_builder(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return lookup_set_builder(key.bits(), key.size(), std::move(val_ref), mode); - } - auto range(bool rev = false, bool sgnd = false) { - return dict_range(*this, rev, sgnd); - } - - private: - bool check_fork(CellSlice& cs, Ref c1, Ref c2, int n) const override { - return cs.empty_ext(); - } - static Ref extract_value_ref(Ref cs); - std::pair, int> dict_filter(Ref dict, td::BitPtr key, int n, const filter_func_t& check_leaf) const; -}; - -class PrefixDictionary final : public DictionaryBase { - public: - PrefixDictionary(int _n, bool validate = true) : DictionaryBase(_n, validate) { - } - PrefixDictionary(Ref _root, int _n, bool validate = true) - : DictionaryBase(std::move(_root), _n, validate) { - } - PrefixDictionary(Ref cell, int _n, bool validate = true) : DictionaryBase(std::move(cell), _n, validate) { - } - Ref lookup(td::ConstBitPtr key, int key_len); - std::pair, int> lookup_prefix(td::ConstBitPtr key, int key_len); - Ref lookup_delete(td::ConstBitPtr key, int key_len); - bool set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode = SetMode::Set); - bool set_builder(td::ConstBitPtr key, int key_len, Ref val_b, SetMode mode = SetMode::Set); - bool set_gen(td::ConstBitPtr key, int key_len, const store_value_func_t& store_val, SetMode mode = SetMode::Set); -}; - -using dict::AugmentationData; - -class AugmentedDictionary final : public DictionaryFixed { - const AugmentationData& aug; - - public: - typedef std::function, Ref, td::ConstBitPtr, int)> foreach_extra_func_t; - // return value of traverse_func: < 0 = error, 0 = skip, 1 = visit only left, 2 = visit only right, 5 = visit right, then left, 6 = visit left, then right - // for leaf nodes, all >0 values mean accept and return node as the final result, 0 = skip (continue scanning) - typedef std::function extra, Ref value)> - traverse_func_t; - AugmentedDictionary(int _n, const AugmentationData& _aug, bool validate = true); - AugmentedDictionary(Ref _root, int _n, const AugmentationData& _aug, bool validate = true); - AugmentedDictionary(Ref cell, int _n, const AugmentationData& _aug, bool validate = true); - AugmentedDictionary(DictNonEmpty, Ref _root, int _n, const AugmentationData& _aug, bool validate = true); - Ref get_empty_dictionary() const; - Ref get_root() const; - Ref extract_root() &&; - bool append_dict_to_bool(CellBuilder& cb) &&; - bool append_dict_to_bool(CellBuilder& cb) const &; - Ref get_root_extra() const; - Ref lookup(td::ConstBitPtr key, int key_len); - Ref lookup_ref(td::ConstBitPtr key, int key_len); - Ref lookup_with_extra(td::ConstBitPtr key, int key_len); - std::pair, Ref> lookup_extra(td::ConstBitPtr key, int key_len); - std::pair, Ref> lookup_ref_extra(td::ConstBitPtr key, int key_len); - Ref lookup_delete(td::ConstBitPtr key, int key_len); - Ref lookup_delete_ref(td::ConstBitPtr key, int key_len); - Ref lookup_delete_with_extra(td::ConstBitPtr key, int key_len); - std::pair, Ref> lookup_delete_extra(td::ConstBitPtr key, int key_len); - std::pair, Ref> lookup_delete_ref_extra(td::ConstBitPtr key, int key_len); - bool set(td::ConstBitPtr key, int key_len, const CellSlice& value, SetMode mode = SetMode::Set); - bool set(td::ConstBitPtr key, int key_len, Ref value, SetMode mode = SetMode::Set); - bool set_ref(td::ConstBitPtr key, int key_len, Ref val_ref, SetMode mode = SetMode::Set); - bool set_builder(td::ConstBitPtr key, int key_len, const CellBuilder& value, SetMode mode = SetMode::Set); - bool check_for_each_extra(const foreach_extra_func_t& foreach_extra_func, bool invert_first = false); - std::pair, Ref> traverse_extra(td::BitPtr key_buffer, int key_len, - const traverse_func_t& traverse_node); - bool validate_check_extra(const foreach_extra_func_t& foreach_extra_func, bool invert_first = false); - bool validate() override; - template - Ref lookup(const T& key) { - return lookup(key.bits(), key.size()); - } - template - Ref lookup_ref(const T& key) { - return lookup_ref(key.bits(), key.size()); - } - template - bool set(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return set(key.bits(), key.size(), std::move(val_ref), mode); - } - template - bool set(const T& key, const CellSlice& value, SetMode mode = SetMode::Set) { - return set(key.bits(), key.size(), value, mode); - } - template - bool set_ref(const T& key, Ref val_ref, SetMode mode = SetMode::Set) { - return set_ref(key.bits(), key.size(), std::move(val_ref), mode); - } - template - bool set_builder(const T& key, const CellBuilder& val_b, SetMode mode = SetMode::Set) { - return set_builder(key.bits(), key.size(), val_b, mode); - } - template - Ref lookup_delete(const T& key) { - return lookup_delete(key.bits(), key.size()); - } - template - Ref lookup_delete_ref(const T& key) { - return lookup_delete_ref(key.bits(), key.size()); - } - auto range(bool rev = false, bool sgnd = false) { - return dict_range(*this, rev, sgnd); - } - - Ref extract_value(Ref value_extra) const; - Ref extract_value_ref(Ref value_extra) const; - std::pair, Ref> decompose_value_extra(Ref value_extra) const; - std::pair, Ref> decompose_value_ref_extra(Ref value_extra) const; - - private: - bool compute_root() const; - Ref get_node_extra(Ref cell_ref, int n) const; - Ref extract_leaf_value(Ref leaf) const override; - bool check_leaf(CellSlice& cs, td::ConstBitPtr key, int key_len) const override; - bool check_fork(CellSlice& cs, Ref c1, Ref c2, int n) const override; - Ref finish_create_leaf(CellBuilder& cb, const CellSlice& value) const override; - Ref finish_create_fork(CellBuilder& cb, Ref c1, Ref c2, int n) const override; - std::pair, bool> dict_set(Ref dict, td::ConstBitPtr key, int n, const CellSlice& value, - SetMode mode = SetMode::Set) const; - int label_mode() const override { - return dict::LabelParser::chk_size; - } - std::pair, Ref> dict_traverse_extra(Ref dict, td::BitPtr key_buffer, int n, - const traverse_func_t& traverse_node) const; -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dictops.cpp b/submodules/ton/tonlib-src/crypto/vm/dictops.cpp deleted file mode 100644 index c798b333..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dictops.cpp +++ /dev/null @@ -1,818 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "vm/dictops.h" -#include "vm/dict.h" - -namespace vm { - -template -void push_dict(Stack& stack, T&& dict) { - stack.push_maybe_cell(std::move(dict).extract_root_cell()); -} - -template -void push_dict(Stack& stack, const T& dict) { - stack.push_maybe_cell(dict.get_root_cell()); -} - -int exec_dict_empty(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICTEMPTY"; - auto dict = stack.pop_cellslice(); - if (!dict->have(1)) { - throw VmError{Excno::cell_und}; - } - stack.push_smallint(~dict->prefetch_long(1)); - return 0; -} - -int exec_store_dict(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute STDICT"; - stack.check_underflow(2); - auto cb = stack.pop_builder(); - auto d = stack.pop_maybe_cell(); - if (!cb.write().store_maybe_ref(std::move(d))) { - throw VmError{Excno::cell_ov}; - } - stack.push_builder(std::move(cb)); - return 0; -} - -int dict_nonempty(const CellSlice& dict) { - if (!dict.have(1)) { - return -1; - } - int res = (int)dict.prefetch_ulong(1); - return dict.have_refs(res) ? res : -1; -} - -int dict_nonempty_chk(const CellSlice& dict) { - int res = dict_nonempty(dict); - if (res < 0) { - throw VmError{Excno::cell_und}; - } - return res; -} - -int exec_skip_dict(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SKIPDICT\n"; - auto dict = stack.pop_cellslice(); - int res = dict_nonempty_chk(*dict); - dict.write().advance_ext(1, res); - stack.push_cellslice(std::move(dict)); - return 0; -} - -int exec_load_optref(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute LDOPTREF\n"; - auto dict = stack.pop_cellslice(); - int res = dict_nonempty_chk(*dict); - dict.write().advance(1); - if (res) { - auto cell = dict.write().fetch_ref(); - stack.push_cellslice(std::move(dict)); - stack.push_cell(std::move(cell)); - } else { - stack.push_cellslice(std::move(dict)); - } - stack.push_smallint(-res); - return 0; -} - -int exec_preload_optref(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PLDOPTREF\n"; - auto dict = stack.pop_cellslice(); - int res = dict_nonempty_chk(*dict); - if (res) { - stack.push_cell(dict->prefetch_ref()); - } - stack.push_smallint(-res); - return 0; -} - -int exec_load_dict_slice(VmState* st, unsigned args) { - bool preload = args & 1, quiet = args & 2; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (preload ? "P" : "") << "LDDICTS" << (quiet ? "Q\n" : "\n"); - auto cs = stack.pop_cellslice(); - int res = dict_nonempty(*cs); - if (res < 0) { - if (!quiet) { - throw VmError{Excno::cell_und}; - } - if (!preload) { - stack.push_cellslice(std::move(cs)); - } - } else { - if (preload) { - stack.push_cellslice(cs->prefetch_subslice(1, res)); - } else { - stack.push_cellslice(cs.write().fetch_subslice(1, res)); - stack.push_cellslice(std::move(cs)); - } - } - if (quiet) { - stack.push_bool(res >= 0); - } - return 0; -} - -int exec_load_dict(VmState* st, unsigned args) { - bool preload = args & 1, quiet = args & 2; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute " << (preload ? "P" : "") << "LDDICT" << (quiet ? "Q\n" : "\n"); - auto cs = stack.pop_cellslice(); - int res = dict_nonempty(*cs); - if (res < 0) { - if (!quiet) { - throw VmError{Excno::cell_und}; - } - if (!preload) { - stack.push_cellslice(std::move(cs)); - } - } else { - stack.push_maybe_cell(res ? cs->prefetch_ref() : Ref{}); - if (!preload) { - cs.write().advance_ext(1, res); - stack.push_cellslice(std::move(cs)); - } - } - if (quiet) { - stack.push_bool(res >= 0); - } - return 0; -} - -std::string dump_dictop(unsigned args, const char* name) { - std::ostringstream os{"DICT"}; - if (args & 4) { - os << (args & 2 ? 'U' : 'I'); - } - os << name; - if (args & 1) { - os << "REF"; - } - return os.str(); -} - -std::string dump_dictop2(unsigned args, const char* name) { - std::ostringstream os{"DICT"}; - if (args & 2) { - os << (args & 1 ? 'U' : 'I'); - } - os << name; - return os.str(); -} - -std::string dump_subdictop2(unsigned args, const char* name) { - std::ostringstream os{"SUBDICT"}; - if (args & 2) { - os << (args & 1 ? 'U' : 'I'); - } - os << name; - return os.str(); -} - -int exec_dict_get(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 4 ? (args & 2 ? "U" : "I") : "") << "GET" << (args & 1 ? "REF" : ""); - stack.check_underflow(3); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 4) { - key = dict.integer_key(stack.pop_int_finite(), n, !(args & 2), buffer, true); - if (!key.is_valid()) { - stack.push_smallint(0); - return 0; - } - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - if (args & 1) { - auto value = dict.lookup_ref(key); - if (value.not_null()) { - stack.push_cell(std::move(value)); - stack.push_smallint(-1); - } else { - stack.push_smallint(0); - } - } else { - auto value = dict.lookup(key); - if (value.not_null()) { - stack.push_cellslice(std::move(value)); - stack.push_smallint(-1); - } else { - stack.push_smallint(0); - } - } - return 0; -} - -int exec_dict_get_optref(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 2 ? (args & 1 ? "U" : "I") : "") << "GETOPTREF"; - stack.check_underflow(3); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 2) { - key = dict.integer_key(stack.pop_int_finite(), n, !(args & 1), buffer, true); - if (!key.is_valid()) { - stack.push_null(); - return 0; - } - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - stack.push_maybe_cell(dict.lookup_ref(key)); - return 0; -} - -int exec_dict_set(VmState* st, unsigned args, Dictionary::SetMode mode, const char* name, bool bld = false) { - args <<= (bld ? 1 : 0); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 4 ? (args & 2 ? "U" : "I") : "") << name - << (args & 1 ? "REF" : (bld ? "B" : "")); - stack.check_underflow(4); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 4) { - key = dict.integer_key(stack.pop_int(), n, !(args & 2), buffer); - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - bool res; - if (bld) { - auto new_value = stack.pop_builder(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - res = dict.set_builder(key, std::move(new_value), mode); - } else if (!(args & 1)) { - auto new_value = stack.pop_cellslice(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - res = dict.set(key, std::move(new_value), mode); - } else { - auto new_value_ref = stack.pop_cell(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - res = dict.set_ref(key, std::move(new_value_ref), mode); - } - push_dict(stack, std::move(dict)); - if (mode == Dictionary::SetMode::Set) { - st->ensure_throw(res); - } else { - stack.push_bool(res); - } - return 0; -} - -int exec_dict_setget(VmState* st, unsigned args, Dictionary::SetMode mode, const char* name, bool bld = false) { - args <<= (bld ? 1 : 0); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 4 ? (args & 2 ? "U" : "I") : "") << name - << (args & 1 ? "REF\n" : (bld ? "B\n" : "\n")); - stack.check_underflow(4); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 4) { - key = dict.integer_key(stack.pop_int(), n, !(args & 2), buffer); - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - bool ok_f = (mode != Dictionary::SetMode::Add); - if (bld) { - auto new_value = stack.pop_builder(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - auto res = dict.lookup_set_builder(key, std::move(new_value), mode); - push_dict(stack, std::move(dict)); - if (res.not_null()) { - stack.push_cellslice(std::move(res)); - stack.push_bool(ok_f); - } else { - stack.push_bool(!ok_f); - } - } else if (!(args & 1)) { - auto new_value = stack.pop_cellslice(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - auto res = dict.lookup_set(key, std::move(new_value), mode); - push_dict(stack, std::move(dict)); - if (res.not_null()) { - stack.push_cellslice(std::move(res)); - stack.push_bool(ok_f); - } else { - stack.push_bool(!ok_f); - } - } else { - auto new_value_ref = stack.pop_cell(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - auto res = dict.lookup_set_ref(key, std::move(new_value_ref), mode); - push_dict(stack, std::move(dict)); - if (res.not_null()) { - stack.push_cell(std::move(res)); - stack.push_bool(ok_f); - } else { - stack.push_bool(!ok_f); - } - } - return 0; -} - -int exec_dict_delete(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 2 ? (args & 1 ? "U" : "I") : "") << "DEL\n"; - stack.check_underflow(3); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 2) { - key = dict.integer_key(stack.pop_int_finite(), n, !(args & 1), buffer); - if (!key.is_valid()) { - push_dict(stack, std::move(dict)); - stack.push_smallint(0); - return 0; - } - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - bool res = dict.lookup_delete(key).not_null(); - push_dict(stack, std::move(dict)); - stack.push_bool(res); - return 0; -} - -int exec_dict_deleteget(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 4 ? (args & 2 ? "U" : "I") : "") << "DELGET" << (args & 1 ? "REF\n" : "\n"); - stack.check_underflow(3); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 4) { - key = dict.integer_key(stack.pop_int_finite(), n, !(args & 2), buffer); - if (!key.is_valid()) { - push_dict(stack, std::move(dict)); - stack.push_smallint(0); - return 0; - } - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - if (!(args & 1)) { - auto res = dict.lookup_delete(key); - push_dict(stack, std::move(dict)); - bool ok = res.not_null(); - if (ok) { - stack.push_cellslice(std::move(res)); - } - stack.push_bool(ok); - } else { - auto res = dict.lookup_delete_ref(key); - push_dict(stack, std::move(dict)); - bool ok = res.not_null(); - if (ok) { - stack.push_cell(std::move(res)); - } - stack.push_bool(ok); - } - return 0; -} - -int exec_dict_setget_optref(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 2 ? (args & 1 ? "U" : "I") : "") << "SETGETOPTREF"; - stack.check_underflow(4); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 2) { - key = dict.integer_key(stack.pop_int(), n, !(args & 1), buffer); - } else { - key = stack.pop_cellslice()->prefetch_bits(n); - } - auto new_value = stack.pop_maybe_cell(); - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key"}; - } - Ref value; - if (new_value.not_null()) { - value = dict.lookup_set_ref(key, std::move(new_value)); - } else { - value = dict.lookup_delete_ref(key); - } - push_dict(stack, std::move(dict)); - stack.push_maybe_cell(std::move(value)); - return 0; -} - -int exec_dict_getmin(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 4 ? (args & 2 ? "U" : "I") : "") << (args & 16 ? "REM" : "") - << (args & 8 ? "MAX" : "MIN") << (args & 1 ? "REF\n" : "\n"); - stack.check_underflow(2); - int n = stack.pop_smallint_range(args & 4 ? (args & 2 ? 256 : 257) : Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - unsigned char buffer[Dictionary::max_key_bytes]; - bool flip_first = !(args & 2); - if (!(args & 1)) { - auto res = (args & 16) ? dict.extract_minmax_key(buffer, n, args & 8, flip_first) - : dict.get_minmax_key(buffer, n, args & 8, flip_first); - if (args & 16) { - push_dict(stack, std::move(dict)); - } - if (res.is_null()) { - stack.push_bool(false); - return 0; - } - stack.push_cellslice(std::move(res)); - } else { - auto res = (args & 16) ? dict.extract_minmax_key_ref(buffer, n, args & 8, flip_first) - : dict.get_minmax_key_ref(buffer, n, args & 8, flip_first); - if (args & 16) { - push_dict(stack, std::move(dict)); - } - if (res.is_null()) { - stack.push_bool(false); - return 0; - } - stack.push_cell(std::move(res)); - } - if (args & 4) { - td::RefInt256 x{true}; - x.unique_write().import_bits(td::ConstBitPtr{buffer}, n, !(args & 2)); - stack.push_int(std::move(x)); - } else { - stack.push_cellslice(Ref{true, CellBuilder().store_bits(td::ConstBitPtr{buffer}, n).finalize()}); - } - stack.push_bool(true); - return 0; -} - -std::string dump_dictop_getnear(CellSlice& cs, unsigned args) { - std::ostringstream os{"DICT"}; - if (args & 8) { - os << (args & 4 ? 'U' : 'I'); - } - os << "GET" << (args & 2 ? "PREV" : "NEXT") << (args & 1 ? "EQ" : ""); - return os.str(); -} - -int exec_dict_getnear(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 8 ? (args & 4 ? "U" : "I") : "") << "GET" << (args & 2 ? "PREV" : "NEXT") - << (args & 1 ? "EQ\n" : "\n"); - stack.check_underflow(3); - int n = stack.pop_smallint_range(args & 8 ? (args & 4 ? 256 : 257) : Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - unsigned char buffer[Dictionary::max_key_bytes]; - bool sgnd = !(args & 4), go_up = !(args & 2), allow_eq = args & 1; - if (!(args & 8)) { - auto key_hint = stack.pop_cellslice()->prefetch_bits(n); - if (!key_hint.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key hint"}; - } - td::BitPtr{buffer}.copy_from(key_hint.bits(), n); - key_hint.forget(); - auto res = dict.lookup_nearest_key(td::BitPtr{buffer}, n, go_up, allow_eq, false); - if (res.is_null()) { - stack.push_bool(false); - return 0; - } - stack.push_cellslice(std::move(res)); - stack.push_cellslice(Ref{true, CellBuilder().store_bits(td::ConstBitPtr{buffer}, n).finalize()}); - } else { - auto key = stack.pop_int_finite(); - Ref res; - if (key->export_bits(td::BitPtr{buffer}, n, sgnd)) { - res = dict.lookup_nearest_key(buffer, n, go_up, allow_eq, sgnd); - } else if ((td::sgn(key) >= 0) ^ go_up) { - res = dict.get_minmax_key(buffer, n, !go_up, sgnd); - } - if (res.is_null()) { - stack.push_bool(false); - return 0; - } - stack.push_cellslice(std::move(res)); - key.write().import_bits(td::ConstBitPtr{buffer}, n, sgnd); - stack.push_int(std::move(key)); - } - stack.push_bool(true); - return 0; -} - -int exec_pfx_dict_set(VmState* st, Dictionary::SetMode mode, const char* name) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PFXDICT" << name; - stack.check_underflow(3); - int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits); - PrefixDictionary dict{stack.pop_maybe_cell(), n}; - auto key_slice = stack.pop_cellslice(); - auto new_value = stack.pop_cellslice(); - bool res = dict.set(key_slice->data_bits(), key_slice->size(), std::move(new_value), mode); - push_dict(stack, std::move(dict)); - stack.push_bool(res); - return 0; -} - -int exec_pfx_dict_delete(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PFXDICTDEL\n"; - stack.check_underflow(2); - int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits); - PrefixDictionary dict{stack.pop_maybe_cell(), n}; - auto key_slice = stack.pop_cellslice(); - bool res = dict.lookup_delete(key_slice->data_bits(), key_slice->size()).not_null(); - push_dict(stack, std::move(dict)); - stack.push_bool(res); - return 0; -} - -int exec_dict_get_exec(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DICT" << (args & 1 ? 'U' : 'I') << "GET" << (args & 2 ? "EXEC" : "JMP") - << (args & 4 ? "Z" : ""); - stack.check_underflow(3); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - unsigned char buffer[Dictionary::max_key_bytes]; - auto idx = stack.pop_int_finite(); - if (dict.integer_key_simple(idx, n, !(args & 1), td::BitPtr{buffer}, true)) { - auto value = dict.lookup(td::BitPtr{buffer}, n); - if (value.not_null()) { - Ref cont{true, std::move(value), st->get_cp()}; - return (args & 2) ? st->call(std::move(cont)) : st->jump(std::move(cont)); - } - } - // key not found or out of range - if (args & 4) { - stack.push_int(std::move(idx)); - } - return 0; -} - -std::string dump_dict_get_exec(CellSlice& cs, unsigned args) { - return std::string{"DICT"} + (args & 1 ? 'U' : 'I') + "GET" + (args & 2 ? "EXEC" : "JMP") + (args & 4 ? "Z" : ""); -} - -int exec_push_const_dict(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have(pfx_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a DICTPUSHCONST instruction"}; - } - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "not enough references for a DICTPUSHCONST instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits - 11); - auto slice = cs.fetch_subslice(1, 1); - int n = (int)cs.fetch_ulong(10); - VM_LOG(st) << "execute DICTPUSHCONST " << n << " (" << slice << ")"; - stack.push_cell(slice->prefetch_ref()); - stack.push_smallint(n); - return 0; -} - -std::string dump_push_const_dict(CellSlice& cs, int pfx_bits, const char* name) { - if (!cs.have(pfx_bits, 1)) { - return ""; - } - cs.advance(pfx_bits - 11); - auto slice = cs.fetch_subslice(1, 1); - int n = (int)cs.fetch_ulong(10); - std::ostringstream os{name}; - os << ' ' << n << " ("; - slice->dump_hex(os, false); - os << ')'; - return os.str(); -} - -int compute_len_push_const_dict(const CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have(pfx_bits, 1)) { - return 0; - } - return 0x10000 + pfx_bits; -} - -int exec_pfx_dict_get(VmState* st, int op, const char* name_suff) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PFXDICTGET" << name_suff; - stack.check_underflow(3); - int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits); - PrefixDictionary dict{stack.pop_maybe_cell(), n}; - auto cs = stack.pop_cellslice(); - auto res = dict.lookup_prefix(cs->data_bits(), cs->size()); - if (res.first.is_null()) { - if (op & 1) { - throw VmError{Excno::cell_und, "cannot parse a prefix belonging to a given prefix code dictionary"}; - } - stack.push_cellslice(std::move(cs)); - if (!op) { - stack.push_bool(false); - } - return 0; - } - stack.push_cellslice(cs.write().fetch_subslice(res.second)); - if (!(op & 2)) { - stack.push_cellslice(std::move(res.first)); - } - stack.push_cellslice(std::move(cs)); - if (!op) { - stack.push_bool(true); - return 0; - } - if (op == 1) { - return 0; - } - Ref cont{true, std::move(res.first), st->get_cp()}; - return op & 1 ? st->call(std::move(cont)) : st->jump(std::move(cont)); -} - -int exec_const_pfx_dict_switch(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) { - if (!cs.have(pfx_bits)) { - throw VmError{Excno::inv_opcode, "not enough data bits for a PFXDICTSWITCH instruction"}; - } - if (!cs.have_refs(1)) { - throw VmError{Excno::inv_opcode, "not enough references for a PFXDICTSWITCH instruction"}; - } - Stack& stack = st->get_stack(); - cs.advance(pfx_bits - 11); - - auto dict_slice = cs.fetch_subslice(1, 1); - int n = (int)cs.fetch_ulong(10); - - VM_LOG(st) << "execute PFXDICTSWITCH " << n << " (" << dict_slice << ")"; - - PrefixDictionary dict{std::move(dict_slice), n}; - auto cs1 = stack.pop_cellslice(); - auto res = dict.lookup_prefix(cs1->data_bits(), cs1->size()); - - if (res.first.is_null()) { - stack.push_cellslice(std::move(cs1)); - return 0; - } else { - stack.push_cellslice(cs1.write().fetch_subslice(res.second)); - stack.push_cellslice(std::move(cs1)); - Ref cont{true, std::move(res.first), st->get_cp()}; - return st->jump(std::move(cont)); - } -} - -int exec_subdict_get(VmState* st, unsigned args) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SUBDICT" << (args & 2 ? (args & 1 ? "U" : "I") : "") << (args & 4 ? "RP" : "") << "GET"; - stack.check_underflow(4); - int n = stack.pop_smallint_range(Dictionary::max_key_bits); - Dictionary dict{stack.pop_maybe_cell(), n}; - int mk = (args & 2 ? (args & 1 ? 256 : 257) : Dictionary::max_key_bits); - int k = stack.pop_smallint_range(std::min(mk, n)); - BitSlice key; - unsigned char buffer[Dictionary::max_key_bytes]; - if (args & 2) { - key = dict.integer_key(stack.pop_int_finite(), k, !(args & 1), buffer, true); - } else { - key = stack.pop_cellslice()->prefetch_bits(k); - } - if (!key.is_valid()) { - throw VmError{Excno::cell_und, "not enough bits for a dictionary key prefix"}; - } - if (!dict.cut_prefix_subdict(key.bits(), k, args & 4)) { - throw VmError{Excno::dict_err, "cannot construct subdictionary by key prefix"}; - } - push_dict(stack, std::move(dict)); - return 0; -} - -void register_dictionary_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xf400, 16, "STDICT", exec_store_dict)) - .insert(OpcodeInstr::mksimple(0xf401, 16, "SKIPDICT", exec_skip_dict)) - .insert(OpcodeInstr::mksimple(0xf402, 16, "LDDICTS", std::bind(exec_load_dict_slice, _1, 0))) - .insert(OpcodeInstr::mksimple(0xf403, 16, "PLDDICTS", std::bind(exec_load_dict_slice, _1, 1))) - .insert(OpcodeInstr::mksimple(0xf404, 16, "LDDICT", std::bind(exec_load_dict, _1, 0))) - .insert(OpcodeInstr::mksimple(0xf405, 16, "PLDDICT", std::bind(exec_load_dict, _1, 1))) - .insert(OpcodeInstr::mksimple(0xf406, 16, "LDDICTQ", std::bind(exec_load_dict, _1, 2))) - .insert(OpcodeInstr::mksimple(0xf407, 16, "PLDDICTQ", std::bind(exec_load_dict, _1, 3))) - .insert(OpcodeInstr::mkfixedrange(0xf40a, 0xf410, 16, 3, std::bind(dump_dictop, _2, "GET"), exec_dict_get)) - .insert(OpcodeInstr::mkfixedrange(0xf412, 0xf418, 16, 3, std::bind(dump_dictop, _2, "SET"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Set, "SET", false))) - .insert(OpcodeInstr::mkfixedrange(0xf41a, 0xf420, 16, 3, std::bind(dump_dictop, _2, "SETGET"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Set, "SETGET", false))) - .insert( - OpcodeInstr::mkfixedrange(0xf422, 0xf428, 16, 3, std::bind(dump_dictop, _2, "REPLACE"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Replace, "REPLACE", false))) - .insert(OpcodeInstr::mkfixedrange( - 0xf42a, 0xf430, 16, 3, std::bind(dump_dictop, _2, "REPLACEGET"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Replace, "REPLACEGET", false))) - .insert(OpcodeInstr::mkfixedrange(0xf432, 0xf438, 16, 3, std::bind(dump_dictop, _2, "ADD"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Add, "ADD", false))) - .insert(OpcodeInstr::mkfixedrange(0xf43a, 0xf440, 16, 3, std::bind(dump_dictop, _2, "ADDGET"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Add, "ADDGET", false))) - .insert(OpcodeInstr::mkfixedrange(0xf441, 0xf444, 16, 2, std::bind(dump_dictop2, _2, "SETB"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Set, "SET", true))) - .insert(OpcodeInstr::mkfixedrange(0xf445, 0xf448, 16, 2, std::bind(dump_dictop2, _2, "SETGETB"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Set, "SETGET", true))) - .insert( - OpcodeInstr::mkfixedrange(0xf449, 0xf44c, 16, 2, std::bind(dump_dictop2, _2, "REPLACEB"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Replace, "REPLACE", true))) - .insert(OpcodeInstr::mkfixedrange( - 0xf44d, 0xf450, 16, 2, std::bind(dump_dictop2, _2, "REPLACEGETB"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Replace, "REPLACEGET", true))) - .insert(OpcodeInstr::mkfixedrange(0xf451, 0xf454, 16, 2, std::bind(dump_dictop2, _2, "ADDB"), - std::bind(exec_dict_set, _1, _2, Dictionary::SetMode::Add, "ADD", true))) - .insert(OpcodeInstr::mkfixedrange(0xf455, 0xf458, 16, 2, std::bind(dump_dictop2, _2, "ADDGETB"), - std::bind(exec_dict_setget, _1, _2, Dictionary::SetMode::Add, "ADDGET", true))) - .insert(OpcodeInstr::mkfixedrange(0xf459, 0xf45c, 16, 2, std::bind(dump_dictop2, _2, "DEL"), exec_dict_delete)) - .insert( - OpcodeInstr::mkfixedrange(0xf462, 0xf468, 16, 3, std::bind(dump_dictop, _2, "DELGET"), exec_dict_deleteget)) - .insert(OpcodeInstr::mkfixedrange(0xf469, 0xf46c, 16, 2, std::bind(dump_dictop2, _2, "GETOPTREF"), - exec_dict_get_optref)) - .insert(OpcodeInstr::mkfixedrange(0xf46d, 0xf470, 16, 2, std::bind(dump_dictop2, _2, "SETGETOPTREF"), - exec_dict_setget_optref)) - .insert(OpcodeInstr::mksimple(0xf470, 16, "PFXDICTSET", - std::bind(exec_pfx_dict_set, _1, PrefixDictionary::SetMode::Set, "SET"))) - .insert(OpcodeInstr::mksimple(0xf471, 16, "PFXDICTREPLACE", - std::bind(exec_pfx_dict_set, _1, PrefixDictionary::SetMode::Replace, "REPLACE"))) - .insert(OpcodeInstr::mksimple(0xf472, 16, "PFXDICTADD", - std::bind(exec_pfx_dict_set, _1, PrefixDictionary::SetMode::Add, "ADD"))) - .insert(OpcodeInstr::mksimple(0xf473, 16, "PFXDICTDEL", exec_pfx_dict_delete)) - .insert(OpcodeInstr::mkfixedrange(0xf474, 0xf480, 16, 4, dump_dictop_getnear, exec_dict_getnear)) - .insert(OpcodeInstr::mkfixedrange(0xf482, 0xf488, 16, 5, std::bind(dump_dictop, _2, "MIN"), exec_dict_getmin)) - .insert(OpcodeInstr::mkfixedrange(0xf48a, 0xf490, 16, 5, std::bind(dump_dictop, _2, "MAX"), exec_dict_getmin)) - .insert(OpcodeInstr::mkfixedrange(0xf492, 0xf498, 16, 5, std::bind(dump_dictop, _2, "REMMIN"), exec_dict_getmin)) - .insert(OpcodeInstr::mkfixedrange(0xf49a, 0xf4a0, 16, 5, std::bind(dump_dictop, _2, "REMMAX"), exec_dict_getmin)) - .insert(OpcodeInstr::mkfixed(0xf4a0 >> 2, 14, 2, dump_dict_get_exec, exec_dict_get_exec)) - .insert(OpcodeInstr::mkextrange(0xf4a400, 0xf4a800, 24, 11, - std::bind(dump_push_const_dict, _1, _3, "DICTPUSHCONST"), exec_push_const_dict, - compute_len_push_const_dict)) - .insert(OpcodeInstr::mksimple(0xf4a8, 16, "PFXDICTGETQ", std::bind(exec_pfx_dict_get, _1, 0, "Q"))) - .insert(OpcodeInstr::mksimple(0xf4a9, 16, "PFXDICTGET", std::bind(exec_pfx_dict_get, _1, 1, ""))) - .insert(OpcodeInstr::mksimple(0xf4aa, 16, "PFXDICTGETJMP", std::bind(exec_pfx_dict_get, _1, 2, "JMP"))) - .insert(OpcodeInstr::mksimple(0xf4ab, 16, "PFXDICTGETEXEC", std::bind(exec_pfx_dict_get, _1, 3, "EXEC"))) - .insert(OpcodeInstr::mkextrange(0xf4ac00, 0xf4b000, 24, 11, - std::bind(dump_push_const_dict, _1, _3, "PFXDICTSWITCH"), - exec_const_pfx_dict_switch, compute_len_push_const_dict)) - .insert(OpcodeInstr::mkfixedrange(0xf4b1, 0xf4b4, 16, 3, std::bind(dump_subdictop2, _2, "GET"), exec_subdict_get)) - .insert( - OpcodeInstr::mkfixedrange(0xf4b5, 0xf4b8, 16, 3, std::bind(dump_subdictop2, _2, "RPGET"), exec_subdict_get)) - .insert(OpcodeInstr::mkfixed(0xf4bc >> 2, 14, 2, dump_dict_get_exec, exec_dict_get_exec)); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dictops.h b/submodules/ton/tonlib-src/crypto/vm/dictops.h deleted file mode 100644 index 7d46213f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dictops.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_dictionary_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dispatch.cpp b/submodules/ton/tonlib-src/crypto/vm/dispatch.cpp deleted file mode 100644 index 53999c7b..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dispatch.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/dispatch.h" -#include "vm/excno.hpp" -#include -#include -#include - -namespace vm { - -namespace { -std::mutex dispatch_tables_mutex; -std::map dispatch_tables; -} // namespace - -DummyDispatchTable dummy_dispatch_table; - -bool DispatchTable::register_table(Codepage _cp, const DispatchTable& dt) { - assert(dt.is_final()); - int cp = (int)_cp; - if (cp < -0x8000 || cp >= 0x8000 || cp == -1) { - return false; - } else { - std::lock_guard guard(dispatch_tables_mutex); - return dispatch_tables.emplace(cp, &dt).second; - } -} - -bool DispatchTable::register_table(Codepage cp) const { - return register_table(cp, *this); -} - -const DispatchTable* DispatchTable::get_table(Codepage cp) { - return get_table((int)cp); -} - -const DispatchTable* DispatchTable::get_table(int cp) { - std::lock_guard guard(dispatch_tables_mutex); - auto entry = dispatch_tables.find(cp); - return entry != dispatch_tables.end() ? entry->second : 0; -} - -int DummyDispatchTable::dispatch(VmState* st, CellSlice& cs) const { - throw VmError{Excno::inv_opcode, "empty opcode table"}; -} - -std::string DummyDispatchTable::dump_instr(CellSlice& cs) const { - return ""; -} - -int DummyDispatchTable::instr_len(const CellSlice& cs) const { - return 0; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/dispatch.h b/submodules/ton/tonlib-src/crypto/vm/dispatch.h deleted file mode 100644 index fde0890f..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/dispatch.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include - -namespace vm { - -class VmState; -class CellSlice; - -enum class Codepage { test_cp = 0 }; - -class DispatchTable { - public: - DispatchTable() = default; - virtual ~DispatchTable() = default; - virtual int dispatch(VmState* st, CellSlice& cs) const = 0; - virtual std::string dump_instr(CellSlice& cs) const = 0; - virtual int instr_len(const CellSlice& cs) const = 0; - virtual DispatchTable* finalize() = 0; - virtual bool is_final() const = 0; - static const DispatchTable* get_table(Codepage cp); - static const DispatchTable* get_table(int cp); - static bool register_table(Codepage cp, const DispatchTable& dt); - bool register_table(Codepage cp) const; -}; - -class DummyDispatchTable : public DispatchTable { - public: - DummyDispatchTable() : DispatchTable() { - } - ~DummyDispatchTable() override = default; - int dispatch(VmState* st, CellSlice& cs) const override; - std::string dump_instr(CellSlice& cs) const override; - int instr_len(const CellSlice& cs) const override; - DispatchTable* finalize() override { - return this; - } - bool is_final() const override { - return true; - } -}; - -extern DummyDispatchTable dummy_dispatch_table; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/excno.hpp b/submodules/ton/tonlib-src/crypto/vm/excno.hpp deleted file mode 100644 index 3be48168..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/excno.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Status.h" - -namespace vm { - -enum class Excno : int { - none = 0, - alt = 1, - stk_und = 2, - stk_ov = 3, - int_ov = 4, - range_chk = 5, - inv_opcode = 6, - type_chk = 7, - cell_ov = 8, - cell_und = 9, - dict_err = 10, - unknown = 11, - fatal = 12, - out_of_gas = 13, - virt_err = 14, - total -}; - -const char* get_exception_msg(Excno exc_no); - -class VmError { - Excno exc_no; - bool msg_alloc = false; - const char* msg; - long long arg; - - public: - VmError(Excno _excno, const char* _msg) : exc_no(_excno), msg(_msg), arg(0) { - } - VmError(Excno _excno) : exc_no(_excno), msg(0), arg(0) { - } - VmError(Excno _excno, const char* _msg, long long _arg) : exc_no(_excno), msg(_msg), arg(_arg) { - } - VmError(Excno _excno, std::string _msg, long long _arg = 0) : exc_no(_excno), msg_alloc(true), arg(_arg) { - msg_alloc = true; - char* p = (char*)malloc(_msg.size() + 1); - memcpy(p, _msg.data(), _msg.size()); - p[_msg.size()] = 0; - msg = p; - } - ~VmError() { - if (msg_alloc) { - free(const_cast(msg)); - } - } - int get_errno() const { - return static_cast(exc_no); - } - const char* get_msg() const { - return msg ? msg : get_exception_msg(exc_no); - } - long long get_arg() const { - return arg; - } - td::Status as_status() const { - return td::Status::Error(td::Slice{get_msg()}); - } - template - td::Status as_status(T pfx) const { - return td::Status::Error(PSLICE() << pfx << get_msg()); - } -}; - -struct VmNoGas { - VmNoGas() = default; - int get_errno() const { - return static_cast(Excno::out_of_gas); - } - const char* get_msg() const { - return "out of gas"; - } - operator VmError() const { - return VmError{Excno::out_of_gas, "out of gas"}; - } - td::Status as_status() const { - return td::Status::Error(td::Slice{get_msg()}); - } - template - td::Status as_status(T pfx) const { - return td::Status::Error(PSLICE() << pfx << get_msg()); - } -}; - -struct VmVirtError { - int virtualization{0}; - VmVirtError() = default; - VmVirtError(int virtualization) : virtualization(virtualization) { - } - int get_errno() const { - return static_cast(Excno::virt_err); - } - const char* get_msg() const { - return "prunned branch"; - } - operator VmError() const { - return VmError{Excno::virt_err, "prunned branch", virtualization}; - } - td::Status as_status() const { - return td::Status::Error(td::Slice{get_msg()}); - } - template - td::Status as_status(T pfx) const { - return td::Status::Error(PSLICE() << pfx << get_msg()); - } -}; - -struct VmFatal {}; - -template -auto try_f(F&& f) noexcept -> decltype(f()) { - try { - return f(); - } catch (vm::VmError& error) { - return error.as_status("Got a vm exception: "); - } catch (vm::VmVirtError& error) { - return error.as_status("Got a vm virtualization exception: "); - } catch (vm::VmNoGas& error) { - return error.as_status("Got a vm no gas exception: "); - } -} - -#define TRY_VM(f) ::vm::try_f([&] { return f; }) - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/fmt.hpp b/submodules/ton/tonlib-src/crypto/vm/fmt.hpp deleted file mode 100644 index dff7290d..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/fmt.hpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refint.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/cellparse.hpp" -#include - -namespace vm { - -namespace fmt { - -// main idea: use cs >> i(32,x) >> ... or cs >> i32(x) to deserialize integers, instead of cs.write().fetch_long(32, true) -// and cb << i(32,x+y) or cb << i32(x+y) will serialize 32-bit integers - -// i, u, i16, u16, i32, u32, ub=u1, ib=i1 for integers - -template -class ConstInt { - int bits; - T value; - - public: - ConstInt(int _bits, T _val) : bits(_bits), value(_val) { - } - bool serialize(CellBuilder& cb) const { - if (C) { - return (S ? cb.store_long_rchk_bool(value, bits) : cb.store_ulong_rchk_bool(value, bits)); - } else { - return cb.store_long_bool(value, bits); - } - } - bool deserialize(CellSlice& cs) const { - if (S) { - long long x; - return cs.fetch_long_bool(bits, x) && x == value; - } else { - unsigned long long x; - return cs.fetch_ulong_bool(bits, x) && x == value; - } - } -}; - -template -class Int { - int bits; - T& value; - - public: - Int(int _bits, T& _val) : bits(_bits), value(_val) { - } - bool deserialize(CellSlice& cs) const { - if (S) { - long long x; - if (cs.fetch_long_bool(bits, x)) { - value = static_cast(x); - return true; - } - } else { - unsigned long long x; - if (cs.fetch_ulong_bool(bits, x)) { - value = static_cast(x); - return true; - } - } - return false; - } - bool serialize(CellBuilder& cb) const { - if (C) { - return S ? cb.store_long_rchk_bool(value, bits) : cb.store_ulong_rchk_bool(value, bits); - } else { - return cb.store_long_bool(value, bits); - } - } -}; - -template -class PrefetchInt { - int bits; - T& value; - - public: - PrefetchInt(int _bits, T& _val) : bits(_bits), value(_val) { - } - bool deserialize(CellSlice& cs) const { - if (S) { - long long x; - if (cs.prefetch_long_bool(bits, x)) { - value = static_cast(x); - return true; - } - } else { - unsigned long long x; - if (cs.prefetch_ulong_bool(bits, x)) { - value = static_cast(x); - return true; - } - } - return false; - } -}; - -template -class ConstRefInt { - int bits; - const td::RefInt256& value; - - public: - ConstRefInt(int _bits, const td::RefInt256& _val) : bits(_bits), value(_val) { - } - bool serialize(CellBuilder& cb) const { - return value.not_null() && cb.store_int256_bool(*value, bits, S); - } -}; - -template -class ConstRefIntVal { - int bits; - td::RefInt256 value; - - public: - ConstRefIntVal(int _bits, const td::RefInt256& _val) : bits(_bits), value(_val) { - } - ConstRefIntVal(int _bits, td::RefInt256&& _val) : bits(_bits), value(std::move(_val)) { - } - bool serialize(CellBuilder& cb) const { - return value.not_null() && cb.store_int256_bool(*value, bits, S); - } -}; - -template -class ConstBigInt { - int bits; - const td::BigInt256& value; - - public: - ConstBigInt(int _bits, const td::BigInt256& _val) : bits(_bits), value(_val) { - } - bool serialize(CellBuilder& cb) const { - return cb.store_int256_bool(value, bits, S); - } -}; - -template -class RefInt { - int bits; - td::RefInt256& value; - - public: - RefInt(int _bits, td::RefInt256& _val) : bits(_bits), value(_val) { - } - bool deserialize(CellSlice& cs) const { - value = cs.fetch_int256(bits, S); - return value.not_null(); - } - bool serialize(CellBuilder& cb) const { - return value.not_null() && cb.store_int256_bool(*value, bits, S); - } -}; - -inline ConstRefInt i(int l, const td::RefInt256& val) { - return {l, val}; -} - -inline ConstRefIntVal i(int l, td::RefInt256&& val) { - return {l, std::move(val)}; -} - -inline ConstBigInt i(int l, const td::BigInt256& val) { - return {l, val}; -} - -inline RefInt i(int l, td::RefInt256& val) { - return {l, val}; -} - -inline ConstRefInt u(int l, const td::RefInt256& val) { - return {l, val}; -} - -inline ConstRefIntVal u(int l, td::RefInt256&& val) { - return {l, std::move(val)}; -} - -inline ConstBigInt u(int l, const td::BigInt256& val) { - return {l, val}; -} - -inline RefInt u(int l, td::RefInt256& val) { - return {l, val}; -} - -template -const ConstInt i(int l, const T& val) { - return {l, val}; -} - -template -Int i(int l, T& val) { - return {l, val}; -} - -template -PrefetchInt pi(int l, T& val) { - return {l, val}; -} - -template -const ConstInt u(int l, const T& val) { - return {l, val}; -} - -template -Int u(int l, T& val) { - return {l, val}; -} - -template -PrefetchInt pu(int l, T& val) { - return {l, val}; -} - -template -const ConstInt iw(int l, const T& val) { - return {l, val}; -} - -template -Int iw(int l, T& val) { - return {l, val}; -} - -inline ConstInt ib(bool flag) { - return {1, flag}; -} - -template -Int ib(T& val) { - return {1, val}; -} - -template -PrefetchInt pib(T& val) { - return {1, val}; -} - -inline ConstInt ub(bool flag) { - return {1, flag}; -} - -template -Int ub(T& val) { - return {1, val}; -} - -template -PrefetchInt pub(T& val) { - return {1, val}; -} - -inline ConstInt i8(signed char val) { - return {8, val}; -} - -template -Int i8(T& val) { - return {8, val}; -} - -inline ConstInt u8(unsigned char val) { - return {8, val}; -} - -template -Int u8(T& val) { - return {8, val}; -} - -inline ConstInt i16(short val) { - return {16, val}; -} - -template -Int i16(T& val) { - static_assert(sizeof(T) >= 2, "i16 needs at least 16-bit integer variable as a result"); - return {16, val}; -} - -inline ConstInt u16(unsigned short val) { - return {16, val}; -} - -template -Int u16(T& val) { - static_assert(sizeof(T) >= 2, "u16 needs at least 16-bit integer variable as a result"); - return {16, val}; -} - -template -const ConstInt i32(const T& val) { - return {32, val}; -} - -template -Int i32(T& val) { - static_assert(sizeof(T) >= 4, "i32 needs at least 32-bit integer variable as a result"); - return {32, val}; -} - -template -PrefetchInt pi32(T& val) { - static_assert(sizeof(T) >= 4, "pi32 needs at least 32-bit integer variable as a result"); - return {32, val}; -} - -template -const ConstInt u32(const T& val) { - return {32, val}; -} - -template -Int u32(T& val) { - static_assert(sizeof(T) >= 4, "u32 needs at least 32-bit integer variable as a result"); - return {32, val}; -} - -template -PrefetchInt pu32(T& val) { - static_assert(sizeof(T) >= 4, "pu32 needs at least 32-bit integer variable as a result"); - return {32, val}; -} - -template -const ConstInt i64(const T& val) { - return {64, val}; -} - -template -Int i64(T& val) { - static_assert(sizeof(T) >= 8, "i64 needs 64-bit integer variable as a result"); - return {64, val}; -} - -template -const ConstInt u64(const T& val) { - return {64, val}; -} - -template -Int u64(T& val) { - static_assert(sizeof(T) >= 8, "u64 needs 64-bit integer variable as a result"); - return {64, val}; -} - -/* - * - * non-integer types - * - */ - -// cr(Ref& cell_ref) for (de)serializing cell references - -class ConstCellRef { - const td::Ref& value; - - public: - ConstCellRef(const td::Ref& _val) : value(_val) { - } - bool serialize(CellBuilder& cb) const { - return cb.store_ref_bool(value); - } -}; - -class ConstCellRefVal { - td::Ref value; - - public: - ConstCellRefVal(const td::Ref& _val) : value(_val) { - } - ConstCellRefVal(td::Ref&& _val) : value(std::move(_val)) { - } - bool serialize(CellBuilder& cb) const { - return cb.store_ref_bool(std::move(value)); - } -}; - -class CellRefFmt { - td::Ref& value; - - public: - CellRefFmt(td::Ref& _val) : value(_val) { - } - bool deserialize(CellSlice& cs) const { - value = cs.fetch_ref(); - return value.not_null(); - } -}; - -inline ConstCellRef cr(const td::Ref& val) { - return {val}; -} - -inline ConstCellRefVal cr(td::Ref&& val) { - return {std::move(val)}; -} - -inline CellRefFmt cr(td::Ref& val) { - return {val}; -} - -// skip(n) will skip n bits - -class SkipFmt { - int bits; - - public: - explicit SkipFmt(int _bits) : bits(_bits) { - } - bool deserialize(CellSlice& cs) const { - return cs.advance(bits); - } -}; - -inline SkipFmt skip(int bits) { - return SkipFmt{bits}; -} - -// end will throw an exception if any bits or references remain, or if a previous operation failed -// ends similar, but checks only bits - -class ChkEnd { - public: - explicit ChkEnd() = default; - bool deserialize(CellSlice& cs) const { - return (cs.empty() && !cs.size_refs()); - } -}; - -class ChkEndS { - public: - explicit ChkEndS() = default; - bool deserialize(CellSlice& cs) const { - return cs.empty(); - } -}; - -template -class Chk { - Cond cond; - - public: - template - explicit constexpr Chk(Args... args) : cond(args...){}; - bool deserialize_ext(CellSlice& cs, bool state) const { - if (!state || !cond.deserialize(cs)) { - cs.error(); - } - return true; - } -}; - -class ChkOk { - public: - explicit ChkOk() = default; - bool deserialize_ext(CellSlice& cs, bool state) const { - if (!state) { - cs.error(); - } - return true; - } -}; - -constexpr ChkEnd end = ChkEnd{}; -constexpr ChkEndS ends = ChkEndS{}; -constexpr Chk okend = Chk{}; -constexpr Chk okends = Chk{}; -constexpr Chk oke = Chk{}; -constexpr ChkOk ok = ChkOk{}; - -inline ::vm::CellParser parser(CellSlice& cs) { - return ::vm::CellParser{cs}; -} - -} // namespace fmt - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/log.h b/submodules/ton/tonlib-src/crypto/vm/log.h deleted file mode 100644 index 30ace2c4..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/log.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/logging.h" - -#define VM_LOG_IMPL(st, mask) \ - LOG_IMPL_FULL(get_log_interface(st), get_log_options(st), DEBUG, VERBOSITY_NAME(DEBUG), \ - (get_log_mask(st) & mask) != 0, "") - -#define VM_LOG(st) VM_LOG_IMPL(st, 1) -#define VM_LOG_MASK(st, mask) VM_LOG_IMPL(st, mask) - -namespace vm { -struct VmLog { - td::LogInterface *log_interface{td::log_interface}; - td::LogOptions log_options{td::log_options}; - enum { DumpStack = 2 }; - int log_mask{1}; - static VmLog Null() { - VmLog res; - res.log_options.level = 0; - res.log_mask = 0; - return res; - } -}; - -template -td::LogInterface &get_log_interface(State *st) { - return st ? *st->get_log().log_interface : *::td::log_interface; -} - -template -auto get_log_options(State *st) { - return st ? st->get_log().log_options : ::td::log_options; -} - -template -auto get_log_mask(State *st) { - return st ? st->get_log().log_mask : 1; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/memo.cpp b/submodules/ton/tonlib-src/crypto/vm/memo.cpp deleted file mode 100644 index 576f28f1..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/memo.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2020 Telegram Systems LLP -*/ -#include "vm/memo.h" -#include "vm/excno.hpp" - -namespace vm { -using td::Ref; - -bool FakeVmStateLimits::register_op(int op_units) { - bool ok = (ops_remaining -= op_units) >= 0; - if (!ok && !quiet) { - throw VmError{Excno::out_of_gas, "too many operations"}; - } - return ok; -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/memo.h b/submodules/ton/tonlib-src/crypto/vm/memo.h deleted file mode 100644 index 3aee39a6..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/memo.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "vm/cells.h" -#include "vm/vmstate.h" - -namespace vm { -using td::Ref; - -class FakeVmStateLimits : public VmStateInterface { - long long ops_remaining; - bool quiet; - - public: - FakeVmStateLimits(long long max_ops = 1LL << 62, bool _quiet = true) : ops_remaining(max_ops), quiet(_quiet) { - } - bool register_op(int op_units = 1) override; -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/opctable.cpp b/submodules/ton/tonlib-src/crypto/vm/opctable.cpp deleted file mode 100644 index d4f0f3e9..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/opctable.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include "vm/opctable.h" -#include "vm/cellslice.h" -#include "vm/excno.hpp" -#include "vm/vm.h" -#include -#include -#include -#include - -#include "td/utils/format.h" - -namespace vm { - -DispatchTable* OpcodeTable::finalize() { - if (final) { - return this; - } - instruction_list.clear(); - instruction_list.reserve(instructions.size() * 2 + 1); - - unsigned upto = 0; - for (const auto& x : instructions) { - auto range = x.second->get_opcode_range(); - assert(range.first == x.first); - assert(range.first < range.second); - assert(range.first >= upto); - assert(range.second <= top_opcode); - if (range.first > upto) { - instruction_list.emplace_back(upto, new OpcodeInstrDummy{upto, range.first}); - } - instruction_list.emplace_back(x); - upto = range.second; - } - - if (upto < top_opcode) { - instruction_list.emplace_back(upto, new OpcodeInstrDummy{upto, top_opcode}); - } - - instruction_list.shrink_to_fit(); - final = true; - return this; -} - -OpcodeTable& OpcodeTable::insert(const OpcodeInstr* instr) { - LOG_IF(FATAL, !insert_bool(instr)) << td::format::lambda([&](auto& sb) { - sb << "cannot insert instruction into table " << name << ": "; - if (!instr) { - sb << "instruction is null"; - } else if (final) { - sb << "instruction table already finalized"; - } else { - auto range = instr->get_opcode_range(); - sb << "opcode range " << td::format::as_hex(range.first) << ".." << td::format::as_hex(range.second - 1) - << " already occupied or invalid"; - } - }); - return *this; -} - -bool OpcodeTable::insert_bool(const OpcodeInstr* instr) { - if (!instr || final) { - return false; - } - auto range = instr->get_opcode_range(); - assert(range.first < range.second); - assert(range.second <= top_opcode); - auto it = instructions.lower_bound(range.first); - if (it != instructions.end() && it->first < range.second) { - return false; - } - if (it != instructions.begin()) { - auto prev_range = std::prev(it)->second->get_opcode_range(); - assert(prev_range.first < prev_range.second); - assert(prev_range.first == std::prev(it)->first); - if (prev_range.second > range.first) { - return false; - } - } - instructions.emplace_hint(it, range.first, instr); - return true; -} - -const OpcodeInstr* OpcodeTable::lookup_instr(unsigned opcode, unsigned bits) const { - std::size_t i = 0, j = instruction_list.size(); - assert(j); - while (j - i > 1) { - auto k = ((j + i) >> 1); - if (instruction_list[k].first <= opcode) { - i = k; - } else { - j = k; - } - } - return instruction_list[i].second; -} - -const OpcodeInstr* OpcodeTable::lookup_instr(const CellSlice& cs, unsigned& opcode, unsigned& bits) const { - bits = max_opcode_bits; - unsigned long long prefetch = cs.prefetch_ulong_top(bits); - opcode = (unsigned)(prefetch >> (64 - max_opcode_bits)); - opcode &= (static_cast(static_cast(-1) << max_opcode_bits) >> bits); - return lookup_instr(opcode, bits); -} - -int OpcodeTable::dispatch(VmState* st, CellSlice& cs) const { - assert(final); - unsigned bits, opcode; - auto instr = lookup_instr(cs, opcode, bits); - //std::cerr << "lookup_instr: cs.size()=" << cs.size() << "; bits=" << bits << "; opcode=" << std::setw(6) << std::setfill('0') << std::hex << opcode << std::dec << std::endl; - return instr->dispatch(st, cs, opcode, bits); -} - -std::string OpcodeTable::dump_instr(CellSlice& cs) const { - assert(final); - unsigned bits, opcode; - auto instr = lookup_instr(cs, opcode, bits); - return instr->dump(cs, opcode, bits); -} - -int OpcodeTable::instr_len(const CellSlice& cs) const { - assert(final); - unsigned bits, opcode; - auto instr = lookup_instr(cs, opcode, bits); - return instr->instr_len(cs, opcode, bits); -} - -OpcodeInstr::OpcodeInstr(unsigned _opcode, unsigned _bits, bool) - : min_opcode(_opcode << (max_opcode_bits - _bits)), max_opcode((_opcode + 1) << (max_opcode_bits - _bits)) { - assert(_opcode < (1U << _bits) && _bits <= max_opcode_bits); -} - -int OpcodeInstrDummy::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const { - st->consume_gas(gas_per_instr); - throw VmError{Excno::inv_opcode, "invalid opcode", opcode}; -} - -std::string OpcodeInstr::dump(CellSlice& cs, unsigned opcode, unsigned bits) const { - return ""; -} - -int OpcodeInstr::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const { - return 0; -} - -OpcodeInstrSimple::OpcodeInstrSimple(unsigned opcode, unsigned _opc_bits, std::string _name, exec_instr_func_t exec) - : OpcodeInstr(opcode, _opc_bits, false) - , opc_bits(static_cast(_opc_bits)) - , name(_name) - , exec_instr(exec) { -} - -int OpcodeInstrSimple::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const { - st->consume_gas(gas_per_instr + opc_bits * gas_per_bit); - if (bits < opc_bits) { - throw VmError{Excno::inv_opcode, "invalid or too short opcode", opcode + (bits << max_opcode_bits)}; - } - cs.advance(opc_bits); - return exec_instr(st, cs, opcode >> (max_opcode_bits - opc_bits), opc_bits); -} - -std::string OpcodeInstrSimple::dump(CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < opc_bits) { - return ""; - } - cs.advance(opc_bits); - return name; -} - -int OpcodeInstrSimple::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < opc_bits) { - return 0; - } else { - return opc_bits; - } -} - -OpcodeInstrSimplest::OpcodeInstrSimplest(unsigned opcode, unsigned _opc_bits, std::string _name, - exec_simple_instr_func_t exec) - : OpcodeInstr(opcode, _opc_bits, false) - , opc_bits(static_cast(_opc_bits)) - , name(_name) - , exec_instr(exec) { -} - -int OpcodeInstrSimplest::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const { - st->consume_gas(gas_per_instr + opc_bits * gas_per_bit); - if (bits < opc_bits) { - throw VmError{Excno::inv_opcode, "invalid or too short opcode", opcode + (bits << max_opcode_bits)}; - } - cs.advance(opc_bits); - return exec_instr(st); -} - -std::string OpcodeInstrSimplest::dump(CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < opc_bits) { - return ""; - } - cs.advance(opc_bits); - return name; -} - -int OpcodeInstrSimplest::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < opc_bits) { - return 0; - } else { - return opc_bits; - } -} - -OpcodeInstrFixed::OpcodeInstrFixed(unsigned opcode, unsigned _opc_bits, unsigned _arg_bits, dump_arg_instr_func_t dump, - exec_arg_instr_func_t exec) - : OpcodeInstr(opcode, _opc_bits, false) - , opc_bits(static_cast(_opc_bits)) - , tot_bits(static_cast(_opc_bits + _arg_bits)) - , dump_instr(dump) - , exec_instr(exec) { - assert(_arg_bits <= max_opcode_bits && _opc_bits <= max_opcode_bits && _arg_bits + _opc_bits <= max_opcode_bits); -} - -OpcodeInstrFixed::OpcodeInstrFixed(unsigned opcode_min, unsigned opcode_max, unsigned _tot_bits, unsigned _arg_bits, - dump_arg_instr_func_t dump, exec_arg_instr_func_t exec) - : OpcodeInstr(opcode_min << (max_opcode_bits - _tot_bits), opcode_max << (max_opcode_bits - _tot_bits)) - , opc_bits(static_cast(_tot_bits - _arg_bits)) - , tot_bits(static_cast(_tot_bits)) - , dump_instr(dump) - , exec_instr(exec) { - assert(_arg_bits <= _tot_bits && _tot_bits <= max_opcode_bits); - assert(opcode_min < opcode_max && opcode_max <= (1U << _tot_bits)); -} - -int OpcodeInstrFixed::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const { - st->consume_gas(gas_per_instr + tot_bits * gas_per_bit); - if (bits < tot_bits) { - throw VmError{Excno::inv_opcode, "invalid or too short opcode", opcode + (bits << max_opcode_bits)}; - } - cs.advance(tot_bits); - return exec_instr(st, opcode >> (max_opcode_bits - tot_bits)); -} - -std::string OpcodeInstrFixed::dump(CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < tot_bits) { - return ""; - } - cs.advance(tot_bits); - return dump_instr(cs, opcode >> (max_opcode_bits - tot_bits)); -} - -int OpcodeInstrFixed::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < tot_bits) { - return 0; - } else { - return tot_bits; - } -} - -OpcodeInstrExt::OpcodeInstrExt(unsigned opcode, unsigned _opc_bits, unsigned _arg_bits, dump_instr_func_t dump, - exec_instr_func_t exec, compute_instr_len_func_t comp_len) - : OpcodeInstr(opcode, _opc_bits, false) - , opc_bits(static_cast(_opc_bits)) - , tot_bits(static_cast(_opc_bits + _arg_bits)) - , dump_instr(dump) - , exec_instr(exec) - , compute_instr_len(comp_len) { - assert(_arg_bits <= max_opcode_bits && _opc_bits <= max_opcode_bits && _arg_bits + _opc_bits <= max_opcode_bits); -} - -OpcodeInstrExt::OpcodeInstrExt(unsigned opcode_min, unsigned opcode_max, unsigned _tot_bits, unsigned _arg_bits, - dump_instr_func_t dump, exec_instr_func_t exec, compute_instr_len_func_t comp_len) - : OpcodeInstr(opcode_min << (max_opcode_bits - _tot_bits), opcode_max << (max_opcode_bits - _tot_bits)) - , opc_bits(static_cast(_tot_bits - _arg_bits)) - , tot_bits(static_cast(_tot_bits)) - , dump_instr(dump) - , exec_instr(exec) - , compute_instr_len(comp_len) { - assert(_arg_bits <= _tot_bits && _tot_bits <= max_opcode_bits); - assert(opcode_min < opcode_max && opcode_max <= (1U << _tot_bits)); -} - -int OpcodeInstrExt::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const { - st->consume_gas(gas_per_instr + tot_bits * gas_per_bit); - if (bits < tot_bits) { - throw VmError{Excno::inv_opcode, "invalid or too short opcode", opcode + (bits << max_opcode_bits)}; - } - return exec_instr(st, cs, opcode >> (max_opcode_bits - tot_bits), tot_bits); -} - -std::string OpcodeInstrExt::dump(CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < tot_bits) { - return ""; - } - return dump_instr(cs, opcode >> (max_opcode_bits - tot_bits), (int)tot_bits); -} - -int OpcodeInstrExt::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const { - if (bits < tot_bits) { - return 0; - } else { - return compute_instr_len(cs, opcode >> (max_opcode_bits - tot_bits), (int)tot_bits); - } -} - -/* -OpcodeInstr* OpcodeInstr::mksimple(unsigned opcode, unsigned opc_bits, std::string _name, exec_instr_func_t exec) { - return new OpcodeInstrSimple(opcode, opc_bits, _name, exec); -} -*/ - -OpcodeInstr* OpcodeInstr::mksimple(unsigned opcode, unsigned opc_bits, std::string _name, - exec_simple_instr_func_t exec) { - return new OpcodeInstrSimplest(opcode, opc_bits, _name, exec); -} - -OpcodeInstr* OpcodeInstr::mkfixed(unsigned opcode, unsigned opc_bits, unsigned arg_bits, dump_arg_instr_func_t dump, - exec_arg_instr_func_t exec) { - return new OpcodeInstrFixed(opcode, opc_bits, arg_bits, dump, exec); -} - -OpcodeInstr* OpcodeInstr::mkfixedrange(unsigned opcode_min, unsigned opcode_max, unsigned tot_bits, unsigned arg_bits, - dump_arg_instr_func_t dump, exec_arg_instr_func_t exec) { - return new OpcodeInstrFixed(opcode_min, opcode_max, tot_bits, arg_bits, dump, exec); -} - -OpcodeInstr* OpcodeInstr::mkext(unsigned opcode, unsigned opc_bits, unsigned arg_bits, dump_instr_func_t dump, - exec_instr_func_t exec, compute_instr_len_func_t comp_len) { - return new OpcodeInstrExt(opcode, opc_bits, arg_bits, dump, exec, comp_len); -} - -OpcodeInstr* OpcodeInstr::mkextrange(unsigned opcode_min, unsigned opcode_max, unsigned tot_bits, unsigned arg_bits, - dump_instr_func_t dump, exec_instr_func_t exec, - compute_instr_len_func_t comp_len) { - return new OpcodeInstrExt(opcode_min, opcode_max, tot_bits, arg_bits, dump, exec, comp_len); -} - -namespace instr { - -using namespace std::placeholders; - -dump_arg_instr_func_t dump_1sr(std::string prefix, std::string suffix) { - return [prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << (args & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_1sr_l(std::string prefix, std::string suffix) { - return [prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << (args & 255) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_2sr(std::string prefix, std::string suffix) { - return [prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << ((args >> 4) & 15) << ",s" << (args & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_2sr_adj(unsigned adj, std::string prefix, std::string suffix) { - return [adj, prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << (int)((args >> 4) & 15) - (int)((adj >> 4) & 15) << ",s" << (int)(args & 15) - (int)(adj & 15) - << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_3sr(std::string prefix, std::string suffix) { - return [prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << ((args >> 8) & 15) << ",s" << ((args >> 4) & 15) << ",s" << (args & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_3sr_adj(unsigned adj, std::string prefix, std::string suffix) { - return [adj, prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << 's' << (int)((args >> 8) & 15) - (int)((adj >> 8) & 15) << ",s" - << (int)((args >> 4) & 15) - (int)((adj >> 4) & 15) << ",s" << (int)(args & 15) - (int)(adj & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_1c(std::string prefix, std::string suffix) { - return [prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << (args & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_1c_l_add(int adj, std::string prefix, std::string suffix) { - return [adj, prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << (int)(args & 255) + adj << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_1c_and(unsigned mask, std::string prefix, std::string suffix) { - return [mask, prefix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << (args & mask) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_2c(std::string prefix, std::string interfix, std::string suffix) { - return [prefix, interfix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << ((args >> 4) & 15) << interfix << (args & 15) << suffix; - return os.str(); - }; -} - -dump_arg_instr_func_t dump_2c_add(unsigned add, std::string prefix, std::string interfix, std::string suffix) { - return [add, prefix, interfix, suffix](CellSlice&, unsigned args) -> std::string { - std::ostringstream os{prefix}; - os << ((args >> 4) & 15) + ((add >> 4) & 15) << interfix << (args & 15) + (add & 15) << suffix; - return os.str(); - }; -} - -} // namespace instr - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/opctable.h b/submodules/ton/tonlib-src/crypto/vm/opctable.h deleted file mode 100644 index f9ea7023..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/opctable.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "vm/dispatch.h" -#include -#include -#include -#include - -namespace vm { - -typedef std::function compute_instr_len_func_t; -//typedef std::function compute_arg_instr_len_func_t; -typedef std::function dump_instr_func_t; -typedef std::function dump_arg_instr_func_t; -typedef std::function exec_instr_func_t; -typedef std::function exec_arg_instr_func_t; -typedef std::function exec_simple_instr_func_t; - -enum { max_opcode_bits = 24 }; -const unsigned top_opcode = (1U << max_opcode_bits); - -class OpcodeInstr { - unsigned min_opcode, max_opcode; - - public: - static constexpr unsigned gas_per_instr = 10, gas_per_bit = 1; - virtual ~OpcodeInstr() = default; - virtual int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const = 0; - virtual std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const; - virtual int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const; - OpcodeInstr(unsigned _min, unsigned _max) : min_opcode(_min), max_opcode(_max) { - } - OpcodeInstr(unsigned _opcode, unsigned _bits, bool); - unsigned get_opcode_min() const { - return min_opcode; - } - unsigned get_opcode_max() const { - return max_opcode; - } - std::pair get_opcode_range() const { - return {min_opcode, max_opcode}; - } - //static OpcodeInstr* mksimple(unsigned opcode, unsigned opc_bits, std::string _name, exec_instr_func_t exec); - static OpcodeInstr* mksimple(unsigned opcode, unsigned opc_bits, std::string _name, exec_simple_instr_func_t exec); - static OpcodeInstr* mkfixed(unsigned opcode, unsigned opc_bits, unsigned arg_bits, dump_arg_instr_func_t dump, - exec_arg_instr_func_t exec); - static OpcodeInstr* mkfixedrange(unsigned opcode_min, unsigned opcode_max, unsigned tot_bits, unsigned arg_bits, - dump_arg_instr_func_t dump, exec_arg_instr_func_t exec); - static OpcodeInstr* mkext(unsigned opcode, unsigned opc_bits, unsigned arg_bits, dump_instr_func_t dump, - exec_instr_func_t exec, compute_instr_len_func_t comp_len); - static OpcodeInstr* mkextrange(unsigned opcode_min, unsigned opcode_max, unsigned tot_bits, unsigned arg_bits, - dump_instr_func_t dump, exec_instr_func_t exec, compute_instr_len_func_t comp_len); -}; - -namespace instr { - -dump_arg_instr_func_t dump_1sr(std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_1sr_l(std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_2sr(std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_2sr_adj(unsigned adj, std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_3sr(std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_3sr_adj(unsigned adj, std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_1c(std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_1c_l_add(int adj, std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_1c_and(unsigned mask, std::string prefix, std::string suffix = ""); -dump_arg_instr_func_t dump_2c(std::string prefix, std::string interfix, std::string suffix = ""); -dump_arg_instr_func_t dump_2c_add(unsigned add, std::string prefix, std::string interfix, std::string suffix = ""); - -} // namespace instr - -class OpcodeTable : public DispatchTable { - std::map instructions; - std::vector> instruction_list; - std::string name; - Codepage codepage; - bool final; - - public: - OpcodeTable(std::string _name, Codepage cp) : name(_name), codepage(cp), final(false) { - } - OpcodeTable(const OpcodeTable&) = delete; - OpcodeTable(OpcodeTable&&) = delete; - OpcodeTable& operator=(const OpcodeTable&) = delete; - OpcodeTable& operator=(OpcodeTable&&) = delete; - ~OpcodeTable() override = default; - DispatchTable* finalize() override; - bool is_final() const override { - return final; - } - int dispatch(VmState* st, CellSlice& cs) const override; - std::string dump_instr(CellSlice& cs) const override; - int instr_len(const CellSlice& cs) const override; - bool insert_bool(const OpcodeInstr*); - OpcodeTable& insert(const OpcodeInstr*); - - private: - const OpcodeInstr* lookup_instr(unsigned opcode, unsigned bits) const; - const OpcodeInstr* lookup_instr(const CellSlice& cs, unsigned& opcode, unsigned& bits) const; -}; - -class OpcodeInstrDummy : public OpcodeInstr { - public: - OpcodeInstrDummy() = delete; - OpcodeInstrDummy(unsigned _minopc, unsigned _maxopc) : OpcodeInstr(_minopc, _maxopc) { - } - ~OpcodeInstrDummy() override = default; - int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override; -}; - -class OpcodeInstrSimple : public OpcodeInstr { - unsigned char opc_bits; - std::string name; - exec_instr_func_t exec_instr; - - public: - OpcodeInstrSimple() = delete; - OpcodeInstrSimple(unsigned opcode, unsigned _opc_bits, std::string _name, exec_instr_func_t exec); - ~OpcodeInstrSimple() override = default; - int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override; - std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const override; - int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override; -}; - -class OpcodeInstrSimplest : public OpcodeInstr { - unsigned char opc_bits; - std::string name; - exec_simple_instr_func_t exec_instr; - - public: - OpcodeInstrSimplest() = delete; - OpcodeInstrSimplest(unsigned opcode, unsigned _opc_bits, std::string _name, exec_simple_instr_func_t exec); - ~OpcodeInstrSimplest() override = default; - int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override; - std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const override; - int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override; -}; - -class OpcodeInstrFixed : public OpcodeInstr { - unsigned char opc_bits, tot_bits; - std::string name; - dump_arg_instr_func_t dump_instr; - exec_arg_instr_func_t exec_instr; - - public: - OpcodeInstrFixed() = delete; - OpcodeInstrFixed(unsigned opcode, unsigned _opc_bits, unsigned _arg_bits, dump_arg_instr_func_t dump, - exec_arg_instr_func_t exec); - OpcodeInstrFixed(unsigned opcode_min, unsigned opcode_max, unsigned _tot_bits, unsigned _arg_bits, - dump_arg_instr_func_t dump, exec_arg_instr_func_t exec); - ~OpcodeInstrFixed() override = default; - int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override; - std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const override; - int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override; -}; - -class OpcodeInstrExt : public OpcodeInstr { - unsigned char opc_bits, tot_bits; - dump_instr_func_t dump_instr; - exec_instr_func_t exec_instr; - compute_instr_len_func_t compute_instr_len; - - public: - OpcodeInstrExt() = delete; - OpcodeInstrExt(unsigned opcode, unsigned _opc_bits, unsigned _arg_bits, dump_instr_func_t dump, - exec_instr_func_t exec, compute_instr_len_func_t comp_len); - OpcodeInstrExt(unsigned opcode_min, unsigned opcode_max, unsigned _tot_bits, unsigned _arg_bits, - dump_instr_func_t dump, exec_instr_func_t exec, compute_instr_len_func_t comp_len); - ~OpcodeInstrExt() override = default; - int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override; - std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const override; - int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override; -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/stack.cpp b/submodules/ton/tonlib-src/crypto/vm/stack.cpp deleted file mode 100644 index c580a3d0..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/stack.cpp +++ /dev/null @@ -1,963 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/stack.hpp" -#include "vm/continuation.h" -#include "vm/box.hpp" -#include "vm/atom.h" -#include "vm/vmstate.h" - -namespace td { -template class td::Cnt; -template class td::Ref>; -template class td::Cnt>; -template class td::Ref>>; -} // namespace td - -namespace vm { - -// from_object_t from_object{}; - -const char* exception_messages[(int)(Excno::total)] = { - "normal termination", "alternative termination", "stack underflow", "stack overflow", "integer overflow", - "integer out of range", "invalid opcode", "type check error", "cell overflow", "cell underflow", - "dictionary error", "unknown error", "fatal error"}; - -const char* get_exception_msg(Excno exc_no) { - if (exc_no >= Excno::none && exc_no < Excno::total) { - return exception_messages[static_cast(exc_no)]; - } else { - return "unknown vm exception"; - } -} - -bool StackEntry::is_list(const StackEntry* se) { - Ref tuple; - while (!se->empty()) { - tuple = se->as_tuple_range(2, 2); - if (tuple.is_null()) { - return false; - } - se = &tuple->at(1); - } - return true; -} - -static const char HEX_digits[] = "0123456789ABCDEF"; - -std::string str_to_hex(std::string data, std::string prefix) { - prefix.reserve(prefix.size() + data.size() * 2); - for (char c : data) { - prefix += HEX_digits[(c >> 4) & 15]; - prefix += HEX_digits[c & 15]; - } - return prefix; -} - -std::string StackEntry::to_string() const { - std::ostringstream os; - dump(os); - return std::move(os).str(); -} - -std::string StackEntry::to_lisp_string() const { - std::ostringstream os; - print_list(os); - return std::move(os).str(); -} - -void StackEntry::dump(std::ostream& os) const { - switch (tp) { - case t_null: - os << "(null)"; - break; - case t_int: - os << dec_string(as_int()); - break; - case t_cell: - os << "C{" << static_cast>(ref)->get_hash().to_hex() << "}"; - break; - case t_builder: - os << "BC{" << static_cast>(ref)->to_hex() << "}"; - break; - case t_slice: { - os << "CS{"; - static_cast>(ref)->dump(os, 1, false); - os << '}'; - break; - } - case t_string: - os << "\"" << as_string() << "\""; - break; - case t_bytes: - os << "BYTES:" << str_to_hex(as_bytes()); - break; - case t_box: { - os << "Box{" << (const void*)&*ref << "}"; - break; - } - case t_atom: - os << as_atom(); - break; - case t_tuple: { - const auto& tuple = *static_cast>(ref); - auto n = tuple.size(); - if (!n) { - os << "[]"; - } else if (n == 1) { - os << "[ "; - tuple[0].dump(os); - os << " ]"; - } else { - os << "[ "; - for (const auto& entry : tuple) { - entry.dump(os); - os << ' '; - } - os << ']'; - } - break; - } - case t_object: { - os << "Object{" << (const void*)&*ref << "}"; - break; - } - default: - os << "???"; - } -} - -void StackEntry::print_list(std::ostream& os) const { - switch (tp) { - case t_null: - os << "()"; - break; - case t_tuple: { - const auto& tuple = *static_cast>(ref); - if (is_list()) { - os << '('; - tuple[0].print_list(os); - print_list_tail(os, &tuple[1]); - break; - } - auto n = tuple.size(); - if (!n) { - os << "[]"; - } else if (n == 1) { - os << "["; - tuple[0].print_list(os); - os << "]"; - } else { - os << "["; - unsigned c = 0; - for (const auto& entry : tuple) { - if (c++) { - os << " "; - } - entry.print_list(os); - } - os << ']'; - } - break; - } - default: - dump(os); - } -} - -void StackEntry::print_list_tail(std::ostream& os, const StackEntry* se) { - Ref tuple; - while (!se->empty()) { - tuple = se->as_tuple_range(2, 2); - if (tuple.is_null()) { - os << " . "; - se->print_list(os); - break; - } - os << ' '; - tuple->at(0).print_list(os); - se = &tuple->at(1); - } - os << ')'; -} - -StackEntry StackEntry::make_list(std::vector&& elems) { - StackEntry tail; - std::size_t n = elems.size(); - while (n > 0) { - --n; - tail = StackEntry{vm::make_tuple_ref(std::move(elems[n]), tail)}; - } - return tail; -} - -StackEntry StackEntry::make_list(const std::vector& elems) { - StackEntry tail; - std::size_t n = elems.size(); - while (n > 0) { - --n; - tail = StackEntry{vm::make_tuple_ref(elems[n], tail)}; - } - return tail; -} - -StackEntry::StackEntry(Ref stack_ref) : ref(std::move(stack_ref)), tp(t_stack) { -} - -StackEntry::StackEntry(Ref cont_ref) : ref(std::move(cont_ref)), tp(t_vmcont) { -} - -Ref StackEntry::as_cont() const& { - return as(); -} - -Ref StackEntry::as_cont() && { - return move_as(); -} - -StackEntry::StackEntry(Ref box_ref) : ref(std::move(box_ref)), tp(t_box) { -} - -Ref StackEntry::as_box() const& { - return as(); -} - -Ref StackEntry::as_box() && { - return move_as(); -} - -StackEntry::StackEntry(Ref tuple_ref) : ref(std::move(tuple_ref)), tp(t_tuple) { -} - -StackEntry::StackEntry(const std::vector& tuple_components) - : ref(Ref{true, tuple_components}), tp(t_tuple) { -} - -StackEntry::StackEntry(std::vector&& tuple_components) - : ref(Ref{true, std::move(tuple_components)}), tp(t_tuple) { -} - -Ref StackEntry::as_tuple() const& { - return as(); -} - -Ref StackEntry::as_tuple() && { - return move_as(); -} - -Ref StackEntry::as_tuple_range(unsigned max_len, unsigned min_len) const& { - auto t = as(); - if (t.not_null() && t->size() <= max_len && t->size() >= min_len) { - return t; - } else { - return {}; - } -} - -Ref StackEntry::as_tuple_range(unsigned max_len, unsigned min_len) && { - auto t = move_as(); - if (t.not_null() && t->size() <= max_len && t->size() >= min_len) { - return t; - } else { - return {}; - } -} - -StackEntry::StackEntry(Ref atom_ref) : ref(std::move(atom_ref)), tp(t_atom) { -} - -Ref StackEntry::as_atom() const& { - return as(); -} - -Ref StackEntry::as_atom() && { - return move_as(); -} - -bool StackEntry::for_each_scalar(const std::function& func) const { - auto t = as(); - if (t.not_null()) { - for (const auto& entry : *t) { - if (!entry.for_each_scalar(func)) { - return false; - } - } - return true; - } else { - return func(*this); - } -} - -void StackEntry::for_each_scalar(const std::function& func) const { - auto t = as(); - if (t.not_null()) { - for (const auto& entry : *t) { - entry.for_each_scalar(func); - } - } else { - func(*this); - } -} - -const StackEntry& tuple_index(const Tuple& tup, unsigned idx) { - if (idx >= tup->size()) { - throw VmError{Excno::range_chk, "tuple index out of range"}; - } - return (*tup)[idx]; -} - -StackEntry tuple_extend_index(const Ref& tup, unsigned idx) { - if (tup.is_null() || idx >= tup->size()) { - return {}; - } else { - return tup->at(idx); - } -} - -unsigned tuple_extend_set_index(Ref& tup, unsigned idx, StackEntry&& value, bool force) { - if (tup.is_null()) { - if (value.empty() && !force) { - return 0; - } - tup = Ref{true, idx + 1}; - tup.unique_write().at(idx) = std::move(value); - return idx + 1; - } - if (tup->size() <= idx) { - if (value.empty() && !force) { - return 0; - } - auto& tuple = tup.write(); - tuple.resize(idx + 1); - tuple.at(idx) = std::move(value); - return idx + 1; - } else { - tup.write().at(idx) = std::move(value); - return (unsigned)tup->size(); - } -} - -Stack::Stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top) { - push_from_stack(old_stack, copy_elem, skip_top); -} - -Stack::Stack(Stack&& old_stack, unsigned copy_elem, unsigned skip_top) { - push_from_stack(old_stack, copy_elem, skip_top); -} - -void Stack::push_from_stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top) { - unsigned n = old_stack.depth(); - if (skip_top > n || copy_elem > n - skip_top) { - throw VmError{Excno::stk_und, "cannot construct stack from another one: not enough elements"}; - } - stack.reserve(stack.size() + copy_elem); - auto it = old_stack.stack.cend() - skip_top; - std::copy(it - copy_elem, it, std::back_inserter(stack)); -} - -void Stack::push_from_stack(Stack&& old_stack, unsigned copy_elem, unsigned skip_top) { - unsigned n = old_stack.depth(); - if (skip_top > n || copy_elem > n - skip_top) { - throw VmError{Excno::stk_und, "cannot construct stack from another one: not enough elements"}; - } - stack.reserve(stack.size() + copy_elem); - auto it = old_stack.stack.cend() - skip_top; - std::move(it - copy_elem, it, std::back_inserter(stack)); -} - -void Stack::move_from_stack(Stack& old_stack, unsigned copy_elem) { - unsigned n = old_stack.depth(); - if (copy_elem > n) { - throw VmError{Excno::stk_und, "cannot construct stack from another one: not enough elements"}; - } - LOG(DEBUG) << "moving " << copy_elem << " top elements to another stack\n"; - stack.reserve(stack.size() + copy_elem); - auto it = old_stack.stack.cend(); - std::move(it - copy_elem, it, std::back_inserter(stack)); - old_stack.pop_many(copy_elem); -} - -void Stack::pop_null() { - check_underflow(1); - if (!pop().empty()) { - throw VmError{Excno::type_chk, "not an null"}; - } -} - -td::RefInt256 Stack::pop_int() { - check_underflow(1); - td::RefInt256 res = pop().as_int(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not an integer"}; - } - return res; -} - -td::RefInt256 Stack::pop_int_finite() { - auto res = pop_int(); - if (!res->is_valid()) { - throw VmError{Excno::int_ov}; - } - return res; -} - -bool Stack::pop_bool() { - return sgn(pop_int_finite()) != 0; -} - -long long Stack::pop_long() { - return pop_int()->to_long(); -} - -long long Stack::pop_long_range(long long max, long long min) { - auto res = pop_long(); - if (res > max || res < min) { - throw VmError{Excno::range_chk}; - } - return res; -} - -int Stack::pop_smallint_range(int max, int min) { - return (int)pop_long_range(max, min); -} - -Ref Stack::pop_cell() { - check_underflow(1); - auto res = pop().as_cell(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a cell"}; - } - return res; -} - -Ref Stack::pop_maybe_cell() { - check_underflow(1); - auto tmp = pop(); - if (tmp.empty()) { - return {}; - } - auto res = std::move(tmp).as_cell(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a cell"}; - } - return res; -} - -Ref Stack::pop_builder() { - check_underflow(1); - auto res = pop().as_builder(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a cell builder"}; - } - return res; -} - -Ref Stack::pop_cellslice() { - check_underflow(1); - auto res = pop().as_slice(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a cell slice"}; - } - return res; -} - -std::string Stack::pop_string() { - check_underflow(1); - auto res = pop().as_string_ref(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a string"}; - } - return *res; -} - -std::string Stack::pop_bytes() { - check_underflow(1); - auto res = pop().as_bytes_ref(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a bytes chunk"}; - } - return *res; -} - -Ref Stack::pop_cont() { - check_underflow(1); - auto res = pop().as_cont(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a continuation"}; - } - return res; -} - -Ref Stack::pop_box() { - check_underflow(1); - auto res = pop().as_box(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a box"}; - } - return res; -} - -Ref Stack::pop_tuple() { - check_underflow(1); - auto res = pop().as_tuple(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a tuple"}; - } - return res; -} - -Ref Stack::pop_tuple_range(unsigned max_len, unsigned min_len) { - check_underflow(1); - auto res = pop().as_tuple(); - if (res.is_null() || res->size() > max_len || res->size() < min_len) { - throw VmError{Excno::type_chk, "not a tuple of valid size"}; - } - return res; -} - -Ref Stack::pop_maybe_tuple() { - check_underflow(1); - auto val = pop(); - if (val.empty()) { - return {}; - } - auto res = std::move(val).as_tuple(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not a tuple"}; - } - return res; -} - -Ref Stack::pop_maybe_tuple_range(unsigned max_len) { - check_underflow(1); - auto val = pop(); - if (val.empty()) { - return {}; - } - auto res = std::move(val).as_tuple(); - if (res.is_null() || res->size() > max_len) { - throw VmError{Excno::type_chk, "not a tuple of valid size"}; - } - return res; -} - -Ref Stack::pop_atom() { - check_underflow(1); - auto res = pop().as_atom(); - if (res.is_null()) { - throw VmError{Excno::type_chk, "not an atom"}; - } - return res; -} - -void Stack::push_null() { - push({}); -} - -void Stack::push_int(td::RefInt256 val) { - if (!val->signed_fits_bits(257)) { - throw VmError{Excno::int_ov}; - } - push(std::move(val)); -} - -void Stack::push_int_quiet(td::RefInt256 val, bool quiet) { - if (!val->signed_fits_bits(257)) { - if (!quiet) { - throw VmError{Excno::int_ov}; - } else if (val->is_valid()) { - push(td::make_refint()); - return; - } - } - push(std::move(val)); -} - -void Stack::push_string(std::string str) { - push(std::move(str)); -} - -void Stack::push_string(td::Slice slice) { - push(slice.str()); -} - -void Stack::push_bytes(std::string str) { - push(std::move(str), true); -} - -void Stack::push_bytes(td::Slice slice) { - push(slice.str(), true); -} - -void Stack::push_cell(Ref cell) { - push(std::move(cell)); -} - -void Stack::push_maybe_cell(Ref cell) { - push_maybe(std::move(cell)); -} - -void Stack::push_builder(Ref cb) { - push(std::move(cb)); -} - -void Stack::push_smallint(long long val) { - push(td::make_refint(val)); -} - -void Stack::push_bool(bool val) { - push_smallint(val ? -1 : 0); -} - -void Stack::push_cont(Ref cont) { - push(std::move(cont)); -} - -void Stack::push_box(Ref box) { - push(std::move(box)); -} - -void Stack::push_tuple(Ref tuple) { - push(std::move(tuple)); -} - -void Stack::push_maybe_tuple(Ref tuple) { - if (tuple.not_null()) { - push(std::move(tuple)); - } else { - push_null(); - } -} - -void Stack::push_tuple(const std::vector& components) { - push(components); -} - -void Stack::push_tuple(std::vector&& components) { - push(std::move(components)); -} - -void Stack::push_atom(Ref atom) { - push(std::move(atom)); -} - -Ref Stack::split_top(unsigned top_cnt, unsigned drop_cnt) { - unsigned n = depth(); - if (top_cnt > n || drop_cnt > n - top_cnt) { - return Ref{}; - } - Ref new_stk = Ref{true}; - if (top_cnt) { - new_stk.unique_write().move_from_stack(*this, top_cnt); - } - if (drop_cnt) { - pop_many(drop_cnt); - } - return new_stk; -} - -void Stack::dump(std::ostream& os, int mode) const { - os << " [ "; - if (mode & 2) { - for (const auto& x : stack) { - x.print_list(os); - os << ' '; - } - } else { - for (const auto& x : stack) { - x.dump(os); - os << ' '; - } - } - os << "] "; - if (mode & 1) { - os << std::endl; - } -} -void Stack::push_cellslice(Ref cs) { - push(std::move(cs)); -} - -void Stack::push_maybe_cellslice(Ref cs) { - push_maybe(std::move(cs)); -} - -bool Stack::for_each_scalar(const std::function& func) const { - for (const auto& v : stack) { - if (!v.for_each_scalar(func)) { - return false; - } - } - return true; -} - -void Stack::for_each_scalar(const std::function& func) const { - for (const auto& v : stack) { - v.for_each_scalar(func); - } -} - -/* - * - * SERIALIZE/DESERIALIZE STACK VALUES - * - */ - -bool StackEntry::serialize(vm::CellBuilder& cb, int mode) const { - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return false; - } - switch (tp) { - case t_null: - return cb.store_long_bool(0, 8); // vm_stk_null#00 = VmStackValue; - case t_int: { - auto val = as_int(); - if (!val->is_valid()) { - // vm_stk_nan#02ff = VmStackValue; - return cb.store_long_bool(0x02ff, 16); - } else if (!(mode & 1) && val->signed_fits_bits(64)) { - // vm_stk_tinyint#01 value:int64 = VmStackValue; - return cb.store_long_bool(1, 8) && cb.store_int256_bool(std::move(val), 64); - } else { - // vm_stk_int#0201_ value:int257 = VmStackValue; - return cb.store_long_bool(0x0200 / 2, 15) && cb.store_int256_bool(std::move(val), 257); - } - } - case t_cell: - // vm_stk_cell#03 cell:^Cell = VmStackValue; - return cb.store_long_bool(3, 8) && cb.store_ref_bool(as_cell()); - case t_slice: { - // _ cell:^Cell st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits } - // st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice; - const auto& cs = *static_cast>(ref); - return ((mode & 0x1000) || cb.store_long_bool(4, 8)) // vm_stk_slice#04 _:VmCellSlice = VmStackValue; - && cb.store_ref_bool(cs.get_base_cell()) // _ cell:^Cell - && cb.store_long_bool(cs.cur_pos(), 10) // st_bits:(## 10) - && cb.store_long_bool(cs.cur_pos() + cs.size(), 10) // end_bits:(## 10) - && cb.store_long_bool(cs.cur_ref(), 3) // st_ref:(#<= 4) - && cb.store_long_bool(cs.cur_ref() + cs.size_refs(), 3); // end_ref:(#<= 4) - } - case t_builder: - // vm_stk_builder#05 cell:^Cell = VmStackValue; - return cb.store_long_bool(5, 8) && cb.store_ref_bool(as_builder()->finalize_copy()); - case t_vmcont: - // vm_stk_cont#06 cont:VmCont = VmStackValue; - return !(mode & 2) && cb.store_long_bool(6, 8) && as_cont()->serialize(cb); - case t_tuple: { - const auto& tuple = *static_cast>(ref); - auto n = tuple.size(); - // vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue; - Ref head, tail; - vm::CellBuilder cb2; - for (std::size_t i = 0; i < n; i++) { - std::swap(head, tail); - if (i > 1 && - !(cb2.store_ref_bool(std::move(tail)) && cb2.store_ref_bool(std::move(head)) && cb2.finalize_to(head))) { - return false; - } - if (!(tuple[i].serialize(cb2, mode) && cb2.finalize_to(tail))) { - return false; - } - } - return cb.store_long_bool(7, 8) && cb.store_long_bool(n, 16) && (head.is_null() || cb.store_ref_bool(head)) && - (tail.is_null() || cb.store_ref_bool(tail)); - } - default: - return false; - } -} - -bool StackEntry::deserialize(CellSlice& cs, int mode) { - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return false; - } - clear(); - int t = (mode & 0xf000) ? ((mode >> 12) & 15) : (int)cs.prefetch_ulong(8); - switch (t) { - case 0: - // vm_stk_null#00 = VmStackValue; - return cs.advance(8); - case 1: { - // vm_stk_tinyint#01 value:int64 = VmStackValue; - td::RefInt256 val; - return !(mode & 1) && cs.advance(8) && cs.fetch_int256_to(64, val) && set_int(std::move(val)); - } - case 2: { - t = (int)cs.prefetch_ulong(16) & 0x1ff; - if (t == 0xff) { - // vm_stk_nan#02ff = VmStackValue; - return cs.advance(16) && set_int(td::make_refint()); - } else { - // vm_stk_int#0201_ value:int257 = VmStackValue; - td::RefInt256 val; - return cs.fetch_ulong(15) == 0x0200 / 2 && cs.fetch_int256_to(257, val) && set_int(std::move(val)); - } - } - case 3: { - // vm_stk_cell#03 cell:^Cell = VmStackValue; - return cs.have_refs() && cs.advance(8) && set(t_cell, cs.fetch_ref()); - } - case 4: { - // _ cell:^Cell st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits } - // st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice; - // vm_stk_slice#04 _:VmCellSlice = VmStackValue; - unsigned st_bits, end_bits, st_ref, end_ref; - Ref cell; - Ref csr; - return ((mode & 0xf000) || cs.advance(8)) // vm_stk_slice#04 - && cs.fetch_ref_to(cell) // cell:^Cell - && cs.fetch_uint_to(10, st_bits) // st_bits:(## 10) - && cs.fetch_uint_to(10, end_bits) // end_bits:(## 10) - && st_bits <= end_bits // { st_bits <= end_bits } - && cs.fetch_uint_to(3, st_ref) // st_ref:(#<= 4) - && cs.fetch_uint_to(3, end_ref) // end_ref:(#<= 4) - && st_ref <= end_ref && end_ref <= 4 // { st_ref <= end_ref } - && (csr = load_cell_slice_ref(std::move(cell))).not_null() // load cell slice - && csr->have(end_bits, end_ref) && - csr.write().skip_last(csr->size() - end_bits, csr->size_refs() - end_ref) && - csr.write().skip_first(st_bits, st_ref) && set(t_slice, std::move(csr)); - } - case 5: { - // vm_stk_builder#05 cell:^Cell = VmStackValue; - Ref cell; - Ref csr; - Ref cb{true}; - return cs.advance(8) && cs.fetch_ref_to(cell) && (csr = load_cell_slice_ref(std::move(cell))).not_null() && - cb.write().append_cellslice_bool(std::move(csr)) && set(t_builder, std::move(cb)); - } - case 6: { - // vm_stk_cont#06 cont:VmCont = VmStackValue; - Ref cont; - return !(mode & 2) && cs.advance(8) && Continuation::deserialize_to(cs, cont, mode) && - set(t_vmcont, std::move(cont)); - } - case 7: { - // vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue; - int n; - if (!(cs.advance(8) && cs.fetch_uint_to(16, n))) { - return false; - } - Ref tuple{true, n}; - auto& t = tuple.write(); - if (n > 1) { - Ref head, tail; - n--; - if (!(cs.fetch_ref_to(head) && cs.fetch_ref_to(tail) && t[n].deserialize(std::move(tail), mode))) { - return false; - } - vm::CellSlice cs2; - while (--n > 0) { - if (!(cs2.load(std::move(head)) && cs2.fetch_ref_to(head) && cs2.fetch_ref_to(tail) && cs2.empty_ext() && - t[n].deserialize(std::move(tail), mode))) { - return false; - } - } - if (!t[0].deserialize(std::move(head), mode)) { - return false; - } - } else if (n == 1) { - return cs.have_refs() && t[0].deserialize(cs.fetch_ref(), mode) && set(t_tuple, std::move(tuple)); - } - return set(t_tuple, std::move(tuple)); - } - default: - return false; - } -} - -bool StackEntry::deserialize(Ref cell, int mode) { - if (cell.is_null()) { - clear(); - return false; - } - CellSlice cs = load_cell_slice(std::move(cell)); - return deserialize(cs, mode) && cs.empty_ext(); -} - -bool Stack::serialize(vm::CellBuilder& cb, int mode) const { - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return false; - } - // vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack; - unsigned n = depth(); - if (!cb.store_ulong_rchk_bool(n, 24)) { // vm_stack#_ depth:(## 24) - return false; - } - if (!n) { - return true; - } - vm::CellBuilder cb2; - Ref rest = cb2.finalize(); // vm_stk_nil#_ = VmStackList 0; - for (unsigned i = 0; i < n - 1; i++) { - // vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1); - if (!(cb2.store_ref_bool(std::move(rest)) && stack[i].serialize(cb2, mode) && cb2.finalize_to(rest))) { - return false; - } - } - return cb.store_ref_bool(std::move(rest)) && stack[n - 1].serialize(cb, mode); -} - -bool Stack::deserialize(vm::CellSlice& cs, int mode) { - auto* vsi = VmStateInterface::get(); - if (vsi && !vsi->register_op()) { - return false; - } - clear(); - // vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack; - int n; - if (!cs.fetch_uint_to(24, n)) { - return false; - } - if (!n) { - return true; - } - stack.resize(n); - Ref rest; - if (!(cs.fetch_ref_to(rest) && stack[n - 1].deserialize(cs, mode))) { - clear(); - return false; - } - for (int i = n - 2; i >= 0; --i) { - // vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1); - vm::CellSlice cs2 = load_cell_slice(std::move(rest)); - if (!(cs2.fetch_ref_to(rest) && stack[i].deserialize(cs2, mode) && cs2.empty_ext())) { - clear(); - return false; - } - } - if (!load_cell_slice(std::move(rest)).empty_ext()) { - clear(); - return false; - } - return true; -} - -bool Stack::deserialize_to(vm::CellSlice& cs, Ref& stack, int mode) { - stack = Ref{true}; - if (stack.unique_write().deserialize(cs, mode)) { - return true; - } else { - stack.clear(); - return false; - } -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/stack.hpp b/submodules/ton/tonlib-src/crypto/vm/stack.hpp deleted file mode 100644 index d67a9dbb..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/stack.hpp +++ /dev/null @@ -1,568 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "common/refcnt.hpp" -#include "common/bigint.hpp" -#include "common/refint.h" -#include "common/bitstring.h" -#include "vm/cells.h" -#include "vm/cellslice.h" -#include "vm/excno.hpp" - -#include "td/utils/Span.h" - -namespace td { -extern template class td::Cnt; -extern template class td::Ref>; -} // namespace td - -namespace vm { - -using td::Cnt; -using td::Ref; -using td::RefAny; - -const char* get_exception_msg(Excno exc_no); -std::string str_to_hex(std::string data, std::string prefix = ""); - -class StackEntry; -class Stack; -class Continuation; -class Box; -class Atom; - -using Tuple = td::Cnt>; - -template -Ref make_tuple_ref(Args&&... args) { - return td::make_cnt_ref>(std::vector{std::forward(args)...}); -} - -struct from_object_t {}; -constexpr from_object_t from_object{}; - -class StackEntry { - public: - enum Type { - t_null, - t_int, - t_cell, - t_builder, - t_slice, - t_vmcont, - t_tuple, - t_stack, - t_string, - t_bytes, - t_bitstring, - t_box, - t_atom, - t_object - }; - - private: - RefAny ref; - Type tp; - - public: - StackEntry() : ref(), tp(t_null) { - } - ~StackEntry() { - } - StackEntry(Ref cell_ref) : ref(std::move(cell_ref)), tp(t_cell) { - } - StackEntry(Ref cb_ref) : ref(std::move(cb_ref)), tp(t_builder) { - } - StackEntry(Ref cs_ref) : ref(std::move(cs_ref)), tp(t_slice) { - } - StackEntry(td::RefInt256 int_ref) : ref(std::move(int_ref)), tp(t_int) { - } - StackEntry(std::string str, bool bytes = false) : ref(), tp(bytes ? t_bytes : t_string) { - ref = Ref>{true, std::move(str)}; - } - StackEntry(Ref stack_ref); - StackEntry(Ref cont_ref); - StackEntry(Ref box_ref); - StackEntry(Ref tuple_ref); - StackEntry(const std::vector& tuple_components); - StackEntry(std::vector&& tuple_components); - StackEntry(Ref atom_ref); - StackEntry(const StackEntry& se) : ref(se.ref), tp(se.tp) { - } - StackEntry(StackEntry&& se) noexcept : ref(std::move(se.ref)), tp(se.tp) { - se.tp = t_null; - } - template - StackEntry(from_object_t, Ref obj_ref) : ref(std::move(obj_ref)), tp(t_object) { - } - StackEntry& operator=(const StackEntry& se) { - ref = se.ref; - tp = se.tp; - return *this; - } - StackEntry& operator=(StackEntry&& se) { - ref = std::move(se.ref); - tp = se.tp; - se.tp = t_null; - return *this; - } - StackEntry& clear() { - ref.clear(); - tp = t_null; - return *this; - } - bool set_int(td::RefInt256 value) { - return set(t_int, std::move(value)); - } - bool empty() const { - return tp == t_null; - } - bool is_tuple() const { - return tp == t_tuple; - } - bool is_atom() const { - return tp == t_atom; - } - bool is_int() const { - return tp == t_int; - } - bool is_cell() const { - return tp == t_cell; - } - bool is_null() const { - return tp == t_null; - } - bool is(int wanted) const { - return tp == wanted; - } - bool is_list() const { - return is_list(this); - } - static bool is_list(const StackEntry& se) { - return is_list(&se); - } - void swap(StackEntry& se) { - ref.swap(se.ref); - std::swap(tp, se.tp); - } - bool operator==(const StackEntry& other) const { - return tp == other.tp && ref == other.ref; - } - bool operator!=(const StackEntry& other) const { - return !(tp == other.tp && ref == other.ref); - } - Type type() const { - return tp; - } - // mode: +1 = disable short ints, +2 = disable continuations - bool serialize(vm::CellBuilder& cb, int mode = 0) const; - bool deserialize(vm::CellSlice& cs, int mode = 0); - bool deserialize(Ref cell, int mode = 0); - - private: - static bool is_list(const StackEntry* se); - template - Ref dynamic_as() const & { - return tp == tag ? static_cast>(ref) : td::Ref{}; - } - template - Ref dynamic_as() && { - return tp == tag ? static_cast>(std::move(ref)) : td::Ref{}; - } - template - Ref dynamic_move_as() & { - return tp == tag ? static_cast>(std::move(ref)) : td::Ref{}; - } - template - Ref as() const & { - return tp == tag ? Ref{td::static_cast_ref(), ref} : td::Ref{}; - } - template - Ref as() && { - return tp == tag ? Ref{td::static_cast_ref(), std::move(ref)} : td::Ref{}; - } - template - Ref move_as() & { - return tp == tag ? Ref{td::static_cast_ref(), std::move(ref)} : td::Ref{}; - } - bool set(Type _tp, RefAny _ref) { - tp = _tp; - ref = std::move(_ref); - return ref.not_null() || tp == t_null; - } - - public: - static StackEntry make_list(std::vector&& elems); - static StackEntry make_list(const std::vector& elems); - template - static StackEntry cons(T1&& x, T2&& y) { - return StackEntry{make_tuple_ref(std::forward(x), std::forward(y))}; - } - template - static StackEntry maybe(Ref ref) { - if (ref.is_null()) { - return {}; - } else { - return ref; - } - } - td::RefInt256 as_int() const & { - return as(); - } - td::RefInt256 as_int() && { - return move_as(); - } - Ref as_cell() const & { - return as(); - } - Ref as_cell() && { - return move_as(); - } - Ref as_builder() const & { - return as(); - } - Ref as_builder() && { - return move_as(); - } - Ref as_slice() const & { - return as(); - } - Ref as_slice() && { - return move_as(); - } - Ref as_cont() const &; - Ref as_cont() &&; - Ref> as_string_ref() const { - return as, t_string>(); - } - Ref> as_bytes_ref() const { - return as, t_bytes>(); - } - std::string as_string() const { - //assert(!as_string_ref().is_null()); - return tp == t_string ? *as_string_ref() : ""; - } - std::string as_bytes() const { - return tp == t_bytes ? *as_bytes_ref() : ""; - } - Ref as_box() const &; - Ref as_box() &&; - Ref as_tuple() const &; - Ref as_tuple() &&; - Ref as_tuple_range(unsigned max_len = 255, unsigned min_len = 0) const &; - Ref as_tuple_range(unsigned max_len = 255, unsigned min_len = 0) &&; - Ref as_atom() const &; - Ref as_atom() &&; - template - Ref as_object() const & { - return dynamic_as(); - } - template - Ref as_object() && { - return dynamic_move_as(); - } - bool for_each_scalar(const std::function& func) const; - void for_each_scalar(const std::function& func) const; - void dump(std::ostream& os) const; - void print_list(std::ostream& os) const; - std::string to_string() const; - std::string to_lisp_string() const; - - private: - static void print_list_tail(std::ostream& os, const StackEntry* se); -}; - -inline void swap(StackEntry& se1, StackEntry& se2) { - se1.swap(se2); -} - -const StackEntry& tuple_index(const Tuple& tup, unsigned idx); -StackEntry tuple_extend_index(const Ref& tup, unsigned idx); -unsigned tuple_extend_set_index(Ref& tup, unsigned idx, StackEntry&& value, bool force = false); - -class Stack : public td::CntObject { - std::vector stack; - - public: - Stack() { - } - ~Stack() override = default; - Stack(const std::vector& _stack) : stack(_stack) { - } - Stack(std::vector&& _stack) : stack(std::move(_stack)) { - } - Stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top); - Stack(Stack&& old_stack, unsigned copy_elem, unsigned skip_top); - td::CntObject* make_copy() const override { - std::cerr << "copy stack at " << (const void*)this << " (" << depth() << " entries)\n"; - return new Stack{stack}; - } - void push_from_stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top = 0); - void push_from_stack(Stack&& old_stack, unsigned copy_elem, unsigned skip_top = 0); - void move_from_stack(Stack& old_stack, unsigned copy_elem); - Ref split_top(unsigned top_cnt, unsigned drop_cnt = 0); - - StackEntry& push() { - stack.emplace_back(); - return stack.back(); - } - template - StackEntry& push(Args&&... args) { - stack.emplace_back(args...); - return stack.back(); - } - StackEntry& push(const StackEntry& se) { - stack.push_back(se); - return stack.back(); - } - StackEntry& push(StackEntry&& se) { - stack.emplace_back(std::move(se)); - return stack.back(); - } - void pop(StackEntry& se) { - stack.back().swap(se); - stack.pop_back(); - } - StackEntry pop() { - StackEntry res = std::move(stack.back()); - stack.pop_back(); - return res; - } - StackEntry pop_chk() { - check_underflow(1); - return pop(); - } - void pop_many(int count) { - stack.resize(stack.size() - count); - } - void pop_many(int count, int offs) { - std::move(stack.cend() - offs, stack.cend(), stack.end() - (count + offs)); - pop_many(count); - } - void drop_bottom(int count) { - std::move(stack.cbegin() + count, stack.cend(), stack.begin()); - pop_many(count); - } - StackEntry& operator[](int idx) { // NB: we sometimes use idx=-1 - return stack[stack.size() - idx - 1]; - } - const StackEntry& operator[](int idx) const { - return stack[stack.size() - idx - 1]; - } - StackEntry& at(int idx) { - return stack.at(stack.size() - idx - 1); - } - const StackEntry& at(int idx) const { - return stack.at(stack.size() - idx - 1); - } - StackEntry fetch(int idx) const { - return stack[stack.size() - idx - 1]; - } - StackEntry& tos() { - return stack.back(); - } - const StackEntry& tos() const { - return stack.back(); - } - bool is_empty() const { - return stack.empty(); - } - int depth() const { - return (int)stack.size(); - } - std::vector::iterator top() { - return stack.end(); - } - std::vector::const_iterator top() const { - return stack.cend(); - } - std::vector::iterator from_top(int offs) { - return stack.end() - offs; - } - std::vector::const_iterator from_top(int offs) const { - return stack.cend() - offs; - } - td::Span as_span() const { - return stack; - } - bool at_least(int req) const { - return depth() >= req; - } - template - bool at_least(int req, Args... args) const { - return at_least(req) && at_least(args...); - } - bool more_than(int req) const { - return depth() > req; - } - template - bool more_than(int req, Args... args) const { - return more_than(req) && more_than(args...); - } - void clear() { - stack.clear(); - } - Stack& set_contents(const Stack& other_stack) { - stack = other_stack.stack; - return *this; - } - Stack& set_contents(Stack&& other_stack) { - stack = std::move(other_stack.stack); - return *this; - } - Stack& set_contents(Ref ref) { - if (ref.is_null()) { - clear(); - } else if (ref->is_unique()) { - set_contents(std::move(ref.unique_write())); - } else { - set_contents(*ref); - } - return *this; - } - std::vector extract_contents() const & { - return stack; - } - std::vector extract_contents() && { - return std::move(stack); - } - template - const Stack& check_underflow(Args... args) const { - if (!at_least(args...)) { - throw VmError{Excno::stk_und}; - } - return *this; - } - template - Stack& check_underflow(Args... args) { - if (!at_least(args...)) { - throw VmError{Excno::stk_und}; - } - return *this; - } - template - const Stack& check_underflow_p(Args... args) const { - if (!more_than(args...)) { - throw VmError{Excno::stk_und}; - } - return *this; - } - template - Stack& check_underflow_p(Args... args) { - if (!more_than(args...)) { - throw VmError{Excno::stk_und}; - } - return *this; - } - Stack& reserve(int cnt) { - stack.reserve(cnt); - return *this; - } - void pop_null(); - td::RefInt256 pop_int(); - td::RefInt256 pop_int_finite(); - bool pop_bool(); - long long pop_long(); - long long pop_long_range(long long max, long long min = 0); - int pop_smallint_range(int max, int min = 0); - Ref pop_cell(); - Ref pop_maybe_cell(); - Ref pop_builder(); - Ref pop_cellslice(); - Ref pop_cont(); - Ref pop_box(); - Ref pop_tuple(); - Ref pop_tuple_range(unsigned max_len = 255, unsigned min_len = 0); - Ref pop_maybe_tuple(); - Ref pop_maybe_tuple_range(unsigned max_len = 255); - Ref pop_atom(); - std::string pop_string(); - std::string pop_bytes(); - template - Ref pop_object() { - return pop_chk().as_object(); - } - template - Ref pop_object_type_chk() { - auto res = pop_object(); - if (!res) { - throw VmError{Excno::type_chk, "not an object of required type"}; - } - return res; - } - void push_null(); - void push_int(td::RefInt256 val); - void push_int_quiet(td::RefInt256 val, bool quiet = true); - void push_smallint(long long val); - void push_bool(bool val); - void push_string(std::string str); - void push_string(td::Slice slice); - void push_bytes(std::string str); - void push_bytes(td::Slice slice); - void push_cell(Ref cell); - void push_maybe_cell(Ref cell); - void push_maybe_cellslice(Ref cs); - void push_builder(Ref cb); - void push_cellslice(Ref cs); - void push_cont(Ref cont); - void push_box(Ref box); - void push_tuple(Ref tuple); - void push_tuple(const std::vector& components); - void push_tuple(std::vector&& components); - void push_maybe_tuple(Ref tuple); - void push_atom(Ref atom); - template - void push_object(Ref obj) { - push({vm::from_object, std::move(obj)}); - } - template - void push_make_object(Args&&... args) { - push_object(td::make_ref(std::forward(args)...)); - } - template - void push_maybe(Ref val) { - if (val.is_null()) { - push({}); - } else { - push(std::move(val)); - } - } - bool for_each_scalar(const std::function& func) const; - void for_each_scalar(const std::function& func) const; - // mode: +1 = add eoln, +2 = Lisp-style lists - void dump(std::ostream& os, int mode = 1) const; - bool serialize(vm::CellBuilder& cb, int mode = 0) const; - bool deserialize(vm::CellSlice& cs, int mode = 0); - static bool deserialize_to(vm::CellSlice& cs, Ref& stack, int mode = 0); -}; - -} // namespace vm - -namespace td { -extern template class td::Cnt>; -extern template class td::Ref>>; -} // namespace td diff --git a/submodules/ton/tonlib-src/crypto/vm/stackops.cpp b/submodules/ton/tonlib-src/crypto/vm/stackops.cpp deleted file mode 100644 index 0f5be6d4..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/stackops.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/log.h" -#include "vm/stackops.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" - -namespace vm { - -int exec_nop(VmState* st) { - VM_LOG(st) << "execute NOP\n"; - return 0; -} - -// basic stack manipulation primitives - -int exec_swap(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute SWAP\n"; - stack.check_underflow(2); - swap(stack[0], stack[1]); - return 0; -} - -int exec_xchg0(VmState* st, unsigned args) { - int x = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHG s" << x; - stack.check_underflow_p(x); - swap(stack[0], stack[x]); - return 0; -} - -int exec_xchg0_l(VmState* st, unsigned args) { - int x = args & 255; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHG s" << x; - stack.check_underflow_p(x); - swap(stack[0], stack[x]); - return 0; -} - -int exec_xchg(VmState* st, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - if (!x || x >= y) { - throw VmError{Excno::inv_opcode, "invalid XCHG arguments"}; - } - VM_LOG(st) << "execute XCHG s" << x << ",s" << y; - Stack& stack = st->get_stack(); - stack.check_underflow_p(y); - swap(stack[x], stack[y]); - return 0; -} - -std::string dump_xchg(CellSlice&, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - if (!x || x >= y) { - return ""; - } - std::ostringstream os{"XCHG s"}; - os << x << ",s" << y; - return os.str(); -} - -int exec_xchg1(VmState* st, unsigned args) { - int x = args & 15; - assert(x >= 2); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHG s1,s" << x; - stack.check_underflow_p(x); - swap(stack[1], stack[x]); - return 0; -} - -int exec_dup(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DUP\n"; - stack.check_underflow(1); - stack.push(stack.fetch(0)); - return 0; -} - -int exec_over(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute OVER\n"; - stack.check_underflow(2); - stack.push(stack.fetch(1)); - return 0; -} - -int exec_push(VmState* st, unsigned args) { - int x = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSH s" << x; - stack.check_underflow_p(x); - stack.push(stack.fetch(x)); - return 0; -} - -int exec_push_l(VmState* st, unsigned args) { - int x = args & 255; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSH s" << x; - stack.check_underflow_p(x); - stack.push(stack.fetch(x)); - return 0; -} - -int exec_drop(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DROP\n"; - stack.check_underflow(1); - stack.pop(); - return 0; -} - -int exec_nip(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NIP\n"; - stack.check_underflow(2); - stack.pop(stack[1]); - return 0; -} - -int exec_pop(VmState* st, unsigned args) { - int x = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute POP s" << x; - stack.check_underflow_p(x); - stack.pop(stack[x]); - return 0; -} - -int exec_pop_l(VmState* st, unsigned args) { - int x = args & 255; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute POP s" << x; - stack.check_underflow_p(x); - stack.pop(stack[x]); - return 0; -} - -// compound stack manipulation primitives - -int exec_xchg2(VmState* st, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHG2 s" << x << ",s" << y; - stack.check_underflow_p(x, y, 1); - swap(stack[1], stack[x]); - swap(stack[0], stack[y]); - return 0; -} - -int exec_xcpu(VmState* st, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCPU s" << x << ",s" << y; - stack.check_underflow_p(x, y); - swap(stack[0], stack[x]); - stack.push(stack.fetch(y)); - return 0; -} - -int exec_puxc(VmState* st, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUXC s" << x << ",s" << y - 1; - stack.check_underflow_p(x).check_underflow(y); - stack.push(stack.fetch(x)); - swap(stack[0], stack[1]); - swap(stack[0], stack[y]); - return 0; -} - -int exec_push2(VmState* st, unsigned args) { - int x = (args >> 4) & 15, y = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSH2 s" << x << ",s" << y; - stack.check_underflow_p(x, y); - stack.push(stack.fetch(x)); - stack.push(stack.fetch(y + 1)); - return 0; -} - -int exec_xchg3(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHG3 s" << x << ",s" << y << ",s" << z; - stack.check_underflow_p(x, y, z, 2); - swap(stack[2], stack[x]); - swap(stack[1], stack[y]); - swap(stack[0], stack[z]); - return 0; -} - -int exec_xc2pu(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XC2PU s" << x << ",s" << y << ",s" << z; - stack.check_underflow_p(x, y, z, 1); - swap(stack[1], stack[x]); - swap(stack[0], stack[y]); - stack.push(stack.fetch(z)); - return 0; -} - -int exec_xcpuxc(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCPUXC s" << x << ",s" << y << ",s" << z - 1; - stack.check_underflow_p(x, y, 1).check_underflow(z); - swap(stack[1], stack[x]); - stack.push(stack.fetch(y)); - swap(stack[0], stack[1]); - swap(stack[0], stack[z]); - return 0; -} - -int exec_xcpu2(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCPU2 s" << x << ",s" << y << ",s" << z; - stack.check_underflow_p(x, y, z); - swap(stack[0], stack[x]); - stack.push(stack.fetch(y)); - stack.push(stack.fetch(z + 1)); - return 0; -} - -int exec_puxc2(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUXC2 s" << x << ",s" << y - 1 << ",s" << z - 1; - stack.check_underflow_p(x, 1).check_underflow(y, z); - stack.push(stack.fetch(x)); - swap(stack[2], stack[0]); - swap(stack[1], stack[y]); - swap(stack[0], stack[z]); - return 0; -} - -int exec_puxcpu(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUXCPU s" << x << ",s" << y - 1 << ",s" << z - 1; - stack.check_underflow_p(x).check_underflow(y, z); - stack.push(stack.fetch(x)); - swap(stack[0], stack[1]); - swap(stack[0], stack[y]); - stack.push(stack.fetch(z)); - return 0; -} - -int exec_pu2xc(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PU2XC s" << x << ",s" << y - 1 << ",s" << z - 2; - stack.check_underflow_p(x).check_underflow(y, z - 1); - stack.push(stack.fetch(x)); - swap(stack[1], stack[0]); - stack.push(stack.fetch(y)); - swap(stack[1], stack[0]); - swap(stack[0], stack[z]); - return 0; -} - -int exec_push3(VmState* st, unsigned args) { - int x = (args >> 8) & 15, y = (args >> 4) & 15, z = args & 15; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PUSH3 s" << x << ",s" << y << ",s" << z; - stack.check_underflow_p(x, y, z); - stack.push(stack.fetch(x)); - stack.push(stack.fetch(y + 1)); - stack.push(stack.fetch(z + 2)); - return 0; -} - -// exotic stack manipulation primitives - -int exec_blkswap(VmState* st, unsigned args) { - int x = ((args >> 4) & 15) + 1, y = (args & 15) + 1; - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLKSWAP " << x << ',' << y; - stack.check_underflow(x + y); - std::reverse(stack.from_top(x + y), stack.from_top(y)); - std::reverse(stack.from_top(y), stack.top()); - std::reverse(stack.from_top(x + y), stack.top()); - return 0; -} - -int exec_rot(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ROT\n"; - stack.check_underflow(3); - swap(stack[1], stack[2]); - swap(stack[0], stack[1]); - return 0; -} - -int exec_rotrev(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ROTREV\n"; - stack.check_underflow(3); - swap(stack[0], stack[1]); - swap(stack[1], stack[2]); - return 0; -} - -int exec_2swap(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute 2SWAP\n"; - stack.check_underflow(4); - swap(stack[1], stack[3]); - swap(stack[0], stack[2]); - return 0; -} - -int exec_2drop(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute 2DROP\n"; - stack.check_underflow(2); - stack.pop(); - stack.pop(); - return 0; -} - -int exec_2dup(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute 2DUP\n"; - stack.check_underflow(2); - stack.push(stack.fetch(1)); - stack.push(stack.fetch(1)); - return 0; -} - -int exec_2over(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute 2OVER\n"; - stack.check_underflow(4); - stack.push(stack.fetch(3)); - stack.push(stack.fetch(3)); - return 0; -} - -int exec_reverse(VmState* st, unsigned args) { - int x = ((args >> 4) & 15) + 2, y = (args & 15); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute REVERSE " << x << ',' << y; - stack.check_underflow(x + y); - std::reverse(stack.from_top(x + y), stack.from_top(y)); - return 0; -} - -int exec_blkdrop(VmState* st, unsigned args) { - int x = (args & 15); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLKDROP " << x; - stack.check_underflow(x); - stack.pop_many(x); - return 0; -} - -int exec_blkdrop2(VmState* st, unsigned args) { - int x = ((args >> 4) & 15), y = (args & 15); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLKDROP2 " << x << ',' << y; - stack.check_underflow(x + y); - stack.pop_many(x, y); - return 0; -} - -int exec_blkpush(VmState* st, unsigned args) { - int x = ((args >> 4) & 15), y = (args & 15); - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLKPUSH " << x << ',' << y; - stack.check_underflow_p(y); - while (--x >= 0) { - stack.push(stack.fetch(y)); - } - return 0; -} - -int exec_pick(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute PICK\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow_p(x); - stack.push(stack.fetch(x)); - return 0; -} - -int exec_roll(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ROLL\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow_p(x); - while (--x >= 0) { - swap(stack[x], stack[x + 1]); - } - return 0; -} - -int exec_rollrev(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ROLLREV\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow_p(x); - for (int i = 0; i < x; i++) { - swap(stack[i], stack[i + 1]); - } - return 0; -} - -int exec_blkswap_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute BLKSWX\n"; - stack.check_underflow(2); - int y = stack.pop_smallint_range(255); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x + y); - if (x > 0 && y > 0) { - std::reverse(stack.from_top(x + y), stack.from_top(y)); - std::reverse(stack.from_top(y), stack.top()); - std::reverse(stack.from_top(x + y), stack.top()); - } - return 0; -} - -int exec_reverse_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute REVX\n"; - stack.check_underflow(2); - int y = stack.pop_smallint_range(255); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x + y); - std::reverse(stack.from_top(x + y), stack.from_top(y)); - return 0; -} - -int exec_drop_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DROPX\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x); - stack.pop_many(x); - return 0; -} - -int exec_tuck(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute TUCK\n"; - stack.check_underflow(2); - swap(stack[0], stack[1]); - stack.push(stack.fetch(1)); - return 0; -} - -int exec_xchg_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute XCHGX\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow_p(x); - swap(stack[0], stack[x]); - return 0; -} - -int exec_depth(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute DEPTH\n"; - stack.push_smallint(stack.depth()); - return 0; -} - -int exec_chkdepth(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute CHKDEPTH\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x); - return 0; -} - -int exec_onlytop_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ONLYTOPX\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x); - int n = stack.depth(), d = n - x; - if (d > 0) { - for (int i = n - 1; i >= d; i--) { - stack[i] = std::move(stack[i - d]); - } - } - stack.pop_many(d); - return 0; -} - -int exec_only_x(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ONLYX\n"; - stack.check_underflow(1); - int x = stack.pop_smallint_range(255); - stack.check_underflow(x); - stack.pop_many(stack.depth() - x); - return 0; -} - -void register_stack_ops(OpcodeTable& cp0) { - cp0.insert(OpcodeInstr::mksimple(0x00, 8, "NOP", exec_nop)) - .insert(OpcodeInstr::mksimple(0x01, 8, "SWAP", exec_swap)) - .insert(OpcodeInstr::mkfixedrange(0x02, 0x10, 8, 4, instr::dump_1sr("XCHG "), exec_xchg0)) - .insert(OpcodeInstr::mkfixed(0x10, 8, 8, dump_xchg, exec_xchg)) - .insert(OpcodeInstr::mkfixed(0x11, 8, 8, instr::dump_1sr_l("XCHG "), exec_xchg0_l)) - .insert(OpcodeInstr::mkfixedrange(0x12, 0x20, 8, 4, instr::dump_1sr("XCHG s1,"), exec_xchg1)) - .insert(OpcodeInstr::mksimple(0x20, 8, "DUP", exec_dup)) - .insert(OpcodeInstr::mksimple(0x21, 8, "OVER", exec_over)) - .insert(OpcodeInstr::mkfixedrange(0x22, 0x30, 8, 4, instr::dump_1sr("PUSH "), exec_push)) - .insert(OpcodeInstr::mksimple(0x30, 8, "DROP", exec_drop)) - .insert(OpcodeInstr::mksimple(0x31, 8, "NIP", exec_nip)) - .insert(OpcodeInstr::mkfixedrange(0x32, 0x40, 8, 4, instr::dump_1sr("POP "), exec_pop)) - .insert(OpcodeInstr::mkfixed(0x4, 4, 12, instr::dump_3sr("XCHG3 "), exec_xchg3)) - .insert(OpcodeInstr::mkfixed(0x50, 8, 8, instr::dump_2sr("XCHG2 "), exec_xchg2)) - .insert(OpcodeInstr::mkfixed(0x51, 8, 8, instr::dump_2sr("XCPU "), exec_xcpu)) - .insert(OpcodeInstr::mkfixed(0x52, 8, 8, instr::dump_2sr_adj(1, "PUXC "), exec_puxc)) - .insert(OpcodeInstr::mkfixed(0x53, 8, 8, instr::dump_2sr("PUSH2 "), exec_push2)) - .insert(OpcodeInstr::mkfixed(0x540, 12, 12, instr::dump_3sr("XCHG3 "), exec_xchg3)) - .insert(OpcodeInstr::mkfixed(0x541, 12, 12, instr::dump_3sr("XC2PU "), exec_xc2pu)) - .insert(OpcodeInstr::mkfixed(0x542, 12, 12, instr::dump_3sr_adj(1, "XCPUXC "), exec_xcpuxc)) - .insert(OpcodeInstr::mkfixed(0x543, 12, 12, instr::dump_3sr("XCPU2 "), exec_xcpu2)) - .insert(OpcodeInstr::mkfixed(0x544, 12, 12, instr::dump_3sr_adj(0x11, "PUXC2 "), exec_puxc2)) - .insert(OpcodeInstr::mkfixed(0x545, 12, 12, instr::dump_3sr_adj(0x11, "PUXCPU "), exec_puxcpu)) - .insert(OpcodeInstr::mkfixed(0x546, 12, 12, instr::dump_3sr_adj(0x12, "PU2XC "), exec_pu2xc)) - .insert(OpcodeInstr::mkfixed(0x547, 12, 12, instr::dump_3sr("PUSH3 "), exec_push3)) - .insert(OpcodeInstr::mkfixed(0x55, 8, 8, instr::dump_2c_add(0x11, "BLKSWAP ", ","), exec_blkswap)) - .insert(OpcodeInstr::mkfixed(0x56, 8, 8, instr::dump_1sr_l("PUSH "), exec_push_l)) - .insert(OpcodeInstr::mkfixed(0x57, 8, 8, instr::dump_1sr_l("POP "), exec_pop_l)) - .insert(OpcodeInstr::mksimple(0x58, 8, "ROT", exec_rot)) - .insert(OpcodeInstr::mksimple(0x59, 8, "ROTREV", exec_rotrev)) - .insert(OpcodeInstr::mksimple(0x5a, 8, "2SWAP", exec_2swap)) - .insert(OpcodeInstr::mksimple(0x5b, 8, "2DROP", exec_2drop)) - .insert(OpcodeInstr::mksimple(0x5c, 8, "2DUP", exec_2dup)) - .insert(OpcodeInstr::mksimple(0x5d, 8, "2OVER", exec_2over)) - .insert(OpcodeInstr::mkfixed(0x5e, 8, 8, instr::dump_2c_add(0x20, "REVERSE ", ","), exec_reverse)) - .insert(OpcodeInstr::mkfixed(0x5f0, 12, 4, instr::dump_1c("BLKDROP "), exec_blkdrop)) - .insert(OpcodeInstr::mkfixedrange(0x5f10, 0x6000, 16, 8, instr::dump_2c("BLKPUSH ", ","), exec_blkpush)) - .insert(OpcodeInstr::mksimple(0x60, 8, "PICK", exec_pick)) - .insert(OpcodeInstr::mksimple(0x61, 8, "ROLL", exec_roll)) - .insert(OpcodeInstr::mksimple(0x62, 8, "ROLLREV", exec_rollrev)) - .insert(OpcodeInstr::mksimple(0x63, 8, "BLKSWX", exec_blkswap_x)) - .insert(OpcodeInstr::mksimple(0x64, 8, "REVX", exec_reverse_x)) - .insert(OpcodeInstr::mksimple(0x65, 8, "DROPX", exec_drop_x)) - .insert(OpcodeInstr::mksimple(0x66, 8, "TUCK", exec_tuck)) - .insert(OpcodeInstr::mksimple(0x67, 8, "XCHGX", exec_xchg_x)) - .insert(OpcodeInstr::mksimple(0x68, 8, "DEPTH", exec_depth)) - .insert(OpcodeInstr::mksimple(0x69, 8, "CHKDEPTH", exec_chkdepth)) - .insert(OpcodeInstr::mksimple(0x6a, 8, "ONLYTOPX", exec_onlytop_x)) - .insert(OpcodeInstr::mksimple(0x6b, 8, "ONLYX", exec_only_x)) - .insert(OpcodeInstr::mkfixedrange(0x6c10, 0x6d00, 16, 8, instr::dump_2c("BLKDROP2 ", ","), exec_blkdrop2)); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/stackops.h b/submodules/ton/tonlib-src/crypto/vm/stackops.h deleted file mode 100644 index 27921a55..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/stackops.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_stack_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/tonops.cpp b/submodules/ton/tonlib-src/crypto/vm/tonops.cpp deleted file mode 100644 index 6a4cceaa..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/tonops.cpp +++ /dev/null @@ -1,869 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include "vm/tonops.h" -#include "vm/log.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" -#include "vm/dict.h" -#include "vm/boc.h" -#include "Ed25519.h" - -#include "openssl/digest.hpp" - -namespace vm { - -namespace { - -bool debug(const char* str) TD_UNUSED; -bool debug(const char* str) { - std::cerr << str; - return true; -} - -bool debug(int x) TD_UNUSED; -bool debug(int x) { - if (x < 100) { - std::cerr << '[' << (char)(64 + x) << ']'; - } else { - std::cerr << '[' << (char)(64 + x / 100) << x % 100 << ']'; - } - return true; -} -} // namespace - -#define DBG_START int dbg = 0; -#define DBG debug(++dbg)&& -#define DEB_START DBG_START -#define DEB DBG - -int exec_set_gas_generic(VmState* st, long long new_gas_limit) { - if (new_gas_limit < st->gas_consumed()) { - throw VmNoGas{}; - } - st->change_gas_limit(new_gas_limit); - return 0; -} - -int exec_accept(VmState* st) { - VM_LOG(st) << "execute ACCEPT"; - return exec_set_gas_generic(st, GasLimits::infty); -} - -int exec_set_gas_limit(VmState* st) { - VM_LOG(st) << "execute SETGASLIMIT"; - td::RefInt256 x = st->get_stack().pop_int_finite(); - long long gas = 0; - if (x->sgn() > 0) { - gas = x->unsigned_fits_bits(63) ? x->to_long() : GasLimits::infty; - } - return exec_set_gas_generic(st, gas); -} - -int exec_commit(VmState* st) { - VM_LOG(st) << "execute COMMIT"; - st->force_commit(); - return 0; -} - -void register_basic_gas_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xf800, 16, "ACCEPT", exec_accept)) - .insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit)) - .insert(OpcodeInstr::mksimple(0xf80f, 16, "COMMIT", exec_commit)); -} - -void register_ton_gas_ops(OpcodeTable& cp0) { - using namespace std::placeholders; -} - -int exec_get_param(VmState* st, unsigned idx, const char* name) { - if (name) { - VM_LOG(st) << "execute " << name; - } - Stack& stack = st->get_stack(); - auto tuple = st->get_c7(); - auto t1 = tuple_index(*tuple, 0).as_tuple_range(255); - if (t1.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - stack.push(tuple_index(*t1, idx)); - return 0; -} - -int exec_get_var_param(VmState* st, unsigned idx) { - idx &= 15; - VM_LOG(st) << "execute GETPARAM " << idx; - return exec_get_param(st, idx, nullptr); -} - -int exec_get_config_dict(VmState* st) { - exec_get_param(st, 9, "CONFIGDICT"); - st->get_stack().push_smallint(32); - return 0; -} - -int exec_get_config_param(VmState* st, bool opt) { - VM_LOG(st) << "execute CONFIG" << (opt ? "OPTPARAM" : "PARAM"); - Stack& stack = st->get_stack(); - auto idx = stack.pop_int(); - exec_get_param(st, 9, nullptr); - Dictionary dict{stack.pop_maybe_cell(), 32}; - td::BitArray<32> key; - Ref value; - if (idx->export_bits(key.bits(), key.size(), true)) { - value = dict.lookup_ref(key); - } - if (opt) { - stack.push_maybe_cell(std::move(value)); - } else if (value.not_null()) { - stack.push_cell(std::move(value)); - stack.push_bool(true); - } else { - stack.push_bool(false); - } - return 0; -} - -int exec_get_global_common(VmState* st, unsigned n) { - st->get_stack().push(tuple_extend_index(st->get_c7(), n)); - return 0; -} - -int exec_get_global(VmState* st, unsigned args) { - args &= 31; - VM_LOG(st) << "execute GETGLOB " << args; - return exec_get_global_common(st, args); -} - -int exec_get_global_var(VmState* st) { - VM_LOG(st) << "execute GETGLOBVAR"; - st->check_underflow(1); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_get_global_common(st, args); -} - -int exec_set_global_common(VmState* st, unsigned idx) { - Stack& stack = st->get_stack(); - auto x = stack.pop(); - auto tuple = st->get_c7(); - if (idx >= 255) { - throw VmError{Excno::range_chk, "tuple index out of range"}; - } - static auto empty_tuple = Ref{true}; - st->set_c7(empty_tuple); // optimization; use only if no exception can be thrown until true set_c7() - auto tpay = tuple_extend_set_index(tuple, idx, std::move(x)); - if (tpay > 0) { - st->consume_tuple_gas(tpay); - } - st->set_c7(std::move(tuple)); - return 0; -} - -int exec_set_global(VmState* st, unsigned args) { - args &= 31; - VM_LOG(st) << "execute SETGLOB " << args; - st->check_underflow(1); - return exec_set_global_common(st, args); -} - -int exec_set_global_var(VmState* st) { - VM_LOG(st) << "execute SETGLOBVAR"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_set_global_common(st, args); -} - -void register_ton_config_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mkfixedrange(0xf820, 0xf823, 16, 4, instr::dump_1c("GETPARAM "), exec_get_var_param)) - .insert(OpcodeInstr::mksimple(0xf823, 16, "NOW", std::bind(exec_get_param, _1, 3, "NOW"))) - .insert(OpcodeInstr::mksimple(0xf824, 16, "BLOCKLT", std::bind(exec_get_param, _1, 4, "BLOCKLT"))) - .insert(OpcodeInstr::mksimple(0xf825, 16, "LTIME", std::bind(exec_get_param, _1, 5, "LTIME"))) - .insert(OpcodeInstr::mksimple(0xf826, 16, "RANDSEED", std::bind(exec_get_param, _1, 6, "RANDSEED"))) - .insert(OpcodeInstr::mksimple(0xf827, 16, "BALANCE", std::bind(exec_get_param, _1, 7, "BALANCE"))) - .insert(OpcodeInstr::mksimple(0xf828, 16, "MYADDR", std::bind(exec_get_param, _1, 8, "MYADDR"))) - .insert(OpcodeInstr::mksimple(0xf829, 16, "CONFIGROOT", std::bind(exec_get_param, _1, 9, "CONFIGROOT"))) - .insert(OpcodeInstr::mkfixedrange(0xf82a, 0xf830, 16, 4, instr::dump_1c("GETPARAM "), exec_get_var_param)) - .insert(OpcodeInstr::mksimple(0xf830, 16, "CONFIGDICT", exec_get_config_dict)) - .insert(OpcodeInstr::mksimple(0xf832, 16, "CONFIGPARAM", std::bind(exec_get_config_param, _1, false))) - .insert(OpcodeInstr::mksimple(0xf833, 16, "CONFIGOPTPARAM", std::bind(exec_get_config_param, _1, true))) - .insert(OpcodeInstr::mksimple(0xf840, 16, "GETGLOBVAR", exec_get_global_var)) - .insert(OpcodeInstr::mkfixedrange(0xf841, 0xf860, 16, 5, instr::dump_1c_and(31, "GETGLOB "), exec_get_global)) - .insert(OpcodeInstr::mksimple(0xf860, 16, "SETGLOBVAR", exec_set_global_var)) - .insert(OpcodeInstr::mkfixedrange(0xf861, 0xf880, 16, 5, instr::dump_1c_and(31, "SETGLOB "), exec_set_global)); -} - -static constexpr int randseed_idx = 6; - -td::RefInt256 generate_randu256(VmState* st) { - auto tuple = st->get_c7(); - auto t1 = tuple_index(*tuple, 0).as_tuple_range(255); - if (t1.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - auto seedv = tuple_index(*t1, randseed_idx).as_int(); - if (seedv.is_null()) { - throw VmError{Excno::type_chk, "random seed is not an integer"}; - } - unsigned char seed[32]; - if (!seedv->export_bytes(seed, 32, false)) { - throw VmError{Excno::range_chk, "random seed out of range"}; - } - unsigned char hash[64]; - digest::hash_str(hash, seed, 32); - if (!seedv.write().import_bytes(hash, 32, false)) { - throw VmError{Excno::range_chk, "cannot store new random seed"}; - } - td::RefInt256 res{true}; - if (!res.write().import_bytes(hash + 32, 32, false)) { - throw VmError{Excno::range_chk, "cannot store new random number"}; - } - static auto empty_tuple = Ref{true}; - st->set_c7(empty_tuple); // optimization; use only if no exception can be thrown until true set_c7() - tuple.write()[0].clear(); - t1.write().at(randseed_idx) = std::move(seedv); - st->consume_tuple_gas(t1); - tuple.write().at(0) = std::move(t1); - st->consume_tuple_gas(tuple); - st->set_c7(std::move(tuple)); - return res; -} - -int exec_randu256(VmState* st) { - VM_LOG(st) << "execute RANDU256"; - st->get_stack().push_int(generate_randu256(st)); - return 0; -} - -int exec_rand_int(VmState* st) { - VM_LOG(st) << "execute RAND"; - auto& stack = st->get_stack(); - stack.check_underflow(1); - auto x = stack.pop_int_finite(); - auto y = generate_randu256(st); - typename td::BigInt256::DoubleInt tmp{0}; - tmp.add_mul(*x, *y); - tmp.rshift(256, -1).normalize(); - stack.push_int(td::make_refint(tmp)); - return 0; -} - -int exec_set_rand(VmState* st, bool mix) { - VM_LOG(st) << "execute " << (mix ? "ADDRAND" : "SETRAND"); - auto& stack = st->get_stack(); - stack.check_underflow(1); - auto x = stack.pop_int_finite(); - if (!x->unsigned_fits_bits(256)) { - throw VmError{Excno::range_chk, "new random seed out of range"}; - } - auto tuple = st->get_c7(); - auto t1 = tuple_index(*tuple, 0).as_tuple_range(255); - if (t1.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - if (mix) { - auto seedv = tuple_index(*t1, randseed_idx).as_int(); - if (seedv.is_null()) { - throw VmError{Excno::type_chk, "random seed is not an integer"}; - } - unsigned char buffer[64], hash[32]; - if (!std::move(seedv)->export_bytes(buffer, 32, false)) { - throw VmError{Excno::range_chk, "random seed out of range"}; - } - if (!x->export_bytes(buffer + 32, 32, false)) { - throw VmError{Excno::range_chk, "mixed seed value out of range"}; - } - digest::hash_str(hash, buffer, 64); - if (!x.write().import_bytes(hash, 32, false)) { - throw VmError{Excno::range_chk, "new random seed value out of range"}; - } - } - static auto empty_tuple = Ref{true}; - st->set_c7(empty_tuple); // optimization; use only if no exception can be thrown until true set_c7() - tuple.write()[0].clear(); - auto tpay = tuple_extend_set_index(t1, randseed_idx, std::move(x)); - if (tpay > 0) { - st->consume_tuple_gas(tpay); - } - tuple.unique_write()[0] = std::move(t1); - st->consume_tuple_gas(tuple); - st->set_c7(std::move(tuple)); - return 0; -} - -void register_prng_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xf810, 16, "RANDU256", exec_randu256)) - .insert(OpcodeInstr::mksimple(0xf811, 16, "RAND", exec_rand_int)) - .insert(OpcodeInstr::mksimple(0xf814, 16, "SETRAND", std::bind(exec_set_rand, _1, false))) - .insert(OpcodeInstr::mksimple(0xf815, 16, "ADDRAND", std::bind(exec_set_rand, _1, true))); -} - -int exec_compute_hash(VmState* st, int mode) { - VM_LOG(st) << "execute HASH" << (mode & 1 ? 'S' : 'C') << 'U'; - Stack& stack = st->get_stack(); - std::array hash; - if (!(mode & 1)) { - auto cell = stack.pop_cell(); - hash = cell->get_hash().as_array(); - } else { - auto cs = stack.pop_cellslice(); - vm::CellBuilder cb; - CHECK(cb.append_cellslice_bool(std::move(cs))); - // TODO: use cb.get_hash() instead - hash = cb.finalize()->get_hash().as_array(); - } - td::RefInt256 res{true}; - CHECK(res.write().import_bytes(hash.data(), hash.size(), false)); - stack.push_int(std::move(res)); - return 0; -} - -int exec_compute_sha256(VmState* st) { - VM_LOG(st) << "execute SHA256U"; - Stack& stack = st->get_stack(); - auto cs = stack.pop_cellslice(); - if (cs->size() & 7) { - throw VmError{Excno::cell_und, "Slice does not consist of an integer number of bytes"}; - } - auto len = (cs->size() >> 3); - unsigned char data[128], hash[32]; - CHECK(len <= sizeof(data)); - CHECK(cs->prefetch_bytes(data, len)); - digest::hash_str(hash, data, len); - td::RefInt256 res{true}; - CHECK(res.write().import_bytes(hash, 32, false)); - stack.push_int(std::move(res)); - return 0; -} - -int exec_ed25519_check_signature(VmState* st, bool from_slice) { - VM_LOG(st) << "execute CHKSIGN" << (from_slice ? 'S' : 'U'); - Stack& stack = st->get_stack(); - stack.check_underflow(3); - auto key_int = stack.pop_int(); - auto signature_cs = stack.pop_cellslice(); - unsigned char data[128], key[32], signature[64]; - unsigned data_len; - if (from_slice) { - auto cs = stack.pop_cellslice(); - if (cs->size() & 7) { - throw VmError{Excno::cell_und, "Slice does not consist of an integer number of bytes"}; - } - data_len = (cs->size() >> 3); - CHECK(data_len <= sizeof(data)); - CHECK(cs->prefetch_bytes(data, data_len)); - } else { - auto hash_int = stack.pop_int(); - data_len = 32; - if (!hash_int->export_bytes(data, data_len, false)) { - throw VmError{Excno::range_chk, "data hash must fit in an unsigned 256-bit integer"}; - } - } - if (!signature_cs->prefetch_bytes(signature, 64)) { - throw VmError{Excno::cell_und, "Ed25519 signature must contain at least 512 data bits"}; - } - if (!key_int->export_bytes(key, 32, false)) { - throw VmError{Excno::range_chk, "Ed25519 public key must fit in an unsigned 256-bit integer"}; - } - td::Ed25519::PublicKey pub_key{td::SecureString(td::Slice{key, 32})}; - auto res = pub_key.verify_signature(td::Slice{data, data_len}, td::Slice{signature, 64}); - stack.push_bool(res.is_ok() || st->get_chksig_always_succeed()); - return 0; -} - -void register_ton_crypto_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xf900, 16, "HASHCU", std::bind(exec_compute_hash, _1, 0))) - .insert(OpcodeInstr::mksimple(0xf901, 16, "HASHSU", std::bind(exec_compute_hash, _1, 1))) - .insert(OpcodeInstr::mksimple(0xf902, 16, "SHA256U", exec_compute_sha256)) - .insert(OpcodeInstr::mksimple(0xf910, 16, "CHKSIGNU", std::bind(exec_ed25519_check_signature, _1, false))) - .insert(OpcodeInstr::mksimple(0xf911, 16, "CHKSIGNS", std::bind(exec_ed25519_check_signature, _1, true))); -} - -int exec_compute_data_size(VmState* st, int mode) { - VM_LOG(st) << (mode & 2 ? 'S' : 'C') << "DATASIZE" << (mode & 1 ? "Q" : ""); - Stack& stack = st->get_stack(); - stack.check_underflow(2); - auto bound = stack.pop_int(); - Ref cell; - Ref cs; - if (mode & 2) { - cs = stack.pop_cellslice(); - } else { - cell = stack.pop_maybe_cell(); - } - if (!bound->is_valid() || bound->sgn() < 0) { - throw VmError{Excno::range_chk, "finite non-negative integer expected"}; - } - VmStorageStat stat{bound->unsigned_fits_bits(63) ? bound->to_long() : (1ULL << 63) - 1}; - bool ok = (mode & 2 ? stat.add_storage(cs.write()) : stat.add_storage(std::move(cell))); - if (ok) { - stack.push_smallint(stat.cells); - stack.push_smallint(stat.bits); - stack.push_smallint(stat.refs); - } else if (!(mode & 1)) { - throw VmError{Excno::cell_ov, "scanned too many cells"}; - } - if (mode & 1) { - stack.push_bool(ok); - } - return 0; -} - -void register_ton_misc_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xf940, 16, "CDATASIZEQ", std::bind(exec_compute_data_size, _1, 1))) - .insert(OpcodeInstr::mksimple(0xf941, 16, "CDATASIZE", std::bind(exec_compute_data_size, _1, 0))) - .insert(OpcodeInstr::mksimple(0xf942, 16, "SDATASIZEQ", std::bind(exec_compute_data_size, _1, 3))) - .insert(OpcodeInstr::mksimple(0xf943, 16, "SDATASIZE", std::bind(exec_compute_data_size, _1, 2))); -} - -int exec_load_var_integer(VmState* st, int len_bits, bool sgnd, bool quiet) { - if (len_bits == 4 && !sgnd) { - VM_LOG(st) << "execute LDGRAMS" << (quiet ? "Q" : ""); - } else { - VM_LOG(st) << "execute LDVAR" << (sgnd ? "" : "U") << "INT" << (1 << len_bits) << (quiet ? "Q" : ""); - } - Stack& stack = st->get_stack(); - auto csr = stack.pop_cellslice(); - td::RefInt256 x; - int len; - if (!(csr.write().fetch_uint_to(len_bits, len) && csr.unique_write().fetch_int256_to(len * 8, x, sgnd))) { - if (quiet) { - stack.push_bool(false); - } else { - throw VmError{Excno::cell_und, "cannot deserialize a variable-length integer"}; - } - } else { - stack.push_int(std::move(x)); - stack.push_cellslice(std::move(csr)); - if (quiet) { - stack.push_bool(true); - } - } - return 0; -} - -int exec_store_var_integer(VmState* st, int len_bits, bool sgnd, bool quiet) { - if (len_bits == 4 && !sgnd) { - VM_LOG(st) << "execute STGRAMS" << (quiet ? "Q" : ""); - } else { - VM_LOG(st) << "execute STVAR" << (sgnd ? "" : "U") << "INT" << (1 << len_bits) << (quiet ? "Q" : ""); - } - Stack& stack = st->get_stack(); - stack.check_underflow(2); - auto x = stack.pop_int(); - auto cbr = stack.pop_builder(); - unsigned len = ((x->bit_size(sgnd) + 7) >> 3); - if (len >= (1u << len_bits)) { - throw VmError{Excno::range_chk}; - } - if (!(cbr.write().store_long_bool(len, len_bits) && cbr.unique_write().store_int256_bool(*x, len * 8, sgnd))) { - if (quiet) { - stack.push_bool(false); - } else { - throw VmError{Excno::cell_ov, "cannot serialize a variable-length integer"}; - } - } else { - stack.push_builder(std::move(cbr)); - if (quiet) { - stack.push_bool(true); - } - } - return 0; -} - -bool skip_maybe_anycast(CellSlice& cs) { - if (cs.prefetch_ulong(1) != 1) { - return cs.advance(1); - } - unsigned depth; - return cs.advance(1) // just$1 - && cs.fetch_uint_leq(30, depth) // anycast_info$_ depth:(#<= 30) - && depth >= 1 // { depth >= 1 } - && cs.advance(depth); // rewrite_pfx:(bits depth) = Anycast; -} - -bool skip_message_addr(CellSlice& cs) { - switch ((unsigned)cs.fetch_ulong(2)) { - case 0: // addr_none$00 = MsgAddressExt; - return true; - case 1: { // addr_extern$01 - unsigned len; - return cs.fetch_uint_to(9, len) // len:(## 9) - && cs.advance(len); // external_address:(bits len) = MsgAddressExt; - } - case 2: { // addr_std$10 - return skip_maybe_anycast(cs) // anycast:(Maybe Anycast) - && cs.advance(8 + 256); // workchain_id:int8 address:bits256 = MsgAddressInt; - } - case 3: { // addr_var$11 - unsigned len; - return skip_maybe_anycast(cs) // anycast:(Maybe Anycast) - && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && cs.advance(32 + len); // workchain_id:int32 address:(bits addr_len) = MsgAddressInt; - } - default: - return false; - } -} - -int exec_load_message_addr(VmState* st, bool quiet) { - VM_LOG(st) << "execute LDMSGADDR" << (quiet ? "Q" : ""); - Stack& stack = st->get_stack(); - auto csr = stack.pop_cellslice(), csr_copy = csr; - auto& cs = csr.write(); - if (!(skip_message_addr(cs) && csr_copy.write().cut_tail(cs))) { - csr.clear(); - if (quiet) { - stack.push_cellslice(std::move(csr_copy)); - stack.push_bool(false); - } else { - throw VmError{Excno::cell_und, "cannot load a MsgAddress"}; - } - } else { - stack.push_cellslice(std::move(csr_copy)); - stack.push_cellslice(std::move(csr)); - if (quiet) { - stack.push_bool(true); - } - } - return 0; -} - -bool parse_maybe_anycast(CellSlice& cs, StackEntry& res) { - res = StackEntry{}; - if (cs.prefetch_ulong(1) != 1) { - return cs.advance(1); - } - unsigned depth; - Ref pfx; - if (cs.advance(1) // just$1 - && cs.fetch_uint_leq(30, depth) // anycast_info$_ depth:(#<= 30) - && depth >= 1 // { depth >= 1 } - && cs.fetch_subslice_to(depth, pfx)) { // rewrite_pfx:(bits depth) = Anycast; - res = std::move(pfx); - return true; - } - return false; -} - -bool parse_message_addr(CellSlice& cs, std::vector& res) { - res.clear(); - switch ((unsigned)cs.fetch_ulong(2)) { - case 0: // addr_none$00 = MsgAddressExt; - res.emplace_back(td::zero_refint()); // -> (0) - return true; - case 1: { // addr_extern$01 - unsigned len; - Ref addr; - if (cs.fetch_uint_to(9, len) // len:(## 9) - && cs.fetch_subslice_to(len, addr)) { // external_address:(bits len) = MsgAddressExt; - res.emplace_back(td::make_refint(1)); - res.emplace_back(std::move(addr)); - return true; - } - break; - } - case 2: { // addr_std$10 - StackEntry v; - int workchain; - Ref addr; - if (parse_maybe_anycast(cs, v) // anycast:(Maybe Anycast) - && cs.fetch_int_to(8, workchain) // workchain_id:int8 - && cs.fetch_subslice_to(256, addr)) { // address:bits256 = MsgAddressInt; - res.emplace_back(td::make_refint(2)); - res.emplace_back(std::move(v)); - res.emplace_back(td::make_refint(workchain)); - res.emplace_back(std::move(addr)); - return true; - } - break; - } - case 3: { // addr_var$11 - StackEntry v; - int len, workchain; - Ref addr; - if (parse_maybe_anycast(cs, v) // anycast:(Maybe Anycast) - && cs.fetch_uint_to(9, len) // addr_len:(## 9) - && cs.fetch_int_to(32, workchain) // workchain_id:int32 - && cs.fetch_subslice_to(len, addr)) { // address:(bits addr_len) = MsgAddressInt; - res.emplace_back(td::make_refint(3)); - res.emplace_back(std::move(v)); - res.emplace_back(td::make_refint(workchain)); - res.emplace_back(std::move(addr)); - return true; - } - break; - } - } - return false; -} - -int exec_parse_message_addr(VmState* st, bool quiet) { - VM_LOG(st) << "execute PARSEMSGADDR" << (quiet ? "Q" : ""); - Stack& stack = st->get_stack(); - auto csr = stack.pop_cellslice(); - auto& cs = csr.write(); - std::vector res; - if (!(parse_message_addr(cs, res) && cs.empty_ext())) { - if (quiet) { - stack.push_bool(false); - } else { - throw VmError{Excno::cell_und, "cannot parse a MsgAddress"}; - } - } else { - stack.push_tuple(std::move(res)); - if (quiet) { - stack.push_bool(true); - } - } - return 0; -} - -// replaces first bits of `addr` with those of `prefix` -Ref do_rewrite_addr(Ref addr, Ref prefix) { - if (prefix.is_null() || !prefix->size()) { - return std::move(addr); - } - if (prefix->size() > addr->size()) { - return {}; - } - if (prefix->size() == addr->size()) { - return std::move(prefix); - } - vm::CellBuilder cb; - if (!(addr.write().advance(prefix->size()) && cb.append_cellslice_bool(std::move(prefix)) && - cb.append_cellslice_bool(std::move(addr)))) { - return {}; - } - return vm::load_cell_slice_ref(cb.finalize()); -} - -int exec_rewrite_message_addr(VmState* st, bool allow_var_addr, bool quiet) { - VM_LOG(st) << "execute REWRITE" << (allow_var_addr ? "VAR" : "STD") << "ADDR" << (quiet ? "Q" : ""); - Stack& stack = st->get_stack(); - auto csr = stack.pop_cellslice(); - auto& cs = csr.write(); - std::vector tuple; - if (!(parse_message_addr(cs, tuple) && cs.empty_ext())) { - if (quiet) { - stack.push_bool(false); - return 0; - } - throw VmError{Excno::cell_und, "cannot parse a MsgAddress"}; - } - int t = (int)std::move(tuple[0]).as_int()->to_long(); - if (t != 2 && t != 3) { - if (quiet) { - stack.push_bool(false); - return 0; - } - throw VmError{Excno::cell_und, "cannot parse a MsgAddressInt"}; - } - auto addr = std::move(tuple[3]).as_slice(); - auto prefix = std::move(tuple[1]).as_slice(); - if (!allow_var_addr) { - if (addr->size() != 256) { - if (quiet) { - stack.push_bool(false); - return 0; - } - throw VmError{Excno::cell_und, "MsgAddressInt is not a standard 256-bit address"}; - } - td::Bits256 rw_addr; - td::RefInt256 int_addr{true}; - CHECK(addr->prefetch_bits_to(rw_addr) && - (prefix.is_null() || prefix->prefetch_bits_to(rw_addr.bits(), prefix->size())) && - int_addr.unique_write().import_bits(rw_addr, false)); - stack.push(std::move(tuple[2])); - stack.push(std::move(int_addr)); - } else { - addr = do_rewrite_addr(std::move(addr), std::move(prefix)); - if (addr.is_null()) { - if (quiet) { - stack.push_bool(false); - return 0; - } - throw VmError{Excno::cell_und, "cannot rewrite address in a MsgAddressInt"}; - } - stack.push(std::move(tuple[2])); - stack.push(std::move(addr)); - } - if (quiet) { - stack.push_bool(true); - } - return 0; -} - -void register_ton_currency_address_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xfa00, 16, "LDGRAMS", std::bind(exec_load_var_integer, _1, 4, false, false))) - .insert(OpcodeInstr::mksimple(0xfa01, 16, "LDVARINT16", std::bind(exec_load_var_integer, _1, 4, true, false))) - .insert(OpcodeInstr::mksimple(0xfa02, 16, "STGRAMS", std::bind(exec_store_var_integer, _1, 4, false, false))) - .insert(OpcodeInstr::mksimple(0xfa03, 16, "STVARINT16", std::bind(exec_store_var_integer, _1, 4, true, false))) - .insert(OpcodeInstr::mksimple(0xfa04, 16, "LDVARUINT32", std::bind(exec_load_var_integer, _1, 5, false, false))) - .insert(OpcodeInstr::mksimple(0xfa05, 16, "LDVARINT32", std::bind(exec_load_var_integer, _1, 5, true, false))) - .insert(OpcodeInstr::mksimple(0xfa06, 16, "STVARUINT32", std::bind(exec_store_var_integer, _1, 5, false, false))) - .insert(OpcodeInstr::mksimple(0xfa07, 16, "STVARINT32", std::bind(exec_store_var_integer, _1, 5, true, false))) - .insert(OpcodeInstr::mksimple(0xfa40, 16, "LDMSGADDR", std::bind(exec_load_message_addr, _1, false))) - .insert(OpcodeInstr::mksimple(0xfa41, 16, "LDMSGADDRQ", std::bind(exec_load_message_addr, _1, true))) - .insert(OpcodeInstr::mksimple(0xfa42, 16, "PARSEMSGADDR", std::bind(exec_parse_message_addr, _1, false))) - .insert(OpcodeInstr::mksimple(0xfa43, 16, "PARSEMSGADDRQ", std::bind(exec_parse_message_addr, _1, true))) - .insert( - OpcodeInstr::mksimple(0xfa44, 16, "REWRITESTDADDR", std::bind(exec_rewrite_message_addr, _1, false, false))) - .insert( - OpcodeInstr::mksimple(0xfa45, 16, "REWRITESTDADDRQ", std::bind(exec_rewrite_message_addr, _1, false, true))) - .insert( - OpcodeInstr::mksimple(0xfa46, 16, "REWRITEVARADDR", std::bind(exec_rewrite_message_addr, _1, true, false))) - .insert( - OpcodeInstr::mksimple(0xfa47, 16, "REWRITEVARADDRQ", std::bind(exec_rewrite_message_addr, _1, true, true))); -} - -static constexpr int output_actions_idx = 5; - -int install_output_action(VmState* st, Ref new_action_head) { - // TODO: increase actions:uint16 and msgs_sent:uint16 in SmartContractInfo at first reference of c5 - VM_LOG(st) << "installing an output action"; - st->set_d(output_actions_idx, std::move(new_action_head)); - return 0; -} - -static inline Ref get_actions(VmState* st) { - return st->get_d(output_actions_idx); -} - -int exec_send_raw_message(VmState* st) { - VM_LOG(st) << "execute SENDRAWMSG"; - Stack& stack = st->get_stack(); - stack.check_underflow(2); - int f = stack.pop_smallint_range(255); - Ref msg_cell = stack.pop_cell(); - CellBuilder cb; - if (!(cb.store_ref_bool(get_actions(st)) // out_list$_ {n:#} prev:^(OutList n) - && cb.store_long_bool(0x0ec3c86d, 32) // action_send_msg#0ec3c86d - && cb.store_long_bool(f, 8) // mode:(## 8) - && cb.store_ref_bool(std::move(msg_cell)))) { - throw VmError{Excno::cell_ov, "cannot serialize raw output message into an output action cell"}; - } - return install_output_action(st, cb.finalize()); -} - -bool store_grams(CellBuilder& cb, td::RefInt256 value) { - int k = value->bit_size(false); - return k <= 15 * 8 && cb.store_long_bool((k + 7) >> 3, 4) && cb.store_int256_bool(*value, (k + 7) & -8, false); -} - -int exec_reserve_raw(VmState* st, int mode) { - VM_LOG(st) << "execute RAWRESERVE" << (mode & 1 ? "X" : ""); - Stack& stack = st->get_stack(); - stack.check_underflow(2 + (mode & 1)); - int f = stack.pop_smallint_range(15); - Ref y; - if (mode & 1) { - y = stack.pop_maybe_cell(); - } - auto x = stack.pop_int_finite(); - if (td::sgn(x) < 0) { - throw VmError{Excno::range_chk, "amount of nanograms must be non-negative"}; - } - CellBuilder cb; - if (!(cb.store_ref_bool(get_actions(st)) // out_list$_ {n:#} prev:^(OutList n) - && cb.store_long_bool(0x36e6b809, 32) // action_reserve_currency#36e6b809 - && cb.store_long_bool(f, 8) // mode:(## 8) - && store_grams(cb, std::move(x)) // - && cb.store_maybe_ref(std::move(y)))) { - throw VmError{Excno::cell_ov, "cannot serialize raw reserved currency amount into an output action cell"}; - } - return install_output_action(st, cb.finalize()); -} - -int exec_set_code(VmState* st) { - VM_LOG(st) << "execute SETCODE"; - auto code = st->get_stack().pop_cell(); - CellBuilder cb; - if (!(cb.store_ref_bool(get_actions(st)) // out_list$_ {n:#} prev:^(OutList n) - && cb.store_long_bool(0xad4de08e, 32) // action_set_code#ad4de08e - && cb.store_ref_bool(std::move(code)))) { // new_code:^Cell = OutAction; - throw VmError{Excno::cell_ov, "cannot serialize new smart contract code into an output action cell"}; - } - return install_output_action(st, cb.finalize()); -} - -int exec_set_lib_code(VmState* st) { - VM_LOG(st) << "execute SETLIBCODE"; - Stack& stack = st->get_stack(); - stack.check_underflow(2); - int mode = stack.pop_smallint_range(2); - auto code = stack.pop_cell(); - CellBuilder cb; - if (!(cb.store_ref_bool(get_actions(st)) // out_list$_ {n:#} prev:^(OutList n) - && cb.store_long_bool(0x26fa1dd4, 32) // action_change_library#26fa1dd4 - && cb.store_long_bool(mode * 2 + 1, 8) // mode:(## 7) { mode <= 2 } - && cb.store_ref_bool(std::move(code)))) { // libref:LibRef = OutAction; - throw VmError{Excno::cell_ov, "cannot serialize new library code into an output action cell"}; - } - return install_output_action(st, cb.finalize()); -} - -int exec_change_lib(VmState* st) { - VM_LOG(st) << "execute CHANGELIB"; - Stack& stack = st->get_stack(); - stack.check_underflow(2); - int mode = stack.pop_smallint_range(2); - auto hash = stack.pop_int_finite(); - if (!hash->unsigned_fits_bits(256)) { - throw VmError{Excno::range_chk, "library hash must be non-negative"}; - } - CellBuilder cb; - if (!(cb.store_ref_bool(get_actions(st)) // out_list$_ {n:#} prev:^(OutList n) - && cb.store_long_bool(0x26fa1dd4, 32) // action_change_library#26fa1dd4 - && cb.store_long_bool(mode * 2, 8) // mode:(## 7) { mode <= 2 } - && cb.store_int256_bool(hash, 256, false))) { // libref:LibRef = OutAction; - throw VmError{Excno::cell_ov, "cannot serialize library hash into an output action cell"}; - } - return install_output_action(st, cb.finalize()); -} - -void register_ton_message_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0xfb00, 16, "SENDRAWMSG", exec_send_raw_message)) - .insert(OpcodeInstr::mksimple(0xfb02, 16, "RAWRESERVE", std::bind(exec_reserve_raw, _1, 0))) - .insert(OpcodeInstr::mksimple(0xfb03, 16, "RAWRESERVEX", std::bind(exec_reserve_raw, _1, 1))) - .insert(OpcodeInstr::mksimple(0xfb04, 16, "SETCODE", exec_set_code)) - .insert(OpcodeInstr::mksimple(0xfb06, 16, "SETLIBCODE", exec_set_lib_code)) - .insert(OpcodeInstr::mksimple(0xfb07, 16, "CHANGELIB", exec_change_lib)); -} - -void register_ton_ops(OpcodeTable& cp0) { - register_basic_gas_ops(cp0); - register_ton_gas_ops(cp0); - register_prng_ops(cp0); - register_ton_config_ops(cp0); - register_ton_crypto_ops(cp0); - register_ton_misc_ops(cp0); - register_ton_currency_address_ops(cp0); - register_ton_message_ops(cp0); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/tonops.h b/submodules/ton/tonlib-src/crypto/vm/tonops.h deleted file mode 100644 index 5b3e14d9..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/tonops.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_ton_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/tupleops.cpp b/submodules/ton/tonlib-src/crypto/vm/tupleops.cpp deleted file mode 100644 index ef906f6a..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/tupleops.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/log.h" -#include "vm/stackops.h" -#include "vm/opctable.h" -#include "vm/stack.hpp" -#include "vm/excno.hpp" -#include "vm/vm.h" - -namespace vm { - -int exec_push_null(VmState* st) { - VM_LOG(st) << "execute PUSHNULL"; - st->get_stack().push({}); - return 0; -} - -int exec_is_null(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ISNULL"; - stack.push_bool(stack.pop_chk().empty()); - return 0; -} - -int exec_null_swap_if(VmState* st, bool cond, int depth) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NULL" << (depth ? "ROTR" : "SWAP") << (cond ? "IF" : "IFNOT"); - stack.check_underflow(depth + 1); - auto x = stack.pop_int_finite(); - if (!x->sgn() != cond) { - stack.push({}); - for (int i = 0; i < depth; i++) { - swap(stack[i], stack[i + 1]); - } - } - stack.push_int(std::move(x)); - return 0; -} - -int exec_null_swap_if_many(VmState* st, bool cond, int depth, int count) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute NULL" << (depth ? "ROTR" : "SWAP") << (cond ? "IF" : "IFNOT") << count; - stack.check_underflow(depth + 1); - auto x = stack.pop_int_finite(); - if (!x->sgn() != cond) { - for (int i = 0; i < count; i++) { - stack.push({}); - } - for (int i = 0; i < depth; i++) { - swap(stack[i], stack[i + count]); - } - } - stack.push_int(std::move(x)); - return 0; -} - -int exec_mktuple_common(VmState* st, unsigned n) { - Stack& stack = st->get_stack(); - stack.check_underflow(n); - Ref ref{true}; - auto& tuple = ref.unique_write(); - tuple.reserve(n); - for (int i = n - 1; i >= 0; i--) { - tuple.push_back(std::move(stack[i])); - } - stack.pop_many(n); - st->consume_tuple_gas(n); - stack.push_tuple(std::move(ref)); - return 0; -} - -int exec_mktuple(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute TUPLE " << args; - return exec_mktuple_common(st, args); -} - -int exec_mktuple_var(VmState* st) { - VM_LOG(st) << "execute TUPLEVAR"; - unsigned args = st->get_stack().pop_smallint_range(255); - return exec_mktuple_common(st, args); -} - -int exec_tuple_index_common(Stack& stack, unsigned n) { - auto tuple = stack.pop_tuple_range(255); - stack.push(tuple_index(*tuple, n)); - return 0; -} - -int exec_tuple_index(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute INDEX " << args; - return exec_tuple_index_common(st->get_stack(), args); -} - -int exec_tuple_index_var(VmState* st) { - VM_LOG(st) << "execute INDEXVAR"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_tuple_index_common(st->get_stack(), args); -} - -int exec_tuple_quiet_index_common(Stack& stack, unsigned n) { - stack.push(tuple_extend_index(stack.pop_maybe_tuple_range(255), n)); - return 0; -} - -int exec_tuple_quiet_index(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute INDEXQ " << args; - return exec_tuple_quiet_index_common(st->get_stack(), args); -} - -int exec_tuple_quiet_index_var(VmState* st) { - VM_LOG(st) << "execute INDEXVARQ"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_tuple_quiet_index_common(st->get_stack(), args); -} - -int do_explode_tuple(VmState* st, Ref tuple, unsigned n) { - auto& stack = st->get_stack(); - if (tuple.is_unique()) { - auto& tw = tuple.unique_write(); - for (unsigned i = 0; i < n; i++) { - stack.push(std::move(tw[i])); - } - } else { - const auto& t = *tuple; - for (unsigned i = 0; i < n; i++) { - stack.push(t[i]); - } - } - st->consume_tuple_gas(n); - return 0; -} - -int exec_untuple_common(VmState* st, unsigned n) { - return do_explode_tuple(st, st->get_stack().pop_tuple_range(n, n), n); -} - -int exec_untuple(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute UNTUPLE " << args; - return exec_untuple_common(st, args); -} - -int exec_untuple_var(VmState* st) { - VM_LOG(st) << "execute UNTUPLEVAR"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(255); - return exec_untuple_common(st, args); -} - -int exec_untuple_first_common(VmState* st, unsigned n) { - return do_explode_tuple(st, st->get_stack().pop_tuple_range(255, n), n); -} - -int exec_untuple_first(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute UNPACKFIRST " << args; - return exec_untuple_first_common(st, args); -} - -int exec_untuple_first_var(VmState* st) { - VM_LOG(st) << "execute UNPACKFIRSTVAR"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(255); - return exec_untuple_first_common(st, args); -} - -int exec_explode_tuple_common(VmState* st, unsigned n) { - auto t = st->get_stack().pop_tuple_range(n); - unsigned l = (unsigned)(t->size()); - do_explode_tuple(st, std::move(t), l); - st->get_stack().push_smallint(l); - return 0; -} - -int exec_explode_tuple(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute EXPLODE " << args; - return exec_explode_tuple_common(st, args); -} - -int exec_explode_tuple_var(VmState* st) { - VM_LOG(st) << "execute EXPLODEVAR"; - st->check_underflow(2); - unsigned args = st->get_stack().pop_smallint_range(255); - return exec_explode_tuple_common(st, args); -} - -int exec_tuple_set_index_common(VmState* st, unsigned idx) { - Stack& stack = st->get_stack(); - auto x = stack.pop(); - auto tuple = stack.pop_tuple_range(255); - if (idx >= tuple->size()) { - throw VmError{Excno::range_chk, "tuple index out of range"}; - } - tuple.write()[idx] = std::move(x); - st->consume_tuple_gas(tuple); - stack.push(std::move(tuple)); - return 0; -} - -int exec_tuple_set_index(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute SETINDEX " << args; - st->check_underflow(2); - return exec_tuple_set_index_common(st, args); -} - -int exec_tuple_set_index_var(VmState* st) { - VM_LOG(st) << "execute SETINDEXVAR"; - st->check_underflow(3); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_tuple_set_index_common(st, args); -} - -int exec_tuple_quiet_set_index_common(VmState* st, unsigned idx) { - Stack& stack = st->get_stack(); - auto x = stack.pop(); - auto tuple = stack.pop_maybe_tuple_range(255); - if (idx >= 255) { - throw VmError{Excno::range_chk, "tuple index out of range"}; - } - auto tpay = tuple_extend_set_index(tuple, idx, std::move(x)); - if (tpay > 0) { - st->consume_tuple_gas(tpay); - } - stack.push_maybe_tuple(std::move(tuple)); - return 0; -} - -int exec_tuple_quiet_set_index(VmState* st, unsigned args) { - args &= 15; - VM_LOG(st) << "execute SETINDEXQ " << args; - st->check_underflow(2); - return exec_tuple_quiet_set_index_common(st, args); -} - -int exec_tuple_quiet_set_index_var(VmState* st) { - VM_LOG(st) << "execute SETINDEXVARQ"; - st->check_underflow(3); - unsigned args = st->get_stack().pop_smallint_range(254); - return exec_tuple_quiet_set_index_common(st, args); -} - -int exec_tuple_length(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute TLEN"; - auto t = stack.pop_tuple_range(255); - stack.push_smallint((long long)(t->size())); - return 0; -} - -int exec_tuple_length_quiet(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute QTLEN"; - auto t = stack.pop_chk(); - stack.push_smallint(t.is_tuple() ? (long long)(t.as_tuple()->size()) : -1LL); - return 0; -} - -int exec_is_tuple(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute ISTUPLE"; - stack.push_bool(stack.pop_chk().is_tuple()); - return 0; -} - -int exec_tuple_last(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute LAST"; - auto t = stack.pop_tuple_range(255, 1); - stack.push(t->back()); - return 0; -} - -int exec_tuple_push(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute TPUSH"; - stack.check_underflow(2); - auto x = stack.pop(); - auto t = stack.pop_tuple_range(254); - t.write().push_back(std::move(x)); - st->consume_tuple_gas(t); - stack.push(std::move(t)); - return 0; -} - -int exec_tuple_pop(VmState* st) { - Stack& stack = st->get_stack(); - VM_LOG(st) << "execute TPOP"; - auto t = stack.pop_tuple_range(255, 1); - auto x = std::move(t.write().back()); - t.write().pop_back(); - st->consume_tuple_gas(t); - stack.push(std::move(t)); - stack.push(std::move(x)); - return 0; -} - -int exec_tuple_index2(VmState* st, unsigned args) { - unsigned i = (args >> 2) & 3, j = args & 3; - VM_LOG(st) << "execute INDEX2 " << i << "," << j; - Stack& stack = st->get_stack(); - auto tuple = stack.pop_tuple_range(255); - auto t1 = tuple_index(*tuple, i).as_tuple_range(255); - if (t1.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - stack.push(tuple_index(*t1, j)); - return 0; -} - -std::string dump_tuple_index2(CellSlice& cs, unsigned args) { - unsigned i = (args >> 2) & 3, j = args & 3; - std::ostringstream os; - os << "INDEX2 " << i << ',' << j; - return os.str(); -} - -int exec_tuple_index3(VmState* st, unsigned args) { - unsigned i = (args >> 4) & 3, j = (args >> 2) & 3, k = args & 3; - VM_LOG(st) << "execute INDEX3 " << i << "," << j << "," << k; - Stack& stack = st->get_stack(); - auto tuple = stack.pop_tuple_range(255); - auto t1 = tuple_index(*tuple, i).as_tuple_range(255); - if (t1.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - auto t2 = tuple_index(*t1, j).as_tuple_range(255); - if (t2.is_null()) { - throw VmError{Excno::type_chk, "intermediate value is not a tuple"}; - } - stack.push(tuple_index(*t2, k)); - return 0; -} - -std::string dump_tuple_index3(CellSlice& cs, unsigned args) { - unsigned i = (args >> 4) & 3, j = (args >> 2) & 3, k = args & 3; - std::ostringstream os; - os << "INDEX3 " << i << ',' << j << ',' << k; - return os.str(); -} - -void register_tuple_ops(OpcodeTable& cp0) { - using namespace std::placeholders; - cp0.insert(OpcodeInstr::mksimple(0x6d, 8, "PUSHNULL", exec_push_null)) - .insert(OpcodeInstr::mksimple(0x6e, 8, "ISNULL", exec_is_null)) - .insert(OpcodeInstr::mkfixed(0x6f0, 12, 4, instr::dump_1c("TUPLE "), exec_mktuple)) - .insert(OpcodeInstr::mkfixed(0x6f1, 12, 4, instr::dump_1c("INDEX "), exec_tuple_index)) - .insert(OpcodeInstr::mkfixed(0x6f2, 12, 4, instr::dump_1c("UNTUPLE "), exec_untuple)) - .insert(OpcodeInstr::mkfixed(0x6f3, 12, 4, instr::dump_1c("UNPACKFIRST "), exec_untuple_first)) - .insert(OpcodeInstr::mkfixed(0x6f4, 12, 4, instr::dump_1c("EXPLODE "), exec_explode_tuple)) - .insert(OpcodeInstr::mkfixed(0x6f5, 12, 4, instr::dump_1c("SETINDEX "), exec_tuple_set_index)) - .insert(OpcodeInstr::mkfixed(0x6f6, 12, 4, instr::dump_1c("INDEXQ "), exec_tuple_quiet_index)) - .insert(OpcodeInstr::mkfixed(0x6f7, 12, 4, instr::dump_1c("SETINDEXQ "), exec_tuple_quiet_set_index)) - .insert(OpcodeInstr::mksimple(0x6f80, 16, "TUPLEVAR", exec_mktuple_var)) - .insert(OpcodeInstr::mksimple(0x6f81, 16, "INDEXVAR", exec_tuple_index_var)) - .insert(OpcodeInstr::mksimple(0x6f82, 16, "UNTUPLEVAR", exec_untuple_var)) - .insert(OpcodeInstr::mksimple(0x6f83, 16, "UNPACKFIRSTVAR", exec_untuple_first_var)) - .insert(OpcodeInstr::mksimple(0x6f84, 16, "EXPLODEVAR", exec_explode_tuple_var)) - .insert(OpcodeInstr::mksimple(0x6f85, 16, "SETINDEXVAR", exec_tuple_set_index_var)) - .insert(OpcodeInstr::mksimple(0x6f86, 16, "INDEXVARQ", exec_tuple_quiet_index_var)) - .insert(OpcodeInstr::mksimple(0x6f87, 16, "SETINDEXVARQ", exec_tuple_quiet_set_index_var)) - .insert(OpcodeInstr::mksimple(0x6f88, 16, "TLEN", exec_tuple_length)) - .insert(OpcodeInstr::mksimple(0x6f89, 16, "QTLEN", exec_tuple_length_quiet)) - .insert(OpcodeInstr::mksimple(0x6f8a, 16, "ISTUPLE", exec_is_tuple)) - .insert(OpcodeInstr::mksimple(0x6f8b, 16, "LAST", exec_tuple_last)) - .insert(OpcodeInstr::mksimple(0x6f8c, 16, "TPUSH", exec_tuple_push)) - .insert(OpcodeInstr::mksimple(0x6f8d, 16, "TPOP", exec_tuple_pop)) - .insert(OpcodeInstr::mksimple(0x6fa0, 16, "NULLSWAPIF", std::bind(exec_null_swap_if, _1, true, 0))) - .insert(OpcodeInstr::mksimple(0x6fa1, 16, "NULLSWAPIFNOT", std::bind(exec_null_swap_if, _1, false, 0))) - .insert(OpcodeInstr::mksimple(0x6fa2, 16, "NULLROTRIF", std::bind(exec_null_swap_if, _1, true, 1))) - .insert(OpcodeInstr::mksimple(0x6fa3, 16, "NULLROTRIFNOT", std::bind(exec_null_swap_if, _1, false, 1))) - .insert(OpcodeInstr::mksimple(0x6fa4, 16, "NULLSWAPIF2", std::bind(exec_null_swap_if_many, _1, true, 0, 2))) - .insert(OpcodeInstr::mksimple(0x6fa5, 16, "NULLSWAPIFNOT2", std::bind(exec_null_swap_if_many, _1, false, 0, 2))) - .insert(OpcodeInstr::mksimple(0x6fa6, 16, "NULLROTRIF2", std::bind(exec_null_swap_if_many, _1, true, 1, 2))) - .insert(OpcodeInstr::mksimple(0x6fa7, 16, "NULLROTRIFNOT2", std::bind(exec_null_swap_if_many, _1, false, 1, 2))) - .insert(OpcodeInstr::mkfixed(0x6fb, 12, 4, dump_tuple_index2, exec_tuple_index2)) - .insert(OpcodeInstr::mkfixed(0x6fc >> 2, 10, 6, dump_tuple_index3, exec_tuple_index3)); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/tupleops.h b/submodules/ton/tonlib-src/crypto/vm/tupleops.h deleted file mode 100644 index f7d48959..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/tupleops.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace vm { - -class OpcodeTable; - -void register_tuple_ops(OpcodeTable& cp0); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/utils.cpp b/submodules/ton/tonlib-src/crypto/vm/utils.cpp deleted file mode 100644 index 783bf132..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/utils.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "utils.h" - -namespace vm { - -td::Result convert_stack_entry(td::Slice word); -td::Result> parse_stack_entries_in(td::Slice& str, bool prefix_only = false); -td::Result parse_stack_entry_in(td::Slice& str, bool prefix_only = false); - -namespace { - -td::Slice& skip_spaces(td::Slice& str, const char* delims) { - while (str.size() > 0 && strchr(delims, str[0])) { - str.remove_prefix(1); - } - return str; -} - -td::Slice get_word(td::Slice& str, const char* delims, const char* specials) { - skip_spaces(str, delims); - - size_t p = 0; - while (p < str.size() && !strchr(delims, str[p])) { - if (specials && strchr(specials, str[p])) { - if (!p) { - p++; - } - break; - } - p++; - } - - td::Slice ret = str.copy().truncate(p); - str.remove_prefix(p); - return ret; -} - -} // namespace - -td::Result parse_stack_entry_in(td::Slice& str, bool prefix_only) { - auto word = get_word(str, " \t", "[()]"); - if (word.empty()) { - return td::Status::Error("stack value expected instead of end-of-line"); - } - if (word.size() == 1 && (word[0] == '[' || word[0] == '(')) { - int expected = (word[0] == '(' ? ')' : ']'); - TRY_RESULT(values, parse_stack_entries_in(str, true)); - word = get_word(str, " \t", "[()]"); - if (word.size() != 1 || word[0] != expected) { - return td::Status::Error("closing bracket expected"); - } - vm::StackEntry value; - if (expected == ']') { - value = vm::StackEntry{std::move(values)}; - } else { - value = vm::StackEntry::make_list(std::move(values)); - } - if (prefix_only || (skip_spaces(str, " \t").size() == 0)) { - return value; - } else { - return td::Status::Error("extra data at the end"); - } - } else { - return convert_stack_entry(word); - } -} - -td::Result convert_stack_entry(td::Slice str) { - if (str.empty() || str.size() > 65535) { - return td::Status::Error("too long string"); - } - int l = (int)str.size(); - if (str[0] == '"') { - vm::CellBuilder cb; - if (l == 1 || str.back() != '"' || l >= 127 + 2 || !cb.store_bytes_bool(str.data() + 1, l - 2)) { - return td::Status::Error("incomplete (or too long) string"); - } - return vm::StackEntry{vm::load_cell_slice_ref(cb.finalize())}; - } - if (l >= 3 && (str[0] == 'x' || str[0] == 'b') && str[1] == '{' && str.back() == '}') { - unsigned char buff[128]; - int bits = - (str[0] == 'x') - ? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1) - : (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1); - if (bits < 0) { - return td::Status::Error("failed to parse raw b{...}/x{...} number"); - } - return vm::StackEntry{ - Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}}; - } - auto num = td::make_refint(); - auto& x = num.unique_write(); - if (l >= 3 && str[0] == '0' && str[1] == 'x') { - if (x.parse_hex(str.data() + 2, l - 2) != l - 2) { - return td::Status::Error("failed to parse 0x... hex number"); - } - } else if (l >= 4 && str[0] == '-' && str[1] == '0' && str[2] == 'x') { - if (x.parse_hex(str.data() + 3, l - 3) != l - 3) { - return td::Status::Error("failed to parse -0x... hex number"); - } - x.negate().normalize(); - } else if (!l || x.parse_dec(str.data(), l) != l) { - return td::Status::Error("failed to parse dec number"); - } - return vm::StackEntry{std::move(num)}; -} - -td::Result> parse_stack_entries_in(td::Slice& str, bool prefix_only) { - std::vector ret; - while (!skip_spaces(str, " \t").empty()) { - auto c = str.copy(); - auto word = get_word(c, " \t", "[()]"); - if (word == "]" || word == ")") { - if (prefix_only) { - return ret; - } else { - return td::Status::Error("not paired closing bracket"); - } - } - TRY_RESULT(value, parse_stack_entry_in(str, true)); - ret.push_back(std::move(value)); - } - return ret; -} - -td::Result> parse_stack_entries(td::Slice str, bool prefix_only) { - return parse_stack_entries_in(str, prefix_only); -} - -td::Result parse_stack_entry(td::Slice str, bool prefix_only) { - return parse_stack_entry_in(str, prefix_only); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/utils.h b/submodules/ton/tonlib-src/crypto/vm/utils.h deleted file mode 100644 index 34d761b1..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/utils.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#pragma once -#include "stack.hpp" - -#include - -namespace vm { - -td::Result> parse_stack_entries(td::Slice str, bool prefix_only = false); -td::Result parse_stack_entry(td::Slice str, bool prefix_only = false); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/vm.cpp b/submodules/ton/tonlib-src/crypto/vm/vm.cpp deleted file mode 100644 index 038640a5..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/vm.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "vm/dispatch.h" -#include "vm/continuation.h" -#include "vm/dict.h" -#include "vm/log.h" -#include "vm/vm.h" - -namespace vm { - -VmState::VmState() : cp(-1), dispatch(&dummy_dispatch_table), quit0(true, 0), quit1(true, 1) { - ensure_throw(init_cp(0)); - init_cregs(); -} - -VmState::VmState(Ref _code) - : code(std::move(_code)), cp(-1), dispatch(&dummy_dispatch_table), quit0(true, 0), quit1(true, 1) { - ensure_throw(init_cp(0)); - init_cregs(); -} - -VmState::VmState(Ref _code, Ref _stack, int flags, Ref _data, VmLog log, - std::vector> _libraries, Ref init_c7) - : code(std::move(_code)) - , stack(std::move(_stack)) - , cp(-1) - , dispatch(&dummy_dispatch_table) - , quit0(true, 0) - , quit1(true, 1) - , log(log) - , libraries(std::move(_libraries)) - , stack_trace((flags >> 2) & 1) { - ensure_throw(init_cp(0)); - set_c4(std::move(_data)); - if (init_c7.not_null()) { - set_c7(std::move(init_c7)); - } - init_cregs(flags & 1, flags & 2); -} - -VmState::VmState(Ref _code, Ref _stack, const GasLimits& gas, int flags, Ref _data, VmLog log, - std::vector> _libraries, Ref init_c7) - : code(std::move(_code)) - , stack(std::move(_stack)) - , cp(-1) - , dispatch(&dummy_dispatch_table) - , quit0(true, 0) - , quit1(true, 1) - , log(log) - , gas(gas) - , libraries(std::move(_libraries)) - , stack_trace((flags >> 2) & 1) { - ensure_throw(init_cp(0)); - set_c4(std::move(_data)); - if (init_c7.not_null()) { - set_c7(std::move(init_c7)); - } - init_cregs(flags & 1, flags & 2); -} - -void VmState::init_cregs(bool same_c3, bool push_0) { - cr.set_c0(quit0); - cr.set_c1(quit1); - cr.set_c2(Ref{true}); - if (same_c3) { - cr.set_c3(Ref{true, code, cp}); - if (push_0) { - VM_LOG(this) << "implicit PUSH 0 at start\n"; - get_stack().push_smallint(0); - } - } else { - cr.set_c3(Ref{true, 11}); - } - if (cr.d[0].is_null() || cr.d[1].is_null()) { - auto empty_cell = CellBuilder{}.finalize(); - for (int i = 0; i < ControlRegs::dreg_num; i++) { - if (cr.d[i].is_null()) { - cr.d[i] = empty_cell; - } - } - } - if (cr.c7.is_null()) { - cr.set_c7(Ref{true}); - } -} - -Ref VmState::convert_code_cell(Ref code_cell) { - if (code_cell.is_null()) { - return {}; - } - Ref csr{true, NoVmOrd(), code_cell}; - if (csr->is_valid()) { - return csr; - } - return load_cell_slice_ref(CellBuilder{}.store_ref(std::move(code_cell)).finalize()); -} - -bool VmState::init_cp(int new_cp) { - const DispatchTable* dt = DispatchTable::get_table(new_cp); - if (dt) { - cp = new_cp; - dispatch = dt; - return true; - } else { - return false; - } -} - -bool VmState::set_cp(int new_cp) { - return new_cp == cp || init_cp(new_cp); -} - -void VmState::force_cp(int new_cp) { - if (!set_cp(new_cp)) { - throw VmError{Excno::inv_opcode, "unsupported codepage"}; - } -} - -// simple call to a continuation cont -int VmState::call(Ref cont) { - const ControlData* cont_data = cont->get_cdata(); - if (cont_data) { - if (cont_data->save.c[0].not_null()) { - // call reduces to a jump - return jump(std::move(cont)); - } - if (cont_data->stack.not_null() || cont_data->nargs >= 0) { - // if cont has non-empty stack or expects fixed number of arguments, call is not simple - return call(std::move(cont), -1, -1); - } - // create return continuation, to be stored into new c0 - Ref ret = Ref{true, std::move(code), cp}; - ret.unique_write().get_cdata()->save.set_c0(std::move(cr.c[0])); - cr.set_c0( - std::move(ret)); // set c0 to its final value before switching to cont; notice that cont.save.c0 is not set - return jump_to(std::move(cont)); - } - // create return continuation, to be stored into new c0 - Ref ret = Ref{true, std::move(code), cp}; - ret.unique_write().get_cdata()->save.set_c0(std::move(cr.c[0])); - // general implementation of a simple call - cr.set_c0(std::move(ret)); // set c0 to its final value before switching to cont; notice that cont.save.c0 is not set - return jump_to(std::move(cont)); -} - -// call with parameters to continuation cont -int VmState::call(Ref cont, int pass_args, int ret_args) { - const ControlData* cont_data = cont->get_cdata(); - if (cont_data) { - if (cont_data->save.c[0].not_null()) { - // call reduces to a jump - return jump(std::move(cont), pass_args); - } - int depth = stack->depth(); - if (pass_args > depth || cont_data->nargs > depth) { - throw VmError{Excno::stk_und, "stack underflow while calling a continuation: not enough arguments on stack"}; - } - if (cont_data->nargs > pass_args && pass_args >= 0) { - throw VmError{Excno::stk_und, - "stack underflow while calling a closure continuation: not enough arguments passed"}; - } - auto old_c0 = std::move(cr.c[0]); - // optimization(?): decrease refcnts of unused continuations in c[i] as early as possible - preclear_cr(cont_data->save); - // no exceptions should be thrown after this point - int copy = cont_data->nargs, skip = 0; - if (pass_args >= 0) { - if (copy >= 0) { - skip = pass_args - copy; - } else { - copy = pass_args; - } - } - // copy=-1 : pass whole stack, else pass top `copy` elements, drop next `skip` elements. - Ref new_stk; - if (cont_data->stack.not_null() && !cont_data->stack->is_empty()) { - // `cont` already has a stack, create resulting stack from it - if (copy < 0) { - copy = stack->depth(); - } - if (cont->is_unique()) { - // optimization: avoid copying stack if we hold the only copy of `cont` - new_stk = std::move(cont.unique_write().get_cdata()->stack); - } else { - new_stk = cont_data->stack; - } - new_stk.write().move_from_stack(get_stack(), copy); - if (skip > 0) { - get_stack().pop_many(skip); - } - consume_stack_gas(new_stk); - } else if (copy >= 0) { - new_stk = get_stack().split_top(copy, skip); - consume_stack_gas(new_stk); - } else { - new_stk = std::move(stack); - stack.clear(); - } - // create return continuation using the remainder of current stack - Ref ret = Ref{true, std::move(code), cp, std::move(stack), ret_args}; - ret.unique_write().get_cdata()->save.set_c0(std::move(old_c0)); - Ref ord_cont = static_cast>(cont); - set_stack(std::move(new_stk)); - cr.set_c0(std::move(ret)); // ??? if codepage of code in ord_cont is unknown, will end up with incorrect c0 - return jump_to(std::move(cont)); - } else { - // have no continuation data, situation is somewhat simpler - int depth = stack->depth(); - if (pass_args > depth) { - throw VmError{Excno::stk_und, "stack underflow while calling a continuation: not enough arguments on stack"}; - } - // create new stack from the top `pass_args` elements of the current stack - Ref new_stk; - if (pass_args >= 0) { - new_stk = get_stack().split_top(pass_args); - consume_stack_gas(new_stk); - } else { - new_stk = std::move(stack); - } - // create return continuation using the remainder of the current stack - Ref ret = Ref{true, std::move(code), cp, std::move(stack), ret_args}; - ret.unique_write().get_cdata()->save.set_c0(std::move(cr.c[0])); - set_stack(std::move(new_stk)); - cr.set_c0(std::move(ret)); // ??? if codepage of code in ord_cont is unknown, will end up with incorrect c0 - return jump_to(std::move(cont)); - } -} - -// simple jump to continuation cont -int VmState::jump(Ref cont) { - const ControlData* cont_data = cont->get_cdata(); - if (cont_data && (cont_data->stack.not_null() || cont_data->nargs >= 0)) { - // if cont has non-empty stack or expects fixed number of arguments, jump is not simple - return jump(std::move(cont), -1); - } else { - return jump_to(std::move(cont)); - } -} - -// general jump to continuation cont -int VmState::jump(Ref cont, int pass_args) { - const ControlData* cont_data = cont->get_cdata(); - if (cont_data) { - // first do the checks - int depth = stack->depth(); - if (pass_args > depth || cont_data->nargs > depth) { - throw VmError{Excno::stk_und, "stack underflow while jumping to a continuation: not enough arguments on stack"}; - } - if (cont_data->nargs > pass_args && pass_args >= 0) { - throw VmError{Excno::stk_und, - "stack underflow while jumping to closure continuation: not enough arguments passed"}; - } - // optimization(?): decrease refcnts of unused continuations in c[i] as early as possible - preclear_cr(cont_data->save); - // no exceptions should be thrown after this point - int copy = cont_data->nargs; - if (pass_args >= 0 && copy < 0) { - copy = pass_args; - } - // copy=-1 : pass whole stack, else pass top `copy` elements, drop the remainder. - if (cont_data->stack.not_null() && !cont_data->stack->is_empty()) { - // `cont` already has a stack, create resulting stack from it - if (copy < 0) { - copy = get_stack().depth(); - } - Ref new_stk; - if (cont->is_unique()) { - // optimization: avoid copying the stack if we hold the only copy of `cont` - new_stk = std::move(cont.unique_write().get_cdata()->stack); - } else { - new_stk = cont_data->stack; - } - new_stk.write().move_from_stack(get_stack(), copy); - consume_stack_gas(new_stk); - set_stack(std::move(new_stk)); - } else { - if (copy >= 0 && copy < stack->depth()) { - get_stack().drop_bottom(stack->depth() - copy); - consume_stack_gas(copy); - } - } - return jump_to(std::move(cont)); - } else { - // have no continuation data, situation is somewhat simpler - if (pass_args >= 0) { - int depth = get_stack().depth(); - if (pass_args > depth) { - throw VmError{Excno::stk_und, "stack underflow while jumping to a continuation: not enough arguments on stack"}; - } else if (pass_args < depth) { - get_stack().drop_bottom(depth - pass_args); - consume_stack_gas(pass_args); - } - } - return jump_to(std::move(cont)); - } -} - -int VmState::ret() { - Ref cont = quit0; - cont.swap(cr.c[0]); - return jump(std::move(cont)); -} - -int VmState::ret(int ret_args) { - Ref cont = quit0; - cont.swap(cr.c[0]); - return jump(std::move(cont), ret_args); -} - -int VmState::ret_alt() { - Ref cont = quit1; - cont.swap(cr.c[1]); - return jump(std::move(cont)); -} - -int VmState::ret_alt(int ret_args) { - Ref cont = quit1; - cont.swap(cr.c[1]); - return jump(std::move(cont), ret_args); -} - -Ref VmState::c1_envelope(Ref cont, bool save) { - if (save) { - force_cregs(cont)->define_c1(cr.c[1]); - force_cregs(cont)->define_c0(cr.c[0]); - } - set_c1(cont); - return cont; -} - -void VmState::c1_save_set(bool save) { - if (save) { - force_cregs(cr.c[0])->define_c1(cr.c[1]); - } - set_c1(cr.c[0]); -} - -Ref VmState::extract_cc(int save_cr, int stack_copy, int cc_args) { - Ref new_stk; - if (stack_copy < 0 || stack_copy == stack->depth()) { - new_stk = std::move(stack); - stack.clear(); - } else if (stack_copy > 0) { - stack->check_underflow(stack_copy); - new_stk = get_stack().split_top(stack_copy); - consume_stack_gas(new_stk); - } else { - new_stk = Ref{true}; - } - Ref cc = Ref{true, std::move(code), cp, std::move(stack), cc_args}; - stack = std::move(new_stk); - if (save_cr & 7) { - ControlData* cdata = cc.unique_write().get_cdata(); - if (save_cr & 1) { - cdata->save.set_c0(std::move(cr.c[0])); - cr.set_c0(quit0); - } - if (save_cr & 2) { - cdata->save.set_c1(std::move(cr.c[1])); - cr.set_c1(quit1); - } - if (save_cr & 4) { - cdata->save.set_c2(std::move(cr.c[2])); - // cr.set_c2(Ref{true}); - } - } - return cc; -} - -int VmState::throw_exception(int excno) { - Stack& stack_ref = get_stack(); - stack_ref.clear(); - stack_ref.push_smallint(0); - stack_ref.push_smallint(excno); - code.clear(); - gas.consume_chk(exception_gas_price); - return jump(get_c2()); -} - -int VmState::throw_exception(int excno, StackEntry&& arg) { - Stack& stack_ref = get_stack(); - stack_ref.clear(); - stack_ref.push(std::move(arg)); - stack_ref.push_smallint(excno); - code.clear(); - gas.consume_chk(exception_gas_price); - return jump(get_c2()); -} - -void GasLimits::gas_exception() const { - throw VmNoGas{}; -} - -void GasLimits::set_limits(long long _max, long long _limit, long long _credit) { - gas_max = _max; - gas_limit = _limit; - gas_credit = _credit; - change_base(_limit + _credit); -} - -void GasLimits::change_limit(long long _limit) { - _limit = std::min(std::max(_limit, 0LL), gas_max); - gas_credit = 0; - gas_limit = _limit; - change_base(_limit); -} - -bool VmState::set_gas_limits(long long _max, long long _limit, long long _credit) { - gas.set_limits(_max, _limit, _credit); - return true; -} - -void VmState::change_gas_limit(long long new_limit) { - VM_LOG(this) << "changing gas limit to " << std::min(new_limit, gas.gas_max); - gas.change_limit(new_limit); -} - -int VmState::step() { - CHECK(code.not_null() && stack.not_null()); - //VM_LOG(st) << "stack:"; stack->dump(VM_LOG(st)); - //VM_LOG(st) << "; cr0.refcnt = " << get_c0()->get_refcnt() - 1 << std::endl; - if (stack_trace) { - stack->dump(std::cerr, 3); - } - ++steps; - if (code->size()) { - return dispatch->dispatch(this, code.write()); - } else if (code->size_refs()) { - VM_LOG(this) << "execute implicit JMPREF"; - gas.consume_chk(implicit_jmpref_gas_price); - Ref cont = Ref{true, load_cell_slice_ref(code->prefetch_ref()), get_cp()}; - return jump(std::move(cont)); - } else { - VM_LOG(this) << "execute implicit RET"; - gas.consume_chk(implicit_ret_gas_price); - return ret(); - } -} - -int VmState::run() { - if (code.is_null() || stack.is_null()) { - // throw VmError{Excno::fatal, "cannot run an uninitialized VM"}; - return (int)Excno::fatal; // no ~ for unhandled exceptions - } - int res; - Guard guard(this); - do { - try { - try { - try { - res = step(); - gas.check(); - } catch (vm::CellBuilder::CellWriteError) { - throw VmError{Excno::cell_ov}; - } catch (vm::CellBuilder::CellCreateError) { - throw VmError{Excno::cell_ov}; - } catch (vm::CellSlice::CellReadError) { - throw VmError{Excno::cell_und}; - } - } catch (const VmError& vme) { - VM_LOG(this) << "handling exception code " << vme.get_errno() << ": " << vme.get_msg(); - try { - ++steps; - res = throw_exception(vme.get_errno()); - } catch (const VmError& vme2) { - VM_LOG(this) << "exception " << vme2.get_errno() << " while handling exception: " << vme.get_msg(); - return ~vme2.get_errno(); - } - } - } catch (VmNoGas vmoog) { - ++steps; - VM_LOG(this) << "unhandled out-of-gas exception: gas consumed=" << gas.gas_consumed() - << ", limit=" << gas.gas_limit; - get_stack().clear(); - get_stack().push_smallint(gas.gas_consumed()); - return vmoog.get_errno(); // no ~ for unhandled exceptions (to make their faking impossible) - } - } while (!res); - if ((res | 1) == -1 && !try_commit()) { - VM_LOG(this) << "automatic commit failed (new data or action cells too deep)"; - get_stack().clear(); - get_stack().push_smallint(0); - return ~(int)Excno::cell_ov; - } - return res; -} - -bool VmState::try_commit() { - if (cr.d[0].not_null() && cr.d[1].not_null() && cr.d[0]->get_depth() <= max_data_depth && - cr.d[1]->get_depth() <= max_data_depth) { - cstate.c4 = cr.d[0]; - cstate.c5 = cr.d[1]; - cstate.committed = true; - return true; - } else { - return false; - } -} - -void VmState::force_commit() { - if (!try_commit()) { - throw VmError{Excno::cell_ov, "cannot commit too deep cells as new data/actions"}; - } -} - -ControlData* force_cdata(Ref& cont) { - if (!cont->get_cdata()) { - cont = Ref{true, cont}; - return cont.unique_write().get_cdata(); - } else { - return cont.write().get_cdata(); - } -} - -ControlRegs* force_cregs(Ref& cont) { - return &force_cdata(cont)->save; -} - -int run_vm_code(Ref code, Ref& stack, int flags, Ref* data_ptr, VmLog log, long long* steps, - GasLimits* gas_limits, std::vector> libraries, Ref init_c7, Ref* actions_ptr) { - VmState vm{code, - std::move(stack), - gas_limits ? *gas_limits : GasLimits{}, - flags, - data_ptr ? *data_ptr : Ref{}, - log, - std::move(libraries), - std::move(init_c7)}; - int res = vm.run(); - stack = vm.get_stack_ref(); - if (vm.committed() && data_ptr) { - *data_ptr = vm.get_committed_state().c4; - } - if (vm.committed() && actions_ptr) { - *actions_ptr = vm.get_committed_state().c5; - } - if (steps) { - *steps = vm.get_steps_count(); - } - if (gas_limits) { - *gas_limits = vm.get_gas_limits(); - LOG(INFO) << "steps: " << vm.get_steps_count() << " gas: used=" << gas_limits->gas_consumed() - << ", max=" << gas_limits->gas_max << ", limit=" << gas_limits->gas_limit - << ", credit=" << gas_limits->gas_credit; - } - if ((vm.get_log().log_mask & vm::VmLog::DumpStack) != 0) { - VM_LOG(&vm) << "BEGIN_STACK_DUMP"; - for (int i = stack->depth(); i > 0; i--) { - VM_LOG(&vm) << (*stack)[i - 1].to_string(); - } - VM_LOG(&vm) << "END_STACK_DUMP"; - } - - return ~res; -} - -int run_vm_code(Ref code, Stack& stack, int flags, Ref* data_ptr, VmLog log, long long* steps, - GasLimits* gas_limits, std::vector> libraries, Ref init_c7, Ref* actions_ptr) { - Ref stk{true}; - stk.unique_write().set_contents(std::move(stack)); - stack.clear(); - int res = run_vm_code(code, stk, flags, data_ptr, log, steps, gas_limits, std::move(libraries), std::move(init_c7), - actions_ptr); - CHECK(stack.is_unique()); - if (stk.is_null()) { - stack.clear(); - } else if (&(*stk) != &stack) { - VmState* st = nullptr; - if (stk->is_unique()) { - VM_LOG(st) << "move resulting stack (" << stk->depth() << " entries)"; - stack.set_contents(std::move(stk.unique_write())); - } else { - VM_LOG(st) << "copying resulting stack (" << stk->depth() << " entries)"; - stack.set_contents(*stk); - } - } - return res; -} - -// may throw a dictionary exception; returns nullptr if library is not found in context -Ref VmState::load_library(td::ConstBitPtr hash) { - std::unique_ptr tmp_ctx; - // install temporary dummy vm state interface to prevent charging for cell load operations during library lookup - VmStateInterface::Guard(tmp_ctx.get()); - for (const auto& lib_collection : libraries) { - auto lib = lookup_library_in(hash, lib_collection); - if (lib.not_null()) { - return lib; - } - } - return {}; -} - -bool VmState::register_library_collection(Ref lib) { - if (lib.is_null()) { - return true; - } - libraries.push_back(std::move(lib)); - return true; -} - -void VmState::register_cell_load(const CellHash& cell_hash) { - if (cell_load_gas_price == cell_reload_gas_price) { - consume_gas(cell_load_gas_price); - } else { - auto ok = loaded_cells.insert(cell_hash); // check whether this is the first time this cell is loaded - if (ok.second) { - loaded_cells_count++; - } - consume_gas(ok.second ? cell_load_gas_price : cell_reload_gas_price); - } -} - -void VmState::register_cell_create() { - consume_gas(cell_create_gas_price); -} - -td::BitArray<256> VmState::get_state_hash() const { - // TODO: implement properly, by serializing the stack etc, and computing the Merkle hash - td::BitArray<256> res; - res.clear(); - return res; -} - -td::BitArray<256> VmState::get_final_state_hash(int exit_code) const { - // TODO: implement properly, by serializing the stack etc, and computing the Merkle hash - td::BitArray<256> res; - res.clear(); - return res; -} - -Ref lookup_library_in(td::ConstBitPtr key, vm::Dictionary& dict) { - try { - auto val = dict.lookup(key, 256); - if (val.is_null() || !val->have_refs()) { - return {}; - } - auto root = val->prefetch_ref(); - if (root.not_null() && !root->get_hash().bits().compare(key, 256)) { - return root; - } - return {}; - } catch (vm::VmError) { - return {}; - } -} - -Ref lookup_library_in(td::ConstBitPtr key, Ref lib_root) { - if (lib_root.is_null()) { - return lib_root; - } - vm::Dictionary dict{std::move(lib_root), 256}; - return lookup_library_in(key, dict); -} - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/vm.h b/submodules/ton/tonlib-src/crypto/vm/vm.h deleted file mode 100644 index 0fef9642..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/vm.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "common/refcnt.hpp" -#include "vm/cellslice.h" -#include "vm/stack.hpp" -#include "vm/vmstate.h" -#include "vm/log.h" -#include "vm/continuation.h" -#include "td/utils/HashSet.h" - -namespace vm { - -using td::Ref; -struct GasLimits { - static constexpr long long infty = (1ULL << 63) - 1; - long long gas_max, gas_limit, gas_credit, gas_remaining, gas_base; - GasLimits() : gas_max(infty), gas_limit(infty), gas_credit(0), gas_remaining(infty), gas_base(infty) { - } - GasLimits(long long _limit, long long _max = infty, long long _credit = 0) - : gas_max(_max) - , gas_limit(_limit) - , gas_credit(_credit) - , gas_remaining(_limit + _credit) - , gas_base(gas_remaining) { - } - long long gas_consumed() const { - return gas_base - gas_remaining; - } - void set_limits(long long _max, long long _limit, long long _credit = 0); - void change_base(long long _base) { - gas_remaining += _base - gas_base; - gas_base = _base; - } - void change_limit(long long _limit); - void consume(long long amount) { - // LOG(DEBUG) << "consume " << amount << " gas (" << gas_remaining << " remaining)"; - gas_remaining -= amount; - } - bool try_consume(long long amount) { - // LOG(DEBUG) << "try consume " << amount << " gas (" << gas_remaining << " remaining)"; - return (gas_remaining -= amount) >= 0; - } - void gas_exception() const; - void gas_exception(bool cond) const { - if (!cond) { - gas_exception(); - } - } - void consume_chk(long long amount) { - gas_exception(try_consume(amount)); - } - void check() const { - gas_exception(gas_remaining >= 0); - } - bool final_ok() const { - return gas_remaining >= gas_credit; - } -}; - -struct CommittedState { - Ref c4, c5; - bool committed{false}; -}; - -class VmState final : public VmStateInterface { - Ref code; - Ref stack; - ControlRegs cr; - CommittedState cstate; - int cp; - long long steps{0}; - const DispatchTable* dispatch; - Ref quit0, quit1; - VmLog log; - GasLimits gas; - std::vector> libraries; - td::HashSet loaded_cells; - td::int64 loaded_cells_count{0}; - int stack_trace{0}, debug_off{0}; - bool chksig_always_succeed{false}; - - public: - enum { - cell_load_gas_price = 100, - cell_reload_gas_price = 25, - cell_create_gas_price = 500, - exception_gas_price = 50, - tuple_entry_gas_price = 1, - implicit_jmpref_gas_price = 10, - implicit_ret_gas_price = 5, - free_stack_depth = 32, - stack_entry_gas_price = 1, - max_data_depth = 512 - }; - VmState(); - VmState(Ref _code); - VmState(Ref _code, Ref _stack, int flags = 0, Ref _data = {}, VmLog log = {}, - std::vector> _libraries = {}, Ref init_c7 = {}); - VmState(Ref _code, Ref _stack, const GasLimits& _gas, int flags = 0, Ref _data = {}, - VmLog log = {}, std::vector> _libraries = {}, Ref init_c7 = {}); - template - VmState(Ref code_cell, Args&&... args) - : VmState(convert_code_cell(std::move(code_cell)), std::forward(args)...) { - } - VmState(const VmState&) = delete; - VmState(VmState&&) = delete; - VmState& operator=(const VmState&) = delete; - VmState& operator=(VmState&&) = delete; - bool set_gas_limits(long long _max, long long _limit, long long _credit = 0); - bool final_gas_ok() const { - return gas.final_ok(); - } - long long gas_consumed() const { - return gas.gas_consumed(); - } - bool committed() const { - return cstate.committed; - } - const CommittedState& get_committed_state() const { - return cstate; - } - void consume_gas(long long amount) { - gas.consume(amount); - } - void consume_tuple_gas(unsigned tuple_len) { - consume_gas(tuple_len * tuple_entry_gas_price); - } - void consume_tuple_gas(const Ref& tup) { - if (tup.not_null()) { - consume_tuple_gas((unsigned)tup->size()); - } - } - void consume_stack_gas(unsigned stack_depth) { - consume_gas((std::max(stack_depth, (unsigned)free_stack_depth) - free_stack_depth) * stack_entry_gas_price); - } - void consume_stack_gas(const Ref& stk) { - if (stk.not_null()) { - consume_stack_gas((unsigned)stk->depth()); - } - } - GasLimits get_gas_limits() const { - return gas; - } - void change_gas_limit(long long new_limit); - template - void check_underflow(Args... args) { - stack->check_underflow(args...); - } - bool register_library_collection(Ref lib); - Ref load_library( - td::ConstBitPtr hash) override; // may throw a dictionary exception; returns nullptr if library is not found - void register_cell_load(const CellHash& cell_hash) override; - void register_cell_create() override; - bool init_cp(int new_cp); - bool set_cp(int new_cp); - void force_cp(int new_cp); - int get_cp() const { - return cp; - } - int incr_stack_trace(int v) { - return stack_trace += v; - } - long long get_steps_count() const { - return steps; - } - td::BitArray<256> get_state_hash() const; - td::BitArray<256> get_final_state_hash(int exit_code) const; - int step(); - int run(); - Stack& get_stack() { - return stack.write(); - } - const Stack& get_stack_const() const { - return *stack; - } - Ref get_stack_ref() const { - return stack; - } - Ref get_c0() const { - return cr.c[0]; - } - Ref get_c1() const { - return cr.c[1]; - } - Ref get_c2() const { - return cr.c[2]; - } - Ref get_c3() const { - return cr.c[3]; - } - Ref get_c4() const { - return cr.d[0]; - } - Ref get_c7() const { - return cr.c7; - } - Ref get_c(unsigned idx) const { - return cr.get_c(idx); - } - Ref get_d(unsigned idx) const { - return cr.get_d(idx); - } - StackEntry get(unsigned idx) const { - return cr.get(idx); - } - const VmLog& get_log() const { - return log; - } - void define_c0(Ref cont) { - cr.define_c0(std::move(cont)); - } - void set_c0(Ref cont) { - cr.set_c0(std::move(cont)); - } - void set_c1(Ref cont) { - cr.set_c1(std::move(cont)); - } - void set_c2(Ref cont) { - cr.set_c2(std::move(cont)); - } - bool set_c(unsigned idx, Ref val) { - return cr.set_c(idx, std::move(val)); - } - bool set_d(unsigned idx, Ref val) { - return cr.set_d(idx, std::move(val)); - } - void set_c4(Ref val) { - cr.set_c4(std::move(val)); - } - bool set_c7(Ref val) { - return cr.set_c7(std::move(val)); - } - bool set(unsigned idx, StackEntry val) { - return cr.set(idx, std::move(val)); - } - void set_stack(Ref new_stk) { - stack = std::move(new_stk); - } - Ref swap_stack(Ref new_stk) { - stack.swap(new_stk); - return new_stk; - } - void ensure_throw(bool cond) const { - if (!cond) { - fatal(); - } - } - void set_code(Ref _code, int _cp) { - code = std::move(_code); - force_cp(_cp); - } - Ref get_code() const { - return code; - } - void push_code() { - get_stack().push_cellslice(get_code()); - } - void adjust_cr(const ControlRegs& save) { - cr ^= save; - } - void adjust_cr(ControlRegs&& save) { - cr ^= save; - } - void preclear_cr(const ControlRegs& save) { - cr &= save; - } - int call(Ref cont); - int call(Ref cont, int pass_args, int ret_args = -1); - int jump(Ref cont); - int jump(Ref cont, int pass_args); - int ret(); - int ret(int ret_args); - int ret_alt(); - int ret_alt(int ret_args); - int repeat(Ref body, Ref after, long long count); - int again(Ref body); - int until(Ref body, Ref after); - int loop_while(Ref cond, Ref body, Ref after); - int throw_exception(int excno, StackEntry&& arg); - int throw_exception(int excno); - Ref extract_cc(int save_cr = 1, int stack_copy = -1, int cc_args = -1); - Ref c1_envelope(Ref cont, bool save = true); - Ref c1_envelope_if(bool cond, Ref cont, bool save = true) { - return cond ? c1_envelope(std::move(cont), save) : std::move(cont); - } - void c1_save_set(bool save = true); - void fatal(void) const { - throw VmFatal{}; - } - int jump_to(Ref cont) { - return cont->is_unique() ? cont.unique_write().jump_w(this) : cont->jump(this); - } - static Ref convert_code_cell(Ref code_cell); - bool try_commit(); - void force_commit(); - - void set_chksig_always_succeed(bool flag) { - chksig_always_succeed = flag; - } - bool get_chksig_always_succeed() const { - return chksig_always_succeed; - } - Ref ref_to_cont(Ref cell) const { - return td::make_ref(load_cell_slice_ref(std::move(cell)), get_cp()); - } - - private: - void init_cregs(bool same_c3 = false, bool push_0 = true); -}; - -int run_vm_code(Ref _code, Ref& _stack, int flags = 0, Ref* data_ptr = nullptr, VmLog log = {}, - long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}, - Ref init_c7 = {}, Ref* actions_ptr = nullptr); -int run_vm_code(Ref _code, Stack& _stack, int flags = 0, Ref* data_ptr = nullptr, VmLog log = {}, - long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}, - Ref init_c7 = {}, Ref* actions_ptr = nullptr); - -Ref lookup_library_in(td::ConstBitPtr key, Ref lib_root); - -} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/vmstate.h b/submodules/ton/tonlib-src/crypto/vm/vmstate.h deleted file mode 100644 index a81a4e78..00000000 --- a/submodules/ton/tonlib-src/crypto/vm/vmstate.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "common/refcnt.hpp" -#include "vm/cells.h" - -#include "td/utils/Context.h" - -namespace vm { -using td::Ref; - -class VmStateInterface : public td::Context { - public: - virtual ~VmStateInterface() = default; - virtual Ref load_library( - td::ConstBitPtr hash) { // may throw a dictionary exception; returns nullptr if library is not found - return {}; - } - virtual void register_cell_load(const CellHash& cell_hash){}; - virtual void register_cell_create(){}; - virtual void register_new_cell(Ref& cell){}; - virtual bool register_op(int op_units = 1) { - return true; - }; -}; - -} // namespace vm diff --git a/submodules/ton/tonlib-src/keys/CMakeLists.txt b/submodules/ton/tonlib-src/keys/CMakeLists.txt deleted file mode 100644 index 486119de..00000000 --- a/submodules/ton/tonlib-src/keys/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -set(KEYS_SOURCE - keys.cpp - encryptor.cpp - keys.hpp - encryptor.h - encryptor.hpp -) - -add_library(keys STATIC ${KEYS_SOURCE}) - -target_include_directories(keys PUBLIC $) -target_link_libraries(keys PUBLIC tdactor ton_crypto tl_api tl-utils ) diff --git a/submodules/ton/tonlib-src/keys/encryptor.cpp b/submodules/ton/tonlib-src/keys/encryptor.cpp deleted file mode 100644 index 0b93d36f..00000000 --- a/submodules/ton/tonlib-src/keys/encryptor.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/crypto.h" -#include "td/utils/overloaded.h" - -#include "encryptor.h" -#include "encryptor.hpp" -#include "auto/tl/ton_api.hpp" - -#include "common/status.h" -#include "common/errorcode.h" -#include "keys.hpp" - -namespace ton { - -td::Result> Encryptor::create(const ton_api::PublicKey *id) { - td::Result> res; - ton_api::downcast_call( - *const_cast(id), - td::overloaded([&](const ton_api::pub_unenc &obj) { res = std::make_unique(); }, - [&](const ton_api::pub_ed25519 &obj) { res = std::make_unique(obj.key_); }, - [&](const ton_api::pub_overlay &obj) { res = std::make_unique(); }, - [&](const ton_api::pub_aes &obj) { res = std::make_unique(obj.key_); })); - return res; -} - -td::Result> Decryptor::create(const ton_api::PrivateKey *id) { - td::Result> res; - ton_api::downcast_call( - *const_cast(id), - td::overloaded([&](const ton_api::pk_unenc &obj) { res = std::make_unique(); }, - [&](const ton_api::pk_ed25519 &obj) { res = std::make_unique(obj.key_); }, - [&](const ton_api::pk_overlay &obj) { res = std::make_unique(); }, - [&](const ton_api::pk_aes &obj) { res = std::make_unique(obj.key_); })); - return res; -} - -td::Result EncryptorEd25519::encrypt(td::Slice data) { - TRY_RESULT_PREFIX(pk, td::Ed25519::generate_private_key(), "failed to generate private key: "); - TRY_RESULT_PREFIX(pubkey, pk.get_public_key(), "failed to get public key from private: "); - auto pubkey_str = pubkey.as_octet_string(); - - td::BufferSlice msg(pubkey_str.size() + 32 + data.size()); - td::MutableSlice slice = msg.as_slice(); - slice.copy_from(pubkey_str); - slice.remove_prefix(pubkey_str.size()); - - TRY_RESULT_PREFIX(shared_secret, td::Ed25519::compute_shared_secret(pub_, pk), "failed to compute shared secret: "); - - td::MutableSlice digest = slice.substr(0, 32); - slice.remove_prefix(32); - td::sha256(data, digest); - - td::SecureString key(32); - { - auto S = key.as_mutable_slice(); - S.copy_from(td::Slice(shared_secret).truncate(16)); - S.remove_prefix(16); - S.copy_from(digest.copy().remove_prefix(16).truncate(16)); - } - - td::SecureString iv(16); - { - auto S = iv.as_mutable_slice(); - S.copy_from(digest.copy().truncate(4)); - S.remove_prefix(4); - S.copy_from(td::Slice(shared_secret).remove_prefix(20).truncate(12)); - } - - td::AesCtrState ctr; - ctr.init(key, iv); - ctr.encrypt(data, slice); - - return std::move(msg); -} - -td::Status EncryptorEd25519::check_signature(td::Slice message, td::Slice signature) { - return td::status_prefix(pub_.verify_signature(message, signature), "bad signature: "); -} - -td::Result DecryptorEd25519::decrypt(td::Slice data) { - if (data.size() < td::Ed25519::PublicKey::LENGTH + 32) { - return td::Status::Error(ErrorCode::protoviolation, "message is too short"); - } - - td::Slice pub = data.substr(0, td::Ed25519::PublicKey::LENGTH); - data.remove_prefix(td::Ed25519::PublicKey::LENGTH); - - td::Slice digest = data.substr(0, 32); - data.remove_prefix(32); - - TRY_RESULT_PREFIX(shared_secret, - td::Ed25519::compute_shared_secret(td::Ed25519::PublicKey(td::SecureString(pub)), pk_), - "failed to generate shared secret: "); - - td::SecureString key(32); - key.as_mutable_slice().copy_from(td::Slice(shared_secret).substr(0, 16)); - key.as_mutable_slice().substr(16).copy_from(digest.substr(16, 16)); - - td::SecureString iv(16); - iv.as_mutable_slice().copy_from(digest.substr(0, 4)); - iv.as_mutable_slice().substr(4).copy_from(td::Slice(shared_secret).substr(20, 12)); - - td::BufferSlice res(data.size()); - - td::AesCtrState ctr; - ctr.init(key, iv); - ctr.encrypt(data, res.as_slice()); - - td::UInt256 real_digest; - td::sha256(res.as_slice(), as_slice(real_digest)); - - if (as_slice(real_digest) != digest) { - return td::Status::Error(ErrorCode::protoviolation, "sha256 mismatch after decryption"); - } - - return std::move(res); -} - -td::Result DecryptorEd25519::sign(td::Slice data) { - TRY_RESULT_PREFIX(signature, pk_.sign(data), "failed to sign: "); - return td::BufferSlice(signature); -} - -td::Result EncryptorAES::encrypt(td::Slice data) { - td::BufferSlice msg(32 + data.size()); - td::MutableSlice slice = msg.as_slice(); - - td::MutableSlice digest = slice.substr(0, 32); - slice.remove_prefix(32); - td::sha256(data, digest); - - td::SecureString key(32); - key.as_mutable_slice().copy_from(shared_secret_.as_slice().substr(0, 16)); - key.as_mutable_slice().substr(16).copy_from(digest.substr(16, 16)); - - td::SecureString iv(16); - iv.as_mutable_slice().copy_from(digest.substr(0, 4)); - iv.as_mutable_slice().substr(4).copy_from(shared_secret_.as_slice().substr(20, 12)); - - td::AesCtrState ctr; - ctr.init(key, iv); - ctr.encrypt(data, slice); - - return std::move(msg); -} - -td::Result DecryptorAES::decrypt(td::Slice data) { - if (data.size() < 32) { - return td::Status::Error(ErrorCode::protoviolation, "message is too short"); - } - - td::Slice digest = data.substr(0, 32); - data.remove_prefix(32); - - td::SecureString key(32); - key.as_mutable_slice().copy_from(shared_secret_.as_slice().substr(0, 16)); - key.as_mutable_slice().substr(16).copy_from(digest.substr(16, 16)); - - td::SecureString iv(16); - iv.as_mutable_slice().copy_from(digest.substr(0, 4)); - iv.as_mutable_slice().substr(4).copy_from(shared_secret_.as_slice().substr(20, 12)); - - td::BufferSlice res(data.size()); - - td::AesCtrState ctr; - ctr.init(key, iv); - ctr.encrypt(data, res.as_slice()); - - td::UInt256 real_digest; - td::sha256(res.as_slice(), as_slice(real_digest)); - - if (as_slice(real_digest) != digest) { - return td::Status::Error(ErrorCode::protoviolation, "sha256 mismatch after decryption"); - } - - return std::move(res); -} - -std::vector> Decryptor::sign_batch(std::vector data) { - std::vector> r; - r.resize(data.size()); - for (size_t i = 0; i < data.size(); i++) { - r[i] = sign(data[i]); - } - return r; -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/keys/encryptor.h b/submodules/ton/tonlib-src/keys/encryptor.h deleted file mode 100644 index 3035a0ce..00000000 --- a/submodules/ton/tonlib-src/keys/encryptor.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" -#include "td/utils/buffer.h" -#include "td/utils/Status.h" -#include "td/actor/PromiseFuture.h" -#include "auto/tl/ton_api.h" - -namespace ton { - -class Encryptor { - public: - virtual td::Result encrypt(td::Slice data) = 0; - virtual td::Status check_signature(td::Slice message, td::Slice signature) = 0; - virtual ~Encryptor() = default; - static td::Result> create(const ton_api::PublicKey *id); -}; - -class Decryptor { - public: - virtual td::Result decrypt(td::Slice data) = 0; - virtual td::Result sign(td::Slice data) = 0; - virtual std::vector> sign_batch(std::vector data); - virtual ~Decryptor() = default; - static td::Result> create(const ton_api::PrivateKey *id); -}; - -class EncryptorAsync : public td::actor::Actor { - private: - std::unique_ptr encryptor_; - - public: - EncryptorAsync(std::unique_ptr encryptor) : encryptor_(std::move(encryptor)) { - } - void check_signature(td::BufferSlice data, td::BufferSlice signature, td::Promise promise) { - auto res = encryptor_->check_signature(data.as_slice(), signature.as_slice()); - if (res.is_ok()) { - promise.set_value(td::Unit()); - } else { - promise.set_error(res.move_as_error()); - } - } - void encrypt(td::BufferSlice data, td::Promise promise) { - promise.set_result(encryptor_->encrypt(data.as_slice())); - } - template - static td::Result> create(T &id) { - TRY_RESULT(d, Encryptor::create(id)); - return td::actor::create_actor("encryptor", std::move(d)); - } - template - static td::Result> create(T *id) { - TRY_RESULT(d, Encryptor::create(id)); - return td::actor::create_actor("encryptor", std::move(d)); - } -}; - -class DecryptorAsync : public td::actor::Actor { - private: - std::unique_ptr decryptor_; - - public: - DecryptorAsync(std::unique_ptr decryptor) : decryptor_(std::move(decryptor)) { - } - auto decrypt(td::BufferSlice data) { - return decryptor_->decrypt(data.as_slice()); - } - auto sign(td::BufferSlice data) { - return decryptor_->sign(data.as_slice()); - } - auto sign_batch(std::vector data) { - std::vector v; - v.resize(data.size()); - for (size_t i = 0; i < data.size(); i++) { - v[i] = data[i].as_slice(); - } - return decryptor_->sign_batch(v); - } - template - static td::Result> create(T &id) { - TRY_RESULT(d, Decryptor::create(id)); - return td::actor::create_actor("decryptor", std::move(d)); - } - template - static td::Result> create(T *id) { - TRY_RESULT(d, Decryptor::create(id)); - return td::actor::create_actor("decryptor", std::move(d)); - } -}; - -} // namespace ton diff --git a/submodules/ton/tonlib-src/keys/encryptor.hpp b/submodules/ton/tonlib-src/keys/encryptor.hpp deleted file mode 100644 index dbe88239..00000000 --- a/submodules/ton/tonlib-src/keys/encryptor.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "encryptor.h" -#include "crypto/Ed25519.h" -#include "auto/tl/ton_api.h" -#include "tl-utils/tl-utils.hpp" - -namespace ton { - -class EncryptorNone : public Encryptor { - public: - td::Result encrypt(td::Slice data) override { - return td::BufferSlice(data); - } - td::Status check_signature(td::Slice message, td::Slice signature) override { - return td::Status::OK(); - } - - EncryptorNone() { - } -}; - -class DecryptorNone : public Decryptor { - public: - td::Result decrypt(td::Slice data) override { - return td::BufferSlice(data); - } - td::Result sign(td::Slice data) override { - return td::BufferSlice(""); - } - DecryptorNone() { - } -}; - -class EncryptorFail : public Encryptor { - public: - td::Result encrypt(td::Slice data) override { - return td::Status::Error("Fail encryptor"); - } - td::Status check_signature(td::Slice message, td::Slice signature) override { - return td::Status::Error("Fail encryptor"); - } - - EncryptorFail() { - } -}; - -class DecryptorFail : public Decryptor { - public: - td::Result decrypt(td::Slice data) override { - return td::Status::Error("Fail decryptor"); - } - td::Result sign(td::Slice data) override { - return td::Status::Error("Fail decryptor"); - } - DecryptorFail() { - } -}; - -class EncryptorEd25519 : public Encryptor { - private: - td::Ed25519::PublicKey pub_; - - public: - td::Result encrypt(td::Slice data) override; - td::Status check_signature(td::Slice message, td::Slice signature) override; - - EncryptorEd25519(td::Bits256 key) : pub_(td::SecureString(as_slice(key))) { - } -}; - -class DecryptorEd25519 : public Decryptor { - private: - td::Ed25519::PrivateKey pk_; - - public: - td::Result decrypt(td::Slice data) override; - td::Result sign(td::Slice data) override; - DecryptorEd25519(td::Bits256 key) : pk_(td::SecureString(as_slice(key))) { - } -}; - -class EncryptorOverlay : public Encryptor { - public: - EncryptorOverlay() { - } - td::Result encrypt(td::Slice data) override { - return td::Status::Error("overlay id can not be used for encryption"); - } - td::Status check_signature(td::Slice message, td::Slice signature) override { - auto R = fetch_tl_object(message, true); - if (R.is_error()) { - return R.move_as_error(); - } - if (signature.size() > 0) { - return td::Status::Error("overlay signature must be empty"); - } - auto G = R.move_as_ok(); - if (G->update_rule_->get_id() != ton_api::dht_updateRule_overlayNodes::ID) { - return td::Status::Error("overlay update rule should be 'overlayNodes'"); - } - if (G->signature_.size() > 0) { - return td::Status::Error("overlay signature must be empty"); - } - return td::Status::OK(); - } -}; - -class EncryptorAES : public Encryptor { - private: - td::Bits256 shared_secret_; - - public: - td::Result encrypt(td::Slice data) override; - td::Status check_signature(td::Slice message, td::Slice signature) override { - return td::Status::Error("can no sign channel messages"); - } - - EncryptorAES(td::Bits256 shared_secret) : shared_secret_(shared_secret) { - } -}; - -class DecryptorAES : public Decryptor { - private: - td::Bits256 shared_secret_; - - public: - td::Result decrypt(td::Slice data) override; - td::Result sign(td::Slice data) override { - return td::Status::Error("can no sign channel messages"); - } - DecryptorAES(td::Bits256 shared_secret) : shared_secret_(shared_secret) { - } -}; - -} // namespace ton diff --git a/submodules/ton/tonlib-src/keys/keys.cpp b/submodules/ton/tonlib-src/keys/keys.cpp deleted file mode 100644 index 7d6c0c2c..00000000 --- a/submodules/ton/tonlib-src/keys/keys.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "keys.hpp" -#include "auto/tl/ton_api.hpp" -#include "td/utils/overloaded.h" -#include "tl-utils/tl-utils.hpp" -#include "encryptor.h" -#include "crypto/Ed25519.h" - -namespace ton { - -PublicKeyHash::PublicKeyHash(const tl_object_ptr &value) { - value_ = get_tl_object_sha_bits256(value); -} - -PublicKey::PublicKey(const tl_object_ptr &id) { - ton_api::downcast_call( - *const_cast(id.get()), - td::overloaded([&](const ton_api::pub_ed25519 &obj) { this->pub_key_ = pubkeys::Ed25519{obj}; }, - [&](const ton_api::pub_aes &obj) { this->pub_key_ = pubkeys::AES{obj}; }, - [&](const ton_api::pub_unenc &obj) { this->pub_key_ = pubkeys::Unenc{obj}; }, - [&](const ton_api::pub_overlay &obj) { this->pub_key_ = pubkeys::Overlay{obj}; })); -} - -PublicKeyHash PublicKey::compute_short_id() const { - return PublicKeyHash{get_tl_object_sha_bits256(tl())}; -} - -td::uint32 PublicKey::serialized_size() const { - td::uint32 res = 0; - pub_key_.visit([&](auto &obj) { res = obj.serialized_size(); }); - return res; -} - -tl_object_ptr PublicKey::tl() const { - tl_object_ptr res; - pub_key_.visit([&](auto &obj) { res = obj.tl(); }); - return res; -} - -td::BufferSlice PublicKey::export_as_slice() const { - return serialize_tl_object(tl(), true); -} - -td::Result PublicKey::import(td::Slice s) { - TRY_RESULT(x, fetch_tl_object(s, true)); - return PublicKey{x}; -} - -td::Result> PublicKey::create_encryptor() const { - return Encryptor::create(tl().get()); -} - -td::Result> PublicKey::create_encryptor_async() const { - return EncryptorAsync::create(tl().get()); -} - -bool PublicKey::empty() const { - return pub_key_.get_offset() == pub_key_.offset(); -} - -tl_object_ptr privkeys::Ed25519::pub_tl() const { - td::Ed25519::PrivateKey pkey(td::SecureString(as_slice(data_))); - auto r_public_key = pkey.get_public_key(); - if (r_public_key.is_error()) { - return nullptr; - } else { - auto public_key = r_public_key.ok().as_octet_string(); - td::Bits256 X; - as_slice(X).copy_from(public_key); - return create_tl_object(X); - } -} - -pubkeys::Ed25519 privkeys::Ed25519::pub() const { - td::Ed25519::PrivateKey pkey(td::SecureString(as_slice(data_))); - return pubkeys::Ed25519{pkey.get_public_key().move_as_ok()}; -} - -privkeys::Ed25519 privkeys::Ed25519::random() { - while (true) { - auto key = td::Ed25519::generate_private_key(); - if (key.is_error()) { - LOG(WARNING) << "failed to generate private key: " << key.move_as_error(); - } - return Ed25519{key.move_as_ok()}; - } -} - -privkeys::Ed25519::Ed25519(td::Ed25519::PrivateKey key) { - auto s = key.as_octet_string(); - CHECK(s.length() == 32); - data_.as_slice().copy_from(td::Slice(s)); -} - -pubkeys::Ed25519::Ed25519(td::Ed25519::PublicKey key) { - auto s = key.as_octet_string(); - CHECK(s.length() == 32); - data_.as_slice().copy_from(td::Slice(s)); -} - -PrivateKey::PrivateKey(const tl_object_ptr &id) { - ton_api::downcast_call( - *const_cast(id.get()), - td::overloaded([&](const ton_api::pk_ed25519 &obj) { this->priv_key_ = privkeys::Ed25519{obj}; }, - [&](const ton_api::pk_aes &obj) { this->priv_key_ = privkeys::AES{obj}; }, - [&](const ton_api::pk_unenc &obj) { this->priv_key_ = privkeys::Unenc{obj}; }, - [&](const ton_api::pk_overlay &obj) { this->priv_key_ = privkeys::Overlay{obj}; })); -} - -bool PrivateKey::empty() const { - return priv_key_.get_offset() == priv_key_.offset(); -} - -PublicKey PrivateKey::compute_public_key() const { - PublicKey res; - priv_key_.visit([&](auto &obj) { res = obj.pub(); }); - return res; -} - -PublicKeyHash PrivateKey::compute_short_id() const { - tl_object_ptr res; - priv_key_.visit([&](auto &obj) { res = obj.pub_tl(); }); - return PublicKeyHash{res}; -} - -td::SecureString PrivateKey::export_as_slice() const { - td::SecureString res; - priv_key_.visit([&](auto &obj) { res = obj.export_as_slice(); }); - return res; -} - -bool PrivateKey::exportable() const { - bool res; - priv_key_.visit([&](auto &obj) { res = obj.exportable(); }); - return res; -} - -td::Result PrivateKey::import(td::Slice s) { - if (s.size() < 4) { - return td::Status::Error(ErrorCode::protoviolation, "too short key"); - } - td::int32 id; - td::MutableSlice{reinterpret_cast(&id), 4}.copy_from(s.copy().truncate(4)); - s.remove_prefix(4); - switch (id) { - case ton_api::pk_ed25519::ID: { - auto R = privkeys::Ed25519::import(s); - if (R.is_error()) { - return R.move_as_error(); - } else { - return R.move_as_ok(); - } - } break; - case ton_api::pk_aes::ID: { - auto R = privkeys::AES::import(s); - if (R.is_error()) { - return R.move_as_error(); - } else { - return R.move_as_ok(); - } - } break; - default: - return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "unknown magic " << id); - } -} - -tl_object_ptr PrivateKey::tl() const { - tl_object_ptr res; - priv_key_.visit([&](auto &obj) { res = obj.tl(); }); - return res; -} - -td::Result> PrivateKey::create_decryptor() const { - return Decryptor::create(tl().get()); -} - -td::Result> PrivateKey::create_decryptor_async() const { - return DecryptorAsync::create(tl().get()); -} - -} // namespace ton diff --git a/submodules/ton/tonlib-src/keys/keys.hpp b/submodules/ton/tonlib-src/keys/keys.hpp deleted file mode 100644 index cf883bbe..00000000 --- a/submodules/ton/tonlib-src/keys/keys.hpp +++ /dev/null @@ -1,477 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/int_types.h" -#include "td/utils/buffer.h" -#include "auto/tl/ton_api.h" -#include "td/utils/UInt.h" -#include "td/utils/Variant.h" -#include "td/actor/actor.h" -#include "crypto/common/bitstring.h" -#include "crypto/Ed25519.h" -#include "common/errorcode.h" - -namespace ton { - -class Encryptor; -class EncryptorAsync; -class Decryptor; -class DecryptorAsync; - -class PublicKeyHash { - public: - explicit PublicKeyHash(td::Bits256 value) : value_(value) { - } - explicit PublicKeyHash(const tl_object_ptr &value); - PublicKeyHash() { - } - static PublicKeyHash zero() { - return PublicKeyHash{td::Bits256::zero()}; - } - explicit PublicKeyHash(td::Slice data) { - CHECK(data.size() == 32); - value_.as_slice().copy_from(data); - } - - td::UInt256 uint256_value() const { - td::UInt256 x; - x.as_slice().copy_from(value_.as_slice()); - return x; - } - td::Bits256 bits256_value() const { - return value_; - } - auto tl() const { - return value_; - } - - bool operator<(const PublicKeyHash &with) const { - return value_ < with.value_; - } - bool operator==(const PublicKeyHash &with) const { - return value_ == with.value_; - } - bool operator!=(const PublicKeyHash &with) const { - return value_ != with.value_; - } - td::Slice as_slice() const { - return td::as_slice(value_); - } - bool is_zero() const { - return value_.is_zero(); - } - - private: - td::Bits256 value_; -}; - -namespace pubkeys { - -class Ed25519 { - private: - td::Bits256 data_; - - public: - Ed25519(const ton_api::pub_ed25519 &obj) { - data_ = obj.key_; - } - Ed25519(td::Bits256 id) : data_(id) { - } - Ed25519() { - } - Ed25519(td::Ed25519::PublicKey pk); - td::Ed25519::PublicKey export_key() { - return td::Ed25519::PublicKey{td::SecureString(data_.as_slice())}; - } - - auto raw() const { - return data_; - } - td::uint32 serialized_size() const { - return 36; - } - tl_object_ptr tl() const { - return create_tl_object(data_); - } - bool operator==(const Ed25519 &with) const { - return data_ == with.data_; - } - bool operator!=(const Ed25519 &with) const { - return data_ != with.data_; - } -}; - -class AES { - private: - td::Bits256 data_; - - public: - ~AES() { - data_.set_zero_s(); - } - AES(const ton_api::pub_aes &obj) { - data_ = obj.key_; - } - AES(td::Slice data) { - CHECK(data.size() == 32); - data_.as_slice().copy_from(data); - } - AES(td::Bits256 data) : data_(data) { - } - td::uint32 serialized_size() const { - return 36; - } - tl_object_ptr tl() const { - return create_tl_object(data_); - } - bool operator==(const AES &with) const { - return data_ == with.data_; - } - bool operator!=(const AES &with) const { - return data_ != with.data_; - } -}; - -class Unenc { - private: - td::SharedSlice data_; - - public: - Unenc(const ton_api::pub_unenc &obj) { - data_ = td::SharedSlice{obj.data_.as_slice()}; - } - Unenc(const Unenc &obj) { - data_ = obj.data_.clone(); - } - explicit Unenc(td::BufferSlice data) : data_(td::SharedSlice{data.as_slice()}) { - } - explicit Unenc(td::Slice data) : data_(td::SharedSlice{data}) { - } - explicit Unenc(td::SharedSlice data) : data_(std::move(data)) { - } - td::uint32 serialized_size() const { - return static_cast(data_.size()) + 8; - } - tl_object_ptr tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - bool operator==(const Unenc &with) const { - return data_.as_slice() == with.data_.as_slice(); - } - bool operator!=(const Unenc &with) const { - return data_.as_slice() != with.data_.as_slice(); - } -}; // namespace pubkeys - -class Overlay { - private: - td::SharedSlice data_; - - public: - Overlay(const ton_api::pub_overlay &obj) { - data_ = td::SharedSlice{obj.name_.as_slice()}; - } - Overlay(const Overlay &obj) { - data_ = obj.data_.clone(); - } - explicit Overlay(td::BufferSlice data) : data_(td::SharedSlice{data.as_slice()}) { - } - explicit Overlay(td::Slice data) : data_(td::SharedSlice{data}) { - } - explicit Overlay(td::SharedSlice data) : data_(std::move(data)) { - } - td::uint32 serialized_size() const { - return static_cast(data_.size()) + 8; - } - tl_object_ptr tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - bool operator==(const Overlay &with) const { - return data_.as_slice() == with.data_.as_slice(); - } - bool operator!=(const Overlay &with) const { - return data_.as_slice() != with.data_.as_slice(); - } -}; - -} // namespace pubkeys - -class PublicKey { - private: - class Empty { - public: - tl_object_ptr tl() const { - UNREACHABLE(); - } - td::uint32 serialized_size() const { - UNREACHABLE(); - } - bool operator==(const Empty &with) const { - return false; - } - bool operator!=(const Empty &with) const { - return true; - } - }; - td::Variant pub_key_{Empty{}}; - - public: - explicit PublicKey(const tl_object_ptr &id); - PublicKey() { - } - PublicKey(pubkeys::Ed25519 pub) : pub_key_(std::move(pub)) { - } - PublicKey(pubkeys::AES pub) : pub_key_(std::move(pub)) { - } - PublicKey(pubkeys::Unenc pub) : pub_key_(std::move(pub)) { - } - PublicKey(pubkeys::Overlay pub) : pub_key_(std::move(pub)) { - } - - bool empty() const; - - PublicKeyHash compute_short_id() const; - td::uint32 serialized_size() const; - tl_object_ptr tl() const; - td::BufferSlice export_as_slice() const; - static td::Result import(td::Slice s); - - pubkeys::Ed25519 ed25519_value() const { - CHECK(pub_key_.get_offset() == pub_key_.offset()); - return pub_key_.get(); - } - - td::Result> create_encryptor() const; - td::Result> create_encryptor_async() const; - - bool operator==(const PublicKey &with) const { - return pub_key_ == with.pub_key_; - } - bool operator!=(const PublicKey &with) const { - return !(pub_key_ == with.pub_key_); - } -}; - -namespace privkeys { - -class Ed25519 { - private: - td::Bits256 data_; - - public: - ~Ed25519() { - data_.set_zero_s(); - } - Ed25519(const ton_api::pk_ed25519 &obj) { - data_ = obj.key_; - } - Ed25519(td::Bits256 id) : data_(id) { - id.set_zero_s(); - } - Ed25519(td::Slice data) { - CHECK(data.size() == 32); - data_.as_slice().copy_from(data); - } - Ed25519() { - } - Ed25519(td::Ed25519::PrivateKey pk); - td::Ed25519::PrivateKey export_key() { - return td::Ed25519::PrivateKey{td::SecureString(data_.as_slice())}; - } - td::SecureString export_as_slice() const { - td::SecureString s{36}; - auto id = ton_api::pk_ed25519::ID; - s.as_mutable_slice().copy_from(td::Slice{reinterpret_cast(&id), 4}); - s.as_mutable_slice().remove_prefix(4).copy_from(data_.as_slice()); - return s; - } - bool exportable() const { - return true; - } - static td::Result import(td::Slice slice) { - if (slice.size() != 32) { - return td::Status::Error(ErrorCode::error, "bad length"); - } - return Ed25519{slice}; - } - tl_object_ptr tl() const { - return create_tl_object(data_); - } - tl_object_ptr pub_tl() const; - pubkeys::Ed25519 pub() const; - static Ed25519 random(); -}; - -class AES { - private: - td::Bits256 data_; - - public: - ~AES() { - data_.set_zero_s(); - } - AES(const ton_api::pk_aes &obj) { - data_ = obj.key_; - } - AES(td::Slice data) { - CHECK(data.size() == 32); - data_.as_slice().copy_from(data); - } - td::SecureString export_as_slice() const { - td::SecureString s{40}; - auto id = ton_api::pk_aes::ID; - s.as_mutable_slice().copy_from(td::Slice{reinterpret_cast(&id), 4}); - s.as_mutable_slice().remove_prefix(4).copy_from(data_.as_slice()); - return s; - } - bool exportable() const { - return true; - } - static td::Result import(td::Slice slice) { - if (slice.size() != 32) { - return td::Status::Error(ErrorCode::error, "bad length"); - } - return AES{slice}; - } - tl_object_ptr tl() const { - return create_tl_object(data_); - } - tl_object_ptr pub_tl() const { - return create_tl_object(data_); - } - pubkeys::AES pub() const { - return pubkeys::AES{data_}; - } -}; - -class Unenc { - private: - td::SharedSlice data_; - - public: - Unenc(const ton_api::pk_unenc &obj) { - data_ = td::SharedSlice{obj.data_.as_slice()}; - } - Unenc(const Unenc &obj) { - data_ = obj.data_.clone(); - } - explicit Unenc(td::BufferSlice data) : data_(td::SharedSlice{data.as_slice()}) { - } - explicit Unenc(td::Slice data) : data_(td::SharedSlice{data}) { - } - explicit Unenc(td::SharedSlice data) : data_(std::move(data)) { - } - td::SecureString export_as_slice() const { - UNREACHABLE(); - } - bool exportable() const { - return false; - } - tl_object_ptr tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - tl_object_ptr pub_tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - pubkeys::Unenc pub() const { - return pubkeys::Unenc{data_.clone()}; - } -}; - -class Overlay { - private: - td::SharedSlice data_; - - public: - Overlay(const ton_api::pk_overlay &obj) { - data_ = td::SharedSlice{obj.name_.as_slice()}; - } - Overlay(const Overlay &obj) { - data_ = obj.data_.clone(); - } - explicit Overlay(td::BufferSlice data) : data_(td::SharedSlice{data.as_slice()}) { - } - explicit Overlay(td::Slice data) : data_(td::SharedSlice{data}) { - } - explicit Overlay(td::SharedSlice data) : data_(std::move(data)) { - } - td::SecureString export_as_slice() const { - UNREACHABLE(); - } - bool exportable() const { - return false; - } - tl_object_ptr tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - tl_object_ptr pub_tl() const { - return create_tl_object(data_.clone_as_buffer_slice()); - } - pubkeys::Overlay pub() const { - return pubkeys::Overlay{data_.clone()}; - } -}; - -} // namespace privkeys - -class PrivateKey { - private: - class Empty { - public: - td::SecureString export_as_slice() const { - UNREACHABLE(); - } - bool exportable() const { - return false; - } - tl_object_ptr tl() const { - UNREACHABLE(); - } - tl_object_ptr pub_tl() const { - UNREACHABLE(); - } - PublicKey pub() const { - UNREACHABLE(); - } - }; - td::Variant priv_key_{Empty{}}; - - public: - explicit PrivateKey(const tl_object_ptr &pk); - template - PrivateKey(T key) : priv_key_(std::move(key)) { - } - PrivateKey() { - } - - bool empty() const; - - PublicKey compute_public_key() const; - PublicKeyHash compute_short_id() const; - td::SecureString export_as_slice() const; - static td::Result import(td::Slice s); - bool exportable() const; - tl_object_ptr tl() const; - - td::Result> create_decryptor() const; - td::Result> create_decryptor_async() const; -}; - -} // namespace ton diff --git a/submodules/ton/tonlib-src/lite-client/CMakeLists.txt b/submodules/ton/tonlib-src/lite-client/CMakeLists.txt deleted file mode 100644 index a1afd529..00000000 --- a/submodules/ton/tonlib-src/lite-client/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -add_library(lite-client-common lite-client-common.cpp lite-client-common.h) -target_link_libraries(lite-client-common PUBLIC tdutils tdactor adnllite tl_api tl_lite_api tl-lite-utils ton_crypto ton_block) - -add_executable(lite-client lite-client.cpp lite-client.h) -target_link_libraries(lite-client tdutils tdactor adnllite tl_api tl_lite_api tl-lite-utils ton_crypto ton_block - terminal lite-client-common) diff --git a/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp b/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp deleted file mode 100644 index 5bc8ca73..00000000 --- a/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "lite-client-common.h" - -#include "auto/tl/lite_api.hpp" -#include "tl-utils/lite-utils.hpp" -#include "ton/lite-tl.hpp" -#include "td/utils/overloaded.h" -#include "td/utils/Random.h" - -using namespace std::literals::string_literals; - -namespace liteclient { - -td::Result> deserialize_proof_chain( - ton::lite_api::object_ptr f) { - // deserialize proof chain - auto chain = std::make_unique(ton::create_block_id(f->from_), ton::create_block_id(f->to_)); - chain->complete = f->complete_; - for (auto& s : f->steps_) { - bool ok = false; - td::BufferSlice dest_proof, proof, state_proof; - ton::lite_api::downcast_call( - *s, - td::overloaded( - [&](ton::lite_api::liteServer_blockLinkBack& s) { - auto& link = chain->new_link(ton::create_block_id(s.from_), ton::create_block_id(s.to_), s.to_key_block_); - link.is_fwd = false; - // dest_proof:bytes state_proof:bytes proof:bytes - dest_proof = std::move(s.dest_proof_); - state_proof = std::move(s.state_proof_); - proof = std::move(s.proof_); - ok = true; - }, - [&](ton::lite_api::liteServer_blockLinkForward& s) { - auto& link = chain->new_link(ton::create_block_id(s.from_), ton::create_block_id(s.to_), s.to_key_block_); - link.is_fwd = true; - // dest_proof:bytes config_proof:bytes signatures:liteServer.SignatureSet - dest_proof = std::move(s.dest_proof_); - proof = std::move(s.config_proof_); - link.cc_seqno = s.signatures_->catchain_seqno_; - link.validator_set_hash = s.signatures_->validator_set_hash_; - for (auto& sig : s.signatures_->signatures_) { - link.signatures.emplace_back(std::move(sig->node_id_short_), std::move(sig->signature_)); - } - ok = true; - }, - [&](auto& obj) {})); - if (!ok) { - return td::Status::Error("unknown constructor of liteServer.BlockLink"); - } - auto& link = chain->last_link(); - if (!dest_proof.empty()) { - auto d_res = vm::std_boc_deserialize(std::move(dest_proof)); - if (d_res.is_error()) { - return td::Status::Error("cannot deserialize dest_proof in a block proof link: "s + - d_res.move_as_error().to_string()); - } - link.dest_proof = d_res.move_as_ok(); - } - auto d_res = vm::std_boc_deserialize(std::move(proof)); - if (d_res.is_error()) { - return td::Status::Error("cannot deserialize proof in a block proof link: "s + d_res.move_as_error().to_string()); - } - link.proof = d_res.move_as_ok(); - if (!link.is_fwd) { - d_res = vm::std_boc_deserialize(std::move(state_proof)); - if (d_res.is_error()) { - return td::Status::Error("cannot deserialize state_proof in a block proof link: "s + - d_res.move_as_error().to_string()); - } - link.state_proof = d_res.move_as_ok(); - } - LOG(DEBUG) << "deserialized a " << (link.is_fwd ? "forward" : "backward") << " BlkProofLink from " - << link.from.to_str() << " to " << link.to.to_str() << " with " << link.signatures.size() - << " signatures"; - } - LOG(DEBUG) << "deserialized a BlkProofChain of " << chain->link_count() << " links"; - return std::move(chain); -} - -td::Ref prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref my_addr, - const block::CurrencyCollection& balance) { - td::BitArray<256> rand_seed; - td::RefInt256 rand_seed_int{true}; - td::Random::secure_bytes(rand_seed.as_slice()); - if (!rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false)) { - return {}; - } - auto tuple = vm::make_tuple_ref(td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea - td::make_refint(0), // actions:Integer - td::make_refint(0), // msgs_sent:Integer - td::make_refint(now), // unixtime:Integer - td::make_refint(lt), // block_lt:Integer - td::make_refint(lt), // trans_lt:Integer - std::move(rand_seed_int), // rand_seed:Integer - balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] - my_addr, // myself:MsgAddressInt - vm::StackEntry()); // global_config:(Maybe Cell) ] = SmartContractInfo; - LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); - return vm::make_tuple_ref(std::move(tuple)); -} - -} // namespace liteclient diff --git a/submodules/ton/tonlib-src/lite-client/lite-client-common.h b/submodules/ton/tonlib-src/lite-client/lite-client-common.h deleted file mode 100644 index a73dab91..00000000 --- a/submodules/ton/tonlib-src/lite-client/lite-client-common.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "crypto/block/block.h" - -#include "auto/tl/lite_api.hpp" - -namespace liteclient { - -td::Result> deserialize_proof_chain( - ton::lite_api::object_ptr f); - -td::Ref prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref my_addr, - const block::CurrencyCollection& balance); -} // namespace liteclient diff --git a/submodules/ton/tonlib-src/lite-client/lite-client.cpp b/submodules/ton/tonlib-src/lite-client/lite-client.cpp deleted file mode 100644 index 98176ba6..00000000 --- a/submodules/ton/tonlib-src/lite-client/lite-client.cpp +++ /dev/null @@ -1,4143 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "lite-client.h" - -#include "lite-client-common.h" - -#include "adnl/adnl-ext-client.h" -#include "tl-utils/lite-utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "auto/tl/lite_api.hpp" -#include "td/utils/OptionsParser.h" -#include "td/utils/Time.h" -#include "td/utils/filesystem.h" -#include "td/utils/format.h" -#include "td/utils/Random.h" -#include "td/utils/crypto.h" -#include "td/utils/overloaded.h" -#include "td/utils/port/signals.h" -#include "td/utils/port/stacktrace.h" -#include "td/utils/port/StdStreams.h" -#include "td/utils/port/FileFd.h" -#include "terminal/terminal.h" -#include "ton/lite-tl.hpp" -#include "block/block-db.h" -#include "block/block.h" -#include "block/block-parse.h" -#include "block/block-auto.h" -#include "block/mc-config.h" -#include "block/check-proof.h" -#include "vm/boc.h" -#include "vm/cellops.h" -#include "vm/cells/MerkleProof.h" -#include "vm/vm.h" -#include "vm/cp0.h" -#include "vm/memo.h" -#include "ton/ton-shard.h" -#include "openssl/rand.hpp" -#include "crypto/vm/utils.h" -#include "crypto/common/util.h" - -#if TD_DARWIN || TD_LINUX -#include -#include -#endif -#include -#include - -using namespace std::literals::string_literals; -using td::Ref; - -int verbosity; - -std::unique_ptr TestNode::make_callback() { - class Callback : public ton::adnl::AdnlExtClient::Callback { - public: - void on_ready() override { - td::actor::send_closure(id_, &TestNode::conn_ready); - } - void on_stop_ready() override { - td::actor::send_closure(id_, &TestNode::conn_closed); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - return std::make_unique(actor_id(this)); -} - -void TestNode::run() { - class Cb : public td::TerminalIO::Callback { - public: - void line_cb(td::BufferSlice line) override { - td::actor::send_closure(id_, &TestNode::parse_line, std::move(line)); - } - Cb(td::actor::ActorId id) : id_(id) { - } - - private: - td::actor::ActorId id_; - }; - io_ = td::TerminalIO::create("> ", readline_enabled_, std::make_unique(actor_id(this))); - td::actor::send_closure(io_, &td::TerminalIO::set_log_interface); - - if (remote_public_key_.empty()) { - auto G = td::read_file(global_config_).move_as_ok(); - auto gc_j = td::json_decode(G.as_slice()).move_as_ok(); - ton::ton_api::liteclient_config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - CHECK(gc.liteservers_.size() > 0); - auto idx = liteserver_idx_ >= 0 ? liteserver_idx_ - : td::Random::fast(0, static_cast(gc.liteservers_.size() - 1)); - CHECK(idx >= 0 && static_cast(idx) <= gc.liteservers_.size()); - auto& cli = gc.liteservers_[idx]; - remote_addr_.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure(); - remote_public_key_ = ton::PublicKey{cli->id_}; - td::TerminalIO::out() << "using liteserver " << idx << " with addr " << remote_addr_ << "\n"; - if (gc.validator_ && gc.validator_->zero_state_) { - zstate_id_.workchain = gc.validator_->zero_state_->workchain_; - if (zstate_id_.workchain != ton::workchainInvalid) { - zstate_id_.root_hash = gc.validator_->zero_state_->root_hash_; - zstate_id_.file_hash = gc.validator_->zero_state_->file_hash_; - td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n"; - } - } - } - - client_ = - ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_, make_callback()); -} - -void TestNode::got_result(td::Result R, td::Promise promise) { - if (R.is_error()) { - auto err = R.move_as_error(); - LOG(ERROR) << "failed query: " << err; - promise.set_error(std::move(err)); - td::actor::send_closure_later(actor_id(this), &TestNode::after_got_result, false); - return; - } - auto data = R.move_as_ok(); - auto F = ton::fetch_tl_object(data.clone(), true); - if (F.is_ok()) { - auto f = F.move_as_ok(); - auto err = td::Status::Error(f->code_, f->message_); - LOG(ERROR) << "liteserver error: " << err; - promise.set_error(std::move(err)); - td::actor::send_closure_later(actor_id(this), &TestNode::after_got_result, false); - return; - } - promise.set_result(std::move(data)); - td::actor::send_closure_later(actor_id(this), &TestNode::after_got_result, true); -} - -void TestNode::after_got_result(bool ok) { - running_queries_--; - if (ex_mode_ && !ok) { - LOG(ERROR) << "fatal error executing command-line queries, skipping the rest"; - std::cout.flush(); - std::cerr.flush(); - std::_Exit(1); - } - if (!running_queries_ && ex_queries_.size() > 0) { - auto data = std::move(ex_queries_[0]); - ex_queries_.erase(ex_queries_.begin()); - parse_line(std::move(data)); - } - if (ex_mode_ && !running_queries_ && ex_queries_.size() == 0) { - std::cout.flush(); - std::cerr.flush(); - std::_Exit(0); - } -} - -bool TestNode::envelope_send_query(td::BufferSlice query, td::Promise promise) { - running_queries_++; - if (!ready_ || client_.empty()) { - got_result(td::Status::Error("failed to send query to server: not ready"), std::move(promise)); - return false; - } - auto P = td::PromiseCreator::lambda( - [SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { - td::actor::send_closure(SelfId, &TestNode::got_result, std::move(R), std::move(promise)); - }); - td::BufferSlice b = - ton::serialize_tl_object(ton::create_tl_object(std::move(query)), true); - td::actor::send_closure(client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), - td::Timestamp::in(10.0), std::move(P)); - return true; -} - -td::Promise TestNode::trivial_promise() { - return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "error: " << res.move_as_error(); - } - }); -} - -bool TestNode::register_blkid(const ton::BlockIdExt& blkid) { - for (const auto& id : known_blk_ids_) { - if (id == blkid) { - return false; - } - } - known_blk_ids_.push_back(blkid); - return true; -} - -bool TestNode::show_new_blkids(bool all) { - if (all) { - shown_blk_ids_ = 0; - } - int cnt = 0; - while (shown_blk_ids_ < known_blk_ids_.size()) { - td::TerminalIO::out() << "BLK#" << shown_blk_ids_ + 1 << " = " << known_blk_ids_[shown_blk_ids_].to_str() - << std::endl; - ++shown_blk_ids_; - ++cnt; - } - return cnt; -} - -bool TestNode::complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const { - auto n = known_blk_ids_.size(); - while (n) { - --n; - if (known_blk_ids_[n].id == partial_blkid) { - complete_blkid = known_blk_ids_[n]; - return true; - } - } - if (partial_blkid.is_masterchain() && partial_blkid.seqno == ~0U) { - complete_blkid.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, ~0U}; - complete_blkid.root_hash.set_zero(); - complete_blkid.file_hash.set_zero(); - return true; - } - return false; -} - -const tlb::TypenameLookup& TestNode::get_tlb_dict() { - static tlb::TypenameLookup tlb_dict = []() { - tlb::TypenameLookup tlb_dict0; - tlb_dict0.register_types(block::gen::register_simple_types); - return tlb_dict0; - }(); - return tlb_dict; -} - -bool TestNode::list_cached_cells() const { - for (const auto& kv : cell_cache_) { - td::TerminalIO::out() << kv.first.to_hex() << std::endl; - } - return true; -} - -bool TestNode::dump_cached_cell(td::Slice hash_pfx, td::Slice type_name) { - if (hash_pfx.size() > 64) { - return false; - } - td::Bits256 hv_min; - int len = (int)hv_min.from_hex(hash_pfx, true); - if (len < 0 || len > 256) { - return set_error("cannot parse hex cell hash prefix"); - } - (hv_min.bits() + len).fill(false, 256 - len); - const tlb::TLB* tptr = nullptr; - block::gen::ConfigParam tpconf(0); - if (type_name.size()) { - td::int32 idx; - if (type_name.substr(0, 11) == "ConfigParam" && convert_int32(type_name.substr(11), idx) && idx >= 0) { - tpconf = block::gen::ConfigParam(idx); - tptr = &tpconf; - } else { - tptr = get_tlb_dict().lookup(type_name); - } - if (!tptr) { - return set_error("unknown TL-B type"); - } - td::TerminalIO::out() << "dumping cells as values of TLB type " << tptr->get_type_name() << std::endl; - } - auto it = std::lower_bound(cell_cache_.begin(), cell_cache_.end(), hv_min, - [](const auto& x, const auto& y) { return x.first < y; }); - int cnt = 0; - for (; it != cell_cache_.end() && it->first.bits().equals(hv_min.bits(), len); ++it) { - std::ostringstream os; - os << "C{" << it->first.to_hex() << "} =" << std::endl; - vm::load_cell_slice(it->second).print_rec(print_limit_, os, 2); - if (tptr) { - tptr->print_ref(print_limit_, os, it->second, 2); - os << std::endl; - } - td::TerminalIO::out() << os.str(); - ++cnt; - } - if (!cnt) { - LOG(ERROR) << "no known cells with specified hash prefix"; - return false; - } - return true; -} - -bool TestNode::get_server_time() { - auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [&, Self = actor_id(this)](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot get server time"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getTime"; - } else { - server_time_ = F.move_as_ok()->now_; - server_time_got_at_ = now(); - LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; - } - } - }); -} - -bool TestNode::get_server_version(int mode) { - auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result res) { - td::actor::send_closure_later(Self, &TestNode::got_server_version, std::move(res), mode); - }); -}; - -void TestNode::got_server_version(td::Result res, int mode) { - server_ok_ = false; - if (res.is_error()) { - LOG(ERROR) << "cannot get server version and time (server too old?)"; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getVersion"; - } else { - auto a = F.move_as_ok(); - set_server_version(a->version_, a->capabilities_); - set_server_time(a->now_); - } - } - if (!server_ok_) { - LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff) - << " with capabilities " << min_ls_capabilities << " required), some queries are unavailable"; - } - if (mode & 0x100) { - get_server_mc_block_id(); - } -} - -void TestNode::set_server_version(td::int32 version, td::int64 capabilities) { - if (server_version_ != version || server_capabilities_ != capabilities) { - server_version_ = version; - server_capabilities_ = capabilities; - LOG(WARNING) << "server version is " << (server_version_ >> 8) << "." << (server_version_ & 0xff) - << ", capabilities " << server_capabilities_; - } - server_ok_ = (server_version_ >= min_ls_version) && !(~server_capabilities_ & min_ls_capabilities); -} - -void TestNode::set_server_time(int server_utime) { - server_time_ = server_utime; - server_time_got_at_ = now(); - LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; -} - -bool TestNode::get_server_mc_block_id() { - int mode = (server_capabilities_ & 2) ? 0 : -1; - if (mode < 0) { - auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [Self = actor_id(this)](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot get masterchain info from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getMasterchainInfo"; - } else { - auto f = F.move_as_ok(); - auto blk_id = create_block_id(f->last_); - auto zstate_id = create_zero_state_id(f->init_); - LOG(INFO) << "last masterchain block is " << blk_id.to_str(); - td::actor::send_closure_later(Self, &TestNode::got_server_mc_block_id, blk_id, zstate_id, 0); - } - } - }); - } else { - auto b = - ton::serialize_tl_object(ton::create_tl_object(mode), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot get extended masterchain info from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getMasterchainInfoExt"; - } else { - auto f = F.move_as_ok(); - auto blk_id = create_block_id(f->last_); - auto zstate_id = create_zero_state_id(f->init_); - LOG(INFO) << "last masterchain block is " << blk_id.to_str(); - td::actor::send_closure_later(Self, &TestNode::got_server_mc_block_id_ext, blk_id, zstate_id, mode, - f->version_, f->capabilities_, f->last_utime_, f->now_); - } - } - }); - } -} - -void TestNode::got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int created) { - if (!zstate_id_.is_valid()) { - zstate_id_ = zstateid; - LOG(INFO) << "zerostate id set to " << zstate_id_.to_str(); - } else if (zstate_id_ != zstateid) { - LOG(FATAL) << "fatal: masterchain zero state id suddenly changed: expected " << zstate_id_.to_str() << ", found " - << zstateid.to_str(); - _exit(3); - return; - } - register_blkid(blkid); - register_blkid(ton::BlockIdExt{ton::masterchainId, ton::shardIdAll, 0, zstateid.root_hash, zstateid.file_hash}); - if (!mc_last_id_.is_valid()) { - mc_last_id_ = blkid; - request_block(blkid); - // request_state(blkid); - } else if (mc_last_id_.id.seqno < blkid.id.seqno) { - mc_last_id_ = blkid; - } - td::TerminalIO::out() << "latest masterchain block known to server is " << blkid.to_str(); - if (created > 0) { - td::TerminalIO::out() << " created at " << created << " (" << now() - created << " seconds ago)\n"; - } else { - td::TerminalIO::out() << "\n"; - } - show_new_blkids(); -} - -void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version, - long long capabilities, int last_utime, int server_now) { - set_server_version(version, capabilities); - set_server_time(server_now); - if (last_utime > server_now) { - LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime - << " (" << last_utime - server_now << " seconds in the future)"; - } else if (last_utime < server_now - 60) { - LOG(WARNING) << "server appears to be out of sync: its newest masterchain block is " << blkid.to_str() - << " created at " << last_utime << " (" << server_now - last_utime - << " seconds ago according to the server's clock)"; - } else if (last_utime < server_time_got_at_ - 60) { - LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain " - "block known to server is " - << blkid.to_str() << " created at " << last_utime << " (" << server_now - server_time_got_at_ - << " seconds ago according to the local clock)"; - } - got_server_mc_block_id(blkid, zstateid, last_utime); -} - -bool TestNode::request_block(ton::BlockIdExt blkid) { - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getBlock"; - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained block " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected data for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); - } - td::actor::send_closure_later(Self, &TestNode::got_mc_block, blk_id, std::move(f->data_)); - } - } - }); -} - -bool TestNode::request_state(ton::BlockIdExt blkid) { - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getState"; - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained state " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected state for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); - } - td::actor::send_closure_later(Self, &TestNode::got_mc_state, blk_id, f->root_hash_, f->file_hash_, - std::move(f->data_)); - } - } - }); -} - -void TestNode::got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data) { - LOG(INFO) << "obtained " << data.size() << " data bytes for block " << blkid.to_str(); - ton::FileHash fhash; - td::sha256(data.as_slice(), fhash.as_slice()); - if (fhash != blkid.file_hash) { - LOG(ERROR) << "file hash mismatch for block " << blkid.to_str() << ": expected " << blkid.file_hash.to_hex() - << ", computed " << fhash.to_hex(); - return; - } - register_blkid(blkid); - last_block_id_ = blkid; - last_block_data_ = data.clone(); - if (!db_root_.empty()) { - auto res = save_db_file(fhash, std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "error saving block file: " << res.to_string(); - } - } - show_new_blkids(); -} - -void TestNode::got_mc_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::FileHash file_hash, - td::BufferSlice data) { - LOG(INFO) << "obtained " << data.size() << " state bytes for block " << blkid.to_str(); - ton::FileHash fhash; - td::sha256(data.as_slice(), fhash.as_slice()); - if (fhash != file_hash) { - LOG(ERROR) << "file hash mismatch for state " << blkid.to_str() << ": expected " << file_hash.to_hex() - << ", computed " << fhash.to_hex(); - return; - } - register_blkid(blkid); - last_state_id_ = blkid; - last_state_data_ = data.clone(); - if (!db_root_.empty()) { - auto res = save_db_file(fhash, std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "error saving state file: " << res.to_string(); - } - } - show_new_blkids(); -} - -td::Status TestNode::save_db_file(ton::FileHash file_hash, td::BufferSlice data) { - std::string fname = block::compute_db_filename(db_root_ + '/', file_hash); - for (int i = 0; i < 10; i++) { - std::string tmp_fname = block::compute_db_tmp_filename(db_root_ + '/', file_hash, i); - auto res = block::save_binary_file(tmp_fname, data); - if (res.is_ok()) { - if (std::rename(tmp_fname.c_str(), fname.c_str()) < 0) { - int err = errno; - LOG(ERROR) << "cannot rename " << tmp_fname << " to " << fname << " : " << std::strerror(err); - return td::Status::Error(std::string{"cannot rename file: "} + std::strerror(err)); - } else { - LOG(INFO) << data.size() << " bytes saved into file " << fname; - return td::Status::OK(); - } - } else if (i == 9) { - return res; - } - } - return td::Status::Error("cannot save data file"); -} - -void TestNode::run_init_queries() { - get_server_version(0x100); -} - -td::Slice TestNode::get_word(char delim) { - if (delim == ' ' || !delim) { - skipspc(); - } - const char* ptr = parse_ptr_; - while (ptr < parse_end_ && *ptr != delim && (*ptr != '\t' || delim != ' ')) { - ptr++; - } - std::swap(ptr, parse_ptr_); - return td::Slice{ptr, parse_ptr_}; -} - -td::Slice TestNode::get_word_ext(const char* delims, const char* specials) { - if (delims[0] == ' ') { - skipspc(); - } - const char* ptr = parse_ptr_; - while (ptr < parse_end_ && !strchr(delims, *ptr)) { - if (specials && strchr(specials, *ptr)) { - if (ptr == parse_ptr_) { - ptr++; - } - break; - } - ptr++; - } - std::swap(ptr, parse_ptr_); - return td::Slice{ptr, parse_ptr_}; -} - -bool TestNode::get_word_to(std::string& str, char delim) { - str = get_word(delim).str(); - return !str.empty(); -} - -bool TestNode::get_word_to(td::Slice& str, char delim) { - str = get_word(delim); - return !str.empty(); -} - -int TestNode::skipspc() { - int i = 0; - while (parse_ptr_ < parse_end_ && (*parse_ptr_ == ' ' || *parse_ptr_ == '\t')) { - i++; - parse_ptr_++; - } - return i; -} - -std::string TestNode::get_line_tail(bool remove_spaces) const { - const char *ptr = parse_ptr_, *end = parse_end_; - if (remove_spaces) { - while (ptr < end && (*ptr == ' ' || *ptr == '\t')) { - ptr++; - } - while (ptr < end && (end[-1] == ' ' || end[-1] == '\t')) { - --end; - } - } - return std::string{ptr, end}; -} - -bool TestNode::eoln() const { - return parse_ptr_ == parse_end_; -} - -bool TestNode::seekeoln() { - skipspc(); - return eoln(); -} - -bool TestNode::parse_account_addr(ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool allow_none) { - auto word = get_word(); - if (allow_none && (word == "none" || word == "root")) { - wc = ton::workchainInvalid; - return true; - } - return block::parse_std_account_addr(word, wc, addr) || set_error("cannot parse account address"); -} - -bool TestNode::convert_uint64(td::Slice word, td::uint64& val) { - val = ~0ULL; - if (word.empty()) { - return false; - } - const char* ptr = word.data(); - char* end = nullptr; - val = std::strtoull(ptr, &end, 10); - if (end == ptr + word.size()) { - return true; - } else { - val = ~0ULL; - return false; - } -} - -bool TestNode::convert_int64(td::Slice word, td::int64& val) { - val = (~0ULL << 63); - if (word.empty()) { - return false; - } - const char* ptr = word.data(); - char* end = nullptr; - val = std::strtoll(ptr, &end, 10); - if (end == ptr + word.size()) { - return true; - } else { - val = (~0ULL << 63); - return false; - } -} - -bool TestNode::convert_uint32(td::Slice word, td::uint32& val) { - td::uint64 tmp; - if (convert_uint64(word, tmp) && (td::uint32)tmp == tmp) { - val = (td::uint32)tmp; - return true; - } else { - return false; - } -} - -bool TestNode::convert_int32(td::Slice word, td::int32& val) { - td::int64 tmp; - if (convert_int64(word, tmp) && (td::int32)tmp == tmp) { - val = (td::int32)tmp; - return true; - } else { - return false; - } -} - -bool TestNode::parse_lt(ton::LogicalTime& lt) { - return convert_uint64(get_word(), lt) || set_error("cannot parse logical time"); -} - -bool TestNode::parse_uint32(td::uint32& val) { - return convert_uint32(get_word(), val) || set_error("cannot parse 32-bit unsigned integer"); -} - -bool TestNode::parse_int32(td::int32& val) { - return convert_int32(get_word(), val) || set_error("cannot parse 32-bit integer"); -} - -bool TestNode::parse_int16(int& val) { - return (convert_int32(get_word(), val) && val == (td::int16)val) || set_error("cannot parse 16-bit integer"); -} - -bool TestNode::set_error(td::Status error) { - if (error.is_ok()) { - return true; - } - LOG(ERROR) << "error: " << error.to_string(); - if (error_.is_ok()) { - error_ = std::move(error); - } - return false; -} - -int TestNode::parse_hex_digit(int c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - c |= 0x20; - if (c >= 'a' && c <= 'z') { - return c - 'a' + 10; - } - return -1; -} - -bool TestNode::parse_hash(td::Slice str, ton::Bits256& hash) { - return str.size() == 64 && parse_hash(str.data(), hash); -} - -bool TestNode::parse_hash(const char* str, ton::Bits256& hash) { - unsigned char* data = hash.data(); - for (int i = 0; i < 32; i++) { - int a = parse_hex_digit(str[2 * i]); - if (a < 0) { - return false; - } - int b = parse_hex_digit(str[2 * i + 1]); - if (b < 0) { - return false; - } - data[i] = (unsigned char)((a << 4) + b); - } - return true; -} - -bool TestNode::parse_block_id_ext(std::string blkid_str, ton::BlockIdExt& blkid, bool allow_incomplete) const { - if (blkid_str.empty()) { - return false; - } - auto fc = blkid_str[0]; - if (fc == 'B' || fc == '#') { - unsigned n = 0; - if (sscanf(blkid_str.c_str(), fc == 'B' ? "BLK#%u" : "#%u", &n) != 1 || !n || n > known_blk_ids_.size()) { - return false; - } - blkid = known_blk_ids_.at(n - 1); - return true; - } - if (blkid_str[0] != '(') { - return false; - } - auto pos = blkid_str.find(')'); - if (pos == std::string::npos || pos >= 38) { - return false; - } - char buffer[40]; - std::memcpy(buffer, blkid_str.c_str(), pos + 1); - buffer[pos + 1] = 0; - unsigned long long shard; - if (sscanf(buffer, "(%d,%016llx,%u)", &blkid.id.workchain, &shard, &blkid.id.seqno) != 3) { - return false; - } - blkid.id.shard = shard; - if (!blkid.id.is_valid_full()) { - return false; - } - pos++; - if (pos == blkid_str.size()) { - blkid.root_hash.set_zero(); - blkid.file_hash.set_zero(); - return complete_blkid(blkid.id, blkid) || allow_incomplete; - } - return pos + 2 * 65 == blkid_str.size() && blkid_str[pos] == ':' && blkid_str[pos + 65] == ':' && - parse_hash(blkid_str.c_str() + pos + 1, blkid.root_hash) && - parse_hash(blkid_str.c_str() + pos + 66, blkid.file_hash) && blkid.is_valid_full(); -} - -bool TestNode::parse_block_id_ext(ton::BlockIdExt& blk, bool allow_incomplete) { - return parse_block_id_ext(get_word().str(), blk, allow_incomplete) || set_error("cannot parse BlockIdExt"); -} - -bool TestNode::parse_hash(ton::Bits256& hash) { - auto word = get_word(); - return parse_hash(word, hash) || set_error("cannot parse hash"); -} - -bool TestNode::convert_shard_id(td::Slice str, ton::ShardIdFull& shard) { - shard.workchain = ton::workchainInvalid; - shard.shard = 0; - auto pos = str.find(':'); - if (pos == std::string::npos || pos > 10) { - return false; - } - if (!convert_int32(str.substr(0, pos), shard.workchain)) { - return false; - } - int t = 64; - while (++pos < str.size()) { - int z = parse_hex_digit(str[pos]); - if (z < 0) { - if (t == 64) { - shard.shard = ton::shardIdAll; - } - return pos == str.size() - 1 && str[pos] == '_'; - } - t -= 4; - if (t >= 0) { - shard.shard |= ((td::uint64)z << t); - } - } - return true; -} - -bool TestNode::parse_shard_id(ton::ShardIdFull& shard) { - return convert_shard_id(get_word(), shard) || set_error("cannot parse full shard identifier or prefix"); -} - -bool TestNode::set_error(std::string err_msg) { - return set_error(td::Status::Error(-1, err_msg)); -} - -void TestNode::parse_line(td::BufferSlice data) { - line_ = data.as_slice().str(); - parse_ptr_ = line_.c_str(); - parse_end_ = parse_ptr_ + line_.size(); - error_ = td::Status::OK(); - if (seekeoln()) { - return; - } - if (!do_parse_line() || error_.is_error()) { - show_context(); - LOG(ERROR) << (error_.is_ok() ? "Syntax error" : error_.to_string()); - error_ = td::Status::OK(); - } - show_new_blkids(); -} - -void TestNode::show_context() const { - const char* ptr = line_.c_str(); - CHECK(parse_ptr_ >= ptr && parse_ptr_ <= parse_end_); - auto out = td::TerminalIO::out(); - for (; ptr < parse_ptr_; ptr++) { - out << (char)(*ptr == '\t' ? *ptr : ' '); - } - out << "^" << '\n'; -} - -bool TestNode::show_help(std::string command) { - td::TerminalIO::out() - << "list of available commands:\n" - "time\tGet server time\n" - "remote-version\tShows server time, version and capabilities\n" - "last\tGet last block and state info from server\n" - "sendfile \tLoad a serialized message from and send it to server\n" - "status\tShow connection and local database status\n" - "getaccount []\tLoads the most recent state of specified account; is in " - "[:] format\n" - "saveaccount[code|data] []\tSaves into specified file the most recent state " - "(StateInit) or just the code or data of specified account; is in " - "[:] format\n" - "runmethod[full] [] ...\tRuns GET method of account " - " " - "with specified parameters\n" - "dnsresolve [] []\tResolves a domain starting from root dns smart contract\n" - "dnsresolvestep [] []\tResolves a subdomain using dns smart contract " - "\n" - "allshards []\tShows shard configuration from the most recent masterchain " - "state or from masterchain state corresponding to \n" - "getconfig [...]\tShows specified or all configuration parameters from the latest masterchain state\n" - "getconfigfrom [...]\tShows specified or all configuration parameters from the " - "masterchain state of \n" - "getkeyconfig [...]\tShows specified or all configuration parameters from the " - "previous key block with respect to \n" - "saveconfig []\tSaves all configuration parameters into specified file\n" - "gethead \tShows block header for \n" - "getblock \tDownloads block\n" - "dumpblock \tDownloads and dumps specified block\n" - "getstate \tDownloads state corresponding to specified block\n" - "dumpstate \tDownloads and dumps state corresponding to specified block\n" - "dumptrans \tDumps one transaction of specified account\n" - "lasttrans[dump] []\tShows or dumps specified transaction and " - "several preceding " - "ones\n" - "listblocktrans[rev] [ ]\tLists block transactions, " - "starting immediately after or before the specified one\n" - "blkproofchain[step] []\tDownloads and checks proof of validity of the " - "second " - "indicated block (or the last known masterchain block) starting from given block\n" - "byseqno \tLooks up a block by workchain, shard and seqno, and shows its " - "header\n" - "bylt \tLooks up a block by workchain, shard and logical time, and shows its " - "header\n" - "byutime \tLooks up a block by workchain, shard and creation time, and " - "shows its header\n" - "creatorstats [ []]\tLists block creator statistics by validator public " - "key\n" - "recentcreatorstats [ []]\tLists block creator statistics " - "updated after by validator public " - "key\n" - "checkload[all|severe] []\tChecks whether all validators worked " - "properly during specified time " - "interval, and optionally saves proofs into -.boc\n" - "loadproofcheck \tChecks a validator misbehavior proof previously created by checkload\n" - "pastvalsets\tLists known past validator set ids and their hashes\n" - "savecomplaints \tSaves all complaints registered for specified validator set id " - "into files .boc\n" - "complaintprice \tComputes the price (in nanograms) for creating a complaint\n" - "known\tShows the list of all known block ids\n" - "knowncells\tShows the list of hashes of all known (cached) cells\n" - "dumpcell \nDumps a cached cell by a prefix of its hash\n" - "dumpcellas \nFinds a cached cell by a prefix of its hash and prints it as a value " - "of \n" - "privkey \tLoads a private key from file\n" - "help []\tThis help\n" - "quit\tExit\n"; - return true; -} - -bool TestNode::do_parse_line() { - ton::WorkchainId workchain = ton::masterchainId; // change to basechain later - ton::StdSmcAddress addr{}; - ton::BlockIdExt blkid{}; - ton::LogicalTime lt{}; - ton::Bits256 hash{}; - ton::ShardIdFull shard{}; - ton::BlockSeqno seqno{}; - ton::UnixTime utime{}; - unsigned count{}; - std::string word = get_word().str(); - skipspc(); - if (word == "time") { - return eoln() && get_server_time(); - } else if (word == "remote-version") { - return eoln() && get_server_version(); - } else if (word == "last") { - return eoln() && get_server_mc_block_id(); - } else if (word == "sendfile") { - return !eoln() && set_error(send_ext_msg_from_filename(get_line_tail())); - } else if (word == "getaccount") { - return parse_account_addr(workchain, addr) && - (seekeoln() ? get_account_state(workchain, addr, mc_last_id_) - : parse_block_id_ext(blkid) && seekeoln() && get_account_state(workchain, addr, blkid)); - } else if (word == "saveaccount" || word == "saveaccountcode" || word == "saveaccountdata") { - std::string filename; - int mode = ((word.c_str()[11] >> 1) & 3); - return get_word_to(filename) && parse_account_addr(workchain, addr) && - (seekeoln() - ? get_account_state(workchain, addr, mc_last_id_, filename, mode) - : parse_block_id_ext(blkid) && seekeoln() && get_account_state(workchain, addr, blkid, filename, mode)); - } else if (word == "runmethod" || word == "runmethodx" || word == "runmethodfull") { - std::string method; - return parse_account_addr(workchain, addr) && get_word_to(method) && - (parse_block_id_ext(method, blkid) ? get_word_to(method) : (blkid = mc_last_id_).is_valid()) && - parse_run_method(workchain, addr, blkid, method, word.size() <= 10); - } else if (word == "dnsresolve" || word == "dnsresolvestep") { - workchain = ton::workchainInvalid; - bool step = (word.size() > 10); - std::string domain; - int cat = 0; - return (!step || parse_account_addr(workchain, addr)) && get_word_to(domain) && - (parse_block_id_ext(domain, blkid) ? get_word_to(domain) : (blkid = mc_last_id_).is_valid()) && - (seekeoln() || parse_int16(cat)) && seekeoln() && - dns_resolve_start(workchain, addr, blkid, domain, cat, step); - } else if (word == "allshards" || word == "allshardssave") { - std::string filename; - return (word.size() <= 9 || get_word_to(filename)) && - (seekeoln() ? get_all_shards(filename) - : (parse_block_id_ext(blkid) && seekeoln() && get_all_shards(filename, false, blkid))); - } else if (word == "saveconfig") { - blkid = mc_last_id_; - std::string filename; - return get_word_to(filename) && (seekeoln() || parse_block_id_ext(blkid)) && seekeoln() && - parse_get_config_params(blkid, -1, filename); - } else if (word == "getconfig" || word == "getconfigfrom") { - blkid = mc_last_id_; - return (word == "getconfig" || parse_block_id_ext(blkid)) && parse_get_config_params(blkid, 0); - } else if (word == "getkeyconfig") { - return parse_block_id_ext(blkid) && parse_get_config_params(blkid, 0x8000); - } else if (word == "getblock") { - return parse_block_id_ext(blkid) && seekeoln() && get_block(blkid, false); - } else if (word == "dumpblock") { - return parse_block_id_ext(blkid) && seekeoln() && get_block(blkid, true); - } else if (word == "getstate") { - return parse_block_id_ext(blkid) && seekeoln() && get_state(blkid, false); - } else if (word == "dumpstate") { - return parse_block_id_ext(blkid) && seekeoln() && get_state(blkid, true); - } else if (word == "gethead") { - return parse_block_id_ext(blkid) && seekeoln() && get_show_block_header(blkid, 0xffff); - } else if (word == "dumptrans") { - return parse_block_id_ext(blkid) && parse_account_addr(workchain, addr) && parse_lt(lt) && seekeoln() && - get_one_transaction(blkid, workchain, addr, lt, true); - } else if (word == "lasttrans" || word == "lasttransdump") { - count = 10; - return parse_account_addr(workchain, addr) && parse_lt(lt) && parse_hash(hash) && - (seekeoln() || parse_uint32(count)) && seekeoln() && - get_last_transactions(workchain, addr, lt, hash, count, word == "lasttransdump"); - } else if (word == "listblocktrans" || word == "listblocktransrev") { - lt = 0; - int mode = (word == "listblocktrans" ? 7 : 0x47); - return parse_block_id_ext(blkid) && parse_uint32(count) && - (seekeoln() || (parse_hash(hash) && parse_lt(lt) && (mode |= 128) && seekeoln())) && - get_block_transactions(blkid, mode, count, hash, lt); - } else if (word == "blkproofchain" || word == "blkproofchainstep") { - ton::BlockIdExt blkid2{}; - return parse_block_id_ext(blkid) && (seekeoln() || parse_block_id_ext(blkid2)) && seekeoln() && - get_block_proof(blkid, blkid2, blkid2.is_valid() + (word == "blkproofchain") * 0x1000); - } else if (word == "byseqno") { - return parse_shard_id(shard) && parse_uint32(seqno) && seekeoln() && lookup_show_block(shard, 1, seqno); - } else if (word == "byutime") { - return parse_shard_id(shard) && parse_uint32(utime) && seekeoln() && lookup_show_block(shard, 4, utime); - } else if (word == "bylt") { - return parse_shard_id(shard) && parse_lt(lt) && seekeoln() && lookup_show_block(shard, 2, lt); - } else if (word == "creatorstats" || word == "recentcreatorstats") { - count = 1000; - int mode = (word == "recentcreatorstats" ? 4 : 0); - return parse_block_id_ext(blkid) && (!mode || parse_uint32(utime)) && - (seekeoln() ? (mode |= 0x100) : parse_uint32(count)) && (seekeoln() || (parse_hash(hash) && (mode |= 1))) && - seekeoln() && get_creator_stats(blkid, mode, count, hash, utime); - } else if (word == "checkload" || word == "checkloadall" || word == "checkloadsevere") { - int time1, time2, mode = (word == "checkloadsevere"); - std::string file_pfx; - return parse_int32(time1) && parse_int32(time2) && (seekeoln() || ((mode |= 2) && get_word_to(file_pfx))) && - seekeoln() && check_validator_load(time1, time2, mode, file_pfx); - } else if (word == "loadproofcheck") { - std::string filename; - return get_word_to(filename) && seekeoln() && set_error(check_validator_load_proof(filename)); - } else if (word == "pastvalsets") { - return eoln() && get_past_validator_sets(); - } else if (word == "savecomplaints") { - td::uint32 elect_id; - std::string file_pfx; - return parse_uint32(elect_id) && get_word_to(file_pfx) && seekeoln() && get_complaints(elect_id, file_pfx); - } else if (word == "complaintprice") { - td::uint32 expire_in; - std::string filename; - return parse_uint32(expire_in) && get_word_to(filename) && seekeoln() && - set_error(get_complaint_price(expire_in, filename)); - } else if (word == "known") { - return eoln() && show_new_blkids(true); - } else if (word == "knowncells") { - return eoln() && list_cached_cells(); - } else if (word == "dumpcell" || word == "dumpcellas") { - td::Slice chash; - td::Slice tname; - return (word == "dumpcell" || get_word_to(tname)) && get_word_to(chash) && seekeoln() && - dump_cached_cell(chash, tname); - } else if (word == "quit" && eoln()) { - LOG(INFO) << "Exiting"; - stop(); - // std::exit(0); - return true; - } else if (word == "help") { - return show_help(get_line_tail()); - } else { - td::TerminalIO::out() << "unknown command: " << word << " ; type `help` to get help" << '\n'; - return false; - } -} - -td::Result, std::shared_ptr>> lazy_boc_deserialize( - td::BufferSlice data) { - vm::StaticBagOfCellsDbLazy::Options options; - options.check_crc32c = true; - TRY_RESULT(boc, vm::StaticBagOfCellsDbLazy::create(vm::BufferSliceBlobView::create(std::move(data)), options)); - TRY_RESULT(rc, boc->get_root_count()); - if (rc != 1) { - return td::Status::Error(-668, "bag-of-cells is not standard (exactly one root cell expected)"); - } - TRY_RESULT(root, boc->get_root_cell(0)); - return std::make_pair(std::move(root), std::move(boc)); -} - -td::Status TestNode::send_ext_msg_from_filename(std::string filename) { - auto F = td::read_file(filename); - if (F.is_error()) { - auto err = F.move_as_error(); - LOG(ERROR) << "failed to read file `" << filename << "`: " << err.to_string(); - return err; - } - if (ready_ && !client_.empty()) { - LOG(ERROR) << "sending query from file " << filename; - auto P = td::PromiseCreator::lambda([](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.sendMessage"; - } else { - int status = F.move_as_ok()->status_; - LOG(INFO) << "external message status is " << status; - } - }); - auto b = - ton::serialize_tl_object(ton::create_tl_object(F.move_as_ok()), true); - return envelope_send_query(std::move(b), std::move(P)) ? td::Status::OK() - : td::Status::Error("cannot send query to server"); - } else { - return td::Status::Error("server connection not ready"); - } -} - -bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string filename, int mode) { - if (!ref_blkid.is_valid()) { - return set_error("must obtain last block information before making other queries"); - } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto a = ton::create_tl_object(workchain, addr); - auto b = ton::serialize_tl_object(ton::create_tl_object( - ton::create_tl_lite_block_id(ref_blkid), std::move(a)), - true); - LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " - << ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode; - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_account_state, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_), workchain, addr, filename, mode); - } - }); -} - -td::int64 TestNode::compute_method_id(std::string method) { - td::int64 method_id; - if (!convert_int64(method, method_id)) { - method_id = (td::crc16(td::Slice{method}) & 0xffff) | 0x10000; - } - return method_id; -} - -bool TestNode::cache_cell(Ref cell) { - if (cell.is_null()) { - return false; - } - td::Bits256 hash = cell->get_hash().bits(); - LOG(INFO) << "caching cell " << hash.to_hex(); - auto res = cell_cache_.emplace(hash, std::move(cell)); - return res.second; -} - -bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string method_name, bool ext_mode) { - auto R = vm::parse_stack_entries(td::Slice(parse_ptr_, parse_end_)); - if (R.is_error()) { - return set_error(R.move_as_error().to_string()); - } - parse_ptr_ = parse_end_; - auto P = td::PromiseCreator::lambda([this](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << R.move_as_error(); - } else { - for (const auto& v : R.move_as_ok()) { - v.for_each_scalar([this](const vm::StackEntry& val) { - if (val.is_cell()) { - cache_cell(val.as_cell()); - } - }); - } - } - }); - return start_run_method(workchain, addr, ref_blkid, method_name, R.move_as_ok(), ext_mode ? 0x1f : 0, std::move(P)); -} - -bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string method_name, std::vector params, int mode, - td::Promise> promise) { - if (!ref_blkid.is_valid()) { - return set_error("must obtain last block information before making other queries"); - } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto a = ton::create_tl_object(workchain, addr); - if (!mode) { - auto b = ton::serialize_tl_object(ton::create_tl_object( - ton::create_tl_lite_block_id(ref_blkid), std::move(a)), - true); - LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " - << ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters"; - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params), - promise = std::move(promise)](td::Result R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; - promise.set_error(td::Status::Error("cannot parse answer to liteServer.getAccountState")); - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::run_smc_method, 0, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_), workchain, addr, method_name, - std::move(params), td::BufferSlice(), td::BufferSlice(), td::BufferSlice(), - -0x10000, std::move(promise)); - } - }); - } else { - td::int64 method_id = compute_method_id(method_name); - // set serialization limits - vm::FakeVmStateLimits fstate(1000); // limit recursive (de)serialization calls - vm::VmStateInterface::Guard guard(&fstate); - // serialize parameters - vm::CellBuilder cb; - Ref cell; - if (!(vm::Stack{params}.serialize(cb) && cb.finalize_to(cell))) { - return set_error("cannot serialize stack with get-method parameters"); - } - auto stk = vm::std_boc_serialize(std::move(cell)); - if (stk.is_error()) { - return set_error("cannot serialize stack with get-method parameters : "s + stk.move_as_error().to_string()); - } - auto b = ton::serialize_tl_object( - ton::create_tl_object(mode, ton::create_tl_lite_block_id(ref_blkid), - std::move(a), method_id, stk.move_as_ok()), - true); - LOG(INFO) << "requesting remote get-method execution for " << workchain << ":" << addr.to_hex() - << " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with " - << params.size() << " parameters"; - return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, - params = std::move(params), - promise = std::move(promise)](td::Result R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.runSmcMethod"; - promise.set_error(td::Status::Error("cannot parse answer to liteServer.runSmcMethod")); - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_proof_), workchain, addr, method_name, - std::move(params), std::move(f->init_c7_), std::move(f->lib_extras_), - std::move(f->result_), f->exit_code_, std::move(promise)); - } - }); - } -} - -bool TestNode::get_elector_addr(td::Promise promise) { - if (elect_addr_queried_) { - promise.set_result(elect_addr_); - return true; - } - auto P = td::PromiseCreator::lambda( - [this, promise = std::move(promise)](td::Result> R) mutable { - TRY_RESULT_PROMISE_PREFIX(promise, config, std::move(R), "cannot obtain elector address from configuration:"); - if (elect_addr_queried_) { - promise.set_result(elect_addr_); - } else { - promise.set_error(td::Status::Error("cannot obtain elector address from configuration parameter #1")); - } - }); - return get_config_params(mc_last_id_, std::move(P), 0x3000, "", {1}); -} - -bool TestNode::get_past_validator_sets() { - return get_elector_addr([this](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << res.move_as_error(); - } else { - send_past_vset_query(res.move_as_ok()); - } - }); -} - -bool TestNode::send_past_vset_query(ton::StdSmcAddress elector_addr) { - std::vector params; - auto P = td::PromiseCreator::lambda([this](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << R.move_as_error(); - return; - } - auto S = R.move_as_ok(); - if (S.size() < 1 || !S.back().is_list()) { - LOG(ERROR) << "past_elections_list did not return a value of type tuple"; - return; - } - register_past_vset_info(std::move(S.back())); - }); - return start_run_method(ton::masterchainId, elector_addr, mc_last_id_, "past_elections_list", std::move(params), 0x1f, - std::move(P)); -} - -void TestNode::register_past_vset_info(vm::StackEntry list) { - try { - while (!list.empty()) { - auto tup = std::move(list).as_tuple_range(2, 2); - if (tup.is_null()) { - LOG(ERROR) << "invalid list in the result of past_elections_list"; - return; - } - list = tup->at(1); - auto t2 = tup->at(0).as_tuple_range(255, 3); - if (t2.is_null()) { - LOG(ERROR) << "invalid list entry in the result of past_elections_list"; - return; - } - auto x = t2->at(0).as_int(), y = t2->at(2).as_int(); - if (x.is_null() || y.is_null() || !x->unsigned_fits_bits(32) || !y->unsigned_fits_bits(256)) { - LOG(ERROR) << "invalid components in a list entry in the result of past_elections_list"; - return; - } - td::TerminalIO::out() << "PAST_VSET\t" << td::dec_string(x) << "\t" << td::hex_string(y, true, 64) << std::endl; - } - } catch (vm::VmError& err) { - LOG(ERROR) << "vm error while scanning result: " << err.get_msg(); - } -} - -bool TestNode::get_complaints(unsigned elect_id, std::string file_pfx) { - return get_elector_addr([this, elect_id, file_pfx](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << res.move_as_error(); - } else { - send_get_complaints_query(elect_id, res.move_as_ok(), file_pfx); - } - }); -} - -void TestNode::send_get_complaints_query(unsigned elect_id, ton::StdSmcAddress elector_addr, std::string file_pfx) { - std::vector params; - params.emplace_back(td::make_refint(elect_id)); - auto P = td::PromiseCreator::lambda([this, elect_id, file_pfx](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << R.move_as_error(); - return; - } - auto S = R.move_as_ok(); - if (S.size() < 1 || !(S.back().empty() || S.back().is_cell())) { - LOG(ERROR) << "get_past_complaints did not return a value of type cell"; - return; - } - try { - save_complaints(elect_id, std::move(S.back()).as_cell(), file_pfx); - } catch (vm::VmError& err) { - LOG(ERROR) << "vm error: " << err.get_msg(); - } catch (vm::VmVirtError& err) { - LOG(ERROR) << "vm virtualization error: " << err.get_msg(); - } - }); - start_run_method(ton::masterchainId, elector_addr, mc_last_id_, "get_past_complaints", std::move(params), 0x1f, - std::move(P)); -} - -void TestNode::save_complaints(unsigned elect_id, Ref complaints, std::string file_pfx) { - vm::Dictionary dict{std::move(complaints), 256}; - for (auto entry : dict) { - block::gen::ValidatorComplaintStatus::Record rec; - block::gen::ValidatorComplaint::Record rec2; - if (!(tlb::csr_unpack(std::move(entry.second), rec) && tlb::unpack_cell(rec.complaint, rec2))) { - LOG(ERROR) << "cannot unpack complaint with key " << entry.first.to_hex(256); - break; - } - if (rec.complaint->get_hash().as_bitslice() != entry.first) { - LOG(ERROR) << "invalid complaint key " << entry.first.to_hex(256) << ": actual complaint hash is " - << rec.complaint->get_hash().to_hex(); - break; - } - std::string filename = file_pfx + entry.first.to_hex(256) + ".boc"; - auto boc = vm::std_boc_serialize(rec.complaint, 2); - if (boc.is_error()) { - LOG(ERROR) << "cannot serialize complaint"; - break; - } - auto len = boc.ok().size(); - auto res1 = td::write_file(filename, boc.move_as_ok()); - if (res1.is_error()) { - LOG(ERROR) << "cannot save serialized complaint to file `" << filename << "` : " << res1.move_as_error(); - return; - } - LOG(DEBUG) << "saved " << len << " bytes into file `" << filename << "`"; - td::TerminalIO::out() << "SAVE_COMPLAINT\t" << elect_id << '\t' << entry.first.to_hex(256) << '\t' - << rec2.validator_pubkey.to_hex() << '\t' << rec2.created_at << '\t' << filename; - } -} - -td::Status TestNode::get_complaint_price(unsigned expires_in, std::string filename) { - LOG(DEBUG) << "reading complaint file " << filename; - TRY_RESULT_PREFIX(data, td::read_file(filename), "cannot read complaint file:"); - TRY_RESULT_PREFIX(complaint, vm::std_boc_deserialize(data), - PSLICE() << "cannot deserialize bag-of-cells read from complaint file `" << filename << "`:"); - if (complaint.is_null()) { - return td::Status::Error("complaint is null"); - } - block::gen::ValidatorComplaint::Record rec; - if (!tlb::unpack_cell(complaint, rec)) { - return td::Status::Error("cannot deserialize complaint"); - } - td::Bits256 chash = complaint->get_hash().bits(); - vm::VmStorageStat stat{1 << 22}; - if (!stat.add_storage(std::move(complaint))) { - return td::Status::Error("cannot compute storage size for this complaint"); - } - return get_complaint_price(expires_in, (unsigned)stat.bits, (unsigned)stat.refs, chash, filename); -} - -td::Status TestNode::get_complaint_price(unsigned expires_in, unsigned bits, unsigned refs, td::Bits256 chash, - std::string filename) { - LOG(INFO) << "complaint `" << filename << "`: " << bits << " bits, " << refs << " references"; - return get_elector_addr([this, filename, expires_in, bits, refs, chash](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << res.move_as_error(); - } else { - send_compute_complaint_price_query(res.move_as_ok(), expires_in, bits, refs, chash, filename); - } - }) - ? td::Status::OK() - : td::Status::Error("cannot obtain elector address"); -} - -void TestNode::send_compute_complaint_price_query(ton::StdSmcAddress elector_addr, unsigned expires_in, unsigned bits, - unsigned refs, td::Bits256 chash, std::string filename) { - std::vector params; - params.emplace_back(td::make_refint(bits)); - params.emplace_back(td::make_refint(refs)); - params.emplace_back(td::make_refint(expires_in)); - auto P = td::PromiseCreator::lambda( - [this, expires_in, bits, refs, chash, filename](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << R.move_as_error(); - return; - } - auto S = R.move_as_ok(); - if (S.size() < 1 || !S.back().is_int()) { - LOG(ERROR) << "complaint_storage_price did not return a value of type cell"; - return; - } - try { - auto price = std::move(S.back()).as_int(); - td::TerminalIO::out() << "COMPLAINT_PRICE\t" << chash.to_hex() << '\t' << td::dec_string(price) << '\t' - << bits << '\t' << refs << '\t' << expires_in << '\t' << filename << std::endl; - } catch (vm::VmError& err) { - LOG(ERROR) << "vm error: " << err.get_msg(); - } catch (vm::VmVirtError& err) { - LOG(ERROR) << "vm virtualization error: " << err.get_msg(); - } - }); - start_run_method(ton::masterchainId, elector_addr, mc_last_id_, "complaint_storage_price", std::move(params), 0x1f, - std::move(P)); -} - -bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, int cat, int mode) { - if (domain.size() > 1023) { - return set_error("domain name too long"); - } - if (domain.size() >= 2 && domain[0] == '"' && domain.back() == '"') { - domain.erase(0, 1); - domain.pop_back(); - } - std::vector components; - std::size_t i, p = 0; - for (i = 0; i < domain.size(); i++) { - if (!domain[i] || (unsigned char)domain[i] >= 0xfe || (unsigned char)domain[i] <= ' ') { - return set_error("invalid characters in a domain name"); - } - if (domain[i] == '.') { - if (i == p) { - return set_error("domain name cannot have an empty component"); - } - components.emplace_back(domain, p, i - p); - p = i + 1; - } - } - if (i > p) { - components.emplace_back(domain, p, i - p); - } - std::string qdomain, qdomain0; - while (!components.empty()) { - qdomain += components.back(); - qdomain += '\0'; - components.pop_back(); - } - - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - - if (workchain == ton::workchainInvalid) { - if (dns_root_queried_) { - workchain = ton::masterchainId; - addr = dns_root_; - } else { - auto P = - td::PromiseCreator::lambda([this, blkid, domain, cat, mode](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << "cannot obtain root dns address from configuration: " << R.move_as_error(); - } else if (dns_root_queried_) { - dns_resolve_start(ton::masterchainId, dns_root_, blkid, domain, cat, mode); - } else { - LOG(ERROR) << "cannot obtain root dns address from configuration parameter #4"; - } - }); - return get_config_params(mc_last_id_, std::move(P), 0x3000, "", {4}); - } - } - return dns_resolve_send(workchain, addr, blkid, domain, qdomain, cat, mode); -} - -bool TestNode::dns_resolve_send(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode) { - LOG(INFO) << "dns_resolve for '" << domain << "' category=" << cat << " mode=" << mode - << " starting from smart contract " << workchain << ":" << addr.to_hex() << " with respect to block " - << blkid.to_str(); - std::string qdomain0; - if (qdomain.size() <= 127) { - qdomain0 = qdomain; - } else { - qdomain0 = std::string{qdomain, 0, 127}; - qdomain[125] = '\xff'; - qdomain[126] = '\x0'; - } - vm::CellBuilder cb; - Ref cell; - if (!(cb.store_bytes_bool(td::Slice(qdomain0)) && cb.finalize_to(cell))) { - return set_error("cannot store domain name into slice"); - } - std::vector params; - params.emplace_back(vm::load_cell_slice_ref(std::move(cell))); - params.emplace_back(td::make_refint(cat)); - auto P = td::PromiseCreator::lambda([this, workchain, addr, blkid, domain, qdomain, cat, - mode](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << R.move_as_error(); - return; - } - auto S = R.move_as_ok(); - if (S.size() < 2 || !S[S.size() - 2].is_int() || !(S.back().is_cell() || S.back().is_null())) { - LOG(ERROR) << "dnsresolve did not return a value of type (int,cell)"; - return; - } - auto cell = S.back().as_cell(); - S.pop_back(); - auto x = S.back().as_int(); - S.clear(); - if (!x->signed_fits_bits(32)) { - LOG(ERROR) << "invalid integer result of dnsresolve (" << x << ")"; - return; - } - return dns_resolve_finish(workchain, addr, blkid, domain, qdomain, cat, mode, (int)x->to_long(), std::move(cell)); - }); - return start_run_method(workchain, addr, blkid, "dnsresolve", std::move(params), 0x1f, std::move(P)); -} - -bool TestNode::show_dns_record(std::ostream& os, int cat, Ref value, bool raw_dump) { - if (raw_dump) { - bool ok = show_dns_record(os, cat, value, false); - if (!ok) { - os << "cannot parse dns record; raw value: "; - vm::load_cell_slice(value).print_rec(print_limit_, os); - } - return ok; - } - if (value.is_null()) { - os << "(null)"; - return true; - } - // block::gen::t_DNSRecord.print_ref(print_limit_, os, value); - if (!block::gen::t_DNSRecord.validate_ref(value)) { - return false; - } - block::gen::t_DNSRecord.print_ref(print_limit_, os, value); - auto cs = vm::load_cell_slice(value); - auto tag = block::gen::t_DNSRecord.get_tag(cs); - ton::WorkchainId wc; - ton::StdSmcAddress addr; - switch (tag) { - case block::gen::DNSRecord::dns_adnl_address: { - block::gen::DNSRecord::Record_dns_adnl_address rec; - if (tlb::unpack_exact(cs, rec)) { - os << "\n\tadnl address " << rec.adnl_addr.to_hex() << " = " << td::adnl_id_encode(rec.adnl_addr, true); - } - break; - } - case block::gen::DNSRecord::dns_smc_address: { - block::gen::DNSRecord::Record_dns_smc_address rec; - if (tlb::unpack_exact(cs, rec) && block::tlb::t_MsgAddressInt.extract_std_address(rec.smc_addr, wc, addr)) { - os << "\tsmart contract " << wc << ":" << addr.to_hex() << " = " - << block::StdAddress{wc, addr}.rserialize(true); - } - break; - } - case block::gen::DNSRecord::dns_next_resolver: { - block::gen::DNSRecord::Record_dns_next_resolver rec; - if (tlb::unpack_exact(cs, rec) && block::tlb::t_MsgAddressInt.extract_std_address(rec.resolver, wc, addr)) { - os << "\tnext resolver " << wc << ":" << addr.to_hex() << " = " << block::StdAddress{wc, addr}.rserialize(true); - } - break; - } - } - return true; -} - -void TestNode::dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode, int used_bits, - Ref value) { - if (used_bits <= 0) { - td::TerminalIO::out() << "domain '" << domain << "' not found" << std::endl; - return; - } - if ((used_bits & 7) || (unsigned)used_bits > 8 * std::min(qdomain.size(), 126)) { - LOG(ERROR) << "too many bits used (" << used_bits << " out of " << qdomain.size() * 8 << ")"; - return; - } - int pos = (used_bits >> 3); - if (qdomain[pos - 1]) { - LOG(ERROR) << "domain split not at a component boundary"; - return; - } - bool end = ((std::size_t)pos == qdomain.size()); - if (!end) { - LOG(INFO) << "partial information obtained"; - if (value.is_null()) { - td::TerminalIO::out() << "domain '" << domain << "' not found: no next resolver" << std::endl; - return; - } - Ref nx_address; - ton::WorkchainId nx_wc; - ton::StdSmcAddress nx_addr; - if (!(block::gen::t_DNSRecord.cell_unpack_dns_next_resolver(value, nx_address) && - block::tlb::t_MsgAddressInt.extract_std_address(std::move(nx_address), nx_wc, nx_addr))) { - LOG(ERROR) << "cannot parse next resolver info for " << domain.substr(qdomain.size() - pos); - std::ostringstream out; - vm::load_cell_slice(value).print_rec(print_limit_, out); - td::TerminalIO::err() << out.str() << std::endl; - return; - } - LOG(INFO) << "next resolver is " << nx_wc << ":" << nx_addr.to_hex(); - if ((mode & 1)) { - return; // no recursive resolving - } - if (!(dns_resolve_send(nx_wc, nx_addr, blkid, domain, qdomain.substr(pos), cat, mode))) { - LOG(ERROR) << "cannot send next dns query"; - return; - } - LOG(INFO) << "recursive dns query to '" << domain.substr(qdomain.size() - pos) << "' sent"; - return; - } - auto out = td::TerminalIO::out(); - out << "Result for domain '" << domain << "' category " << cat << (cat ? "" : " (all categories)") << std::endl; - try { - if (value.not_null()) { - std::ostringstream os0; - vm::load_cell_slice(value).print_rec(print_limit_, os0); - out << "raw data: " << os0.str() << std::endl; - } - if (!cat) { - vm::Dictionary dict{value, 16}; - if (!dict.check_for_each([this, &out](Ref cs, td::ConstBitPtr key, int n) { - CHECK(n == 16); - int x = (int)key.get_int(16); - if (cs.is_null() || cs->size_ext() != 0x10000) { - out << "category #" << x << " : value is not a reference" << std::endl; - return false; - } - std::ostringstream os; - (void)show_dns_record(os, x, cs->prefetch_ref(), true); - out << "category #" << x << " : " << os.str() << std::endl; - return true; - })) { - out << "invalid dns record dictionary" << std::endl; - } - } else { - std::ostringstream os; - (void)show_dns_record(os, cat, value, true); - out << "category #" << cat << " : " << os.str() << std::endl; - } - } catch (vm::VmError& err) { - LOG(ERROR) << "vm error while traversing dns resolve result: " << err.get_msg(); - } catch (vm::VmVirtError& err) { - LOG(ERROR) << "vm virtualization error while traversing dns resolve result: " << err.get_msg(); - } -} - -bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workchain, ton::StdSmcAddress addr, - ton::LogicalTime lt, bool dump) { - if (!blkid.is_valid_full()) { - return set_error("invalid block id"); - } - if (!ton::shard_contains(blkid.shard_full(), ton::extract_addr_prefix(workchain, addr))) { - return set_error("the shard of this block cannot contain this account"); - } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto a = ton::create_tl_object(workchain, addr); - auto b = ton::serialize_tl_object(ton::create_tl_object( - ton::create_tl_lite_block_id(blkid), std::move(a), lt), - true); - LOG(INFO) << "requesting transaction " << lt << " of " << workchain << ":" << addr.to_hex() << " from block " - << blkid.to_str(); - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result R) -> void { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getOneTransaction"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_one_transaction, blkid, ton::create_block_id(f->id_), - std::move(f->proof_), std::move(f->transaction_), workchain, addr, lt, dump); - } - }); -} - -bool TestNode::get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, - ton::Bits256 hash, unsigned count, bool dump) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto a = ton::create_tl_object(workchain, addr); - auto b = ton::serialize_tl_object( - ton::create_tl_object(count, std::move(a), lt, hash), true); - LOG(INFO) << "requesting " << count << " last transactions from " << lt << ":" << hash.to_hex() << " of " << workchain - << ":" << addr.to_hex(); - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getTransactions"; - } else { - auto f = F.move_as_ok(); - std::vector blkids; - for (auto& id : f->ids_) { - blkids.push_back(ton::create_block_id(std::move(id))); - } - td::actor::send_closure_later(Self, &TestNode::got_last_transactions, std::move(blkids), - std::move(f->transactions_), workchain, addr, lt, hash, count, dump); - } - }); -} - -void TestNode::got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, - td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode) { - LOG(INFO) << "got account state for " << workchain << ":" << addr.to_hex() << " with respect to blocks " - << blk.to_str() << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str()); - block::AccountState account_state; - account_state.blk = blk; - account_state.shard_blk = shard_blk; - account_state.shard_proof = std::move(shard_proof); - account_state.proof = std::move(proof); - account_state.state = std::move(state); - auto r_info = account_state.validate(ref_blk, block::StdAddress(workchain, addr)); - if (r_info.is_error()) { - LOG(ERROR) << r_info.error().message(); - return; - } - auto out = td::TerminalIO::out(); - auto info = r_info.move_as_ok(); - if (mode < 0) { - if (info.root.not_null()) { - out << "account state is "; - std::ostringstream outp; - block::gen::t_Account.print_ref(print_limit_, outp, info.root); - vm::load_cell_slice(info.root).print_rec(print_limit_, outp); - out << outp.str(); - out << "last transaction lt = " << info.last_trans_lt << " hash = " << info.last_trans_hash.to_hex() << std::endl; - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record store; - block::CurrencyCollection balance; - if (tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && balance.unpack(store.balance)) { - out << "account balance is " << balance.to_str() << std::endl; - } - } else { - out << "account state is empty" << std::endl; - } - } else if (info.root.not_null()) { - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record store; - block::CurrencyCollection balance; - if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && balance.unpack(store.balance))) { - LOG(ERROR) << "error unpacking account state"; - return; - } - out << "account balance is " << balance.to_str() << std::endl; - int tag = block::gen::t_AccountState.get_tag(*store.state); - switch (tag) { - case block::gen::AccountState::account_uninit: - out << "account not initialized (no StateInit to save into file)" << std::endl; - return; - case block::gen::AccountState::account_frozen: - out << "account frozen (no StateInit to save into file)" << std::endl; - return; - } - CHECK(store.state.write().fetch_ulong(1) == 1); // account_init$1 _:StateInit = AccountState; - block::gen::StateInit::Record state; - CHECK(tlb::csr_unpack(store.state, state)); - Ref cell; - const char* name = ""; - if (mode == 0) { - // save all state - vm::CellBuilder cb; - CHECK(cb.append_cellslice_bool(store.state) && cb.finalize_to(cell)); - name = "StateInit"; - } else if (mode == 1) { - // save code - cell = state.code->prefetch_ref(); - name = "code"; - } else if (mode == 2) { - // save data - cell = state.data->prefetch_ref(); - name = "data"; - } - if (cell.is_null()) { - out << "no " << name << " to save to file" << std::endl; - return; - } - auto res = vm::std_boc_serialize(std::move(cell), 2); - if (res.is_error()) { - LOG(ERROR) << "cannot serialize extracted information from account state : " << res.move_as_error(); - return; - } - auto len = res.ok().size(); - auto res1 = td::write_file(filename, res.move_as_ok()); - if (res1.is_error()) { - LOG(ERROR) << "cannot write " << name << " of account " << workchain << ":" << addr.to_hex() << " to file `" - << filename << "` : " << res1.move_as_error(); - return; - } - out << "written " << name << " of account " << workchain << ":" << addr.to_hex() << " to file `" << filename - << "` (" << len << " bytes)" << std::endl; - } else { - out << "account state is empty (nothing saved to file `" << filename << "`)" << std::endl; - } -} - -void TestNode::run_smc_method(int mode, ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, - td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string method, - std::vector params, td::BufferSlice remote_c7, - td::BufferSlice remote_libs, td::BufferSlice remote_result, int remote_exit_code, - td::Promise> promise) { - LOG(INFO) << "got (partial) account state (" << state.size() << " bytes) with mode=" << mode << " for " << workchain - << ":" << addr.to_hex() << " with respect to blocks " << blk.to_str() - << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str()); - auto out = td::TerminalIO::out(); - try { - block::AccountState account_state; - account_state.blk = blk; - account_state.shard_blk = shard_blk; - account_state.shard_proof = std::move(shard_proof); - account_state.proof = std::move(proof); - LOG(DEBUG) << "serialized state is " << state.size() << " bytes"; - LOG(DEBUG) << "serialized remote c7 is " << remote_c7.size() << " bytes"; - account_state.state = std::move(state); - account_state.is_virtualized = (mode > 0); - auto r_info = account_state.validate(ref_blk, block::StdAddress(workchain, addr)); - if (r_info.is_error()) { - LOG(ERROR) << r_info.error().message(); - promise.set_error(r_info.move_as_error()); - return; - } - auto out = td::TerminalIO::out(); - auto info = r_info.move_as_ok(); - if (info.root.is_null()) { - LOG(ERROR) << "account state of " << workchain << ":" << addr.to_hex() << " is empty (cannot run method `" - << method << "`)"; - promise.set_error(td::Status::Error(PSLICE() << "account state of " << workchain << ":" << addr.to_hex() - << " is empty (cannot run method `" << method << "`)")); - return; - } - if (false) { - // DEBUG (dump state) - std::ostringstream os; - vm::CellSlice{vm::NoVm(), info.true_root}.print_rec(print_limit_, os); - out << "dump of account state (proof): " << os.str() << std::endl; - } - // set deserialization limits - vm::FakeVmStateLimits fstate(1000); // limit recursive (de)serialization calls - vm::VmStateInterface::Guard guard(&fstate); - if (false && remote_c7.size()) { - // DEBUG (dump remote_c7) - auto r_c7 = vm::std_boc_deserialize(remote_c7).move_as_ok(); - std::ostringstream os; - vm::StackEntry val; - bool ok = val.deserialize(r_c7); - val.dump(os); - // os << std::endl; - // block::gen::t_VmStackValue.print_ref(print_limit_, os, r_c7); - // os << std::endl; - // vm::CellSlice{vm::NoVmOrd(), r_c7}.print_rec(print_limit_, os); - out << "remote_c7 (deserialized=" << ok << "): " << os.str() << std::endl; - } - block::gen::Account::Record_account acc; - block::gen::AccountStorage::Record store; - block::CurrencyCollection balance; - if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && - balance.validate_unpack(store.balance))) { - LOG(ERROR) << "error unpacking account state"; - promise.set_error(td::Status::Error("error unpacking account state")); - return; - } - int tag = block::gen::t_AccountState.get_tag(*store.state); - switch (tag) { - case block::gen::AccountState::account_uninit: - LOG(ERROR) << "account " << workchain << ":" << addr.to_hex() - << " not initialized yet (cannot run any methods)"; - promise.set_error(td::Status::Error(PSLICE() << "account " << workchain << ":" << addr.to_hex() - << " not initialized yet (cannot run any methods)")); - return; - case block::gen::AccountState::account_frozen: - LOG(ERROR) << "account " << workchain << ":" << addr.to_hex() << " frozen (cannot run any methods)"; - promise.set_error(td::Status::Error(PSLICE() << "account " << workchain << ":" << addr.to_hex() - << " frozen (cannot run any methods)")); - return; - } - CHECK(store.state.write().fetch_ulong(1) == 1); // account_init$1 _:StateInit = AccountState; - block::gen::StateInit::Record state_init; - CHECK(tlb::csr_unpack(store.state, state_init)); - auto code = state_init.code->prefetch_ref(); - auto data = state_init.data->prefetch_ref(); - auto stack = td::make_ref(std::move(params)); - td::int64 method_id = compute_method_id(method); - stack.write().push_smallint(method_id); - { - std::ostringstream os; - os << "arguments: "; - stack->dump(os, 3); - out << os.str(); - } - long long gas_limit = /* vm::GasLimits::infty */ 10000000; - // OstreamLogger ostream_logger(ctx.error_stream); - // auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr); - vm::GasLimits gas{gas_limit}; - LOG(DEBUG) << "creating VM"; - vm::VmState vm{code, std::move(stack), gas, 1, data, vm::VmLog()}; - vm.set_c7(liteclient::prepare_vm_c7(info.gen_utime, info.gen_lt, td::make_ref(acc.addr->clone()), - balance)); // tuple with SmartContractInfo - // vm.incr_stack_trace(1); // enable stack dump after each step - LOG(INFO) << "starting VM to run method `" << method << "` (" << method_id << ") of smart contract " << workchain - << ":" << addr.to_hex(); - int exit_code; - try { - exit_code = ~vm.run(); - } catch (vm::VmVirtError& err) { - LOG(ERROR) << "virtualization error while running VM to locally compute runSmcMethod result: " << err.get_msg(); - promise.set_error( - td::Status::Error(PSLICE() << "virtualization error while running VM to locally compute runSmcMethod result: " - << err.get_msg())); - exit_code = -1001; - } catch (vm::VmError& err) { - LOG(ERROR) << "error while running VM to locally compute runSmcMethod result: " << err.get_msg(); - promise.set_error(td::Status::Error(PSLICE() << "error while running VM to locally compute runSmcMethod result: " - << err.get_msg())); - exit_code = -1000; - } - LOG(DEBUG) << "VM terminated with exit code " << exit_code; - if (mode > 0) { - LOG(DEBUG) << "remote VM exit code is " << remote_exit_code; - if (remote_exit_code == ~(int)vm::Excno::out_of_gas) { - LOG(WARNING) << "remote server ran out of gas while performing this request; consider using runmethodfull"; - } - } - if (exit_code != 0) { - LOG(ERROR) << "VM terminated with error code " << exit_code; - out << "result: error " << exit_code << std::endl; - promise.set_error(td::Status::Error(PSLICE() << "VM terminated with non-zero exit code " << exit_code)); - return; - } - stack = vm.get_stack_ref(); - { - std::ostringstream os; - os << "result: "; - stack->dump(os, 3); - out << os.str(); - } - if (mode & 4) { - if (remote_result.empty()) { - out << "remote result: , exit code " << remote_exit_code; - } else { - auto res = vm::std_boc_deserialize(std::move(remote_result)); - if (res.is_error()) { - auto err = res.move_as_error(); - LOG(ERROR) << "cannot deserialize remote VM result boc: " << err; - promise.set_error( - td::Status::Error(PSLICE() << "cannot deserialize remote VM result boc: " << std::move(err))); - return; - } - auto cs = vm::load_cell_slice(res.move_as_ok()); - Ref remote_stack; - if (!(vm::Stack::deserialize_to(cs, remote_stack, 0) && cs.empty_ext())) { - LOG(ERROR) << "remote VM result boc cannot be deserialized as a VmStack"; - promise.set_error(td::Status::Error("remote VM result boc cannot be deserialized as a VmStack")); - return; - } - std::ostringstream os; - os << "remote result (not to be trusted): "; - remote_stack->dump(os, 3); - out << os.str(); - } - } - out.flush(); - promise.set_result(stack->extract_contents()); - } catch (vm::VmVirtError& err) { - out << "virtualization error while parsing runSmcMethod result: " << err.get_msg(); - promise.set_error( - td::Status::Error(PSLICE() << "virtualization error while parsing runSmcMethod result: " << err.get_msg())); - } catch (vm::VmError& err) { - out << "error while parsing runSmcMethod result: " << err.get_msg(); - promise.set_error(td::Status::Error(PSLICE() << "error while parsing runSmcMethod result: " << err.get_msg())); - } -} - -void TestNode::got_one_transaction(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice proof, - td::BufferSlice transaction, ton::WorkchainId workchain, ton::StdSmcAddress addr, - ton::LogicalTime trans_lt, bool dump) { - LOG(INFO) << "got transaction " << trans_lt << " for " << workchain << ":" << addr.to_hex() - << " with respect to block " << blkid.to_str(); - if (blkid != req_blkid) { - LOG(ERROR) << "obtained TransactionInfo for a different block " << blkid.to_str() << " instead of requested " - << req_blkid.to_str(); - return; - } - if (!ton::shard_contains(blkid.shard_full(), ton::extract_addr_prefix(workchain, addr))) { - LOG(ERROR) << "received data from block " << blkid.to_str() << " that cannot contain requested account " - << workchain << ":" << addr.to_hex(); - return; - } - Ref root; - if (!transaction.empty()) { - auto R = vm::std_boc_deserialize(std::move(transaction)); - if (R.is_error()) { - LOG(ERROR) << "cannot deserialize transaction"; - return; - } - root = R.move_as_ok(); - CHECK(root.not_null()); - } - auto P = vm::std_boc_deserialize(std::move(proof)); - if (P.is_error()) { - LOG(ERROR) << "cannot deserialize block transaction proof"; - return; - } - auto proof_root = P.move_as_ok(); - try { - auto block_root = vm::MerkleProof::virtualize(std::move(proof_root), 1); - if (block_root.is_null()) { - LOG(ERROR) << "transaction block proof is invalid"; - return; - } - auto res1 = block::check_block_header_proof(block_root, blkid); - if (res1.is_error()) { - LOG(ERROR) << "error in transaction block header proof : " << res1.move_as_error().to_string(); - return; - } - auto trans_root_res = block::get_block_transaction_try(std::move(block_root), workchain, addr, trans_lt); - if (trans_root_res.is_error()) { - LOG(ERROR) << trans_root_res.move_as_error().message(); - return; - } - auto trans_root = trans_root_res.move_as_ok(); - if (trans_root.is_null() && root.not_null()) { - LOG(ERROR) << "error checking transaction proof: proof claims there is no such transaction, but we have got " - "transaction data with hash " - << root->get_hash().bits().to_hex(256); - return; - } - if (trans_root.not_null() && root.is_null()) { - LOG(ERROR) << "error checking transaction proof: proof claims there is such a transaction with hash " - << trans_root->get_hash().bits().to_hex(256) - << ", but we have got no " - "transaction data"; - return; - } - if (trans_root.not_null() && trans_root->get_hash().bits().compare(root->get_hash().bits(), 256)) { - LOG(ERROR) << "transaction hash mismatch: Merkle proof expects " << trans_root->get_hash().bits().to_hex(256) - << " but received data has " << root->get_hash().bits().to_hex(256); - return; - } - } catch (vm::VmError err) { - LOG(ERROR) << "error while traversing block transaction proof : " << err.get_msg(); - return; - } catch (vm::VmVirtError err) { - LOG(ERROR) << "virtualization error while traversing block transaction proof : " << err.get_msg(); - return; - } - auto out = td::TerminalIO::out(); - if (root.is_null()) { - out << "transaction not found" << std::endl; - } else { - out << "transaction is "; - std::ostringstream outp; - block::gen::t_Transaction.print_ref(print_limit_, outp, root, 0); - vm::load_cell_slice(root).print_rec(print_limit_, outp); - out << outp.str(); - } -} - -bool unpack_addr(std::ostream& os, Ref csr) { - ton::WorkchainId wc; - ton::StdSmcAddress addr; - if (!block::tlb::t_MsgAddressInt.extract_std_address(std::move(csr), wc, addr)) { - os << ""; - return false; - } - os << wc << ":" << addr.to_hex(); - return true; -} - -bool unpack_message(std::ostream& os, Ref msg, int mode) { - if (msg.is_null()) { - os << ""; - return true; - } - vm::CellSlice cs{vm::NoVmOrd(), msg}; - switch (block::gen::t_CommonMsgInfo.get_tag(cs)) { - case block::gen::CommonMsgInfo::ext_in_msg_info: { - block::gen::CommonMsgInfo::Record_ext_in_msg_info info; - if (!tlb::unpack(cs, info)) { - LOG(DEBUG) << "cannot unpack inbound external message"; - return false; - } - os << "EXT-IN-MSG"; - if (!(mode & 2)) { - os << " TO: "; - if (!unpack_addr(os, std::move(info.dest))) { - return false; - } - } - return true; - } - case block::gen::CommonMsgInfo::ext_out_msg_info: { - block::gen::CommonMsgInfo::Record_ext_out_msg_info info; - if (!tlb::unpack(cs, info)) { - LOG(DEBUG) << "cannot unpack outbound external message"; - return false; - } - os << "EXT-OUT-MSG"; - if (!(mode & 1)) { - os << " FROM: "; - if (!unpack_addr(os, std::move(info.src))) { - return false; - } - } - os << " LT:" << info.created_lt << " UTIME:" << info.created_at; - return true; - } - case block::gen::CommonMsgInfo::int_msg_info: { - block::gen::CommonMsgInfo::Record_int_msg_info info; - if (!tlb::unpack(cs, info)) { - LOG(DEBUG) << "cannot unpack internal message"; - return false; - } - os << "INT-MSG"; - if (!(mode & 1)) { - os << " FROM: "; - if (!unpack_addr(os, std::move(info.src))) { - return false; - } - } - if (!(mode & 2)) { - os << " TO: "; - if (!unpack_addr(os, std::move(info.dest))) { - return false; - } - } - os << " LT:" << info.created_lt << " UTIME:" << info.created_at; - td::RefInt256 value; - Ref extra; - if (!block::unpack_CurrencyCollection(info.value, value, extra)) { - LOG(ERROR) << "cannot unpack message value"; - return false; - } - os << " VALUE:" << value; - if (extra.not_null()) { - os << "+extra"; - } - return true; - } - default: - LOG(ERROR) << "cannot unpack message"; - return false; - } -} - -std::string message_info_str(Ref msg, int mode) { - std::ostringstream os; - if (!unpack_message(os, msg, mode)) { - return ""; - } else { - return os.str(); - } -} - -void TestNode::got_last_transactions(std::vector blkids, td::BufferSlice transactions_boc, - ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, - ton::Bits256 hash, unsigned count, bool dump) { - LOG(INFO) << "got up to " << count << " transactions for " << workchain << ":" << addr.to_hex() - << " from last transaction " << lt << ":" << hash.to_hex(); - block::TransactionList transaction_list; - transaction_list.blkids = blkids; - transaction_list.lt = lt; - transaction_list.hash = hash; - transaction_list.transactions_boc = std::move(transactions_boc); - auto r_account_state_info = transaction_list.validate(); - if (r_account_state_info.is_error()) { - LOG(ERROR) << "got_last_transactions: " << r_account_state_info.error(); - return; - } - auto account_state_info = r_account_state_info.move_as_ok(); - unsigned c = 0; - auto out = td::TerminalIO::out(); - CHECK(!account_state_info.transactions.empty()); - for (auto& info : account_state_info.transactions) { - const auto& blkid = info.blkid; - out << "transaction #" << c << " from block " << blkid.to_str() << (dump ? " is " : "\n"); - if (dump) { - std::ostringstream outp; - block::gen::t_Transaction.print_ref(print_limit_, outp, info.transaction); - vm::load_cell_slice(info.transaction).print_rec(print_limit_, outp); - out << outp.str(); - } - block::gen::Transaction::Record trans; - if (!tlb::unpack_cell(info.transaction, trans)) { - LOG(ERROR) << "cannot unpack transaction #" << c; - return; - } - out << " time=" << trans.now << " outmsg_cnt=" << trans.outmsg_cnt << std::endl; - auto in_msg = trans.r1.in_msg->prefetch_ref(); - if (in_msg.is_null()) { - out << " (no inbound message)" << std::endl; - } else { - out << " inbound message: " << message_info_str(in_msg, 2 * 0) << std::endl; - if (dump) { - out << " " << block::gen::t_Message_Any.as_string_ref(in_msg, 4); // indentation = 4 spaces - } - } - vm::Dictionary dict{trans.r1.out_msgs, 15}; - for (int x = 0; x < trans.outmsg_cnt && x < 100; x++) { - auto out_msg = dict.lookup_ref(td::BitArray<15>{x}); - out << " outbound message #" << x << ": " << message_info_str(out_msg, 1 * 0) << std::endl; - if (dump) { - out << " " << block::gen::t_Message_Any.as_string_ref(out_msg, 4); - } - } - register_blkid(blkid); // unsafe? - } - auto& last = account_state_info.transactions.back(); - if (last.prev_trans_lt > 0) { - out << "previous transaction has lt " << last.prev_trans_lt << " hash " << last.prev_trans_hash.to_hex() - << std::endl; - if (account_state_info.transactions.size() < count) { - LOG(WARNING) << "obtained less transactions than required"; - } - } else { - out << "no preceding transactions (list complete)" << std::endl; - } -} - -bool TestNode::get_block_transactions(ton::BlockIdExt blkid, int mode, unsigned count, ton::Bits256 acc_addr, - ton::LogicalTime lt) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto a = ton::create_tl_object(acc_addr, lt); - auto b = ton::serialize_tl_object(ton::create_tl_object( - ton::create_tl_lite_block_id(blkid), mode, count, std::move(a), false, false), - true); - LOG(INFO) << "requesting " << count << " transactions from block " << blkid.to_str() << " starting from account " - << acc_addr.to_hex() << " lt " << lt; - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.listBlockTransactions"; - } else { - auto f = F.move_as_ok(); - std::vector transactions; - for (auto& id : f->ids_) { - transactions.emplace_back(id->account_, id->lt_, id->hash_); - } - td::actor::send_closure_later(Self, &TestNode::got_block_transactions, ton::create_block_id(f->id_), mode, - f->req_count_, f->incomplete_, std::move(transactions), std::move(f->proof_)); - } - }); -} - -void TestNode::got_block_transactions(ton::BlockIdExt blkid, int mode, unsigned req_count, bool incomplete, - std::vector trans, td::BufferSlice proof) { - LOG(INFO) << "got up to " << req_count << " transactions from block " << blkid.to_str(); - auto out = td::TerminalIO::out(); - int count = 0; - for (auto& t : trans) { - out << "transaction #" << ++count << ": account " << t.acc_addr.to_hex() << " lt " << t.trans_lt << " hash " - << t.trans_hash.to_hex() << std::endl; - } - out << (incomplete ? "(block transaction list incomplete)" : "(end of block transaction list)") << std::endl; -} - -bool TestNode::get_all_shards(std::string filename, bool use_last, ton::BlockIdExt blkid) { - if (use_last) { - blkid = mc_last_id_; - } - if (!blkid.is_valid_full()) { - return set_error(use_last ? "must obtain last block information before making other queries" - : "invalid masterchain block id"); - } - if (!blkid.is_masterchain()) { - return set_error("only masterchain blocks contain shard configuration"); - } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - LOG(INFO) << "requesting recent shard configuration"; - return envelope_send_query(std::move(b), [Self = actor_id(this), filename](td::Result R) -> void { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAllShardsInfo"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_), std::move(f->proof_), - std::move(f->data_), filename); - } - }); -} - -void TestNode::got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data, std::string filename) { - LOG(INFO) << "got shard configuration with respect to block " << blk.to_str(); - if (data.empty()) { - td::TerminalIO::out() << "shard configuration is empty" << '\n'; - } else { - auto R = vm::std_boc_deserialize(data.clone()); - if (R.is_error()) { - LOG(ERROR) << "cannot deserialize shard configuration"; - return; - } - auto root = R.move_as_ok(); - auto out = td::TerminalIO::out(); - out << "shard configuration is "; - std::ostringstream outp; - block::gen::t_ShardHashes.print_ref(print_limit_, outp, root); - vm::load_cell_slice(root).print_rec(print_limit_, outp); - out << outp.str(); - block::ShardConfig sh_conf; - if (!sh_conf.unpack(vm::load_cell_slice_ref(root))) { - out << "cannot extract shard block list from shard configuration\n"; - } else { - auto ids = sh_conf.get_shard_hash_ids(true); - int cnt = 0; - for (auto id : ids) { - auto ref = sh_conf.get_shard_hash(ton::ShardIdFull(id)); - if (ref.not_null()) { - register_blkid(ref->top_block_id()); - out << "shard #" << ++cnt << " : " << ref->top_block_id().to_str() << " @ " << ref->created_at() << " lt " - << ref->start_lt() << " .. " << ref->end_lt() << std::endl; - } else { - out << "shard #" << ++cnt << " : " << id.to_str() << " (cannot unpack)\n"; - } - } - } - if (!filename.empty()) { - auto res1 = td::write_file(filename, data.as_slice()); - if (res1.is_error()) { - LOG(ERROR) << "cannot write shard configuration to file `" << filename << "` : " << res1.move_as_error(); - } else { - out << "saved shard configuration (ShardHashes) to file `" << filename << "` (" << data.size() << " bytes)" - << std::endl; - } - } - } - show_new_blkids(); -} - -bool TestNode::parse_get_config_params(ton::BlockIdExt blkid, int mode, std::string filename, std::vector params) { - if (mode < 0) { - mode = 0x80000; - } - if (!(mode & 0x81000) && !seekeoln()) { - mode |= 0x1000; - while (!seekeoln()) { - int x; - if (!convert_int32(get_word(), x)) { - return set_error("integer configuration parameter id expected"); - } - params.push_back(x); - } - } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - if (!blkid.is_masterchain_ext()) { - return set_error("only masterchain blocks contain configuration"); - } - if (blkid == mc_last_id_) { - mode |= 0x2000; - } - return get_config_params(blkid, trivial_promise_of>(), mode, filename, - std::move(params)); -} - -bool TestNode::get_config_params(ton::BlockIdExt blkid, td::Promise> promise, int mode, - std::string filename, std::vector params) { - return get_config_params_ext(blkid, promise.wrap([](ConfigInfo&& info) { return std::move(info.config); }), - mode | 0x10000, filename, params); -} - -bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise promise, int mode, - std::string filename, std::vector params) { - if (!(ready_ && !client_.empty())) { - promise.set_error(td::Status::Error("server connection not ready")); - return false; - } - if (!blkid.is_masterchain_ext()) { - promise.set_error(td::Status::Error("masterchain reference block expected")); - return false; - } - if (blkid == mc_last_id_) { - mode |= 0x2000; - } - auto params_copy = params; - auto b = (mode & 0x1000) ? ton::serialize_tl_object( - ton::create_tl_object( - mode & 0x8fff, ton::create_tl_lite_block_id(blkid), std::move(params_copy)), - true) - : ton::serialize_tl_object(ton::create_tl_object( - mode & 0x8fff, ton::create_tl_lite_block_id(blkid)), - true); - LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block " - << blkid.to_str(); - return envelope_send_query(std::move(b), [Self = actor_id(this), mode, filename, blkid, params = std::move(params), - promise = std::move(promise)](td::Result R) mutable { - td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params), - std::move(R), std::move(promise)); - }); -} - -void TestNode::got_config_params(ton::BlockIdExt req_blkid, int mode, std::string filename, std::vector params, - td::Result R, td::Promise promise) { - TRY_RESULT_PROMISE(promise, res, std::move(R)); - TRY_RESULT_PROMISE_PREFIX(promise, f, - ton::fetch_tl_object(std::move(res), true), - "cannot parse answer to liteServer.getConfigParams"); - auto blkid = ton::create_block_id(f->id_); - LOG(INFO) << "got configuration parameters"; - if (!blkid.is_masterchain_ext()) { - promise.set_error(td::Status::Error("reference block "s + blkid.to_str() + - " for the configuration is not a valid masterchain block")); - return; - } - bool from_key = (mode & 0x8000); - if (blkid.seqno() > req_blkid.seqno() || (!from_key && blkid != req_blkid)) { - promise.set_error(td::Status::Error("got configuration parameters with respect to block "s + blkid.to_str() + - " instead of " + req_blkid.to_str())); - return; - } - try { - Ref state, block, state_proof, config_proof; - if (!(mode & 0x10000) && !from_key) { - TRY_RESULT_PROMISE_PREFIX_ASSIGN(promise, state_proof, vm::std_boc_deserialize(f->state_proof_.as_slice()), - "cannot deserialize state proof :"); - } - if (!(mode & 0x10000) || from_key) { - TRY_RESULT_PROMISE_PREFIX_ASSIGN(promise, config_proof, vm::std_boc_deserialize(f->config_proof_.as_slice()), - "cannot deserialize config proof :"); - } - if (!from_key) { - TRY_RESULT_PROMISE_PREFIX_ASSIGN( - promise, state, - block::check_extract_state_proof(blkid, f->state_proof_.as_slice(), f->config_proof_.as_slice()), - PSLICE() << "masterchain state proof for " << blkid.to_str() << " is invalid :"); - } else { - block = vm::MerkleProof::virtualize(config_proof, 1); - if (block.is_null()) { - promise.set_error( - td::Status::Error("cannot virtualize configuration proof constructed from key block "s + blkid.to_str())); - return; - } - //TRY_STATUS_PROMISE_PREFIX(promise, block::check_block_header_proof(block, blkid), - // PSLICE() << "incorrect header for key block " << blkid.to_str()); - } - TRY_RESULT_PROMISE_PREFIX(promise, config, - from_key ? block::Config::extract_from_key_block(block, mode & 0xfff) - : block::Config::extract_from_state(state, mode & 0xfff), - "cannot unpack configuration:"); - ConfigInfo cinfo{std::move(config), std::move(state_proof), std::move(config_proof)}; - if (mode & 0x80000) { - TRY_RESULT_PROMISE_PREFIX(promise, boc, vm::std_boc_serialize(cinfo.config->get_root_cell(), 2), - "cannot serialize configuration:"); - auto size = boc.size(); - TRY_STATUS_PROMISE_PREFIX(promise, td::write_file(filename, std::move(boc)), - PSLICE() << "cannot save file `" << filename << "` :"); - td::TerminalIO::out() << "saved configuration dictionary into file `" << filename << "` (" << size - << " bytes written)" << std::endl; - promise.set_result(std::move(cinfo)); - return; - } - if (mode & 0x4000) { - promise.set_result(std::move(cinfo)); - return; - } - auto out = td::TerminalIO::out(); - if (mode & 0x1000) { - for (int i : params) { - out << "ConfigParam(" << i << ") = "; - auto value = cinfo.config->get_config_param(i); - if (value.is_null()) { - out << "(null)\n"; - } else { - std::ostringstream os; - if (i >= 0) { - block::gen::ConfigParam{i}.print_ref(print_limit_, os, value); - os << std::endl; - } - vm::load_cell_slice(value).print_rec(print_limit_, os); - out << os.str() << std::endl; - if (mode & 0x2000) { - register_config_param(i, value); - } - } - } - } else { - cinfo.config->foreach_config_param([this, &out, mode](int i, Ref value) { - out << "ConfigParam(" << i << ") = "; - if (value.is_null()) { - out << "(null)\n"; - } else { - std::ostringstream os; - if (i >= 0) { - block::gen::ConfigParam{i}.print_ref(print_limit_, os, value); - os << std::endl; - } - vm::load_cell_slice(value).print_rec(print_limit_, os); - out << os.str() << std::endl; - if (mode & 0x2000) { - register_config_param(i, value); - } - } - return true; - }); - } - promise.set_result(std::move(cinfo)); - } catch (vm::VmError& err) { - promise.set_error(err.as_status("error while traversing configuration: ")); - return; - } catch (vm::VmVirtError& err) { - promise.set_error(err.as_status("virtualization error while traversing configuration: ")); - return; - } -} - -bool TestNode::register_config_param(int idx, Ref value) { - if (idx == 1) { - return register_config_param1(std::move(value)); - } else if (idx == 4) { - return register_config_param4(std::move(value)); - } else { - return true; - } -} - -bool TestNode::register_config_param4(Ref value) { - if (value.is_null()) { - return false; - } - vm::CellSlice cs{vm::NoVmOrd(), std::move(value)}; - ton::StdSmcAddress addr; - if (cs.size_ext() == 256 && cs.fetch_bits_to(addr)) { - dns_root_queried_ = true; - if (dns_root_ != addr) { - dns_root_ = addr; - LOG(INFO) << "dns root set to -1:" << addr.to_hex(); - } - return true; - } else { - return false; - } -} - -bool TestNode::register_config_param1(Ref value) { - if (value.is_null()) { - return false; - } - vm::CellSlice cs{vm::NoVmOrd(), std::move(value)}; - ton::StdSmcAddress addr; - if (cs.size_ext() == 256 && cs.fetch_bits_to(addr)) { - elect_addr_queried_ = true; - if (elect_addr_ != addr) { - elect_addr_ = addr; - LOG(INFO) << "elector smart contract address set to -1:" << addr.to_hex(); - } - return true; - } else { - return false; - } -} - -bool TestNode::get_block(ton::BlockIdExt blkid, bool dump) { - LOG(INFO) << "got block download request for " << blkid.to_str(); - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query( - std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain block " << blkid.to_str() - << " from server : " << res.move_as_error().to_string(); - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getBlock : " << res.move_as_error().to_string(); - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained block " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected data for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); - return; - } - td::actor::send_closure_later(Self, &TestNode::got_block, blk_id, std::move(f->data_), dump); - } - } - }); -} - -bool TestNode::get_state(ton::BlockIdExt blkid, bool dump) { - LOG(INFO) << "got state download request for " << blkid.to_str(); - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query( - std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain state " << blkid.to_str() - << " from server : " << res.move_as_error().to_string(); - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getState"; - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained state " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected state for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); - return; - } - td::actor::send_closure_later(Self, &TestNode::got_state, blk_id, f->root_hash_, f->file_hash_, - std::move(f->data_), dump); - } - } - }); -} - -void TestNode::got_block(ton::BlockIdExt blkid, td::BufferSlice data, bool dump) { - LOG(INFO) << "obtained " << data.size() << " data bytes for block " << blkid.to_str(); - ton::FileHash fhash; - td::sha256(data.as_slice(), fhash.as_slice()); - if (fhash != blkid.file_hash) { - LOG(ERROR) << "file hash mismatch for block " << blkid.to_str() << ": expected " << blkid.file_hash.to_hex() - << ", computed " << fhash.to_hex(); - return; - } - register_blkid(blkid); - if (!db_root_.empty()) { - auto res = save_db_file(fhash, data.clone()); - if (res.is_error()) { - LOG(ERROR) << "error saving block file: " << res.to_string(); - } - } - if (dump) { - auto res = vm::std_boc_deserialize(std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "cannot deserialize block data : " << res.move_as_error().to_string(); - return; - } - auto root = res.move_as_ok(); - ton::RootHash rhash{root->get_hash().bits()}; - if (rhash != blkid.root_hash) { - LOG(ERROR) << "block root hash mismatch: data has " << rhash.to_hex() << " , expected " - << blkid.root_hash.to_hex(); - return; - } - auto out = td::TerminalIO::out(); - out << "block contents is "; - std::ostringstream outp; - block::gen::t_Block.print_ref(print_limit_, outp, root); - vm::load_cell_slice(root).print_rec(print_limit_, outp); - out << outp.str(); - show_block_header(blkid, std::move(root), 0xffff); - } else { - auto res = lazy_boc_deserialize(std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "cannot lazily deserialize block data : " << res.move_as_error().to_string(); - return; - } - auto pair = res.move_as_ok(); - auto root = std::move(pair.first); - ton::RootHash rhash{root->get_hash().bits()}; - if (rhash != blkid.root_hash) { - LOG(ERROR) << "block root hash mismatch: data has " << rhash.to_hex() << " , expected " - << blkid.root_hash.to_hex(); - return; - } - show_block_header(blkid, std::move(root), 0xffff); - } - show_new_blkids(); -} - -void TestNode::got_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::FileHash file_hash, td::BufferSlice data, - bool dump) { - LOG(INFO) << "obtained " << data.size() << " state bytes for block " << blkid.to_str(); - ton::FileHash fhash; - td::sha256(data.as_slice(), fhash.as_slice()); - if (fhash != file_hash) { - LOG(ERROR) << "file hash mismatch for state " << blkid.to_str() << ": expected " << file_hash.to_hex() - << ", computed " << fhash.to_hex(); - return; - } - register_blkid(blkid); - if (!db_root_.empty()) { - auto res = save_db_file(fhash, data.clone()); - if (res.is_error()) { - LOG(ERROR) << "error saving state file: " << res.to_string(); - } - } - if (dump) { - auto res = vm::std_boc_deserialize(std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "cannot deserialize block data : " << res.move_as_error().to_string(); - return; - } - auto root = res.move_as_ok(); - ton::RootHash rhash{root->get_hash().bits()}; - if (rhash != root_hash) { - LOG(ERROR) << "block state root hash mismatch: data has " << rhash.to_hex() << " , expected " - << root_hash.to_hex(); - return; - } - auto out = td::TerminalIO::out(); - out << "shard state contents is "; - std::ostringstream outp; - block::gen::t_ShardState.print_ref(print_limit_, outp, root); - vm::load_cell_slice(root).print_rec(print_limit_, outp); - out << outp.str(); - show_state_header(blkid, std::move(root), 0xffff); - } else { - auto res = lazy_boc_deserialize(std::move(data)); - if (res.is_error()) { - LOG(ERROR) << "cannot lazily deserialize block data : " << res.move_as_error().to_string(); - return; - } - auto pair = res.move_as_ok(); - auto root = std::move(pair.first); - ton::RootHash rhash{root->get_hash().bits()}; - if (rhash != root_hash) { - LOG(ERROR) << "block state root hash mismatch: data has " << rhash.to_hex() << " , expected " - << root_hash.to_hex(); - return; - } - show_state_header(blkid, std::move(root), 0xffff); - } - show_new_blkids(); -} - -bool TestNode::get_show_block_header(ton::BlockIdExt blkid, int mode) { - return get_block_header(blkid, mode, [this, blkid](td::Result R) { - if (R.is_error()) { - LOG(ERROR) << "unable to fetch block header: " << R.move_as_error(); - } else { - auto res = R.move_as_ok(); - show_block_header(res.blk_id, res.virt_blk_root, res.mode); - show_new_blkids(); - } - }); -} - -bool TestNode::get_block_header(ton::BlockIdExt blkid, int mode, td::Promise promise) { - LOG(INFO) << "got block header request for " << blkid.to_str() << " with mode " << mode; - auto b = ton::serialize_tl_object( - ton::create_tl_object(ton::create_tl_lite_block_id(blkid), mode), true); - return envelope_send_query( - std::move(b), [this, blkid, promise = std::move(promise)](td::Result R) mutable -> void { - TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), - PSLICE() << "cannot obtain block header for " << blkid.to_str() << " from server :"); - got_block_header_raw(std::move(res), std::move(promise), blkid); - }); -} - -bool TestNode::lookup_show_block(ton::ShardIdFull shard, int mode, td::uint64 arg) { - return lookup_block(shard, mode, arg, [this](td::Result R) { - if (R.is_error()) { - LOG(ERROR) << "unable to look up block: " << R.move_as_error(); - } else { - auto res = R.move_as_ok(); - show_block_header(res.blk_id, res.virt_blk_root, res.mode); - show_new_blkids(); - } - }); -} - -bool TestNode::lookup_block(ton::ShardIdFull shard, int mode, td::uint64 arg, - td::Promise promise) { - ton::BlockId id{shard, mode & 1 ? (td::uint32)arg : 0}; - LOG(INFO) << "got block lookup request for " << id.to_str() << " with mode " << mode << " and argument " << arg; - auto b = ton::serialize_tl_object(ton::create_tl_object( - mode, ton::create_tl_lite_block_id_simple(id), arg, (td::uint32)arg), - true); - return envelope_send_query( - std::move(b), [this, id, mode, arg, promise = std::move(promise)](td::Result R) mutable -> void { - TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), - PSLICE() << "cannot look up block header for " << id.to_str() << " with mode " << mode - << " and argument " << arg << " from server :"); - got_block_header_raw(std::move(res), std::move(promise)); - }); -} - -void TestNode::got_block_header_raw(td::BufferSlice res, td::Promise promise, - ton::BlockIdExt req_blkid) { - TRY_RESULT_PROMISE_PREFIX(promise, f, - ton::fetch_tl_object(std::move(res), true), - "cannot parse answer to liteServer.lookupBlock :"); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained block header for " << blk_id.to_str() << " from server (" << f->header_proof_.size() - << " data bytes)"; - if (req_blkid.is_valid() && blk_id != req_blkid) { - promise.set_error(td::Status::Error(PSLICE() << "block id mismatch: expected data for block " << req_blkid.to_str() - << ", obtained for " << blk_id.to_str())); - return; - } - TRY_RESULT_PROMISE_PREFIX(promise, root, vm::std_boc_deserialize(std::move(f->header_proof_)), - "cannot deserialize block header data :"); - bool ok = false; - td::Status E; - try { - auto virt_root = vm::MerkleProof::virtualize(root, 1); - if (virt_root.is_null()) { - promise.set_error(td::Status::Error(PSLICE() << "block header proof for block " << blk_id.to_str() - << " is not a valid Merkle proof")); - return; - } - ok = true; - promise.set_result(BlockHdrInfo{blk_id, std::move(root), std::move(virt_root), f->mode_}); - return; - } catch (vm::VmError& err) { - E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); - } catch (vm::VmVirtError& err) { - E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); - } - if (ok) { - LOG(ERROR) << std::move(E); - } else { - promise.set_error(std::move(E)); - } -} - -bool TestNode::show_block_header(ton::BlockIdExt blkid, Ref root, int mode) { - ton::RootHash vhash{root->get_hash().bits()}; - if (vhash != blkid.root_hash) { - LOG(ERROR) << " block header for block " << blkid.to_str() << " has incorrect root hash " << vhash.to_hex() - << " instead of " << blkid.root_hash.to_hex(); - return false; - } - std::vector prev; - ton::BlockIdExt mc_blkid; - bool after_split; - auto res = block::unpack_block_prev_blk_ext(root, blkid, prev, mc_blkid, after_split); - if (res.is_error()) { - LOG(ERROR) << "cannot unpack header for block " << blkid.to_str() << " : " << res.to_string(); - return false; - } - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) { - LOG(ERROR) << "cannot unpack header for block " << blkid.to_str(); - return false; - } - auto out = td::TerminalIO::out(); - out << "block header of " << blkid.to_str() << " @ " << info.gen_utime << " lt " << info.start_lt << " .. " - << info.end_lt << std::endl; - out << "global_id=" << blk.global_id << " version=" << info.version << " not_master=" << info.not_master - << " after_merge=" << info.after_merge << " after_split=" << info.after_split - << " before_split=" << info.before_split << " want_merge=" << info.want_merge << " want_split=" << info.want_split - << " validator_list_hash_short=" << info.gen_validator_list_hash_short - << " catchain_seqno=" << info.gen_catchain_seqno << " min_ref_mc_seqno=" << info.min_ref_mc_seqno; - if (!info.not_master) { - out << " is_key_block=" << info.key_block << " prev_key_block_seqno=" << info.prev_key_block_seqno; - } - out << std::endl; - register_blkid(blkid); - int cnt = 0; - for (auto id : prev) { - out << "previous block #" << ++cnt << " : " << id.to_str() << std::endl; - register_blkid(id); - } - out << "reference masterchain block : " << mc_blkid.to_str() << std::endl; - register_blkid(mc_blkid); - return true; -} - -bool TestNode::show_state_header(ton::BlockIdExt blkid, Ref root, int mode) { - return true; -} - -void TestNode::got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int mode) { - LOG(INFO) << "obtained " << data.size() << " data bytes as block header for " << blkid.to_str(); - auto res = vm::std_boc_deserialize(data.clone()); - if (res.is_error()) { - LOG(ERROR) << "cannot deserialize block header data : " << res.move_as_error().to_string(); - return; - } - auto root = res.move_as_ok(); - std::ostringstream outp; - vm::CellSlice cs{vm::NoVm(), root}; - cs.print_rec(print_limit_, outp); - td::TerminalIO::out() << outp.str(); - try { - auto virt_root = vm::MerkleProof::virtualize(root, 1); - if (virt_root.is_null()) { - LOG(ERROR) << " block header proof for block " << blkid.to_str() << " is not a valid Merkle proof"; - return; - } - show_block_header(blkid, std::move(virt_root), mode); - } catch (vm::VmError err) { - LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); - } catch (vm::VmVirtError err) { - LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); - } - show_new_blkids(); -} - -bool TestNode::get_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mode) { - if (!(mode & 1)) { - to.invalidate_clear(); - } - if (!(mode & 0x2000)) { - LOG(INFO) << "got block proof request from " << from.to_str() << " to " - << ((mode & 1) ? to.to_str() : "last masterchain block") << " with mode=" << mode; - } else { - LOG(DEBUG) << "got block proof request from " << from.to_str() << " to " - << ((mode & 1) ? to.to_str() : "last masterchain block") << " with mode=" << mode; - } - if (!from.is_masterchain_ext()) { - LOG(ERROR) << "source block " << from.to_str() << " is not a valid masterchain block id"; - return false; - } - if ((mode & 1) && !to.is_masterchain_ext()) { - LOG(ERROR) << "destination block " << to.to_str() << " is not a valid masterchain block id"; - return false; - } - auto b = - ton::serialize_tl_object(ton::create_tl_object( - mode & 0xfff, ton::create_tl_lite_block_id(from), ton::create_tl_lite_block_id(to)), - true); - return envelope_send_query(std::move(b), [Self = actor_id(this), from, to, mode](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain block proof for " << ((mode & 1) ? to.to_str() : "last masterchain block") - << " starting from " << from.to_str() << " from server : " << res.move_as_error().to_string(); - } else { - td::actor::send_closure_later(Self, &TestNode::got_block_proof, from, to, mode, res.move_as_ok()); - } - }); -} - -void TestNode::got_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, td::BufferSlice pchain) { - LOG(INFO) << "got block proof from " << from.to_str() << " to " - << ((mode & 1) ? to.to_str() : "last masterchain block") << " with mode=" << mode << " (" << pchain.size() - << " bytes)"; - auto r_f = ton::fetch_tl_object(std::move(pchain), true); - if (r_f.is_error()) { - LOG(ERROR) << "cannot deserialize liteServer.partialBlockProof: " << r_f.move_as_error(); - return; - } - auto f = r_f.move_as_ok(); - auto res = liteclient::deserialize_proof_chain(std::move(f)); - if (res.is_error()) { - LOG(ERROR) << "cannot deserialize liteServer.partialBlockProof: " << res.move_as_error(); - return; - } - auto chain = res.move_as_ok(); - if (chain->from != from) { - LOG(ERROR) << "block proof chain starts from block " << chain->from.to_str() << ", not from requested block " - << from.to_str(); - return; - } - auto err = chain->validate(); - if (err.is_error()) { - LOG(ERROR) << "block proof chain is invalid: " << err; - return; - } - // TODO: if `from` was a trusted key block, then mark `to` as a trusted key block, and update the known value of latest trusted key block if `to` is newer - if (!chain->complete && (mode & 0x1000)) { - LOG(INFO) << "valid " << (chain->complete ? "" : "in") << "complete proof chain: last block is " - << chain->to.to_str() << ", last key block is " - << (chain->has_key_block ? chain->key_blkid.to_str() : "(undefined)"); - get_block_proof(chain->to, to, mode | 0x2000); - return; - } - td::TerminalIO::out() << "valid " << (chain->complete ? "" : "in") << "complete proof chain: last block is " - << chain->to.to_str() << ", last key block is " - << (chain->has_key_block ? chain->key_blkid.to_str() : "(undefined)") << std::endl; - if (chain->has_key_block) { - register_blkid(chain->key_blkid); - } - register_blkid(chain->to); - auto time = now(); - if (!(mode & 1) || (chain->last_utime > time - 3600)) { - td::TerminalIO::out() << "last block in chain was generated at " << chain->last_utime << " (" - << time - chain->last_utime << " seconds ago)\n"; - } - show_new_blkids(); -} - -bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, - ton::UnixTime min_utime) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - if (!blkid.is_masterchain_ext()) { - return set_error("only masterchain blocks contain block creator statistics"); - } - if (!(mode & 1)) { - start_after.set_zero(); - } - auto osp = std::make_unique(); - auto& os = *osp; - return get_creator_stats( - blkid, mode, req_count, start_after, min_utime, - [min_utime, &os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt) -> bool { - os << key.to_hex() << " mc_cnt:" << mc_cnt << " shard_cnt:" << shard_cnt << std::endl; - return true; - }, - td::PromiseCreator::lambda([os = std::move(osp)](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "error obtaining creator stats: " << res.move_as_error(); - } else { - if (res.ok().is_zero()) { - *os << "(complete)" << std::endl; - } else { - *os << "(incomplete, repeat query from " << res.move_as_ok().to_hex() << " )" << std::endl; - } - td::TerminalIO::out() << os->str(); - } - })); -} - -bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, - ton::UnixTime min_utime, TestNode::creator_stats_func_t func, - td::Promise promise) { - return get_creator_stats(blkid, req_count, min_utime, std::move(func), - std::make_unique(mode | 0x10000, start_after), - promise.wrap([](auto&& p) { return p->last_key; })); -} - -bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton::UnixTime min_utime, - TestNode::creator_stats_func_t func, std::unique_ptr state, - td::Promise> promise) { - if (!(ready_ && !client_.empty())) { - promise.set_error(td::Status::Error("server connection not ready")); - return false; - } - if (!state) { - promise.set_error(td::Status::Error("null CreatorStatsRes")); - return false; - } - if (!blkid.is_masterchain_ext()) { - promise.set_error(td::Status::Error("only masterchain blocks contain block creator statistics")); - return false; - } - if (!(state->mode & 1)) { - state->last_key.set_zero(); - } - auto b = ton::serialize_tl_object( - ton::create_tl_object( - state->mode & 0xff, ton::create_tl_lite_block_id(blkid), req_count, state->last_key, min_utime), - true); - LOG(INFO) << "requesting up to " << req_count << " block creator stats records with respect to masterchain block " - << blkid.to_str() << " starting from validator public key " << state->last_key.to_hex() << " created after " - << min_utime << " (mode=" << state->mode << ")"; - return envelope_send_query( - std::move(b), [this, blkid, req_count, state = std::move(state), min_utime, func = std::move(func), - promise = std::move(promise)](td::Result R) mutable { - TRY_RESULT_PROMISE(promise, res, std::move(R)); - TRY_RESULT_PROMISE_PREFIX(promise, f, - ton::fetch_tl_object(std::move(res), true), - "cannot parse answer to liteServer.getValidatorStats"); - got_creator_stats(blkid, ton::create_block_id(f->id_), f->mode_, min_utime, std::move(f->state_proof_), - std::move(f->data_proof_), f->count_, req_count, f->complete_, std::move(func), - std::move(state), std::move(promise)); - }); -} - -void TestNode::got_creator_stats(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, int mode, ton::UnixTime min_utime, - td::BufferSlice state_proof, td::BufferSlice data_proof, int count, int req_count, - bool complete, TestNode::creator_stats_func_t func, - std::unique_ptr status, - td::Promise> promise) { - LOG(INFO) << "got answer to getValidatorStats query: " << count << " records out of " << req_count << ", " - << (complete ? "complete" : "incomplete"); - if (!blkid.is_masterchain_ext()) { - promise.set_error(td::Status::Error(PSLICE() << "reference block " << blkid.to_str() - << " for block creator statistics is not a valid masterchain block")); - return; - } - if (count > req_count) { - promise.set_error(td::Status::Error(PSLICE() - << "obtained " << count << " answers to getValidatorStats query, but only " - << req_count << " were requested")); - return; - } - if (blkid != req_blkid) { - promise.set_error(td::Status::Error(PSLICE() - << "answer to getValidatorStats refers to masterchain block " << blkid.to_str() - << " different from requested " << req_blkid.to_str())); - return; - } - TRY_RESULT_PROMISE_PREFIX(promise, state, - block::check_extract_state_proof(blkid, state_proof.as_slice(), data_proof.as_slice()), - PSLICE() << "masterchain state proof for " << blkid.to_str() << " is invalid :"); - if (!(mode & 0x10000)) { - if (status->state_proof.is_null()) { - TRY_RESULT_PROMISE_PREFIX( - promise, state_root, vm::std_boc_deserialize(state_proof.as_slice()), - PSLICE() << "cannot deserialize masterchain state proof for " << blkid.to_str() << ": "); - status->state_proof = std::move(state_root); - } - TRY_RESULT_PROMISE_PREFIX( - promise, data_root, vm::std_boc_deserialize(data_proof.as_slice()), - PSLICE() << "cannot deserialize masterchain creators data proof for " << blkid.to_str() << ": "); - if (status->data_proof.is_null()) { - status->data_proof = std::move(data_root); - } else { - TRY_RESULT_PROMISE_PREFIX(promise, data_proof2, - vm::MerkleProof::combine_fast_status(status->data_proof, std::move(data_root)), - "cannot combine Merkle proofs for creator data"); - status->data_proof = std::move(data_proof2); - } - } - bool allow_eq = (mode & 3) != 1; - ton::Bits256 key{status->last_key}; - std::ostringstream os; - try { - auto dict = block::get_block_create_stats_dict(std::move(state)); - if (!dict) { - promise.set_error(td::Status::Error("cannot extract BlockCreateStats from mc state")); - return; - } - for (int i = 0; i < count + (int)complete; i++) { - auto v = dict->lookup_nearest_key(key, true, allow_eq); - if (v.is_null()) { - if (i != count) { - promise.set_error(td::Status::Error(PSLICE() << "could fetch only " << i << " CreatorStats entries out of " - << count << " declared in answer to getValidatorStats")); - return; - } - break; - } - block::DiscountedCounter mc_cnt, shard_cnt; - if (!block::unpack_CreatorStats(std::move(v), mc_cnt, shard_cnt)) { - promise.set_error(td::Status::Error(PSLICE() << "invalid CreatorStats record with key " << key.to_hex())); - return; - } - if (mc_cnt.modified_since(min_utime) || shard_cnt.modified_since(min_utime)) { - func(key, mc_cnt, shard_cnt); - } - allow_eq = false; - } - if (complete) { - status->last_key.set_zero(); - status->complete = true; - promise.set_result(std::move(status)); - } else if (!(status->mode & 0x100)) { - status->last_key = key; - promise.set_result(std::move(status)); - } else { - // incomplete, send new query to fetch next entries - status->last_key = key; - status->mode |= 1; - get_creator_stats(blkid, req_count, min_utime, std::move(func), std::move(status), std::move(promise)); - } - } catch (vm::VmError& err) { - promise.set_error(err.as_status("error while traversing block creator stats:")); - } catch (vm::VmVirtError& err) { - promise.set_error(err.as_status("virtualization error while traversing block creator stats:")); - } -} - -bool TestNode::check_validator_load(int start_time, int end_time, int mode, std::string file_pfx) { - int time = now(); - if (start_time <= 0) { - start_time += time; - } - if (end_time <= 0) { - end_time += time; - } - if (start_time >= end_time) { - return set_error("end time must be later than start time"); - } - LOG(INFO) << "requesting masterchain blocks corresponding to unixtime " << start_time << " and " << end_time; - auto P = td::split_promise([this, mode, file_pfx](td::Result> R) { - if (R.is_error()) { - LOG(ERROR) << "cannot obtain block info: " << R.move_as_error(); - return; - } - auto res = R.move_as_ok(); - continue_check_validator_load(res.first.blk_id, res.first.proof, res.second.blk_id, res.second.proof, mode, - file_pfx); - }); - lookup_block(ton::ShardIdFull(ton::masterchainId), 4, start_time, std::move(P.first)); - return lookup_block(ton::ShardIdFull(ton::masterchainId), 4, end_time, std::move(P.second)); -} - -void TestNode::continue_check_validator_load(ton::BlockIdExt blkid1, Ref root1, ton::BlockIdExt blkid2, - Ref root2, int mode, std::string file_pfx) { - LOG(INFO) << "continue_check_validator_load for blocks " << blkid1.to_str() << " and " << blkid2.to_str() - << " : requesting configuration parameter #34"; - auto P = td::split_promise( - [this, blkid1, root1, blkid2, root2, mode, file_pfx](td::Result> R) mutable { - if (R.is_error()) { - LOG(ERROR) << "cannot obtain configuration parameter #34 : " << R.move_as_error(); - return; - } - auto res = R.move_as_ok(); - root1 = vm::MerkleProof::combine_fast(std::move(root1), std::move(res.first.state_proof)); - root2 = vm::MerkleProof::combine_fast(std::move(root2), std::move(res.second.state_proof)); - if (root1.is_null() || root2.is_null()) { - LOG(ERROR) << "cannot merge block header proof with block state proof"; - return; - } - auto info1 = std::make_unique(blkid1, std::move(root1), std::move(res.first.config_proof), - std::move(res.first.config)); - auto info2 = std::make_unique(blkid2, std::move(root2), std::move(res.second.config_proof), - std::move(res.second.config)); - continue_check_validator_load2(std::move(info1), std::move(info2), mode, file_pfx); - }); - get_config_params_ext(blkid1, std::move(P.first), 0x4000, "", {28, 34}); - get_config_params_ext(blkid2, std::move(P.second), 0x4000, "", {28, 34}); -} - -td::Status TestNode::ValidatorLoadInfo::unpack_vset() { - if (!config) { - return td::Status::Error("no configuration to unpack validator set"); - } - auto vset_root_c = config->get_config_param(34); - if (vset_root_c.is_null()) { - vset_hash.set_zero(); - return td::Status::Error("no configuration parameter 34 for block "s + blk_id.to_str()); - } - if (vset_root.not_null() && vset_root->get_hash() == vset_root_c->get_hash()) { - vset_root_c = vset_root; - } else { - vset_root = vset_root_c; - } - vset_hash = vset_root->get_hash().bits(); - TRY_RESULT_PREFIX_ASSIGN( - vset, block::Config::unpack_validator_set(vset_root), - PSLICE() << "cannot unpack validator set from configuration parameter 34 of block " << blk_id.to_str() << " :"); - valid_since = vset->utime_since; - vset_map = vset->compute_validator_map(); - return td::Status::OK(); -} - -bool TestNode::ValidatorLoadInfo::store_record(const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt) { - if (!(mc_cnt.is_valid() && shard_cnt.is_valid())) { - return false; - } - if (mc_cnt.total >= (1ULL << 60) || shard_cnt.total >= (1ULL << 60)) { - return false; - } - if (key.is_zero()) { - created_total.first = (td::int64)mc_cnt.total; - created_total.second = (td::int64)shard_cnt.total; - return true; - } - auto it = vset_map.find(key); - if (it == vset_map.end()) { - return false; - } - created.at(it->second) = std::make_pair(mc_cnt.total, shard_cnt.total); - return true; -} - -bool TestNode::load_creator_stats(std::unique_ptr load_to, - td::Promise> promise, bool need_proofs) { - if (!load_to) { - promise.set_error(td::Status::Error("no ValidatorLoadInfo")); - return false; - } - auto& info = *load_to; - info.created_total.first = info.created_total.second = 0; - info.created.resize(0); - info.created.resize(info.vset->total, std::make_pair(0, 0)); - ton::UnixTime min_utime = info.valid_since - 1000; - return get_creator_stats( - info.blk_id, 1000, min_utime, - [min_utime, &info](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt) -> bool { - info.store_record(key, mc_cnt, shard_cnt); - return true; - }, - std::make_unique(need_proofs ? 0x100 : 0x10100), - td::PromiseCreator::lambda([load_to = std::move(load_to), promise = std::move(promise)]( - td::Result> R) mutable { - TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), "error obtaining creator stats:"); - if (!res->complete) { - promise.set_error(td::Status::Error("incomplete creator stats")); - return; - } - // merge - load_to->state_proof = - vm::MerkleProof::combine_fast(std::move(load_to->state_proof), std::move(res->state_proof)); - load_to->data_proof = vm::MerkleProof::combine_fast(std::move(load_to->data_proof), std::move(res->data_proof)); - promise.set_result(std::move(load_to)); - })); -} - -void TestNode::continue_check_validator_load2(std::unique_ptr info1, - std::unique_ptr info2, int mode, - std::string file_pfx) { - LOG(INFO) << "continue_check_validator_load2 for blocks " << info1->blk_id.to_str() << " and " - << info1->blk_id.to_str() << " : requesting block creators data"; - td::Status st = info1->unpack_vset(); - if (st.is_error()) { - LOG(ERROR) << "cannot unpack validator set from block " << info1->blk_id.to_str() << " :" << st.move_as_error(); - return; - } - st = info2->unpack_vset(); - if (st.is_error()) { - LOG(ERROR) << "cannot unpack validator set from block " << info2->blk_id.to_str() << " :" << st.move_as_error(); - return; - } - if (info1->vset_hash != info2->vset_hash || info1->valid_since != info2->valid_since) { - LOG(ERROR) << "blocks appear to have different validator sets"; - return; - } - LOG(INFO) << "validator sets valid since " << info1->valid_since; - auto P = td::split_promise( - [this, mode, - file_pfx](td::Result, std::unique_ptr>> R) { - if (R.is_error()) { - LOG(ERROR) << "cannot load block creation statistics : " << R.move_as_error(); - return; - } - auto res = R.move_as_ok(); - continue_check_validator_load3(std::move(res.first), std::move(res.second), mode, file_pfx); - }); - load_creator_stats(std::move(info1), std::move(P.first), true); - load_creator_stats(std::move(info2), std::move(P.second), true); -} - -// computes the probability of creating <= x masterchain blocks if the expected value is y -static double create_prob(int x, double y) { - if (x < 0 || y < 0) { - return .5; - } - if (x >= y) { - return .5; - } - if (x <= 20) { - // Poisson - double t = exp(-y), s = t; - for (int n = 1; n <= x; n++) { - s += t = (t * y) / n; - } - return s; - } - // normal approximation - double z = (x - y) / sqrt(2. * y); - return (1. + erf(z)) / 2; -} - -static double shard_create_prob(int x, double y, double chunk_size) { - if (x < 0 || y < 0) { - return .5; - } - if (x >= y) { - return .5; - } - double y0 = y / chunk_size; // expected chunks - if (!x) { - return y0 > 100 ? 0 : exp(-y0); // Poisson approximation for having participated in zero chunks - } - // at least ten chunks, normal approximation - double z = (x - y) / sqrt(2. * y * chunk_size); - return (1. + erf(z)) / 2; -} - -void TestNode::continue_check_validator_load3(std::unique_ptr info1, - std::unique_ptr info2, int mode, - std::string file_pfx) { - LOG(INFO) << "continue_check_validator_load3 for blocks " << info1->blk_id.to_str() << " and " - << info1->blk_id.to_str() << " with mode=" << mode << " and file prefix `" << file_pfx - << "`: comparing block creators data"; - if (info1->created_total.first <= 0 || info2->created_total.first <= 0) { - LOG(ERROR) << "no total created blocks statistics"; - return; - } - td::TerminalIO::out() << "total: (" << info1->created_total.first << "," << info1->created_total.second << ") -> (" - << info2->created_total.first << "," << info2->created_total.second << ")\n"; - auto x = info2->created_total.first - info1->created_total.first; - auto y = info2->created_total.second - info1->created_total.second; - td::int64 xs = 0, ys = 0; - if (x <= 0 || y < 0 || (x | y) >= (1u << 31)) { - LOG(ERROR) << "impossible situation: zero or no blocks created: " << x << " masterchain blocks, " << y - << " shardchain blocks"; - return; - } - std::pair created_total{(int)x, (int)y}; - int count = info1->vset->total; - CHECK(info2->vset->total == count); - CHECK((int)info1->created.size() == count); - CHECK((int)info2->created.size() == count); - std::vector> d; - d.reserve(count); - for (int i = 0; i < count; i++) { - auto x1 = info2->created[i].first - info1->created[i].first; - auto y1 = info2->created[i].second - info1->created[i].second; - if (x1 < 0 || y1 < 0 || (x1 | y1) >= (1u << 31)) { - LOG(ERROR) << "impossible situation: validator #i created a negative amount of blocks: " << x1 - << " masterchain blocks, " << y1 << " shardchain blocks"; - return; - } - xs += x1; - ys += y1; - d.emplace_back((int)x1, (int)y1); - td::TerminalIO::out() << "val #" << i << ": created (" << x1 << "," << y1 << ") ; was (" << info1->created[i].first - << "," << info1->created[i].second << ")\n"; - } - if (xs != x || ys != y) { - LOG(ERROR) << "cannot account for all blocks created: total is (" << x << "," << y - << "), but the sum for all validators is (" << xs << "," << ys << ")"; - return; - } - td::TerminalIO::out() << "total: (" << x << "," << y << ")\n"; - auto ccfg = block::Config::unpack_catchain_validators_config(info2->config->get_config_param(28)); - auto ccfg_old = block::Config::unpack_catchain_validators_config(info1->config->get_config_param(28)); - if (ccfg.shard_val_num != ccfg_old.shard_val_num || ccfg.shard_val_num <= 0) { - LOG(ERROR) << "shard validator group size changed from " << ccfg_old.shard_val_num << " to " << ccfg.shard_val_num - << ", or is not positive"; - return; - } - int shard_count = ccfg.shard_val_num, main_count = info2->vset->main; - if (info1->vset->main != main_count || main_count <= 0) { - LOG(ERROR) << "masterchain validator group size changed from " << info1->vset->main << " to " << main_count - << ", or is not positive"; - return; - } - int cnt = 0, cnt_ok = 0; - double chunk_size = ccfg.shard_val_lifetime / 3. / shard_count; - block::MtCarloComputeShare shard_share(shard_count, info2->vset->export_scaled_validator_weights()); - for (int i = 0; i < count; i++) { - int x1 = d[i].first, y1 = d[i].second; - double xe = (i < main_count ? (double)xs / main_count : 0); - double ye = shard_share[i] * (double)ys / shard_count; - td::Bits256 pk = info2->vset->list[i].pubkey.as_bits256(); - double p1 = create_prob(x1, .9 * xe), p2 = shard_create_prob(y1, .9 * ye, chunk_size); - td::TerminalIO::out() << "val #" << i << ": pubkey " << pk.to_hex() << ", blocks created (" << x1 << "," << y1 - << "), expected (" << xe << "," << ye << "), probabilities " << p1 << " and " << p2 << "\n"; - if (std::min(p1, p2) < .00001) { - LOG(ERROR) << "validator #" << i << " with pubkey " << pk.to_hex() - << " : serious misbehavior detected: created less than 90% of the expected amount of blocks with " - "probability 99.999% : created (" - << x1 << "," << y1 << "), expected (" << xe << "," << ye << ") masterchain/shardchain blocks\n"; - if (mode & 2) { - auto st = write_val_create_proof(*info1, *info2, i, true, file_pfx, ++cnt); - if (st.is_error()) { - LOG(ERROR) << "cannot create proof: " << st.move_as_error(); - } else { - cnt_ok++; - } - } - } else if (std::min(p1, p2) < .001) { - LOG(ERROR) << "validator #" << i << " with pubkey " << pk.to_hex() - << " : moderate misbehavior detected: created less than 90% of the expected amount of blocks with " - "probability 99.9% : created (" - << x1 << "," << y1 << "), expected (" << xe << "," << ye << ") masterchain/shardchain blocks\n"; - if ((mode & 3) == 2) { - auto st = write_val_create_proof(*info1, *info2, i, false, file_pfx, ++cnt); - if (st.is_error()) { - LOG(ERROR) << "cannot create proof: " << st.move_as_error(); - } else { - cnt_ok++; - } - } - } - } - if (cnt > 0) { - LOG(INFO) << cnt_ok << " out of " << cnt << " proofs written to " << file_pfx << "-*.boc"; - } -} - -bool compute_punishment(int interval, bool severe, td::RefInt256& fine, unsigned& fine_part) { - if (interval <= 1000) { - return false; // no punishments for less than 1000 seconds - } - if (severe) { - fine = td::make_refint(2500 * 1000000000LL); // GR$2500 - fine_part = (1 << 30); // 1/4 of stake - } else { - fine = td::make_refint(1000 * 1000000000LL); // GR$1000 - fine_part = (1 << 28); // 1/16 of stake - } - if (interval >= 80000) { - return true; - } - if (interval >= 20000) { - fine >>= 2; - fine_part >>= 2; - return true; - } - fine >>= 4; - fine_part >>= 4; - return true; -} - -bool check_punishment(int interval, bool severe, td::RefInt256 fine, unsigned fine_part) { - td::RefInt256 computed_fine; - unsigned computed_fine_part; - return compute_punishment(interval, severe, computed_fine, computed_fine_part) && - std::llabs((long long)fine_part - (long long)computed_fine_part) <= - (std::max(fine_part, computed_fine_part) >> 3) && - fine * 7 <= computed_fine * 8 && computed_fine * 7 <= fine * 8; -} - -td::Status TestNode::write_val_create_proof(TestNode::ValidatorLoadInfo& info1, TestNode::ValidatorLoadInfo& info2, - int idx, bool severe, std::string file_pfx, int cnt) { - std::string filename = PSTRING() << file_pfx << '-' << cnt << ".boc"; - if (!info1.has_data()) { - return td::Status::Error("first block information is incomplete"); - } - if (!info2.has_data()) { - return td::Status::Error("second block information is incomplete"); - } - LOG(INFO) << "creating proof file " << filename; - TRY_STATUS(info1.check_header_proof(&info1.block_created_at, &info1.end_lt)); - TRY_STATUS(info2.check_header_proof(&info2.block_created_at, &info2.end_lt)); - td::Bits256 val_pk1, val_pk2; - TRY_RESULT(prod1, info1.build_producer_info(idx, &val_pk1)); - TRY_RESULT(prod2, info2.build_producer_info(idx, &val_pk2)); - if (val_pk1 != val_pk2) { - return td::Status::Error("validator public key mismatch"); - } - int interval = (int)(info2.block_created_at - info1.block_created_at); - if (interval <= 0) { - return td::Status::Error("non-positive time interval"); - } - int severity = (severe ? 2 : 1); - td::RefInt256 fine = td::make_refint(1000000000); - unsigned fine_part = 0xffffffff / 16; // 1/16 - if (!compute_punishment(interval, severe, fine, fine_part)) { - return td::Status::Error("cannot compute adequate punishment"); - } - Ref cpl_descr, complaint; - vm::CellBuilder cb; - // no_blk_gen_diff prod_info_old:^ProducerInfo prod_info_new:^ProducerInfo = ComplaintDescr - if (!(block::gen::t_ComplaintDescr.cell_pack_no_blk_gen_diff(cpl_descr, prod1, prod2) && - cb.store_long_bool(0xbc, 8) // validator_complaint#bc - && cb.store_bits_bool(val_pk1) // validator_pubkey:uint256 - && cb.store_ref_bool(cpl_descr) // description:^ComplaintDescr - && cb.store_long_bool(now(), 32) // created_at:uint32 - && cb.store_long_bool(severity, 8) // severity:uint8 - && cb.store_zeroes_bool(256) // reward_addr:uint256 - && cb.store_zeroes_bool(4) // paid:Grams - && block::tlb::t_Grams.store_integer_ref(cb, std::move(fine)) // suggested_fine:Grams - && cb.store_long_bool(fine_part, 32) // suggested_fine_part:uint32 - && cb.finalize_to(complaint))) { - return td::Status::Error("cannot serialize ValidatorComplaint"); - } - if (verbosity >= 5) { - std::ostringstream os; - os << "complaint: "; - block::gen::t_ValidatorComplaint.print_ref(print_limit_, os, complaint); - td::TerminalIO::out() << os.str() << std::endl; - } - if (!block::gen::t_ComplaintDescr.validate_ref(cpl_descr)) { - return td::Status::Error("created an invalid ComplaintDescr"); - } - if (!block::gen::t_ValidatorComplaint.validate_ref(complaint)) { - return td::Status::Error("created an invalid ValidatorComplaint"); - } - TRY_RESULT_PREFIX(boc, vm::std_boc_serialize(complaint, 2), "cannot create boc:"); - auto size = boc.size(); - TRY_STATUS_PREFIX(td::write_file(filename, std::move(boc)), PSLICE() << "cannot save file `" << filename << "` :"); - td::TerminalIO::out() << "saved validator misbehavior proof into file `" << filename << "` (" << size - << " bytes written)" << std::endl; - td::TerminalIO::out() << "COMPLAINT_SAVED\t" << info1.vset_hash.to_hex() << "\t" << complaint->get_hash().to_hex() - << "\t" << filename << std::endl; - return td::Status::OK(); -} - -td::Status TestNode::ValidatorLoadInfo::check_header_proof(ton::UnixTime* save_utime, ton::LogicalTime* save_lt) const { - auto state_virt_root = vm::MerkleProof::virtualize(std::move(data_proof), 1); - if (state_virt_root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - td::Bits256 state_hash = state_virt_root->get_hash().bits(); - TRY_STATUS(block::check_block_header_proof(vm::MerkleProof::virtualize(state_proof, 1), blk_id, &state_hash, true, - save_utime, save_lt)); - return td::Status::OK(); -} - -static bool visit(Ref cell); - -static bool visit(const vm::CellSlice& cs) { - auto cnt = cs.size_refs(); - bool res = true; - for (unsigned i = 0; i < cnt; i++) { - res &= visit(cs.prefetch_ref(i)); - } - return res; -} - -static bool visit(Ref cell) { - if (cell.is_null()) { - return true; - } - vm::CellSlice cs{vm::NoVm{}, std::move(cell)}; - return visit(cs); -} - -static bool visit(Ref cs_ref) { - return cs_ref.is_null() || visit(*cs_ref); -} - -td::Result> TestNode::ValidatorLoadInfo::build_proof(int idx, td::Bits256* save_pubkey) const { - try { - auto state_virt_root = vm::MerkleProof::virtualize(std::move(data_proof), 1); - if (state_virt_root.is_null()) { - return td::Status::Error("account state proof is invalid"); - } - vm::MerkleProofBuilder pb{std::move(state_virt_root)}; - TRY_RESULT(cfg, block::Config::extract_from_state(pb.root())); - visit(cfg->get_config_param(28)); - block::gen::ValidatorSet::Record_validators_ext rec; - if (!tlb::unpack_cell(cfg->get_config_param(34), rec)) { - return td::Status::Error("cannot unpack ValidatorSet"); - } - vm::Dictionary vdict{rec.list, 16}; - auto entry = vdict.lookup(td::BitArray<16>(idx)); - if (entry.is_null()) { - return td::Status::Error("validator entry not found"); - } - Ref pk; - block::gen::ValidatorDescr::Record_validator rec1; - block::gen::ValidatorDescr::Record_validator_addr rec2; - if (tlb::csr_unpack(entry, rec1)) { - pk = std::move(rec1.public_key); - } else if (tlb::csr_unpack(std::move(entry), rec2)) { - pk = std::move(rec2.public_key); - } else { - return td::Status::Error("cannot unpack ValidatorDescr"); - } - block::gen::SigPubKey::Record rec3; - if (!tlb::csr_unpack(std::move(pk), rec3)) { - return td::Status::Error("cannot unpack ed25519_pubkey"); - } - if (save_pubkey) { - *save_pubkey = rec3.pubkey; - } - visit(std::move(entry)); - auto dict = block::get_block_create_stats_dict(pb.root()); - if (!dict) { - return td::Status::Error("cannot extract BlockCreateStats from mc state"); - } - visit(dict->lookup(rec3.pubkey)); - visit(dict->lookup(td::Bits256::zero())); - return pb.extract_proof(); - } catch (vm::VmError& err) { - return err.as_status("cannot build proof: "); - } catch (vm::VmVirtError& err) { - return err.as_status("cannot build proof: "); - } -} - -td::Result> TestNode::ValidatorLoadInfo::build_producer_info(int idx, td::Bits256* save_pubkey) const { - TRY_RESULT(proof, build_proof(idx, save_pubkey)); - vm::CellBuilder cb; - Ref res; - if (!(cb.store_long_bool(0x34, 8) // prod_info#34 - && cb.store_long_bool(block_created_at, 32) // utime:uint32 - && block::tlb::t_ExtBlkRef.store(cb, blk_id, end_lt) // mc_blk_ref:ExtBlkRef - && cb.store_ref_bool(state_proof) // state_proof:^Cell - && cb.store_ref_bool(proof) // prod_proof:^Cell = ProducerInfo - && cb.finalize_to(res))) { - return td::Status::Error("cannot construct ProducerInfo"); - } - if (!block::gen::t_ProducerInfo.validate_ref(res)) { - return td::Status::Error("constructed ProducerInfo failed to pass automated validity checks"); - } - return std::move(res); -} - -td::Status TestNode::check_validator_load_proof(std::string filename, std::string vset_filename, - ton::Bits256 vset_hash) { - TRY_RESULT_PREFIX(data, td::read_file(filename), "cannot read proof file:"); - TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(std::move(data)), - PSTRING() << "cannot deserialize boc from file `" << filename << "`:"); - Ref vset_root; - if (!vset_filename.empty()) { - TRY_RESULT_PREFIX(vdata, td::read_file(vset_filename), "cannot read validator set file:"); - TRY_RESULT_PREFIX_ASSIGN(vset_root, vm::std_boc_deserialize(std::move(vdata)), - PSLICE() << "cannot deserialize validator set boc from file `" << vset_filename << "`:"); - if (vset_hash.is_zero()) { - vset_hash = vset_root->get_hash().bits(); - } else if (vset_hash != vset_root->get_hash().bits()) { - return td::Status::Error("validator set hash mismatch: indicated "s + vset_hash.to_hex() + ", loaded from file " + - vset_root->get_hash().to_hex()); - } - } - if (verbosity >= 5) { - std::ostringstream os; - os << "complaint: "; - block::gen::t_ValidatorComplaint.print_ref(print_limit_, os, root); - td::TerminalIO::out() << os.str() << std::endl; - } - if (!block::gen::t_ValidatorComplaint.validate_ref(root)) { - return td::Status::Error("proof file does not contain a valid ValidatorComplaint"); - } - block::gen::ValidatorComplaint::Record rec; - if (!tlb::unpack_cell(root, rec)) { - return td::Status::Error("cannot unpack ValidatorComplaint"); - } - auto cs = vm::load_cell_slice(rec.description); - int tag = block::gen::t_ComplaintDescr.get_tag(cs); - if (tag < 0) { - return td::Status::Error("ComplaintDescr has an unknown tag"); - } - if (tag != block::gen::ComplaintDescr::no_blk_gen_diff) { - return td::Status::Error("can check only ComplaintDescr of type no_blk_gen_diff"); - } - block::gen::ComplaintDescr::Record_no_blk_gen_diff crec; - if (!tlb::unpack_exact(cs, crec)) { - return td::Status::Error("cannot unpack ComplaintDescr"); - } - TRY_RESULT_PREFIX(info1, ValidatorLoadInfo::preinit_from_producer_info(crec.prod_info_old), - "cannot unpack ProducerInfo in prod_info_old:") - TRY_RESULT_PREFIX(info2, ValidatorLoadInfo::preinit_from_producer_info(crec.prod_info_new), - "cannot unpack ProducerInfo in prod_info_new:") - if (info1->vset_hash != info2->vset_hash) { - return td::Status::Error("validator hash changed between the two blocks: "s + info1->vset_hash.to_hex() + " and " + - info2->vset_hash.to_hex()); - } - if (vset_hash.is_zero()) { - vset_hash = info1->vset_hash; - } else if (vset_hash != info1->vset_hash) { - return td::Status::Error("validator set hash mismatch: blocks have "s + info1->vset_hash.to_hex() + - ", actual value is " + vset_hash.to_hex()); - } - auto blkid2 = info2->blk_id; - if (vset_root.not_null()) { - info1->vset_root = info2->vset_root = std::move(vset_root); - set_error(continue_check_validator_load_proof(std::move(info1), std::move(info2), std::move(root))); - } else if (!get_config_params(blkid2, - [this, info1 = std::move(info1), info2 = std::move(info2), - root = std::move(root)](td::Result> res) mutable { - if (res.is_error()) { - LOG(ERROR) - << "cannot fetch configuration parameters from key block corresponding to " - << info2->blk_id.to_str() << " : " << res.move_as_error(); - } else { - auto vset_root = res.move_as_ok()->get_config_param(34); - if (vset_root.is_null()) { - LOG(ERROR) << "no configuration parameter #34 in key block corresponding to " - << info2->blk_id.to_str(); - } else if (info2->vset_hash != vset_root->get_hash().bits()) { - LOG(ERROR) << "validator hash set mismatch for block " << info2->blk_id.to_str(); - } else { - info1->vset_root = info2->vset_root = std::move(vset_root); - set_error(continue_check_validator_load_proof(std::move(info1), std::move(info2), - std::move(root))); - } - } - }, - 0xd000, "", {28, 34})) { - return td::Status::Error("cannot request configuration parameters from key block corresponding to "s + - blkid2.to_str()); - } - return td::Status::OK(); -} - -static void show_vote(td::Bits256 complaint_hash, bool outcome) { - td::TerminalIO::out() << "COMPLAINT_VOTE_FOR\t" << complaint_hash.to_hex() << "\t" << (outcome ? "YES" : "NO") - << std::endl; -} - -td::Status TestNode::continue_check_validator_load_proof(std::unique_ptr info1, - std::unique_ptr info2, Ref root) { - TRY_STATUS(info1->unpack_vset()); - TRY_STATUS(info2->unpack_vset()); - int interval = (int)(info2->block_created_at - info1->block_created_at); - if (interval <= 0) { - return td::Status::Error("non-positive time interval"); - } - block::gen::ValidatorComplaint::Record rec; - block::gen::ComplaintDescr::Record_no_blk_gen_diff crec; - if (!(tlb::unpack_cell(root, rec) && tlb::unpack_cell(rec.description, crec))) { - return td::Status::Error("cannot unpack ValidatorComplaint second time (?)"); - } - td::Bits256 val_pubkey = rec.validator_pubkey; - int val_idx = info1->vset->lookup_public_key(val_pubkey); - if (val_idx < 0) { - return td::Status::Error("validator with public key "s + val_pubkey.to_hex() + - " is not present in active validator set"); - } - TRY_STATUS(info1->load_special_creator_stat(val_pubkey, true)); - TRY_STATUS(info2->load_special_creator_stat(val_pubkey, true)); - td::TerminalIO::out() << "total: (" << info1->created_total.first << "," << info1->created_total.second << ") -> (" - << info2->created_total.first << "," << info2->created_total.second << ")\n"; - auto x = info2->created_total.first - info1->created_total.first; - auto y = info2->created_total.second - info1->created_total.second; - if (x <= 0 || y < 0 || (x | y) >= (1u << 31)) { - return td::Status::Error(PSLICE() << "impossible situation: zero or no blocks created: " << x - << " masterchain blocks, " << y << " shardchain blocks"); - } - auto x1 = info2->created_special.first - info1->created_special.first; - auto y1 = info2->created_special.second - info1->created_special.second; - if ((x1 | y1) < 0 || (x1 | y1) >= (1u << 31)) { - return td::Status::Error(PSLICE() << "impossible situation: validator " << val_pubkey.to_hex() << " created " << x1 - << " masterchain blocks, " << y1 << " shardchain blocks"); - } - td::TerminalIO::out() << "total: (" << x << "," << y << ")\n"; - try { - auto ccfg = block::Config::unpack_catchain_validators_config(info2->config->get_config_param(28)); - auto ccfg_old = block::Config::unpack_catchain_validators_config(info1->config->get_config_param(28)); - if (ccfg.shard_val_num != ccfg_old.shard_val_num || ccfg.shard_val_num <= 0) { - return td::Status::Error(PSLICE() << "shard validator group size changed from " << ccfg_old.shard_val_num - << " to " << ccfg.shard_val_num << ", or is not positive"); - } - int shard_count = ccfg.shard_val_num, main_count = info2->vset->main; - if (info1->vset->main != main_count || main_count <= 0) { - return td::Status::Error(PSLICE() << "masterchain validator group size changed from " << info1->vset->main - << " to " << main_count << ", or is not positive"); - } - double chunk_size = ccfg.shard_val_lifetime / 3. / shard_count; - block::MtCarloComputeShare shard_share(shard_count, info2->vset->export_scaled_validator_weights()); - - double xe = (val_idx < main_count ? (double)x / main_count : 0); - double ye = shard_share[val_idx] * (double)y / shard_count; - td::Bits256 pk = info2->vset->list[val_idx].pubkey.as_bits256(); - CHECK(pk == val_pubkey); - double p1 = create_prob((int)x1, .9 * xe), p2 = shard_create_prob((int)y1, .9 * ye, chunk_size); - td::TerminalIO::out() << "val #" << val_idx << ": pubkey " << pk.to_hex() << ", blocks created (" << x1 << "," << y1 - << "), expected (" << xe << "," << ye << "), probabilities " << p1 << " and " << p2 << "\n"; - bool severe = (rec.severity >= 2); - if (severe && std::min(p1, p2) < .00001) { - LOG(ERROR) << "validator #" << val_idx << " with pubkey " << pk.to_hex() - << " : serious misbehavior detected: created less than 90% of the expected amount of blocks with " - "probability 99.999% : created (" - << x1 << "," << y1 << "), expected (" << xe << "," << ye << ") masterchain/shardchain blocks\n"; - } else if (!severe && std::min(p1, p2) < .001) { - LOG(ERROR) << "validator #" << val_idx << " with pubkey " << pk.to_hex() - << " : moderate misbehavior detected: created less than 90% of the expected amount of blocks with " - "probability 99.9% : created (" - << x1 << "," << y1 << "), expected (" << xe << "," << ye << ") masterchain/shardchain blocks\n"; - } else { - LOG(ERROR) << "invalid (unsupported) complaint for validator #" << val_idx << " with pubkey " << pk.to_hex(); - show_vote(root->get_hash().bits(), false); - return td::Status::OK(); - } - auto suggested_fine = block::tlb::t_Grams.as_integer(rec.suggested_fine); - if (suggested_fine.is_null()) { - return td::Status::Error("cannot parse suggested fine"); - } - if (!check_punishment(interval, severe, suggested_fine, rec.suggested_fine_part)) { - LOG(ERROR) << "proposed punishment (fine " << td::dec_string(suggested_fine) - << ", fine_part=" << (double)rec.suggested_fine_part / (1LL << 32) << " is too harsh"; - show_vote(root->get_hash().bits(), false); - return td::Status::OK(); - } - LOG(INFO) << "accepting suggested punishment (affirmative vote)"; - show_vote(root->get_hash().bits(), true); - return td::Status::OK(); - } catch (vm::VmError& err) { - return err.as_status("vm error while scanning configuration proof:"); - } catch (vm::VmVirtError& err) { - return err.as_status("virtualization error while scanning configuration proof:"); - } -} - -td::Status TestNode::ValidatorLoadInfo::load_special_creator_stat(const td::Bits256& spec_pubkey, bool load_total) { - if (!vset) { - return td::Status::Error("no validator set loaded"); - } - int idx = vset->lookup_public_key(spec_pubkey); - if (idx < 0) { - return td::Status::Error("validator with public key "s + spec_pubkey.to_hex() + " not present in validator set"); - } - if (virt_root.is_null()) { - return td::Status::Error("no virtualized block state"); - } - try { - auto dict = block::get_block_create_stats_dict(virt_root); - if (!dict) { - return td::Status::Error("cannot extract BlockCreateStats from virtualized mc state"); - } - for (int i = 0; i <= (int)load_total; i++) { - td::Bits256 key = (i ? td::Bits256::zero() : spec_pubkey); - auto& p = *(i ? &created_total : &created_special); - auto cell = dict->lookup(key); - if (cell.is_null()) { - p.first = p.second = 0; - if (i) { - return td::Status::Error("no total created block statistics in BlockCreateStats"); - } - } else { - block::DiscountedCounter mc_cnt, shard_cnt; - if (!block::unpack_CreatorStats(std::move(cell), mc_cnt, shard_cnt)) { - return td::Status::Error(PSLICE() << "invalid CreatorStats record with key " << key.to_hex()); - } - p.first = mc_cnt.total; - p.second = shard_cnt.total; - } - } - special_idx = idx; - return td::Status::OK(); - } catch (vm::VmError& err) { - return err.as_status("vm error while extracting block creator data: "); - } catch (vm::VmVirtError& err) { - return err.as_status("virtualization error while extracting block creator data: "); - } -} - -td::Result> TestNode::ValidatorLoadInfo::preinit_from_producer_info( - Ref prod_info) { - if (prod_info.is_null()) { - return td::Status::Error("ProducerInfo cell is null"); - } - if (!block::gen::t_ProducerInfo.validate_ref(prod_info)) { - return td::Status::Error("invalid ProducerInfo"); - } - block::gen::ProducerInfo::Record rec; - ton::BlockIdExt blk_id; - ton::LogicalTime end_lt; - if (!(tlb::unpack_cell(prod_info, rec) && - block::tlb::t_ExtBlkRef.unpack(std::move(rec.mc_blk_ref), blk_id, &end_lt))) { - return td::Status::Error("cannot unpack ProducerInfo"); - } - auto info = std::make_unique(blk_id, std::move(rec.state_proof), std::move(rec.prod_proof)); - CHECK(info); - info->end_lt = end_lt; - info->block_created_at = rec.utime; - TRY_STATUS_PREFIX(info->init_check_proofs(), "error checking block/state proofs:"); - return std::move(info); -} - -td::Status TestNode::ValidatorLoadInfo::init_check_proofs() { - try { - ton::UnixTime utime; - ton::LogicalTime lt; - TRY_STATUS(check_header_proof(&utime, <)); - if (utime != block_created_at) { - return td::Status::Error(PSLICE() << "incorrect block creation time: declared " << block_created_at << ", actual " - << utime); - } - if (lt != end_lt) { - return td::Status::Error(PSLICE() << "incorrect block logical time: declared " << end_lt << ", actual " << lt); - } - auto vstate = vm::MerkleProof::virtualize(data_proof, 1); - if (vstate.is_null()) { - return td::Status::Error(PSLICE() << "cannot virtualize state of block " << blk_id.to_str()); - } - TRY_RESULT_PREFIX_ASSIGN(config, block::Config::extract_from_state(vstate, 0), "cannot unpack configuration:"); - auto vset_root = config->get_config_param(34); - if (vset_root.is_null()) { - vset_hash.set_zero(); - return td::Status::Error(PSLICE() << "no configuration parameter 34 (validator set) for block " - << blk_id.to_str()); - } - vset_hash = vset_root->get_hash().bits(); - virt_root = vstate; - return td::Status::OK(); - } catch (vm::VmError& err) { - return err.as_status("vm error:"); - } catch (vm::VmVirtError& err) { - return err.as_status("virtualization error:"); - } -} - -int main(int argc, char* argv[]) { - SET_VERBOSITY_LEVEL(verbosity_INFO); - td::set_default_failure_signal_handler(); - - td::actor::ActorOwn x; - - td::OptionsParser p; - p.set_description("Test Lite Client for TON Blockchain"); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb(td::MutableSlice{b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('r', "disable-readline", "", [&]() { - td::actor::send_closure(x, &TestNode::set_readline_enabled, false); - return td::Status::OK(); - }); - p.add_option('R', "enable-readline", "", [&]() { - td::actor::send_closure(x, &TestNode::set_readline_enabled, true); - return td::Status::OK(); - }); - p.add_option('D', "db", "root for dbs", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_db_root, fname.str()); - return td::Status::OK(); - }); - p.add_option('L', "print-limit", "sets maximum count of recursively printed objects", [&](td::Slice arg) { - auto plimit = td::to_integer(arg); - td::actor::send_closure(x, &TestNode::set_print_limit, plimit); - return plimit >= 0 ? td::Status::OK() : td::Status::Error("printing limit must be non-negative"); - }); - p.add_option('v', "verbosity", "set verbosity level", [&](td::Slice arg) { - verbosity = td::to_integer(arg); - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(FATAL) + verbosity); - return (verbosity >= 0 && verbosity <= 9) ? td::Status::OK() : td::Status::Error("verbosity must be 0..9"); - }); - p.add_option('i', "idx", "set liteserver idx", [&](td::Slice arg) { - auto idx = td::to_integer(arg); - td::actor::send_closure(x, &TestNode::set_liteserver_idx, idx); - return td::Status::OK(); - }); - p.add_option('a', "addr", "connect to ip:port", [&](td::Slice arg) { - td::IPAddress addr; - TRY_STATUS(addr.init_host_port(arg.str())); - td::actor::send_closure(x, &TestNode::set_remote_addr, addr); - return td::Status::OK(); - }); - p.add_option('c', "cmd", "schedule command", [&](td::Slice arg) { - td::actor::send_closure(x, &TestNode::add_cmd, td::BufferSlice{arg}); - return td::Status::OK(); - }); - p.add_option('t', "timeout", "timeout in batch mode", [&](td::Slice arg) { - auto d = td::to_double(arg); - td::actor::send_closure(x, &TestNode::set_fail_timeout, td::Timestamp::in(d)); - return td::Status::OK(); - }); - p.add_option('p', "pub", "remote public key", [&](td::Slice arg) { - td::actor::send_closure(x, &TestNode::set_public_key, td::BufferSlice{arg}); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()), - td::FileFd::Flags::Create | td::FileFd::Flags::Append | td::FileFd::Flags::Write) - .move_as_ok(); - - dup2(FileLog.get_native_fd().fd(), 1); - dup2(FileLog.get_native_fd().fd(), 2); - return td::Status::OK(); - }); -#endif - - vm::init_op_cp0(true); // enable vm debug - - td::actor::Scheduler scheduler({2}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { - td::actor::send_closure(x, &TestNode::run); - x.release(); - }); - scheduler.run(); - - return 0; -} diff --git a/submodules/ton/tonlib-src/lite-client/lite-client.h b/submodules/ton/tonlib-src/lite-client/lite-client.h deleted file mode 100644 index 6ebf0356..00000000 --- a/submodules/ton/tonlib-src/lite-client/lite-client.h +++ /dev/null @@ -1,430 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "adnl/adnl-ext-client.h" -#include "tl-utils/tl-utils.hpp" -#include "ton/ton-types.h" -#include "terminal/terminal.h" -#include "vm/cells.h" -#include "vm/stack.hpp" -#include "block/block.h" -#include "block/mc-config.h" -#include "td/utils/filesystem.h" - -using td::Ref; - -class TestNode : public td::actor::Actor { - private: - std::string global_config_ = "ton-global.config"; - enum { - min_ls_version = 0x101, - min_ls_capabilities = 1 - }; // server version >= 1.1, capabilities at least +1 = build proof chains - td::actor::ActorOwn client_; - td::actor::ActorOwn io_; - - bool readline_enabled_ = true; - bool server_ok_ = false; - td::int32 liteserver_idx_ = -1; - int print_limit_ = 1024; - - bool ready_ = false; - bool inited_ = false; - std::string db_root_; - - int server_time_ = 0; - int server_time_got_at_ = 0; - int server_version_ = 0; - long long server_capabilities_ = 0; - - ton::ZeroStateIdExt zstate_id_; - ton::BlockIdExt mc_last_id_; - - ton::BlockIdExt last_block_id_, last_state_id_; - td::BufferSlice last_block_data_, last_state_data_; - - ton::StdSmcAddress dns_root_, elect_addr_; - bool dns_root_queried_{false}, elect_addr_queried_{false}; - - std::string line_; - const char *parse_ptr_, *parse_end_; - td::Status error_; - - td::IPAddress remote_addr_; - ton::PublicKey remote_public_key_; - - std::vector known_blk_ids_; - std::size_t shown_blk_ids_ = 0; - - td::Timestamp fail_timeout_; - td::uint32 running_queries_ = 0; - bool ex_mode_ = false; - std::vector ex_queries_; - - std::map> cell_cache_; - - std::unique_ptr make_callback(); - - using creator_stats_func_t = - std::function; - - struct TransId { - ton::Bits256 acc_addr; - ton::LogicalTime trans_lt; - ton::Bits256 trans_hash; - TransId(const ton::Bits256& addr_, ton::LogicalTime lt_, const ton::Bits256& hash_) - : acc_addr(addr_), trans_lt(lt_), trans_hash(hash_) { - } - }; - - struct BlockHdrInfo { - ton::BlockIdExt blk_id; - Ref proof, virt_blk_root; - int mode; - BlockHdrInfo() : mode(-1) { - } - BlockHdrInfo(const ton::BlockIdExt blk_id_, Ref proof_, Ref vroot_, int mode_) - : blk_id(blk_id_), proof(std::move(proof_)), virt_blk_root(std::move(vroot_)), mode(mode_) { - } - }; - - struct ConfigInfo { - std::unique_ptr config; - Ref state_proof, config_proof; - ConfigInfo() = default; - ConfigInfo(std::unique_ptr config_, Ref state_proof_, Ref config_proof_) - : config(std::move(config_)), state_proof(std::move(state_proof_)), config_proof(std::move(config_proof_)) { - } - }; - - struct CreatorStatsRes { - int mode; - bool complete{false}; - td::Bits256 last_key; - Ref state_proof, data_proof; - CreatorStatsRes(int mode_ = 0) : mode(mode_) { - last_key.set_zero(); - } - CreatorStatsRes(int mode_, const td::Bits256& key_, Ref st_proof_ = {}, Ref dproof_ = {}) - : mode(mode_), last_key(key_), state_proof(std::move(st_proof_)), data_proof(std::move(dproof_)) { - } - }; - - struct ValidatorLoadInfo { - ton::BlockIdExt blk_id; - Ref state_proof, data_proof, virt_root; - std::unique_ptr config; - ton::UnixTime block_created_at{0}; - ton::UnixTime valid_since{0}; - ton::LogicalTime end_lt{0}; - ton::Bits256 vset_hash; - Ref vset_root; - std::unique_ptr vset; - std::map vset_map; - int special_idx{-1}; - std::pair created_total, created_special; - std::vector> created; - ValidatorLoadInfo(ton::BlockIdExt blkid, Ref root, Ref root2, - std::unique_ptr cfg = {}) - : blk_id(blkid) - , state_proof(std::move(root)) - , data_proof(std::move(root2)) - , config(std::move(cfg)) - , valid_since(0) { - } - td::Status unpack_vset(); - bool store_record(const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt); - bool has_data() const { - return blk_id.is_masterchain_ext() && state_proof.not_null() && data_proof.not_null() && config; - } - td::Status check_header_proof(ton::UnixTime* save_utime = nullptr, ton::LogicalTime* save_lt = nullptr) const; - td::Result> build_proof(int idx, td::Bits256* save_pubkey = nullptr) const; - td::Result> build_producer_info(int idx, td::Bits256* save_pubkey = nullptr) const; - td::Status init_check_proofs(); - static td::Result> preinit_from_producer_info(Ref prod_info); - td::Status load_special_creator_stat(const td::Bits256& spec_pubkey, bool load_total = true); - }; - - void run_init_queries(); - char cur() const { - return *parse_ptr_; - } - bool get_server_time(); - bool get_server_version(int mode = 0); - void got_server_version(td::Result res, int mode); - bool get_server_mc_block_id(); - void got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int created_at); - void got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version, - long long capabilities, int last_utime, int server_now); - void set_server_version(td::int32 version, td::int64 capabilities); - void set_server_time(int server_utime); - bool request_block(ton::BlockIdExt blkid); - bool request_state(ton::BlockIdExt blkid); - void got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data); - void got_mc_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::FileHash file_hash, td::BufferSlice data); - td::Status send_ext_msg_from_filename(std::string filename); - td::Status save_db_file(ton::FileHash file_hash, td::BufferSlice data); - bool get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string filename = "", int mode = -1); - void got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, - td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode); - bool parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string method_name, bool ext_mode); - bool start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - std::string method_name, std::vector params, int mode, - td::Promise> promise); - void run_smc_method(int mode, ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, - td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string method, - std::vector params, td::BufferSlice remote_c7, td::BufferSlice remote_libs, - td::BufferSlice remote_result, int remote_exit_code, - td::Promise> promise); - bool register_config_param(int idx, Ref value); - bool register_config_param1(Ref value); - bool register_config_param4(Ref value); - bool dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, std::string domain, - int cat, int mode); - bool dns_resolve_send(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, std::string domain, - std::string qdomain, int cat, int mode); - void dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode, int used_bits, - Ref value); - bool show_dns_record(std::ostream& os, int cat, Ref value, bool raw_dump); - bool get_all_shards(std::string filename = "", bool use_last = true, ton::BlockIdExt blkid = {}); - void got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data, std::string filename); - bool parse_get_config_params(ton::BlockIdExt blkid, int mode = 0, std::string filename = "", - std::vector params = {}); - bool get_config_params(ton::BlockIdExt blkid, td::Promise> promise, int mode = 0, - std::string filename = "", std::vector params = {}); - bool get_config_params_ext(ton::BlockIdExt blkid, td::Promise promise, int mode = 0, - std::string filename = "", std::vector params = {}); - void got_config_params(ton::BlockIdExt req_blkid, int mode, std::string filename, std::vector params, - td::Result R, td::Promise promise); - bool get_block(ton::BlockIdExt blk, bool dump = false); - void got_block(ton::BlockIdExt blkid, td::BufferSlice data, bool dump); - bool get_state(ton::BlockIdExt blk, bool dump = false); - void got_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::FileHash file_hash, td::BufferSlice data, - bool dump); - bool get_show_block_header(ton::BlockIdExt blk, int mode); - bool get_block_header(ton::BlockIdExt blk, int mode, td::Promise promise); - bool lookup_show_block(ton::ShardIdFull shard, int mode, td::uint64 arg); - bool lookup_block(ton::ShardIdFull shard, int mode, td::uint64 arg, td::Promise); - void got_block_header_raw(td::BufferSlice res, td::Promise promise, ton::BlockIdExt req_blkid = {}); - void got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int mode); - bool show_block_header(ton::BlockIdExt blkid, Ref root, int mode); - bool show_state_header(ton::BlockIdExt blkid, Ref root, int mode); - bool get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workchain, ton::StdSmcAddress addr, - ton::LogicalTime lt, bool dump = false); - void got_one_transaction(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice proof, - td::BufferSlice transaction, ton::WorkchainId workchain, ton::StdSmcAddress addr, - ton::LogicalTime trans_lt, bool dump); - bool get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, - ton::Bits256 hash, unsigned count, bool dump); - void got_last_transactions(std::vector blkids, td::BufferSlice transactions_boc, - ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, - ton::Bits256 hash, unsigned count, bool dump); - bool get_block_transactions(ton::BlockIdExt blkid, int mode, unsigned count, ton::Bits256 acc_addr, - ton::LogicalTime lt); - void got_block_transactions(ton::BlockIdExt blkid, int mode, unsigned req_count, bool incomplete, - std::vector trans, td::BufferSlice proof); - bool get_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mode); - void got_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, td::BufferSlice res); - bool get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, - ton::UnixTime min_utime); - bool get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, - ton::UnixTime min_utime, creator_stats_func_t func, td::Promise promise); - bool get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton::UnixTime min_utime, creator_stats_func_t func, - std::unique_ptr state, td::Promise> promise); - void got_creator_stats(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, int mode, ton::UnixTime min_utime, - td::BufferSlice state_proof, td::BufferSlice data_proof, int count, int req_count, - bool complete, creator_stats_func_t func, std::unique_ptr state, - td::Promise> promise); - bool check_validator_load(int start_time, int end_time, int mode = 0, std::string file_pfx = ""); - void continue_check_validator_load(ton::BlockIdExt blkid1, Ref root1, ton::BlockIdExt blkid2, - Ref root2, int mode = 0, std::string file_pfx = ""); - void continue_check_validator_load2(std::unique_ptr info1, - std::unique_ptr info2, int mode = 0, - std::string file_pfx = ""); - void continue_check_validator_load3(std::unique_ptr info1, - std::unique_ptr info2, int mode = 0, - std::string file_pfx = ""); - td::Status write_val_create_proof(ValidatorLoadInfo& info1, ValidatorLoadInfo& info2, int idx, bool severe, - std::string file_pfx, int cnt); - bool load_creator_stats(std::unique_ptr load_to, - td::Promise> promise, bool need_proofs); - td::Status check_validator_load_proof(std::string filename, std::string vset_filename = "", - ton::Bits256 vset_hash = ton::Bits256::zero()); - td::Status continue_check_validator_load_proof(std::unique_ptr info1, - std::unique_ptr info2, Ref root); - bool get_elector_addr(td::Promise promise); - bool get_past_validator_sets(); - bool send_past_vset_query(ton::StdSmcAddress elector_addr); - void register_past_vset_info(vm::StackEntry list); - bool get_complaints(unsigned elect_id, std::string file_pfx); - void send_get_complaints_query(unsigned elect_id, ton::StdSmcAddress elector_addr, std::string file_pfx); - void save_complaints(unsigned elect_id, Ref complaints, std::string file_pfx); - td::Status get_complaint_price(unsigned expires_in, std::string filename); - td::Status get_complaint_price(unsigned expires_in, unsigned bits, unsigned refs, - td::Bits256 chash = td::Bits256::zero(), std::string filename = ""); - void send_compute_complaint_price_query(ton::StdSmcAddress elector_addr, unsigned expires_in, unsigned bits, - unsigned refs, td::Bits256 chash, std::string filename); - bool cache_cell(Ref cell); - bool list_cached_cells() const; - bool dump_cached_cell(td::Slice hash_pfx, td::Slice type_name = {}); - // parser - bool do_parse_line(); - bool show_help(std::string command); - td::Slice get_word(char delim = ' '); - td::Slice get_word_ext(const char* delims, const char* specials = nullptr); - bool get_word_to(std::string& str, char delim = ' '); - bool get_word_to(td::Slice& str, char delim = ' '); - int skipspc(); - std::string get_line_tail(bool remove_spaces = true) const; - bool eoln() const; - bool seekeoln(); - bool set_error(td::Status error); - bool set_error(std::string err_msg); - void show_context() const; - bool parse_account_addr(ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool allow_none = false); - static int parse_hex_digit(int c); - static bool parse_hash(const char* str, ton::Bits256& hash); - static bool parse_hash(td::Slice str, ton::Bits256& hash); - static bool convert_uint64(td::Slice word, td::uint64& val); - static bool convert_int64(td::Slice word, td::int64& val); - static bool convert_uint32(td::Slice word, td::uint32& val); - static bool convert_int32(td::Slice word, td::int32& val); - static bool convert_shard_id(td::Slice str, ton::ShardIdFull& shard); - static td::int64 compute_method_id(std::string method); - bool parse_hash(ton::Bits256& hash); - bool parse_lt(ton::LogicalTime& lt); - bool parse_uint32(td::uint32& val); - bool parse_int32(td::int32& val); - bool parse_int16(int& val); - bool parse_shard_id(ton::ShardIdFull& shard); - bool parse_block_id_ext(ton::BlockIdExt& blkid, bool allow_incomplete = false); - bool parse_block_id_ext(std::string blk_id_string, ton::BlockIdExt& blkid, bool allow_incomplete = false) const; - bool parse_stack_value(td::Slice str, vm::StackEntry& value); - bool parse_stack_value(vm::StackEntry& value); - bool parse_stack_values(std::vector& values); - bool register_blkid(const ton::BlockIdExt& blkid); - bool show_new_blkids(bool all = false); - bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const; - td::Promise trivial_promise(); - template - td::Promise trivial_promise_of() { - return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "error: " << res.move_as_error(); - } - }); - } - static ton::UnixTime now() { - return static_cast(td::Clocks::system()); - } - static const tlb::TypenameLookup& get_tlb_dict(); - - public: - void conn_ready() { - LOG(ERROR) << "conn ready"; - ready_ = true; - if (!inited_) { - run_init_queries(); - } - } - void conn_closed() { - ready_ = false; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void set_db_root(std::string db_root) { - db_root_ = db_root; - } - void set_readline_enabled(bool value) { - readline_enabled_ = value; - } - void set_liteserver_idx(td::int32 idx) { - liteserver_idx_ = idx; - } - void set_remote_addr(td::IPAddress addr) { - remote_addr_ = addr; - } - void set_public_key(td::BufferSlice file_name) { - auto R = [&]() -> td::Result { - TRY_RESULT_PREFIX(conf_data, td::read_file(file_name.as_slice().str()), "failed to read: "); - return ton::PublicKey::import(conf_data.as_slice()); - }(); - - if (R.is_error()) { - LOG(FATAL) << "bad server public key: " << R.move_as_error(); - } - remote_public_key_ = R.move_as_ok(); - } - void set_fail_timeout(td::Timestamp ts) { - fail_timeout_ = ts; - alarm_timestamp().relax(fail_timeout_); - } - void set_print_limit(int plimit) { - if (plimit >= 0) { - print_limit_ = plimit; - } - } - void add_cmd(td::BufferSlice data) { - ex_mode_ = true; - ex_queries_.push_back(std::move(data)); - readline_enabled_ = false; - } - void alarm() override { - if (fail_timeout_.is_in_past()) { - std::_Exit(7); - } - if (ex_mode_ && !running_queries_ && ex_queries_.size() == 0) { - std::_Exit(0); - } - alarm_timestamp().relax(fail_timeout_); - } - - void start_up() override { - } - void tear_down() override { - // FIXME: do not work in windows - //td::actor::SchedulerContext::get()->stop(); - } - - void got_result(td::Result R, td::Promise promise); - void after_got_result(bool ok); - bool envelope_send_query(td::BufferSlice query, td::Promise promise); - void parse_line(td::BufferSlice data); - - TestNode() { - } - - void run(); -}; diff --git a/submodules/ton/tonlib-src/memprof/CMakeLists.txt b/submodules/ton/tonlib-src/memprof/CMakeLists.txt deleted file mode 100644 index 8559c4d9..00000000 --- a/submodules/ton/tonlib-src/memprof/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -set(MEMPROF_SOURCE - memprof/memprof.cpp - memprof/memprof.h -) - -# memprof - simple library for memory usage profiling -add_library(memprof STATIC ${MEMPROF_SOURCE}) -target_include_directories(memprof PUBLIC $) -target_link_libraries(memprof PRIVATE tdutils) -if (MEMPROF) - target_compile_definitions(memprof PRIVATE -DUSE_MEMPROF=1) - if (MEMPROF STREQUAL "SAFE") - target_compile_definitions(memprof PRIVATE -DUSE_MEMPROF_SAFE=1) - elseif (MEMPROF STREQUAL "FAST") - target_compile_definitions(memprof PRIVATE -DUSE_MEMPROF_FAST=1) - elseif (NOT MEMPROF) - message(FATAL_ERROR "Unsupported MEMPROF value \"${MEMPROF}\"") - endif() -endif() - diff --git a/submodules/ton/tonlib-src/memprof/memprof/memprof.cpp b/submodules/ton/tonlib-src/memprof/memprof/memprof.cpp deleted file mode 100644 index ce2554e1..00000000 --- a/submodules/ton/tonlib-src/memprof/memprof/memprof.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#undef NDEBUG -#include "memprof/memprof.h" - -#include "td/utils/port/platform.h" - -#if (TD_DARWIN || TD_LINUX) && defined(USE_MEMPROF) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -bool is_memprof_on() { - return true; -} - -#if USE_MEMPROF_SAFE -double get_fast_backtrace_success_rate() { - return 0; -} -#else - -#if TD_LINUX -extern void *__libc_stack_end; -#endif - -static void *get_bp() { - void *bp; -#if defined(__i386__) - __asm__ volatile("movl %%ebp, %[r]" : [r] "=r"(bp)); -#elif defined(__x86_64__) - __asm__ volatile("movq %%rbp, %[r]" : [r] "=r"(bp)); -#endif - return bp; -} - -static int fast_backtrace(void **buffer, int size) { - struct stack_frame { - stack_frame *bp; - void *ip; - }; - - stack_frame *bp = reinterpret_cast(get_bp()); - int i = 0; - while (i < size && -#if TD_LINUX - static_cast(bp) <= __libc_stack_end && -#endif - !(reinterpret_cast(static_cast(bp)) & (sizeof(void *) - 1))) { - void *ip = bp->ip; - buffer[i++] = ip; - stack_frame *p = bp->bp; - if (p <= bp) { - break; - } - bp = p; - } - return i; -} - -static std::atomic fast_backtrace_failed_cnt; -static std::atomic backtrace_total_cnt; -double get_fast_backtrace_success_rate() { - return 1 - static_cast(fast_backtrace_failed_cnt.load(std::memory_order_relaxed)) / - static_cast(std::max(std::size_t(1), backtrace_total_cnt.load(std::memory_order_relaxed))); -} - -#endif - -static Backtrace get_backtrace() { - static __thread bool in_backtrace; // static zero-initialized - Backtrace res{{nullptr}}; - if (in_backtrace) { - return res; - } - in_backtrace = true; - std::array tmp{{nullptr}}; - std::size_t n; -#if USE_MEMPROF_SAFE - n = backtrace(tmp.data(), static_cast(tmp.size())); -#else - n = fast_backtrace(tmp.data(), static_cast(tmp.size())); - auto from_shared = [](void *ptr) { - return reinterpret_cast(ptr) > static_cast(0x700000000000ull); - }; - -#if !USE_MEMPROF_FAST - auto end = tmp.begin() + std::min(res.size() + BACKTRACE_SHIFT, n); - if (std::find_if(tmp.begin(), end, from_shared) != end) { - fast_backtrace_failed_cnt.fetch_add(1, std::memory_order_relaxed); - n = backtrace(tmp.data(), static_cast(tmp.size())); - } - backtrace_total_cnt.fetch_add(1, std::memory_order_relaxed); -#endif - n = std::remove_if(tmp.begin(), tmp.begin() + n, from_shared) - tmp.begin(); -#endif - n = std::min(res.size() + BACKTRACE_SHIFT, n); - - for (std::size_t i = BACKTRACE_SHIFT; i < n; i++) { - res[i - BACKTRACE_SHIFT] = tmp[i]; - } - in_backtrace = false; - return res; -} - -static constexpr std::size_t reserved = 16; -static constexpr std::int32_t malloc_info_magic = 0x27138373; -struct malloc_info { - std::int32_t magic; - std::uint32_t size; - std::int32_t offset; - std::int32_t ht_pos; -}; - -static std::uint64_t get_hash(const Backtrace &bt) { - std::uint64_t h = 7; - for (std::size_t i = 0; i < bt.size() && i < BACKTRACE_HASHED_LENGTH; i++) { - h = h * 0x4372897893428797lu + reinterpret_cast(bt[i]); - } - return h; -} - -struct HashtableNode { - std::atomic hash; - Backtrace backtrace; - std::atomic size; -}; - -static constexpr std::size_t ht_max_size = 1000000; -static std::atomic ht_size{0}; -static std::array ht; - -std::size_t get_ht_size() { - return ht_size.load(); -} - -std::int32_t get_ht_pos(const Backtrace &bt, bool force = false) { - auto hash = get_hash(bt); - std::int32_t pos = static_cast(hash % ht.size()); - bool was_overflow = false; - while (true) { - auto pos_hash = ht[pos].hash.load(); - if (pos_hash == 0) { - if (ht_size > ht_max_size / 2) { - if (force) { - assert(ht_size * 10 < ht_max_size * 7); - } else { - Backtrace unknown_bt{{nullptr}}; - unknown_bt[0] = reinterpret_cast(1); - return get_ht_pos(unknown_bt, true); - } - } - - std::uint64_t expected = 0; - if (ht[pos].hash.compare_exchange_strong(expected, hash)) { - ht[pos].backtrace = bt; - ++ht_size; - return pos; - } - } else if (pos_hash == hash) { - return pos; - } else { - pos++; - if (pos == static_cast(ht.size())) { - pos = 0; - if (was_overflow) { - // unreachable - std::abort(); - } - was_overflow = true; - } - } - } -} - -void dump_alloc(const std::function &func) { - for (auto &node : ht) { - if (node.size == 0) { - continue; - } - func(AllocInfo{node.backtrace, node.size.load()}); - } -} - -void register_xalloc(malloc_info *info, std::int32_t diff) { - if (diff > 0) { - ht[info->ht_pos].size += info->size; - } else { - assert(ht[info->ht_pos].size >= info->size); - ht[info->ht_pos].size -= info->size; - } - assert(info->magic == malloc_info_magic); - assert(info->size < 1000000000000ull); - assert(ht[info->ht_pos].size < 1000000000000ull); -} - -extern "C" { - -static void *malloc_with_frame(std::size_t size, const Backtrace &frame, std::size_t aligment = 0) { - static_assert(reserved % alignof(std::max_align_t) == 0, "fail"); - static_assert(reserved >= sizeof(malloc_info), "fail"); -#if TD_DARWIN - static void *malloc_void = dlsym(RTLD_NEXT, "malloc"); - static auto malloc_old = *reinterpret_cast(&malloc_void); -#else - extern decltype(malloc) __libc_malloc; - static auto malloc_old = __libc_malloc; -#endif - if (aligment < alignof(std::max_align_t)) { - aligment = 0; - } - assert(aligment % alignof(std::max_align_t) == 0); - std::size_t extra = aligment == 0 ? 0 : aligment - alignof(std::max_align_t); - auto *ptr = malloc_old(size + reserved + extra); - std::int32_t offset = 0; - if (aligment != 0) { - // (ptr + reserved + offset) % aligment == 0 - offset = - static_cast((aligment - (reinterpret_cast(ptr) + reserved) % aligment) % aligment); - assert(offset % alignof(std::max_align_t) == 0); - assert(static_cast(offset) <= extra); - ptr = static_cast(static_cast(ptr) + offset); - } - auto *info = static_cast(ptr); - auto *buf = reinterpret_cast(info); - - info->magic = malloc_info_magic; - info->size = static_cast(size); - assert(info->size == size); - info->offset = offset; - info->ht_pos = get_ht_pos(frame); - - register_xalloc(info, +1); - - void *data = buf + reserved; - - if (aligment != 0) { - assert(reinterpret_cast(data) % aligment == 0); - } - - return data; -} - -static malloc_info *get_info(void *data_void) { - char *data = static_cast(data_void); - auto *buf = data - reserved; - - auto *info = reinterpret_cast(buf); - assert(info->magic == malloc_info_magic); - return info; -} - -void *malloc(std::size_t size) { - return malloc_with_frame(size, get_backtrace()); -} - -void free(void *data_void) { - if (data_void == nullptr) { - return; - } - auto *info = get_info(data_void); - register_xalloc(info, -1); - auto ptr = static_cast(static_cast(info)); - info->magic = 0; - ptr -= info->offset; - -#if TD_DARWIN - static void *free_void = dlsym(RTLD_NEXT, "free"); - static auto free_old = *reinterpret_cast(&free_void); -#else - extern decltype(free) __libc_free; - static auto free_old = __libc_free; -#endif - return free_old(ptr); -} -void *calloc(std::size_t size_a, std::size_t size_b) { - auto size = size_a * size_b; - void *res = malloc_with_frame(size, get_backtrace()); - std::memset(res, 0, size); - return res; -} -void *realloc(void *ptr, std::size_t size) { - if (ptr == nullptr) { - return malloc_with_frame(size, get_backtrace()); - } - auto *info = get_info(ptr); - auto *new_ptr = malloc_with_frame(size, get_backtrace()); - auto to_copy = std::min(static_cast(size), info->size); - std::memcpy(new_ptr, ptr, to_copy); - free(ptr); - return new_ptr; -} -int posix_memalign(void **res, std::size_t aligment, std::size_t size) { - *res = malloc_with_frame(size, get_backtrace(), aligment); - return 0; -} -void *memalign(std::size_t aligment, std::size_t size) { - return malloc_with_frame(size, get_backtrace(), aligment); -} -std::size_t malloc_usable_size(void *ptr) { - if (ptr == nullptr) { - return 0; - } - auto *info = get_info(ptr); - return info->size + info->offset + reserved; -} -} - -// c++14 guarantees that it is enough to override these two operators. -void *operator new(std::size_t count) { - return malloc_with_frame(count, get_backtrace()); -} -void operator delete(void *ptr) noexcept(true) { - free(ptr); -} -// because of gcc warning: the program should also define 'void operator delete(void*, std::size_t)' -void operator delete(void *ptr, std::size_t) noexcept(true) { - free(ptr); -} - -// c++17 -// void *operator new(std::size_t count, std::align_val_t al); -// void operator delete(void *ptr, std::align_val_t al); - -#else -bool is_memprof_on() { - return false; -} -void dump_alloc(const std::function &func) { -} -double get_fast_backtrace_success_rate() { - return 0; -} -std::size_t get_ht_size() { - return 0; -} -#endif - -std::size_t get_used_memory_size() { - std::size_t res = 0; - dump_alloc([&](const auto info) { res += info.size; }); - return res; -} diff --git a/submodules/ton/tonlib-src/memprof/memprof/memprof.h b/submodules/ton/tonlib-src/memprof/memprof/memprof.h deleted file mode 100644 index 280f1d26..00000000 --- a/submodules/ton/tonlib-src/memprof/memprof/memprof.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include - -constexpr std::size_t BACKTRACE_SHIFT = 2; -constexpr std::size_t BACKTRACE_HASHED_LENGTH = 6; -constexpr std::size_t BACKTRACE_LENGTH = 10; - -using Backtrace = std::array; -struct AllocInfo { - Backtrace backtrace; - std::size_t size; -}; - -bool is_memprof_on(); -std::size_t get_ht_size(); -double get_fast_backtrace_success_rate(); -void dump_alloc(const std::function &func); -std::size_t get_used_memory_size(); diff --git a/submodules/ton/tonlib-src/tdactor/.gitrepo b/submodules/ton/tonlib-src/tdactor/.gitrepo deleted file mode 100644 index c0249850..00000000 --- a/submodules/ton/tonlib-src/tdactor/.gitrepo +++ /dev/null @@ -1,11 +0,0 @@ -; DO NOT EDIT (unless you know what you are doing) -; -; This subdirectory is a git "subrepo", and this file is maintained by the -; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme -; -[subrepo] - remote = git@github.com:arseny30/tdactor.git - branch = master - commit = 023418469da909416b067660cc44bb4d9e9a4739 - parent = da0d81f9227112f21b00dfcd060e19b44f12f1f8 - cmdver = 0.3.1 diff --git a/submodules/ton/tonlib-src/tdactor/CMakeLists.txt b/submodules/ton/tonlib-src/tdactor/CMakeLists.txt deleted file mode 100644 index 3490eb17..00000000 --- a/submodules/ton/tonlib-src/tdactor/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -#SOURCE SETS -set(TDACTOR_SOURCE - td/actor/core/ActorExecutor.cpp - td/actor/core/CpuWorker.cpp - td/actor/core/IoWorker.cpp - td/actor/core/Scheduler.cpp - - td/actor/MultiPromise.cpp - - td/actor/actor.h - td/actor/ActorId.h - td/actor/ActorOwn.h - td/actor/ActorShared.h - td/actor/common.h - td/actor/PromiseFuture.h - td/actor/MultiPromise.h - - td/actor/core/Actor.h - td/actor/core/ActorExecuteContext.h - td/actor/core/ActorExecutor.h - td/actor/core/ActorInfo.h - td/actor/core/ActorInfoCreator.h - td/actor/core/ActorLocker.h - td/actor/core/ActorMailbox.h - td/actor/core/ActorMessage.h - td/actor/core/ActorSignals.h - td/actor/core/ActorState.h - td/actor/core/CpuWorker.h - td/actor/core/Context.h - td/actor/core/IoWorker.h - td/actor/core/Scheduler.h - td/actor/core/SchedulerContext.h - td/actor/core/SchedulerId.h - td/actor/core/SchedulerMessage.h -) - -set(TDACTOR_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/actors_promise.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/actors_core.cpp - PARENT_SCOPE -) - -#RULES - -#LIBRARIES - -add_library(tdactor STATIC ${TDACTOR_SOURCE}) -target_include_directories(tdactor PUBLIC $) -target_link_libraries(tdactor PUBLIC tdutils) - -# BEGIN-INTERNAL -add_subdirectory(benchmark) - -# END-INTERNAL -install(TARGETS tdactor EXPORT TdTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include -) diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/CMakeLists.txt b/submodules/ton/tonlib-src/tdactor/benchmark/CMakeLists.txt deleted file mode 100644 index e01d33dc..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -set(BENCHMARK_SOURCE - benchmark.cpp - third_party/mp-queue.c - - third_party/FAAArrayQueue.h - third_party/LCRQueue.h - third_party/LazyIndexArrayQueue.h - third_party/MoodyCamelQueue.h -) -add_executable(benchmark ${BENCHMARK_SOURCE}) -target_include_directories(benchmark PUBLIC $) -target_link_libraries(benchmark PRIVATE tdactor) - -if (MSVC) - set_property(SOURCE benchmark.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4457 /wd4316") -endif() - diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/benchmark.cpp b/submodules/ton/tonlib-src/tdactor/benchmark/benchmark.cpp deleted file mode 100644 index deddcb22..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/benchmark.cpp +++ /dev/null @@ -1,1712 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "third_party/FAAArrayQueue.h" -#include "third_party/HazardPointers.h" -#include "third_party/LazyIndexArrayQueue.h" -#include "third_party/MoodyCamelQueue.h" - -#if TG_LCR_QUEUE -#include "third_party/LCRQueue.h" - -extern "C" { -#include "third_party/mp-queue.h" -} - -#include -#include -#include -#endif - -#include "td/actor/core/ActorLocker.h" -#include "td/actor/actor.h" - -#include "td/utils/benchmark.h" -#include "td/utils/crypto.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/MpmcQueue.h" -#include "td/utils/MpmcWaiter.h" -#include "td/utils/port/thread.h" -#include "td/utils/queue.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/StealingQueue.h" -#include "td/utils/ThreadSafeCounter.h" -#include "td/utils/UInt.h" -#include "td/utils/VectorQueue.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -using td::int32; -using td::uint32; - -// Concurrent SHA256 benchmark -// Simplified ton Cell and Block structures -struct CellRef { - int32 cell_id{0}; - td::MutableSlice hash_slice; -}; -struct Cell { - bool has_hash = false; - td::UInt256 hash; - td::MutableSlice data; - std::array next{}; -}; - -struct Block { - std::string data; - std::vector cells; - Cell &get_cell(int32 id) { - return cells[id]; - } - const Cell &get_cell(int32 id) const { - return cells[id]; - } -}; - -class Generator { - public: - static std::string random_bytes(int length) { - std::string res(length, ' '); - for (auto &c : res) { - c = static_cast(td::Random::fast_uint32() % 256); - } - return res; - } - - static Block random_block(int cells_count) { - const size_t cell_size = 256; - Block block; - block.data = random_bytes(td::narrow_cast(cell_size * cells_count)); - block.cells.reserve(cells_count); - for (int i = 0; i < cells_count; i++) { - Cell cell; - cell.data = td::MutableSlice(block.data).substr(i * cell_size, cell_size); - for (int j = 0; j < 4; j++) { - cell.next[j] = [&] { - CellRef cell_ref; - if (i == 0) { - return cell_ref; - } - cell_ref.cell_id = td::Random::fast(0, i - 1); - cell_ref.hash_slice = cell.data.substr(cell_size - 128 + j * 32, 32); - return cell_ref; - }(); - } - block.cells.push_back(std::move(cell)); - } - return block; - } -}; - -class BlockSha256Baseline { - public: - static std::string get_description() { - return "Baseline"; - } - static void calc_hash(Block &block) { - for (auto &cell : block.cells) { - td::sha256(cell.data, as_slice(cell.hash)); - } - } - static td::Status check(Block &block) { - for (auto &cell : block.cells) { - for (auto &cell_ref : cell.next) { - if (cell_ref.hash_slice.empty()) { - continue; - } - if (cell_ref.hash_slice != as_slice(block.get_cell(cell_ref.cell_id).hash)) { - return td::Status::Error("Sha mismatch"); - } - } - } - return td::Status::OK(); - } - static void calc_refs(Block &block) { - for (auto &cell : block.cells) { - for (auto &cell_ref : cell.next) { - if (cell_ref.hash_slice.empty()) { - continue; - } - cell_ref.hash_slice.copy_from(as_slice(block.get_cell(cell_ref.cell_id).hash)); - } - td::sha256(cell.data, as_slice(cell.hash)); - } - } -}; - -class BlockSha256Threads { - public: - static std::string get_description() { - return "Threads"; - } - template - static void parallel_map(Iterator begin, Iterator end, F &&f) { - size_t size = end - begin; - auto threads_count = std::max(td::thread::hardware_concurrency(), 1u) * 2; - auto thread_part_size = (size + threads_count - 1) / threads_count; - std::vector threads; - for (size_t i = 0; i < size; i += thread_part_size) { - auto part_begin = begin + i; - auto part_size = std::min(thread_part_size, size - i); - auto part_end = part_begin + part_size; - threads.push_back(td::thread([part_begin, part_end, &f] { - for (auto it = part_begin; it != part_end; it++) { - f(*it); - } - })); - } - for (auto &thread : threads) { - thread.join(); - } - } - static void calc_hash(Block &block) { - parallel_map(block.cells.begin(), block.cells.end(), - [](Cell &cell) { td::sha256(cell.data, as_slice(cell.hash)); }); - } - static td::Status check_refs(Block &block) { - std::atomic mismatch{false}; - parallel_map(block.cells.begin(), block.cells.end(), [&](Cell &cell) { - for (auto &cell_ref : cell.next) { - if (cell_ref.hash_slice.empty()) { - continue; - } - if (cell_ref.hash_slice != as_slice(block.get_cell(cell_ref.cell_id).hash)) { - mismatch = true; - break; - } - } - }); - if (mismatch) { - return td::Status::Error("sha256 mismatch"); - } - return td::Status::OK(); - } -}; - -class InfBackoff { - private: - int cnt = 0; - - public: - bool next() { - cnt++; - if (cnt < 50) { - return true; - } else { - td::this_thread::yield(); - return true; - } - } -}; - -template -class BlockSha256MpmcQueue { - public: - static std::string get_description() { - return Q::get_description(); - } - static void calc_hash(Block &block) { - std::vector threads; - auto threads_count = std::max(td::thread::hardware_concurrency(), 1u) * 2; - auto queue = std::make_unique(threads_count + 1); - for (size_t thread_id = 0; thread_id < threads_count; thread_id++) { - threads.push_back(td::thread([&, thread_id] { - while (true) { - auto f = queue->pop(thread_id); - if (!f) { - return; - } - f(); - } - })); - } - for (auto &cell : block.cells) { - queue->push([&cell]() { td::sha256(cell.data, as_slice(cell.hash)); }, threads_count); - } - for (size_t thread_id = 0; thread_id < threads_count; thread_id++) { - queue->push(nullptr, threads_count); - } - for (auto &thread : threads) { - thread.join(); - } - } -}; -template -class BlockSha256MpmcQueueCellPtr { - public: - static std::string get_description() { - return "ptr " + Q::get_description(); - } - static void calc_hash(Block &block) { - std::vector threads; - auto threads_count = std::max(td::thread::hardware_concurrency(), 1u) * 2; - auto queue = std::make_unique(threads_count + 1); - Cell poison; - for (size_t thread_id = 0; thread_id < threads_count; thread_id++) { - threads.push_back(td::thread([&, thread_id] { - while (true) { - auto cell = queue->pop(thread_id); - if (cell == &poison) { - return; - } - td::sha256(cell->data, as_slice(cell->hash)); - } - })); - } - for (auto &cell : block.cells) { - queue->push(&cell, threads_count); - } - for (size_t thread_id = 0; thread_id < threads_count; thread_id++) { - queue->push(&poison, threads_count); - } - for (auto &thread : threads) { - thread.join(); - } - } -}; -std::atomic flag; -class ActorExecutorBenchmark : public td::Benchmark { - std::string get_description() const { - return "Executor Benchmark"; - } - - void run(int n) { - using namespace td::actor::core; - using namespace td::actor; - using td::actor::detail::ActorMessageCreator; - struct Dispatcher : public SchedulerDispatcher { - void add_to_queue(ActorInfoPtr ptr, SchedulerId scheduler_id, bool need_poll) override { - //queue.push_back(std::move(ptr)); - q.push(ptr, 0); - } - void set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) override { - UNREACHABLE(); - } - SchedulerId get_scheduler_id() const override { - return SchedulerId{0}; - } - std::deque queue; - td::MpmcQueue q{1}; - }; - Dispatcher dispatcher; - - class TestActor : public Actor { - public: - void close() { - stop(); - } - - private: - void start_up() override { - //LOG(ERROR) << "start up"; - } - void tear_down() override { - } - void wake_up() override { - //LOG(ERROR) << "wake up"; - } - }; - ActorInfoCreator actor_info_creator; - auto actor = actor_info_creator.create(std::make_unique(), - ActorInfoCreator::Options().on_scheduler(SchedulerId{0}).with_name("A")); - auto actor2 = actor_info_creator.create(std::make_unique(), - ActorInfoCreator::Options().on_scheduler(SchedulerId{0}).with_name("B")); - - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options().with_from_queue()); - for (int i = 0; i < n; i++) { - //int old = i; - //flag.compare_exchange_strong(old, i + 1, std::memory_order_acquire, std::memory_order_relaxed); - ActorExecutor executor2(*actor2, dispatcher, ActorExecutor::Options()); - } - } - for (int i = 0; i < 0; i++) { - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options().with_from_queue()); - executor.send_immediate( - [&] { - ActorExecutor executor2(*actor2, dispatcher, ActorExecutor::Options()); - executor2.send_immediate( - [&] { - ActorExecutor executor3(*actor, dispatcher, ActorExecutor::Options()); - executor3.send(td::actor::core::ActorSignals::one(td::actor::core::ActorSignals::Wakeup)); - }, - 0); - }, - 0); - } - dispatcher.q.pop(0); - } - - //{ - //ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - //executor.send( - //ActorMessageCreator::lambda([&] { static_cast(ActorExecuteContext::get()->actor()).close(); })); - //} - dispatcher.queue.clear(); - } -}; -namespace actor_signal_query_test { -using namespace td::actor; -class Master; -class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher, ActorId master) - : watcher_(std::move(watcher)), master_(std::move(master)) { - } - void wake_up() override; - - private: - std::shared_ptr watcher_; - ActorId master_; -}; -class Master : public td::actor::Actor { - public: - Master(std::shared_ptr watcher, int n) : watcher_(std::move(watcher)), n_(n) { - } - - void start_up() override { - worker_ = create_actor(ActorOptions().with_name("Worker"), watcher_, actor_id(this)); - send_signals(worker_, ActorSignals::wakeup()); - } - - void wake_up() override { - n_--; - if (n_ <= 0) { - return stop(); - } - send_signals(worker_, ActorSignals::wakeup()); - } - - private: - std::shared_ptr watcher_; - ActorOwn worker_; - int n_; -}; -void Worker::wake_up() { - send_signals(master_, ActorSignals::wakeup()); -} -} // namespace actor_signal_query_test -class ActorSignalQuery : public td::Benchmark { - public: - std::string get_description() const override { - return "ActorSignalQuery"; - } - void run(int n) override { - using namespace actor_signal_query_test; - size_t threads_count = 1; - Scheduler scheduler{{threads_count}}; - - scheduler.run_in_context([&] { - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - create_actor(ActorOptions().with_name(PSLICE() << "Master"), watcher, n).release(); - }); - scheduler.run(); - } -}; - -namespace actor_query_test { -using namespace td::actor; -class Master; -class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void query(int x, ActorId master); - - private: - std::shared_ptr watcher_; -}; -class Master : public td::actor::Actor { - public: - Master(std::shared_ptr watcher, int n) : watcher_(std::move(watcher)), n_(n) { - } - - void start_up() override { - worker_ = create_actor(ActorOptions().with_name("Worker"), watcher_); - send_closure(worker_, &Worker::query, n_, actor_id(this)); - } - - void answer(int x, int y) { - if (x == 0) { - return stop(); - } - send_closure(worker_, &Worker::query, x - 1, actor_id(this)); - } - - private: - std::shared_ptr watcher_; - ActorOwn worker_; - int n_; -}; -void Worker::query(int x, ActorId master) { - send_closure(master, &Master::answer, x, x + x); -} -} // namespace actor_query_test -class ActorQuery : public td::Benchmark { - public: - std::string get_description() const override { - return "ActorQuery"; - } - void run(int n) override { - using namespace actor_query_test; - size_t threads_count = 1; - Scheduler scheduler({threads_count}); - - scheduler.run_in_context([&] { - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - create_actor(ActorOptions().with_name(PSLICE() << "Master"), watcher, n).release(); - }); - scheduler.run(); - } -}; - -namespace actor_dummy_query_test { -using namespace td::actor; -class Master; -class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void query(int x, int *y) { - *y = x + x; - } - void start_up() override { - } - - private: - std::shared_ptr watcher_; -}; -class Master : public td::actor::Actor { - public: - Master(std::shared_ptr watcher, int n) : watcher_(std::move(watcher)), n_(n) { - } - - void start_up() override { - worker_ = create_actor(ActorOptions().with_name("Worker"), watcher_); - int res; - for (int i = 0; i < n_; i++) { - send_closure(worker_, &Worker::query, i, &res); - CHECK(res == i + i); - } - stop(); - } - - private: - std::shared_ptr watcher_; - ActorOwn worker_; - int n_; -}; -} // namespace actor_dummy_query_test -class ActorDummyQuery : public td::Benchmark { - public: - std::string get_description() const override { - return "ActorDummyQuery"; - } - void run(int n) override { - using namespace actor_dummy_query_test; - size_t threads_count = 1; - Scheduler scheduler({threads_count}); - - scheduler.run_in_context([&] { - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - create_actor(ActorOptions().with_name(PSLICE() << "Master"), watcher, n).release(); - }); - - scheduler.run(); - } -}; - -namespace actor_task_query_test { -using namespace td::actor; -class Master; -class Worker : public td::actor::Actor { - public: - Worker(int x, ActorId master) : x_(x), master_(std::move(master)) { - } - void start_up() override; - - private: - int x_; - ActorId master_; -}; -class Master : public td::actor::Actor { - public: - Master(std::shared_ptr watcher, int n) : watcher_(std::move(watcher)), n_(n) { - } - - void start_up() override { - create_actor(ActorOptions().with_name("Worker"), n_, actor_id(this)).release(); - } - - void answer(int x, int y) { - if (x == 0) { - return stop(); - } - create_actor(ActorOptions().with_name("Worker"), x - 1, actor_id(this)).release(); - } - - private: - std::shared_ptr watcher_; - ActorOwn worker_; - int n_; -}; -void Worker::start_up() { - send_closure(master_, &Master::answer, x_, x_ + x_); - stop(); -} -} // namespace actor_task_query_test -class ActorTaskQuery : public td::Benchmark { - public: - std::string get_description() const override { - return "ActorTaskQuery"; - } - void run(int n) override { - using namespace actor_task_query_test; - size_t threads_count = 1; - Scheduler scheduler({threads_count}); - - scheduler.run_in_context([&] { - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - create_actor(ActorOptions().with_name(PSLICE() << "Master"), watcher, n).release(); - }); - scheduler.run(); - } -}; -class BlockSha256Actors { - public: - static std::string get_description() { - return "Actors"; - } - template - static void parallel_map(Iterator begin, Iterator end, F &&f) { - auto threads_count = std::max(td::thread::hardware_concurrency(), 1u) * 2; - using namespace td::actor; - Scheduler scheduler({threads_count}); - - scheduler.run_in_context([&] { - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher, td::Promise<> promise) - : watcher_(std::move(watcher)), promise_(std::move(promise)) { - } - void start_up() override { - promise_.set_value(td::Unit()); - stop(); - } - - private: - std::shared_ptr watcher_; - td::Promise<> promise_; - }; - - for (auto it = begin; it != end; it++) { - create_actor(ActorOptions().with_name(PSLICE() << "Worker#"), watcher, - td::Promise<>([&, it](td::Unit) { f(*it); })) - .release(); - } - }); - scheduler.run(); - } - static void calc_hash(Block &block) { - parallel_map(block.cells.begin(), block.cells.end(), - [](Cell &cell) { td::sha256(cell.data, as_slice(cell.hash)); }); - } -}; - -class ActorLockerBenchmark : public td::Benchmark { - public: - explicit ActorLockerBenchmark(int threads_n) : threads_n_(threads_n) { - } - std::string get_description() const override { - return PSTRING() << "ActorLockerBenchmark " << threads_n_; - } - void run(int n) override { - std::vector threads(threads_n_); - using namespace td::actor::core; - ActorState state; - std::atomic ready{0}; - for (auto &thread : threads) { - thread = td::thread([&] { - ActorLocker locker(&state); - ready++; - while (ready != threads_n_) { - td::this_thread::yield(); - } - for (int i = 0; i < n / threads_n_; i++) { - if (locker.add_signals(ActorSignals::one(ActorSignals::Kill))) { - while (!locker.try_unlock(ActorState::Flags{})) { - } - } - } - }); - } - for (auto &thread : threads) { - thread.join(); - } - } - - private: - int threads_n_; -}; - -template -class CalcHashSha256Benchmark : public td::Benchmark { - public: - std::string get_description() const override { - return "CheckSha256: " + impl_.get_description(); - } - void start_up_n(int n) override { - block_ = Generator::random_block(n); - } - - void run(int n) override { - Impl::calc_hash(block_); - } - - private: - Impl impl_; - Block block_; -}; - -/* -template -class MpmcQueueInterface { - public: - explicit MpmcQueueInterface(size_t thread_n); - static std::string get_description(); - void push(T value, size_t thread_id); - T pop(size_t thread_id); - bool try_pop(T &value, size_t thread_id); -}; -*/ - -// Simple bounded mpmc queue -template -class BoundedMpmcQueue { - public: - explicit BoundedMpmcQueue(size_t threads_n) : data_(1 << 20) { - } - static std::string get_description() { - return "BoundedMpmc queue"; - } - void push(ValueT value, size_t = 0) { - auto pos = write_pos_.fetch_add(1, std::memory_order_relaxed); - auto generation = pos / data_.size() * 2 + 0; - auto &element = data_[pos % data_.size()]; - - InfBackoff backoff; - while (element.generation.load(std::memory_order_acquire) != generation) { - backoff.next(); - } - element.value = std::move(value); - element.generation.fetch_add(1, std::memory_order_release); - } - - ValueT pop(size_t = 0) { - auto pos = read_pos_.fetch_add(1, std::memory_order_relaxed); - auto generation = pos / data_.size() * 2 + 1; - auto &element = data_[pos % data_.size()]; - - InfBackoff backoff; - while (element.generation.load(std::memory_order_acquire) != generation) { - backoff.next(); - } - auto result = std::move(element.value); - element.generation.fetch_add(1, std::memory_order_release); - return result; - } - bool try_pop(ValueT &value, size_t = 0) { - auto pos = read_pos_.load(std::memory_order_relaxed); - auto generation = pos / data_.size() * 2 + 1; - auto &element = data_[pos % data_.size()]; - - if (element.generation.load(std::memory_order_acquire) != generation) { - return false; - } - if (!read_pos_.compare_exchange_strong(pos, pos + 1, std::memory_order_acq_rel)) { - return false; - } - value = std::move(element.value); - element.generation.fetch_add(1, std::memory_order_release); - return true; - } - - private: - std::atomic write_pos_{0}; - char pad[128]; - std::atomic read_pos_{0}; - char pad2[128]; - struct Element { - std::atomic generation{0}; - ValueT value; - //char pad2[128]; - }; - std::vector data_; - char pad3[128]; -}; - -template -class MpmcQueueBenchmark : public td::Benchmark { - public: - MpmcQueueBenchmark(int n, int m) : n_(n), m_(m) { - } - std::string get_description() const override { - return PSTRING() << "MpmcQueueBenchmark " << n_ << " " << m_ << " " << Impl::get_description(); - } - - void run(int n) override { - std::vector n_threads(n_); - std::vector m_threads(m_); - auto impl = std::make_unique(n_ + m_ + 1); - size_t thread_id = 0; - td::ThreadSafeCounter counter; - CHECK(counter.sum() == 0); - for (auto &thread : m_threads) { - thread = td::thread([&, thread_id] { - while (true) { - size_t value = impl->pop(thread_id); - counter.add(-static_cast(value)); - if (!value) { - break; - } - } - }); - thread_id++; - } - for (auto &thread : n_threads) { - thread = td::thread([&, thread_id] { - for (int i = 0; i < n / n_; i++) { - impl->push(static_cast(i + 1), thread_id); - counter.add(i + 1); - } - }); - thread_id++; - } - for (auto &thread : n_threads) { - thread.join(); - } - while (counter.sum() != 0) { - td::this_thread::yield(); - } - for (int i = 0; i < m_ + n_ + 1; i++) { - impl->push(0, thread_id); - } - for (auto &thread : m_threads) { - thread.join(); - } - impl.reset(); - } - - private: - int n_; - int m_; -}; - -template -class MpmcQueueBenchmark2 : public td::Benchmark { - public: - MpmcQueueBenchmark2(int n, int k) : n_(n), k_(k) { - } - std::string get_description() const override { - return PSTRING() << "MpmcQueueBenchmark2 " << n_ << " " << k_ << " " << Impl::get_description(); - } - - void run(int n) override { - std::vector n_threads(n_); - auto impl = std::make_unique(n_ + 1); - size_t thread_id = 0; - std::atomic left{k_}; - - for (int i = 0; i < k_; i++) { - impl->push(n, thread_id); - } - - for (auto &thread : n_threads) { - thread = td::thread([&, thread_id] { - while (true) { - size_t value = impl->pop(thread_id); - if (value > 1) { - impl->push(value - 1, thread_id); - } - if (value == 1) { - left--; - } - if (!value) { - break; - } - } - }); - thread_id++; - } - - while (left.load() != 0) { - td::this_thread::yield(); - } - - for (int i = 0; i < n_ + 1; i++) { - impl->push(0, thread_id); - } - - for (auto &thread : n_threads) { - thread.join(); - } - impl.reset(); - } - - private: - int n_; - int k_; -}; - -class Cheat { - public: - explicit Cheat(size_t thread_n) : impl_(static_cast(thread_n)) { - } - static std::string get_description() { - return "td::MpmcQueue (cheat)"; - } - void push(size_t value, size_t thread_id) { - impl_.push(reinterpret_cast(value + 1), static_cast(thread_id)); - } - size_t pop(size_t thread_id) { - auto res = impl_.pop(thread_id); - return reinterpret_cast(res) - 1; - } - bool try_pop(size_t &value, size_t thread_id) { - size_t *was; - if (impl_.try_pop(was, thread_id)) { - value = reinterpret_cast(was) - 1; - return true; - } - return false; - } - - private: - td::MpmcQueue impl_; -}; - -using ConcurrencyFreaks::FAAArrayQueue; -using ConcurrencyFreaks::LazyIndexArrayQueue; -#if TG_LCR_QUEUE -using ConcurrencyFreaks::LCRQueue; -#endif - -template -class CfQueue { - public: - explicit CfQueue(size_t thread_n) : impl_(static_cast(thread_n)) { - } - static std::string get_description() { - return "TODO"; - } - void push(size_t value, size_t thread_id) { - impl_.enqueue(reinterpret_cast(value + 1), static_cast(thread_id)); - } - size_t pop(size_t thread_id) { - size_t res; - while (!try_pop(res, thread_id)) { - td::this_thread::yield(); - } - return res; - } - bool try_pop(size_t &value, size_t thread_id) { - auto ptr = impl_.dequeue(static_cast(thread_id)); - if (!ptr) { - return false; - } - value = reinterpret_cast(ptr) - 1; - return true; - } - - private: - Impl impl_; -}; - -#if TG_LCR_QUEUE -template <> -std::string CfQueue>::get_description() { - return "LCRQueue (cf)"; -} -#endif -template <> -std::string CfQueue>::get_description() { - return "LazyIndexArrayQueue (cf)"; -} -template <> -std::string CfQueue>::get_description() { - return "FAAArrayQueue (cf)"; -} -template -class CfQueueT { - public: - explicit CfQueueT(size_t thread_n) : impl_(static_cast(thread_n)) { - } - static std::string get_description() { - return "TODO"; - } - void push(T *value, size_t thread_id) { - impl_.enqueue(value, static_cast(thread_id)); - } - T *pop(size_t thread_id) { - td::detail::Backoff backoff; - while (true) { - auto ptr = impl_.dequeue(static_cast(thread_id)); - if (!ptr) { - backoff.next(); - } else { - return ptr; - } - } - } - bool try_pop(T *&value, size_t thread_id) { - value = impl_.dequeue(static_cast(thread_id)); - return value != nullptr; - } - - private: - Impl impl_; -}; - -#if TG_LCR_QUEUE -template <> -std::string CfQueueT, Cell>::get_description() { - return "LCRQueue (cf)"; -} -#endif -template <> -std::string CfQueueT, Cell>::get_description() { - return "LazyIndexArrayQueue (cf)"; -} -template <> -std::string CfQueueT, Cell>::get_description() { - return "FAAArrayQueue (cf)"; -} - -template -class MoodyQueue { - public: - explicit MoodyQueue(size_t n) { - for (size_t i = 0; i < n; i++) { - p.push_back(moodycamel::ProducerToken(q)); - c.push_back(moodycamel::ConsumerToken(q)); - } - } - static std::string get_description() { - return "moodycamel queue"; - } - void push(Value v, size_t tid) { - q.enqueue(p[tid], v); - } - Value pop(size_t tid) { - Value res; - while (!q.try_dequeue(c[tid], res)) { - } - //q.wait_dequeue(c[tid], res); - return res; - } - bool try_pop(Value &value, size_t tid) { - return q.try_dequeue(c[tid], value); - } - - private: - moodycamel::ConcurrentQueue q; - std::vector p; - std::vector c; -}; - -struct Sem { - public: - void post() { - if (++cnt_ == 0) { - { - std::unique_lock lk(mutex_); - } - cnd_.notify_one(); - } - } - void wait(int cnt = 1) { - auto was = cnt_.fetch_sub(cnt); - if (was >= cnt) { - return; - } - std::unique_lock lk(mutex_); - cnd_.wait(lk, [&] { return cnt_ >= 0; }); - } - - private: - std::mutex mutex_; - std::condition_variable cnd_; - std::atomic cnt_{0}; -}; - -template -class MagicQueue { - public: - explicit MagicQueue(size_t n) : n_(n), qs_(n_ - 1), pos_{0} { - } - static std::string get_description() { - return "magic queue"; - } - void push(Value v, size_t tid) { - if (v == 0) { - return; - } - - if (tid + 1 == n_) { - qs_[pos_].push(v); - pos_ = (pos_ + 1) % (n_ - 1); - } else { - qs_[tid].push(v); - } - } - Value pop(size_t tid) { - CHECK(tid + 1 != n_); - if (qs_[tid].empty()) { - return 0; - } - return qs_[tid].pop(); - } - bool try_pop(Value &value, size_t) { - UNREACHABLE(); - } - - private: - size_t n_; - std::vector> qs_; - size_t pos_; -}; - -#if TG_LCR_QUEUE -class MpQueue { - public: - explicit MpQueue(size_t) { - q_ = alloc_mp_queue(); - } - ~MpQueue() { - free_mp_queue(q_); - clear_thread_ids(); - } - void push(size_t value, size_t) { - mpq_push(q_, reinterpret_cast(value + 1), 0); - } - size_t pop(size_t) { - td::detail::Backoff backoff; - while (true) { - auto ptr = mpq_pop(q_, 0); - if (!ptr) { - backoff.next(); - } else { - return reinterpret_cast(ptr) - 1; - } - } - } - bool try_pop(size_t &value, size_t) { - auto ptr = mpq_pop(q_, 0); - if (!ptr) { - return false; - } - value = reinterpret_cast(ptr) - 1; - return true; - } - - static std::string get_description() { - return "mp-queue"; - } - - public: - struct mp_queue *q_; -}; - -class Semaphore { - public: - Semaphore() { - impl->value = 0; - impl->waiting = 0; - } - void wait() { - mp_sem_wait(impl.get()); - } - void post() { - mp_sem_post(impl.get()); - } - std::unique_ptr impl = std::make_unique(); -}; - -template -class SemQueue { - public: - static std::string get_description() { - return "Sem + " + Q::get_description(); - } - explicit SemQueue(size_t threads_n) : impl(threads_n) { - } - T pop(size_t thread_id) { - T res; - td::detail::Backoff backoff; - while (!impl.try_pop(res, thread_id)) { - if (!backoff.next()) { - sem.wait(); - } - } - return res; - } - void push(T value, size_t thread_id) { - impl.push(std::move(value), thread_id); - sem.post(); - } - - private: - Semaphore sem; - Q impl; -}; -#endif - -template -class StupidQueue { - public: - explicit StupidQueue(size_t) { - } - static std::string get_description() { - return "Mutex queue"; - } - T pop(size_t) { - std::unique_lock guard(mutex_); - cv_.wait(guard, [&] { return !queue_.empty(); }); - auto front = queue_.front(); - queue_.pop(); - return front; - } - void push(T value, size_t) { - { - std::unique_lock guard(mutex_); - queue_.push(std::move(value)); - } - cv_.notify_one(); - } - bool try_pop(T &value, size_t) { - std::lock_guard guard(mutex_); - if (!queue_.empty()) { - value = std::move(queue_.front()); - queue_.pop(); - return true; - } - return false; - } - - private: - std::mutex mutex_; - std::queue queue_; - std::condition_variable cv_; -}; - -template -class WaitQueue { - public: - static std::string get_description() { - return "Wait + " + Q::get_description(); - } - - explicit WaitQueue(size_t threads_n) : impl(threads_n), slots(threads_n) { - for (size_t i = 0; i < threads_n; i++) { - waiter.init_slot(slots[i].slot, static_cast(i)); - } - } - - T pop(size_t thread_id) { - T res; - while (true) { - if (slots[thread_id].local_queue.try_pop(res)) { - break; - } - if (impl.try_pop(res, thread_id)) { - break; - } - waiter.wait(slots[thread_id].slot); - } - waiter.stop_wait(slots[thread_id].slot); - //LOG(ERROR) << "GOT"; - return res; - } - - void push_local(T value, size_t thread_id) { - auto o_value = slots[thread_id].local_queue.push(value); - if (o_value) { - push(o_value.unwrap, thread_id); - } - } - - void push(T value, size_t thread_id) { - impl.push(value, static_cast(thread_id)); - waiter.notify(); - } - - private: - W waiter; - Q impl; - struct Slot { - typename W::Slot slot; - td::actor::core::LocalQueue local_queue; - }; - std::vector slots; -}; -template -class StealingWaitQueue { - public: - static std::string get_description() { - return "StealWait + " + Q::get_description(); - } - - explicit StealingWaitQueue(size_t threads_n) : impl(threads_n), slots(threads_n) { - for (size_t i = 0; i < threads_n; i++) { - waiter.init_slot(slots[i].slot, static_cast(i)); - } - } - - T pop(size_t thread_id) { - T res; - while (true) { - if (slots[thread_id].stealing_queue.local_pop(res)) { - break; - } - if (slots[thread_id].local_queue.try_pop(res)) { - break; - } - if (impl.try_pop(res, thread_id)) { - break; - } - - bool ok = false; - for (size_t i = 1; i < slots.size(); i++) { - auto pos = (i + thread_id) % slots.size(); - if (slots[thread_id].stealing_queue.steal(res, slots[pos].stealing_queue)) { - ok = true; - break; - } - } - if (ok) { - break; - } - waiter.wait(slots[thread_id].slot); - } - waiter.stop_wait(slots[thread_id].slot); - //LOG(ERROR) << "GOT"; - return res; - } - - void push_local(T value, size_t thread_id) { - auto o_value = slots[thread_id].local_queue.push(value); - if (o_value) { - push(o_value.unwrap, thread_id); - } - } - - void push(T value, size_t thread_id) { - slots[thread_id].stealing_queue.local_push(value, - [&](auto value) { impl.push(value, static_cast(thread_id)); }); - waiter.notify(); - } - - private: - W waiter; - Q impl; - struct Slot { - typename W::Slot slot; - td::actor::core::LocalQueue local_queue; - td::StealingQueue stealing_queue; - }; - std::vector slots; -}; - -void run_queue_bench(int n, int m) { - bench(MpmcQueueBenchmark>(n, m), 2); - bench(MpmcQueueBenchmark, td::MpmcEagerWaiter, size_t>>(n, m), 2); - bench(MpmcQueueBenchmark, td::MpmcSleepyWaiter, size_t>>(n, m), 2); - bench(MpmcQueueBenchmark, td::MpmcEagerWaiter, size_t>>(n, m), 2); - bench(MpmcQueueBenchmark, td::MpmcSleepyWaiter, size_t>>(n, m), 2); - //bench(MpmcQueueBenchmark>(n, m), 2); - //bench(MpmcQueueBenchmark>(n, m), 2); - //bench(MpmcQueueBenchmark(n, m), 2); - //bench(MpmcQueueBenchmark>>(n, m), 2); - //bench(MpmcQueueBenchmark>>(n, m), 2); - //bench(MpmcQueueBenchmark>(n, m), 2); - - //bench(MpmcQueueBenchmark(n, m), 2); -#if TG_LCR_QUEUE - bench(MpmcQueueBenchmark>>(n, m), 2); -#endif -} -void run_queue_bench2(int n, int k) { - bench(MpmcQueueBenchmark2, td::MpmcSleepyWaiter, size_t>>(n, k), 2); - bench(MpmcQueueBenchmark2, td::MpmcEagerWaiter, size_t>>(n, k), 2); - bench(MpmcQueueBenchmark2>(n, k), 2); - bench(MpmcQueueBenchmark2>(n, k), 2); - bench(MpmcQueueBenchmark2, td::MpmcEagerWaiter, size_t>>(n, k), 2); - bench(MpmcQueueBenchmark2, td::MpmcSleepyWaiter, size_t>>(n, k), 2); - //bench(MpmcQueueBenchmark2>(n, k), 2); - //bench(MpmcQueueBenchmark2>(n, k), 2); - //bench(MpmcQueueBenchmark2(n, k), 2); - //bench(MpmcQueueBenchmark2>>(n, k), 2); - //bench(MpmcQueueBenchmark2>>(n, k), 2); - //bench(MpmcQueueBenchmark2>(n, k), 2); - - //bench(MpmcQueueBenchmark(n, m), 2); -#if TG_LCR_QUEUE - bench(MpmcQueueBenchmark2>>(n, k), 2); -#endif -} - -class ChainedSpawn : public td::Benchmark { - public: - ChainedSpawn(bool use_io) : use_io_(use_io) { - } - std::string get_description() const { - return PSTRING() << "Chained create_actor use_io(" << use_io_ << ")"; - } - - void run(int n) { - class Task : public td::actor::Actor { - public: - Task(int n, Sem *sem) : n_(n), sem_(sem) { - } - void start_up() override { - if (n_ == 0) { - sem_->post(); - } else { - td::actor::create_actor("Task", n_ - 1, sem_).release(); - } - stop(); - }; - - private: - int n_; - Sem *sem_{nullptr}; - }; - td::actor::Scheduler scheduler{{8}}; - auto sch = td::thread([&] { scheduler.run(); }); - - Sem sem; - scheduler.run_in_context_external([&] { - for (int i = 0; i < n; i++) { - td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem) - .release(); - sem.wait(); - } - td::actor::SchedulerContext::get()->stop(); - }); - - sch.join(); - } - - private: - bool use_io_{false}; -}; - -class ChainedSpawnInplace : public td::Benchmark { - public: - ChainedSpawnInplace(bool use_io) : use_io_(use_io) { - } - std::string get_description() const { - return PSTRING() << "Chained send_signal(self) use_io(" << use_io_ << ")"; - } - - void run(int n) { - class Task : public td::actor::Actor { - public: - Task(int n, Sem *sem) : n_(n), sem_(sem) { - } - void loop() override { - if (n_ == 0) { - sem_->post(); - stop(); - } else { - n_--; - send_signals(actor_id(this), td::actor::ActorSignals::wakeup()); - } - }; - - private: - int n_; - Sem *sem_; - }; - td::actor::Scheduler scheduler{{8}}; - auto sch = td::thread([&] { scheduler.run(); }); - - Sem sem; - scheduler.run_in_context_external([&] { - for (int i = 0; i < n; i++) { - td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem) - .release(); - sem.wait(); - } - td::actor::SchedulerContext::get()->stop(); - }); - - sch.join(); - } - - private: - bool use_io_{false}; -}; - -class PingPong : public td::Benchmark { - public: - PingPong(bool use_io) : use_io_(use_io) { - } - std::string get_description() const { - return PSTRING() << "PingPong use_io(" << use_io_ << ")"; - } - - void run(int n) { - if (n < 3) { - n = 3; - } - class Task : public td::actor::Actor { - public: - explicit Task(Sem *sem) : sem_(sem) { - } - void set_peer(td::actor::ActorId peer) { - peer_ = peer; - } - void ping(int n) { - if (n < 0) { - sem_->post(); - stop(); - } - send_closure(peer_, &Task::ping, n - 1); - } - - private: - td::actor::ActorId peer_; - Sem *sem_; - }; - td::actor::Scheduler scheduler{{8}}; - auto sch = td::thread([&] { scheduler.run(); }); - - Sem sem; - scheduler.run_in_context_external([&] { - for (int i = 0; i < n; i++) { - auto a = td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem) - .release(); - auto b = td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem) - .release(); - send_closure(a, &Task::set_peer, b); - send_closure(b, &Task::set_peer, a); - send_closure(a, &Task::ping, 1000); - sem.wait(2); - } - td::actor::SchedulerContext::get()->stop(); - }); - - sch.join(); - } - - private: - bool use_io_{false}; -}; - -class SpawnMany : public td::Benchmark { - public: - SpawnMany(bool use_io) : use_io_(use_io) { - } - std::string get_description() const { - return PSTRING() << "Spawn many use_io(" << use_io_ << ")"; - } - - void run(int n) { - class Task : public td::actor::Actor { - public: - Task(Sem *sem) : sem_(sem) { - } - void start_up() override { - sem_->post(); - stop(); - }; - - private: - Sem *sem_; - }; - td::actor::Scheduler scheduler{{8}}; - Sem sem; - auto sch = td::thread([&] { scheduler.run(); }); - scheduler.run_in_context_external([&] { - for (int i = 0; i < n; i++) { - int spawn_cnt = 10000; - for (int j = 0; j < spawn_cnt; j++) { - td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem).release(); - } - sem.wait(spawn_cnt); - } - td::actor::SchedulerContext::get()->stop(); - }); - sch.join(); - } - - private: - bool use_io_{false}; -}; - -class YieldMany : public td::Benchmark { - public: - YieldMany(bool use_io) : use_io_(use_io) { - } - std::string get_description() const { - return PSTRING() << "Yield many use_io(" << use_io_ << ")"; - } - - void run(int n) { - int num_yield = 1000; - unsigned tasks_per_cpu = 50; - unsigned cpu_n = td::thread::hardware_concurrency(); - class Task : public td::actor::Actor { - public: - explicit Task(int n, Sem *sem) : n_(n), sem_(sem) { - } - void loop() override { - if (n_ == 0) { - sem_->post(); - stop(); - } else { - n_--; - yield(); - } - }; - - private: - int n_; - Sem *sem_; - }; - td::actor::Scheduler scheduler{{cpu_n}}; - auto sch = td::thread([&] { scheduler.run(); }); - unsigned tasks = tasks_per_cpu * cpu_n; - Sem sem; - scheduler.run_in_context_external([&] { - for (int i = 0; i < n; i++) { - for (unsigned j = 0; j < tasks; j++) { - td::actor::create_actor(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), num_yield, &sem) - .release(); - } - sem.wait(tasks); - } - }); - - scheduler.run_in_context_external([&] { td::actor::SchedulerContext::get()->stop(); }); - sch.join(); - } - - private: - bool use_io_{false}; -}; - -int main(int argc, char **argv) { - if (argc > 1) { - if (argv[1][0] == 'a') { - bench_n(MpmcQueueBenchmark2, td::MpmcEagerWaiter, size_t>>(50, 1), 1 << 26); - //bench_n(MpmcQueueBenchmark>(1, 1), 1 << 26); - //bench_n(MpmcQueueBenchmark(1, 40), 1 << 20); - //bench_n(MpmcQueueBenchmark>>(1, 40), 1 << 20); - } else { - bench_n(MpmcQueueBenchmark2, td::MpmcSleepyWaiter, size_t>>(50, 1), 1 << 26); - //bench_n(MpmcQueueBenchmark>(1, 1), 1 << 26); - //bench_n(MpmcQueueBenchmark>>(1, 40), 1 << 20); - //bench_n(MpmcQueueBenchmark>>(1, 1), 1 << 26); - } - return 0; - } - bench(YieldMany(false)); - bench(YieldMany(true)); - bench(SpawnMany(false)); - bench(SpawnMany(true)); - bench(PingPong(false)); - bench(PingPong(true)); - bench(ChainedSpawnInplace(false)); - bench(ChainedSpawnInplace(true)); - bench(ChainedSpawn(false)); - bench(ChainedSpawn(true)); - - run_queue_bench(10, 10); - run_queue_bench(10, 1); - run_queue_bench(1, 10); - run_queue_bench(1, 1); - run_queue_bench(2, 10); - run_queue_bench(2, 2); - run_queue_bench(10, 1); - - run_queue_bench2(50, 1); - run_queue_bench2(50, 2); - run_queue_bench2(1, 100); - run_queue_bench2(1, 1000); - run_queue_bench2(10, 2); - run_queue_bench2(10, 1000); - - return 0; - - bench(ActorDummyQuery()); - bench(ActorExecutorBenchmark()); - bench(ActorSignalQuery()); - bench(ActorQuery()); - bench(ActorTaskQuery()); - bench(CalcHashSha256Benchmark()); - bench(CalcHashSha256Benchmark()); - bench(CalcHashSha256Benchmark()); - bench(ActorLockerBenchmark(1)); - bench(ActorLockerBenchmark(2)); - bench(ActorLockerBenchmark(5)); - bench(ActorLockerBenchmark(20)); - - bench(CalcHashSha256Benchmark>>()); - bench(CalcHashSha256Benchmark>>()); - bench(CalcHashSha256Benchmark, Cell>>>()); - - bench(CalcHashSha256Benchmark>>()); - bench(CalcHashSha256Benchmark, Cell>>>()); -#if TG_LCR_QUEUE - bench(CalcHashSha256Benchmark, Cell>>>()); -#endif - bench(CalcHashSha256Benchmark>>()); - bench(CalcHashSha256Benchmark>>()); - - bench(CalcHashSha256Benchmark>>>()); - bench(CalcHashSha256Benchmark>>>()); - - return 0; -} diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/FAAArrayQueue.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/FAAArrayQueue.h deleted file mode 100644 index 84238265..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/FAAArrayQueue.h +++ /dev/null @@ -1,371 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2014-2016, Pedro Ramalhete, Andreia Correia - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Concurrency Freaks nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ****************************************************************************** - */ - -#ifndef _FAA_ARRAY_QUEUE_HP_H_ -#define _FAA_ARRAY_QUEUE_HP_H_ - -#include "HazardPointers.h" - -#include -#include - -namespace ConcurrencyFreaks { -/** - *

Fetch-And-Add Array Queue

- * - * Each node has one array but we don't search for a vacant entry. Instead, we - * use FAA to obtain an index in the array, for enqueueing or dequeuing. - * - * There are some similarities between this queue and the basic queue in YMC: - * http://chaoran.me/assets/pdf/wfq-ppopp16.pdf - * but it's not the same because the queue in listing 1 is obstruction-free, while - * our algorithm is lock-free. - * In FAAArrayQueue eventually a new node will be inserted (using Michael-Scott's - * algorithm) and it will have an item pre-filled in the first position, which means - * that at most, after BUFFER_SIZE steps, one item will be enqueued (and it can then - * be dequeued). This kind of progress is lock-free. - * - * Each entry in the array may contain one of three possible values: - * - A valid item that has been enqueued; - * - nullptr, which means no item has yet been enqueued in that position; - * - taken, a special value that means there was an item but it has been dequeued; - * - * Enqueue algorithm: FAA + CAS(null,item) - * Dequeue algorithm: FAA + CAS(item,taken) - * Consistency: Linearizable - * enqueue() progress: lock-free - * dequeue() progress: lock-free - * Memory Reclamation: Hazard Pointers (lock-free) - * Uncontended enqueue: 1 FAA + 1 CAS + 1 HP - * Uncontended dequeue: 1 FAA + 1 CAS + 1 HP - * - * - *

- * Lock-Free Linked List as described in Maged Michael and Michael Scott's paper: - * {@link http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf} - * - * Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms - *

- * The paper on Hazard Pointers is named "Hazard Pointers: Safe Memory - * Reclamation for Lock-Free objects" and it is available here: - * http://web.cecs.pdx.edu/~walpole/class/cs510/papers/11.pdf - * - * @author Pedro Ramalhete - * @author Andreia Correia - */ -template -class FAAArrayQueue { - static const long BUFFER_SIZE = 1024; // 1024 - - private: - struct Node { - std::atomic deqidx; - std::atomic items[BUFFER_SIZE]; - std::atomic enqidx; - std::atomic next; - - // Start with the first entry pre-filled and enqidx at 1 - Node(T* item) : deqidx{0}, enqidx{1}, next{nullptr} { - items[0].store(item, std::memory_order_relaxed); - for (long i = 1; i < BUFFER_SIZE; i++) { - items[i].store(nullptr, std::memory_order_relaxed); - } - } - - bool casNext(Node* cmp, Node* val) { - return next.compare_exchange_strong(cmp, val); - } - }; - - bool casTail(Node* cmp, Node* val) { - return tail.compare_exchange_strong(cmp, val); - } - - bool casHead(Node* cmp, Node* val) { - return head.compare_exchange_strong(cmp, val); - } - - // Pointers to head and tail of the list - alignas(128) std::atomic head; - alignas(128) std::atomic tail; - - static const int MAX_THREADS = 128; - const int maxThreads; - - T* taken = (T*)new int(); // Muuuahahah ! - - // We need just one hazard pointer - HazardPointers hp{1, maxThreads}; - const int kHpTail = 0; - const int kHpHead = 0; - - public: - FAAArrayQueue(int maxThreads = MAX_THREADS) : maxThreads{maxThreads} { - Node* sentinelNode = new Node(nullptr); - sentinelNode->enqidx.store(0, std::memory_order_relaxed); - head.store(sentinelNode, std::memory_order_relaxed); - tail.store(sentinelNode, std::memory_order_relaxed); - } - - ~FAAArrayQueue() { - while (dequeue(0) != nullptr) - ; // Drain the queue - delete head.load(); // Delete the last node - delete (int*)taken; - } - - std::string className() { - return "FAAArrayQueue"; - } - - void enqueue(T* item, const int tid) { - while (true) { - Node* ltail = hp.protect(kHpTail, tail, tid); - const int idx = ltail->enqidx.fetch_add(1); - if (idx > BUFFER_SIZE - 1) { // This node is full - if (ltail != tail.load()) - continue; - Node* lnext = ltail->next.load(); - if (lnext == nullptr) { - Node* newNode = new Node(item); - if (ltail->casNext(nullptr, newNode)) { - casTail(ltail, newNode); - hp.clear(tid); - return; - } - delete newNode; - } else { - casTail(ltail, lnext); - } - continue; - } - T* itemnull = nullptr; - if (ltail->items[idx].compare_exchange_strong(itemnull, item)) { - hp.clear(tid); - return; - } - } - } - - T* dequeue(const int tid) { - while (true) { - Node* lhead = hp.protect(kHpHead, head, tid); - if (lhead->deqidx.load() >= lhead->enqidx.load() && lhead->next.load() == nullptr) - break; - const int idx = lhead->deqidx.fetch_add(1); - if (idx > BUFFER_SIZE - 1) { // This node has been drained, check if there is another one - Node* lnext = lhead->next.load(); - if (lnext == nullptr) - break; // No more nodes in the queue - if (casHead(lhead, lnext)) - hp.retire(lhead, tid); - continue; - } - T* item = lhead->items[idx].exchange(taken); - if (item == nullptr) - continue; - hp.clear(tid); - return item; - } - hp.clear(tid); - return nullptr; - } -}; -/** - *

Lazy Index Array Queue

- * - * Same as Linear Array Queue but with lazy indexes for both enqueuers and dequeuers. - * - * This is a lock-free queue where each node contains an array of items. - * Each entry in the array may contain on of three possible values: - * - A valid item that has been enqueued; - * - nullptr, which means no item has yet been enqueued in that position; - * - taken, a special value that means there was an item but it has been dequeued; - * The enqueue() searches for the first nullptr entry in the array and tries - * to CAS from nullptr to its item. - * The dequeue() searches for the first valid item in the array and tries to - * CAS from item to "taken". - * - * Enqueue algorithm: Linear array search starting at lazy index with CAS(nullptr,item) - * Dequeue algorithm: Linear array search starting at lazy index with CAS(item,taken) - * Consistency: Linearizable - * enqueue() progress: lock-free - * dequeue() progress: lock-free - * Memory Reclamation: Hazard Pointers (lock-free) - * Uncontended enqueue: 1 CAS + 1 HP - * Uncontended dequeue: 1 CAS + 1 HP - * - * - *

- * Lock-Free Linked List as described in Maged Michael and Michael Scott's paper: - * {@link http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf} - * - * Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms - *

- * The paper on Hazard Pointers is named "Hazard Pointers: Safe Memory - * Reclamation for Lock-Free objects" and it is available here: - * http://web.cecs.pdx.edu/~walpole/class/cs510/papers/11.pdf - * - * @author Pedro Ramalhete - * @author Andreia Correia - */ -template -class LazyIndexArrayQueue { - static const long BUFFER_SIZE = 1024; - - private: - struct Node { - std::atomic deqidx; - std::atomic items[BUFFER_SIZE]; - std::atomic enqidx; - std::atomic next; - - Node(T* item) : deqidx{0}, enqidx{0}, next{nullptr} { - items[0].store(item, std::memory_order_relaxed); - for (int i = 1; i < BUFFER_SIZE; i++) { - items[i].store(nullptr, std::memory_order_relaxed); - } - } - - bool casNext(Node* cmp, Node* val) { - return next.compare_exchange_strong(cmp, val); - } - }; - - bool casTail(Node* cmp, Node* val) { - return tail.compare_exchange_strong(cmp, val); - } - - bool casHead(Node* cmp, Node* val) { - return head.compare_exchange_strong(cmp, val); - } - - // Pointers to head and tail of the list - alignas(128) std::atomic head; - alignas(128) std::atomic tail; - - static const int MAX_THREADS = 128; - const int maxThreads; - - T* taken = (T*)new int(); // Muuuahahah ! - - // We need just one hazard pointer - HazardPointers hp{1, maxThreads}; - const int kHpTail = 0; - const int kHpHead = 0; - - public: - LazyIndexArrayQueue(int maxThreads = MAX_THREADS) : maxThreads{maxThreads} { - Node* sentinelNode = new Node(nullptr); - head.store(sentinelNode, std::memory_order_relaxed); - tail.store(sentinelNode, std::memory_order_relaxed); - } - - ~LazyIndexArrayQueue() { - while (dequeue(0) != nullptr) - ; // Drain the queue - delete head.load(); // Delete the last node - delete (int*)taken; - } - - std::string className() { - return "LazyIndexArrayQueue"; - } - - void enqueue(T* item, const int tid) { - while (true) { - Node* ltail = hp.protect(kHpTail, tail, tid); - if (ltail->items[BUFFER_SIZE - 1].load() != nullptr) { // This node is full - if (ltail != tail.load()) - continue; - Node* lnext = ltail->next.load(); - if (lnext == nullptr) { - Node* newNode = new Node(item); - if (ltail->casNext(nullptr, newNode)) { - casTail(ltail, newNode); - hp.clear(tid); - return; - } - delete newNode; - } else { - casTail(ltail, lnext); - } - continue; - } - // Find the first null entry in items[] and try to CAS from null to item - for (int i = ltail->enqidx.load(); i < BUFFER_SIZE; i++) { - if (ltail->items[i].load() != nullptr) - continue; - T* itemnull = nullptr; - if (ltail->items[i].compare_exchange_strong(itemnull, item)) { - ltail->enqidx.store(i + 1, std::memory_order_release); - hp.clear(tid); - return; - } - if (ltail != tail.load()) - break; - } - } - } - - T* dequeue(const int tid) { - while (true) { - Node* lhead = hp.protect(kHpHead, head, tid); - if (lhead->items[BUFFER_SIZE - 1].load() == taken) { // This node has been drained, check if there is another one - Node* lnext = lhead->next.load(); - if (lnext == nullptr) { // No more nodes in the queue - hp.clear(tid); - return nullptr; - } - if (casHead(lhead, lnext)) - hp.retire(lhead, tid); - continue; - } - // Find the first non taken entry in items[] and try to CAS from item to taken - for (int i = lhead->deqidx.load(); i < BUFFER_SIZE; i++) { - T* item = lhead->items[i].load(); - if (item == nullptr) { - hp.clear(tid); - return nullptr; // This node is empty - } - if (item == taken) - continue; - if (lhead->items[i].compare_exchange_strong(item, taken)) { - lhead->deqidx.store(i + 1, std::memory_order_release); - hp.clear(tid); - return item; - } - if (lhead != head.load()) - break; - } - } - } -}; -} // namespace ConcurrencyFreaks - -#endif /* _FAA_ARRAY_QUEUE_HP_H_ */ diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/HazardPointers.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/HazardPointers.h deleted file mode 100644 index e562486a..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/HazardPointers.h +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2014-2016, Pedro Ramalhete, Andreia Correia - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Concurrency Freaks nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ****************************************************************************** - */ - -#ifndef _HAZARD_POINTERS_H_ -#define _HAZARD_POINTERS_H_ - -#include -#include -#include - -namespace ConcurrencyFreaks { -template -class HazardPointers { - private: - static const int HP_MAX_THREADS = 128; - static const int HP_MAX_HPS = 4; // This is named 'K' in the HP paper - static const int CLPAD = 128 / sizeof(std::atomic); - static const int HP_THRESHOLD_R = 0; // This is named 'R' in the HP paper - static const int MAX_RETIRED = HP_MAX_THREADS * HP_MAX_HPS; // Maximum number of retired objects per thread - - const int maxHPs; - const int maxThreads; - - std::atomic* hp[HP_MAX_THREADS]; - // It's not nice that we have a lot of empty vectors, but we need padding to avoid false sharing - std::vector retiredList[HP_MAX_THREADS * CLPAD]; - - public: - HazardPointers(int maxHPs = HP_MAX_HPS, int maxThreads = HP_MAX_THREADS) : maxHPs{maxHPs}, maxThreads{maxThreads} { - for (int ithread = 0; ithread < HP_MAX_THREADS; ithread++) { - hp[ithread] = - new std::atomic[CLPAD * - 2]; // We allocate four cache lines to allow for many hps and without false sharing - for (int ihp = 0; ihp < HP_MAX_HPS; ihp++) { - hp[ithread][ihp].store(nullptr, std::memory_order_relaxed); - } - } - } - - ~HazardPointers() { - for (int ithread = 0; ithread < HP_MAX_THREADS; ithread++) { - delete[] hp[ithread]; - // Clear the current retired nodes - for (unsigned iret = 0; iret < retiredList[ithread * CLPAD].size(); iret++) { - delete retiredList[ithread * CLPAD][iret]; - } - } - } - - /** - * Progress Condition: wait-free bounded (by maxHPs) - */ - void clear(const int tid) { - for (int ihp = 0; ihp < maxHPs; ihp++) { - hp[tid][ihp].store(nullptr, std::memory_order_release); - } - } - - /** - * Progress Condition: wait-free population oblivious - */ - void clearOne(int ihp, const int tid) { - hp[tid][ihp].store(nullptr, std::memory_order_release); - } - - /** - * Progress Condition: lock-free - */ - T* protect(int index, const std::atomic& atom, const int tid) { - T* n = nullptr; - T* ret; - while ((ret = atom.load()) != n) { - hp[tid][index].store(ret); - n = ret; - } - return ret; - } - - /** - * This returns the same value that is passed as ptr, which is sometimes useful - * Progress Condition: wait-free population oblivious - */ - T* protectPtr(int index, T* ptr, const int tid) { - hp[tid][index].store(ptr); - return ptr; - } - - /** - * This returns the same value that is passed as ptr, which is sometimes useful - * Progress Condition: wait-free population oblivious - */ - T* protectRelease(int index, T* ptr, const int tid) { - hp[tid][index].store(ptr, std::memory_order_release); - return ptr; - } - - /** - * Progress Condition: wait-free bounded (by the number of threads squared) - */ - void retire(T* ptr, const int tid) { - retiredList[tid * CLPAD].push_back(ptr); - if (retiredList[tid * CLPAD].size() < HP_THRESHOLD_R) - return; - for (unsigned iret = 0; iret < retiredList[tid * CLPAD].size();) { - auto obj = retiredList[tid * CLPAD][iret]; - bool canDelete = true; - for (int tid = 0; tid < maxThreads && canDelete; tid++) { - for (int ihp = maxHPs - 1; ihp >= 0; ihp--) { - if (hp[tid][ihp].load() == obj) { - canDelete = false; - break; - } - } - } - if (canDelete) { - retiredList[tid * CLPAD].erase(retiredList[tid * CLPAD].begin() + iret); - delete obj; - continue; - } - iret++; - } - } -}; -} // namespace ConcurrencyFreaks - -#endif /* _HAZARD_POINTERS_H_ */ diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/LCRQueue.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/LCRQueue.h deleted file mode 100644 index 17e4b168..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/LCRQueue.h +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2014-2016, Pedro Ramalhete, Andreia Correia - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Concurrency Freaks nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ****************************************************************************** - */ - -#ifndef _LCRQ_QUEUE_HP_H_ -#define _LCRQ_QUEUE_HP_H_ - -#include - -// CAS2 macro - -#define __CAS2(ptr, o1, o2, n1, n2) \ - ({ \ - char __ret; \ - __typeof__(o2) __junk; \ - __typeof__(*(ptr)) __old1 = (o1); \ - __typeof__(o2) __old2 = (o2); \ - __typeof__(*(ptr)) __new1 = (n1); \ - __typeof__(o2) __new2 = (n2); \ - asm volatile("lock cmpxchg16b %2;setz %1" \ - : "=d"(__junk), "=a"(__ret), "+m"(*ptr) \ - : "b"(__new1), "c"(__new2), "a"(__old1), "d"(__old2)); \ - __ret; \ - }) - -#define CAS2(ptr, o1, o2, n1, n2) __CAS2(ptr, o1, o2, n1, n2) - -#define BIT_TEST_AND_SET(ptr, b) \ - ({ \ - char __ret; \ - asm volatile("lock btsq $63, %0; setnc %1" : "+m"(*ptr), "=a"(__ret) : : "cc"); \ - __ret; \ - }) - -/** - *

LCRQ Queue

- * - * This is LCRQ by Adam Morrison and Yehuda Afek - * http://www.cs.tau.ac.il/~mad/publications/ppopp2013-x86queues.pdf - * - * This implementation does NOT obey the C++ memory model rules AND it is x86 specific. - * No guarantees are given on the correctness or consistency of the results if you use this queue. - * - * Bugs fixed: - * tt was not initialized in dequeue(); - * - *

- * enqueue algorithm: MS enqueue + LCRQ with re-usage - * dequeue algorithm: MS dequeue + LCRQ with re-usage - * Consistency: Linearizable - * enqueue() progress: lock-free - * dequeue() progress: lock-free - * Memory Reclamation: Hazard Pointers (lock-free) - * - *

- * The paper on Hazard Pointers is named "Hazard Pointers: Safe Memory - * Reclamation for Lock-Free objects" and it is available here: - * http://web.cecs.pdx.edu/~walpole/class/cs510/papers/11.pdf - * - * @author Pedro Ramalhete - * @author Andreia Correia - */ -namespace ConcurrencyFreaks { -template -class LCRQueue { - private: - static const int RING_POW = 10; - static const uint64_t RING_SIZE = 1ull << RING_POW; - - struct Cell { - std::atomic val; - std::atomic idx; - uint64_t pad[14]; - } __attribute__((aligned(128))); - - struct Node { - std::atomic head __attribute__((aligned(128))); - std::atomic tail __attribute__((aligned(128))); - std::atomic next __attribute__((aligned(128))); - Cell array[RING_SIZE]; - - Node() { - for (unsigned i = 0; i < RING_SIZE; i++) { - array[i].val.store(nullptr, std::memory_order_relaxed); - array[i].idx.store(i, std::memory_order_relaxed); - } - head.store(0, std::memory_order_relaxed); - tail.store(0, std::memory_order_relaxed); - next.store(nullptr, std::memory_order_relaxed); - } - }; - - alignas(128) std::atomic head; - alignas(128) std::atomic tail; - - static const int MAX_THREADS = 128; - const int maxThreads; - - HazardPointers hp{1, maxThreads}; - const int kHpTail = 0; - const int kHpHead = 0; - - /* - * Private methods - */ - int is_empty(T* v) { - return (v == nullptr); - } - - uint64_t node_index(uint64_t i) { - return (i & ~(1ull << 63)); - } - - uint64_t set_unsafe(uint64_t i) { - return (i | (1ull << 63)); - } - - uint64_t node_unsafe(uint64_t i) { - return (i & (1ull << 63)); - } - - inline uint64_t tail_index(uint64_t t) { - return (t & ~(1ull << 63)); - } - - int crq_is_closed(uint64_t t) { - return (t & (1ull << 63)) != 0; - } - - void fixState(Node* lhead) { - while (1) { - uint64_t t = lhead->tail.fetch_add(0); - uint64_t h = lhead->head.fetch_add(0); - // TODO: is it ok or not to cast "t" to int64_t ? - if (lhead->tail.load() != (int64_t)t) - continue; - if (h > t) { - int64_t tmp = t; - if (lhead->tail.compare_exchange_strong(tmp, h)) - break; - continue; - } - break; - } - } - - int close_crq(Node* rq, const uint64_t tailticket, const int tries) { - if (tries < 10) { - int64_t tmp = tailticket + 1; - return rq->tail.compare_exchange_strong(tmp, (tailticket + 1) | (1ull << 63)); - } else { - return BIT_TEST_AND_SET(&rq->tail, 63); - } - } - - public: - LCRQueue(int maxThreads = MAX_THREADS) : maxThreads{maxThreads} { - // Shared object init - Node* sentinel = new Node; - head.store(sentinel, std::memory_order_relaxed); - tail.store(sentinel, std::memory_order_relaxed); - } - - ~LCRQueue() { - while (dequeue(0) != nullptr) - ; // Drain the queue - delete head.load(); // Delete the last node - } - - std::string className() { - return "LCRQueue"; - } - - void enqueue(T* item, const int tid) { - int try_close = 0; - while (true) { - Node* ltail = hp.protectPtr(kHpTail, tail.load(), tid); - if (ltail != tail.load()) - continue; - Node* lnext = ltail->next.load(); - if (lnext != nullptr) { // Help advance the tail - tail.compare_exchange_strong(ltail, lnext); - continue; - } - - uint64_t tailticket = ltail->tail.fetch_add(1); - if (crq_is_closed(tailticket)) { - Node* newNode = new Node(); - // Solo enqueue (superfluous?) - newNode->tail.store(1, std::memory_order_relaxed); - newNode->array[0].val.store(item, std::memory_order_relaxed); - newNode->array[0].idx.store(0, std::memory_order_relaxed); - Node* nullnode = nullptr; - if (ltail->next.compare_exchange_strong(nullnode, newNode)) { // Insert new ring - tail.compare_exchange_strong(ltail, newNode); // Advance the tail - hp.clear(tid); - return; - } - delete newNode; - continue; - } - Cell* cell = <ail->array[tailticket & (RING_SIZE - 1)]; - uint64_t idx = cell->idx.load(); - if (cell->val.load() == nullptr) { - if (node_index(idx) <= tailticket) { - // TODO: is the missing cast before "t" ok or not to add? - if ((!node_unsafe(idx) || ltail->head.load() < (int64_t)tailticket)) { - if (CAS2((void**)cell, nullptr, idx, item, tailticket)) { - hp.clear(tid); - return; - } - } - } - } - if (((int64_t)(tailticket - ltail->head.load()) >= (int64_t)RING_SIZE) && - close_crq(ltail, tailticket, ++try_close)) - continue; - } - } - - T* dequeue(const int tid) { - while (true) { - Node* lhead = hp.protectPtr(kHpHead, head.load(), tid); - if (lhead != head.load()) - continue; - uint64_t headticket = lhead->head.fetch_add(1); - Cell* cell = &lhead->array[headticket & (RING_SIZE - 1)]; - - int r = 0; - uint64_t tt = 0; - - while (true) { - uint64_t cell_idx = cell->idx.load(); - uint64_t unsafe = node_unsafe(cell_idx); - uint64_t idx = node_index(cell_idx); - T* val = cell->val.load(); - - if (idx > headticket) - break; - - if (val != nullptr) { - if (idx == headticket) { - if (CAS2((void**)cell, val, cell_idx, nullptr, unsafe | (headticket + RING_SIZE))) { - hp.clear(tid); - return val; - } - } else { - if (CAS2((void**)cell, val, cell_idx, val, set_unsafe(idx))) - break; - } - } else { - if ((r & ((1ull << 10) - 1)) == 0) - tt = lhead->tail.load(); - // Optimization: try to bail quickly if queue is closed. - int crq_closed = crq_is_closed(tt); - uint64_t t = tail_index(tt); - if (unsafe) { // Nothing to do, move along - if (CAS2((void**)cell, val, cell_idx, val, unsafe | (headticket + RING_SIZE))) - break; - } else if (t < headticket + 1 || r > 200000 || crq_closed) { - if (CAS2((void**)cell, val, idx, val, headticket + RING_SIZE)) { - if (r > 200000 && tt > RING_SIZE) - BIT_TEST_AND_SET(&lhead->tail, 63); - break; - } - } else { - ++r; - } - } - } - - if (tail_index(lhead->tail.load()) <= headticket + 1) { - fixState(lhead); - // try to return empty - Node* lnext = lhead->next.load(); - if (lnext == nullptr) { - hp.clear(tid); - return nullptr; // Queue is empty - } - if (tail_index(lhead->tail) <= headticket + 1) { - if (head.compare_exchange_strong(lhead, lnext)) - hp.retire(lhead, tid); - } - } - } - } -}; -} // namespace ConcurrencyFreaks -#endif /* _LCRQ_QUEUE_HP_H_ */ diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/LazyIndexArrayQueue.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/LazyIndexArrayQueue.h deleted file mode 100644 index e69de29b..00000000 diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/MoodyCamelQueue.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/MoodyCamelQueue.h deleted file mode 100644 index 1c7cf801..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/MoodyCamelQueue.h +++ /dev/null @@ -1,3724 +0,0 @@ -// Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue. -// An overview, including benchmark results, is provided here: -// http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++ -// The full design is also described in excruciating detail at: -// http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue - -// Simplified BSD license: -// Copyright (c) 2013-2016, Cameron Desrochers. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// - Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// - Redistributions in binary form must reproduce the above copyright notice, this list of -// conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#if defined(__GNUC__) -// Disable -Wconversion warnings (spuriously triggered when Traits::size_t and -// Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings -// upon assigning any computed values) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" - -#ifdef MCDBGQ_USE_RELACY -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" -#endif -#endif - -#if defined(__APPLE__) -#include "TargetConditionals.h" -#endif - -#ifdef MCDBGQ_USE_RELACY -#include "relacy/relacy_std.hpp" -#include "relacy_shims.h" -// We only use malloc/free anyway, and the delete macro messes up `= delete` method declarations. -// We'll override the default trait malloc ourselves without a macro. -#undef new -#undef delete -#undef malloc -#undef free -#else -#include // Requires C++11. Sorry VS2010. -#include -#endif -#include // for max_align_t -#include -#include -#include -#include -#include -#include -#include // for CHAR_BIT -#include -#include // partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading - -// Platform-specific definitions of a numeric thread ID type and an invalid value -namespace moodycamel { -namespace details { -template -struct thread_id_converter { - typedef thread_id_t thread_id_numeric_size_t; - typedef thread_id_t thread_id_hash_t; - static thread_id_hash_t prehash(thread_id_t const& x) { - return x; - } -}; -} // namespace details -} // namespace moodycamel -#if defined(MCDBGQ_USE_RELACY) -namespace moodycamel { -namespace details { -typedef std::uint32_t thread_id_t; -static const thread_id_t invalid_thread_id = 0xFFFFFFFFU; -static const thread_id_t invalid_thread_id2 = 0xFFFFFFFEU; -static inline thread_id_t thread_id() { - return rl::thread_index(); -} -} // namespace details -} // namespace moodycamel -#elif defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__) -// No sense pulling in windows.h in a header, we'll manually declare the function -// we use and rely on backwards-compatibility for this not to break -extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(void); -namespace moodycamel { -namespace details { -static_assert(sizeof(unsigned long) == sizeof(std::uint32_t), - "Expected size of unsigned long to be 32 bits on Windows"); -typedef std::uint32_t thread_id_t; -static const thread_id_t invalid_thread_id = - 0; // See http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx -static const thread_id_t invalid_thread_id2 = - 0xFFFFFFFFU; // Not technically guaranteed to be invalid, but is never used in practice. Note that all Win32 thread IDs are presently multiples of 4. -static inline thread_id_t thread_id() { - return static_cast(::GetCurrentThreadId()); -} -} // namespace details -} // namespace moodycamel -#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE) -namespace moodycamel { -namespace details { -static_assert(sizeof(std::thread::id) == 4 || sizeof(std::thread::id) == 8, - "std::thread::id is expected to be either 4 or 8 bytes"); - -typedef std::thread::id thread_id_t; -static const thread_id_t invalid_thread_id; // Default ctor creates invalid ID - -// Note we don't define a invalid_thread_id2 since std::thread::id doesn't have one; it's -// only used if MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is defined anyway, which it won't -// be. -static inline thread_id_t thread_id() { - return std::this_thread::get_id(); -} - -template -struct thread_id_size {}; -template <> -struct thread_id_size<4> { - typedef std::uint32_t numeric_t; -}; -template <> -struct thread_id_size<8> { - typedef std::uint64_t numeric_t; -}; - -template <> -struct thread_id_converter { - typedef thread_id_size::numeric_t thread_id_numeric_size_t; -#ifndef __APPLE__ - typedef std::size_t thread_id_hash_t; -#else - typedef thread_id_numeric_size_t thread_id_hash_t; -#endif - - static thread_id_hash_t prehash(thread_id_t const& x) { -#ifndef __APPLE__ - return std::hash()(x); -#else - return *reinterpret_cast(&x); -#endif - } -}; -} // namespace details -} // namespace moodycamel -#else -// Use a nice trick from this answer: http://stackoverflow.com/a/8438730/21475 -// In order to get a numeric thread ID in a platform-independent way, we use a thread-local -// static variable's address as a thread identifier :-) -#if defined(__GNUC__) || defined(__INTEL_COMPILER) -#define MOODYCAMEL_THREADLOCAL __thread -#elif defined(_MSC_VER) -#define MOODYCAMEL_THREADLOCAL __declspec(thread) -#else -// Assume C++11 compliant compiler -#define MOODYCAMEL_THREADLOCAL thread_local -#endif -namespace moodycamel { -namespace details { -typedef std::uintptr_t thread_id_t; -static const thread_id_t invalid_thread_id = 0; // Address can't be nullptr -static const thread_id_t invalid_thread_id2 = - 1; // Member accesses off a null pointer are also generally invalid. Plus it's not aligned. -static inline thread_id_t thread_id() { - static MOODYCAMEL_THREADLOCAL int x; - return reinterpret_cast(&x); -} -} // namespace details -} // namespace moodycamel -#endif - -// Exceptions -#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED -#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || \ - (!defined(_MSC_VER) && !defined(__GNUC__)) -#define MOODYCAMEL_EXCEPTIONS_ENABLED -#endif -#endif -#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED -#define MOODYCAMEL_TRY try -#define MOODYCAMEL_CATCH(...) catch (__VA_ARGS__) -#define MOODYCAMEL_RETHROW throw -#define MOODYCAMEL_THROW(expr) throw(expr) -#else -#define MOODYCAMEL_TRY if (true) -#define MOODYCAMEL_CATCH(...) else if (false) -#define MOODYCAMEL_RETHROW -#define MOODYCAMEL_THROW(expr) -#endif - -#ifndef MOODYCAMEL_NOEXCEPT -#if !defined(MOODYCAMEL_EXCEPTIONS_ENABLED) -#define MOODYCAMEL_NOEXCEPT -#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) true -#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) true -#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1800 -// VS2012's std::is_nothrow_[move_]constructible is broken and returns true when it shouldn't :-( -// We have to assume *all* non-trivial constructors may throw on VS2012! -#define MOODYCAMEL_NOEXCEPT _NOEXCEPT -#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) \ - (std::is_rvalue_reference::value && std::is_move_constructible::value \ - ? std::is_trivially_move_constructible::value \ - : std::is_trivially_copy_constructible::value) -#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) \ - ((std::is_rvalue_reference::value && std::is_move_assignable::value \ - ? std::is_trivially_move_assignable::value || std::is_nothrow_move_assignable::value \ - : std::is_trivially_copy_assignable::value || std::is_nothrow_copy_assignable::value) && \ - MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr)) -#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1900 -#define MOODYCAMEL_NOEXCEPT _NOEXCEPT -#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) \ - (std::is_rvalue_reference::value && std::is_move_constructible::value \ - ? std::is_trivially_move_constructible::value || std::is_nothrow_move_constructible::value \ - : std::is_trivially_copy_constructible::value || std::is_nothrow_copy_constructible::value) -#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) \ - ((std::is_rvalue_reference::value && std::is_move_assignable::value \ - ? std::is_trivially_move_assignable::value || std::is_nothrow_move_assignable::value \ - : std::is_trivially_copy_assignable::value || std::is_nothrow_copy_assignable::value) && \ - MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr)) -#else -#define MOODYCAMEL_NOEXCEPT noexcept -#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) noexcept(expr) -#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) noexcept(expr) -#endif -#endif - -#ifndef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED -#ifdef MCDBGQ_USE_RELACY -#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED -#else -// VS2013 doesn't support `thread_local`, and MinGW-w64 w/ POSIX threading has a crippling bug: http://sourceforge.net/p/mingw-w64/bugs/445 -// g++ <=4.7 doesn't support thread_local either. -// Finally, iOS/ARM doesn't have support for it either, and g++/ARM allows it to compile but it's unconfirmed to actually work -#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ - (!defined(__MINGW32__) && !defined(__MINGW64__) || !defined(__WINPTHREADS_VERSION)) && \ - (!defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && \ - (!defined(__APPLE__) || !TARGET_OS_IPHONE) && !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) -// Assume `thread_local` is fully supported in all other C++11 compilers/platforms -//#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED // always disabled for now since several users report having problems with it on -#endif -#endif -#endif - -// VS2012 doesn't support deleted functions. -// In this case, we declare the function normally but don't define it. A link error will be generated if the function is called. -#ifndef MOODYCAMEL_DELETE_FUNCTION -#if defined(_MSC_VER) && _MSC_VER < 1800 -#define MOODYCAMEL_DELETE_FUNCTION -#else -#define MOODYCAMEL_DELETE_FUNCTION = delete -#endif -#endif - -// Compiler-specific likely/unlikely hints -namespace moodycamel { -namespace details { -#if defined(__GNUC__) -static inline bool(likely)(bool x) { - return __builtin_expect((x), true); -} -static inline bool(unlikely)(bool x) { - return __builtin_expect((x), false); -} -#else -static inline bool(likely)(bool x) { - return x; -} -static inline bool(unlikely)(bool x) { - return x; -} -#endif -} // namespace details -} // namespace moodycamel - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG -#include "internal/concurrentqueue_internal_debug.h" -#endif - -namespace moodycamel { -namespace details { -template -struct const_numeric_max { - static_assert(std::is_integral::value, "const_numeric_max can only be used with integers"); - static const T value = std::numeric_limits::is_signed - ? (static_cast(1) << (sizeof(T) * CHAR_BIT - 1)) - static_cast(1) - : static_cast(-1); -}; - -#if defined(__GLIBCXX__) -typedef ::max_align_t std_max_align_t; // libstdc++ forgot to add it to std:: for a while -#else -typedef std::max_align_t std_max_align_t; // Others (e.g. MSVC) insist it can *only* be accessed via std:: -#endif - -// Some platforms have incorrectly set max_align_t to a type with <8 bytes alignment even while supporting -// 8-byte aligned scalar values (*cough* 32-bit iOS). Work around this with our own union. See issue #64. -typedef union { - std_max_align_t x; - long long y; - void* z; -} max_align_t; -} // namespace details - -// Default traits for the ConcurrentQueue. To change some of the -// traits without re-implementing all of them, inherit from this -// struct and shadow the declarations you wish to be different; -// since the traits are used as a template type parameter, the -// shadowed declarations will be used where defined, and the defaults -// otherwise. -struct ConcurrentQueueDefaultTraits { - // General-purpose size type. std::size_t is strongly recommended. - typedef std::size_t size_t; - - // The type used for the enqueue and dequeue indices. Must be at least as - // large as size_t. Should be significantly larger than the number of elements - // you expect to hold at once, especially if you have a high turnover rate; - // for example, on 32-bit x86, if you expect to have over a hundred million - // elements or pump several million elements through your queue in a very - // short space of time, using a 32-bit type *may* trigger a race condition. - // A 64-bit int type is recommended in that case, and in practice will - // prevent a race condition no matter the usage of the queue. Note that - // whether the queue is lock-free with a 64-int type depends on the whether - // std::atomic is lock-free, which is platform-specific. - typedef std::size_t index_t; - - // Internally, all elements are enqueued and dequeued from multi-element - // blocks; this is the smallest controllable unit. If you expect few elements - // but many producers, a smaller block size should be favoured. For few producers - // and/or many elements, a larger block size is preferred. A sane default - // is provided. Must be a power of 2. - static const size_t BLOCK_SIZE = 32; - - // For explicit producers (i.e. when using a producer token), the block is - // checked for being empty by iterating through a list of flags, one per element. - // For large block sizes, this is too inefficient, and switching to an atomic - // counter-based approach is faster. The switch is made for block sizes strictly - // larger than this threshold. - static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = 32; - - // How many full blocks can be expected for a single explicit producer? This should - // reflect that number's maximum for optimal performance. Must be a power of 2. - static const size_t EXPLICIT_INITIAL_INDEX_SIZE = 32; - - // How many full blocks can be expected for a single implicit producer? This should - // reflect that number's maximum for optimal performance. Must be a power of 2. - static const size_t IMPLICIT_INITIAL_INDEX_SIZE = 32; - - // The initial size of the hash table mapping thread IDs to implicit producers. - // Note that the hash is resized every time it becomes half full. - // Must be a power of two, and either 0 or at least 1. If 0, implicit production - // (using the enqueue methods without an explicit producer token) is disabled. - static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = 32; - - // Controls the number of items that an explicit consumer (i.e. one with a token) - // must consume before it causes all consumers to rotate and move on to the next - // internal queue. - static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = 256; - - // The maximum number of elements (inclusive) that can be enqueued to a sub-queue. - // Enqueue operations that would cause this limit to be surpassed will fail. Note - // that this limit is enforced at the block level (for performance reasons), i.e. - // it's rounded up to the nearest block size. - static const size_t MAX_SUBQUEUE_SIZE = details::const_numeric_max::value; - -#ifndef MCDBGQ_USE_RELACY - // Memory allocation can be customized if needed. - // malloc should return nullptr on failure, and handle alignment like std::malloc. -#if defined(malloc) || defined(free) - // Gah, this is 2015, stop defining macros that break standard code already! - // Work around malloc/free being special macros: - static inline void* WORKAROUND_malloc(size_t size) { - return malloc(size); - } - static inline void WORKAROUND_free(void* ptr) { - return free(ptr); - } - static inline void*(malloc)(size_t size) { - return WORKAROUND_malloc(size); - } - static inline void(free)(void* ptr) { - return WORKAROUND_free(ptr); - } -#else - static inline void* malloc(size_t size) { - return std::malloc(size); - } - static inline void free(void* ptr) { - return std::free(ptr); - } -#endif -#else - // Debug versions when running under the Relacy race detector (ignore - // these in user code) - static inline void* malloc(size_t size) { - return rl::rl_malloc(size, $); - } - static inline void free(void* ptr) { - return rl::rl_free(ptr, $); - } -#endif -}; - -// When producing or consuming many elements, the most efficient way is to: -// 1) Use one of the bulk-operation methods of the queue with a token -// 2) Failing that, use the bulk-operation methods without a token -// 3) Failing that, create a token and use that with the single-item methods -// 4) Failing that, use the single-parameter methods of the queue -// Having said that, don't create tokens willy-nilly -- ideally there should be -// a maximum of one token per thread (of each kind). -struct ProducerToken; -struct ConsumerToken; - -template -class ConcurrentQueue; -template -class BlockingConcurrentQueue; -class ConcurrentQueueTests; - -namespace details { -struct ConcurrentQueueProducerTypelessBase { - ConcurrentQueueProducerTypelessBase* next; - std::atomic inactive; - ProducerToken* token; - - ConcurrentQueueProducerTypelessBase() : next(nullptr), inactive(false), token(nullptr) { - } -}; - -template -struct _hash_32_or_64 { - static inline std::uint32_t hash(std::uint32_t h) { - // MurmurHash3 finalizer -- see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp - // Since the thread ID is already unique, all we really want to do is propagate that - // uniqueness evenly across all the bits, so that we can use a subset of the bits while - // reducing collisions significantly - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - return h ^ (h >> 16); - } -}; -template <> -struct _hash_32_or_64<1> { - static inline std::uint64_t hash(std::uint64_t h) { - h ^= h >> 33; - h *= 0xff51afd7ed558ccd; - h ^= h >> 33; - h *= 0xc4ceb9fe1a85ec53; - return h ^ (h >> 33); - } -}; -template -struct hash_32_or_64 : public _hash_32_or_64<(size > 4)> {}; - -static inline size_t hash_thread_id(thread_id_t id) { - static_assert(sizeof(thread_id_t) <= 8, "Expected a platform where thread IDs are at most 64-bit values"); - return static_cast(hash_32_or_64::thread_id_hash_t)>::hash( - thread_id_converter::prehash(id))); -} - -template -static inline bool circular_less_than(T a, T b) { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4554) -#endif - static_assert(std::is_integral::value && !std::numeric_limits::is_signed, - "circular_less_than is intended to be used only with unsigned integer types"); - return static_cast(a - b) > static_cast(static_cast(1) << static_cast(sizeof(T) * CHAR_BIT - 1)); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -} - -template -static inline char* align_for(char* ptr) { - const std::size_t alignment = std::alignment_of::value; - return ptr + (alignment - (reinterpret_cast(ptr) % alignment)) % alignment; -} - -template -static inline T ceil_to_pow_2(T x) { - static_assert(std::is_integral::value && !std::numeric_limits::is_signed, - "ceil_to_pow_2 is intended to be used only with unsigned integer types"); - - // Adapted from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - --x; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - for (std::size_t i = 1; i < sizeof(T); i <<= 1) { - x |= x >> (i << 3); - } - ++x; - return x; -} - -template -static inline void swap_relaxed(std::atomic& left, std::atomic& right) { - T temp = std::move(left.load(std::memory_order_relaxed)); - left.store(std::move(right.load(std::memory_order_relaxed)), std::memory_order_relaxed); - right.store(std::move(temp), std::memory_order_relaxed); -} - -template -static inline T const& nomove(T const& x) { - return x; -} - -template -struct nomove_if { - template - static inline T const& eval(T const& x) { - return x; - } -}; - -template <> -struct nomove_if { - template - static inline auto eval(U&& x) -> decltype(std::forward(x)) { - return std::forward(x); - } -}; - -template -static inline auto deref_noexcept(It& it) MOODYCAMEL_NOEXCEPT -> decltype(*it) { - return *it; -} - -#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -template -struct is_trivially_destructible : std::is_trivially_destructible {}; -#else -template -struct is_trivially_destructible : std::has_trivial_destructor {}; -#endif - -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED -#ifdef MCDBGQ_USE_RELACY -typedef RelacyThreadExitListener ThreadExitListener; -typedef RelacyThreadExitNotifier ThreadExitNotifier; -#else -struct ThreadExitListener { - typedef void (*callback_t)(void*); - callback_t callback; - void* userData; - - ThreadExitListener* next; // reserved for use by the ThreadExitNotifier -}; - -class ThreadExitNotifier { - public: - static void subscribe(ThreadExitListener* listener) { - auto& tlsInst = instance(); - listener->next = tlsInst.tail; - tlsInst.tail = listener; - } - - static void unsubscribe(ThreadExitListener* listener) { - auto& tlsInst = instance(); - ThreadExitListener** prev = &tlsInst.tail; - for (auto ptr = tlsInst.tail; ptr != nullptr; ptr = ptr->next) { - if (ptr == listener) { - *prev = ptr->next; - break; - } - prev = &ptr->next; - } - } - - private: - ThreadExitNotifier() : tail(nullptr) { - } - ThreadExitNotifier(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION; - ThreadExitNotifier& operator=(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION; - - ~ThreadExitNotifier() { - // This thread is about to exit, let everyone know! - assert(this == &instance() && - "If this assert fails, you likely have a buggy compiler! Change the preprocessor conditions such that " - "MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is no longer defined."); - for (auto ptr = tail; ptr != nullptr; ptr = ptr->next) { - ptr->callback(ptr->userData); - } - } - - // Thread-local - static inline ThreadExitNotifier& instance() { - static thread_local ThreadExitNotifier notifier; - return notifier; - } - - private: - ThreadExitListener* tail; -}; -#endif -#endif - -template -struct static_is_lock_free_num { - enum { value = 0 }; -}; -template <> -struct static_is_lock_free_num { - enum { value = ATOMIC_CHAR_LOCK_FREE }; -}; -template <> -struct static_is_lock_free_num { - enum { value = ATOMIC_SHORT_LOCK_FREE }; -}; -template <> -struct static_is_lock_free_num { - enum { value = ATOMIC_INT_LOCK_FREE }; -}; -template <> -struct static_is_lock_free_num { - enum { value = ATOMIC_LONG_LOCK_FREE }; -}; -template <> -struct static_is_lock_free_num { - enum { value = ATOMIC_LLONG_LOCK_FREE }; -}; -template -struct static_is_lock_free : static_is_lock_free_num::type> {}; -template <> -struct static_is_lock_free { - enum { value = ATOMIC_BOOL_LOCK_FREE }; -}; -template -struct static_is_lock_free { - enum { value = ATOMIC_POINTER_LOCK_FREE }; -}; -} // namespace details - -struct ProducerToken { - template - explicit ProducerToken(ConcurrentQueue& queue); - - template - explicit ProducerToken(BlockingConcurrentQueue& queue); - - ProducerToken(ProducerToken&& other) MOODYCAMEL_NOEXCEPT : producer(other.producer) { - other.producer = nullptr; - if (producer != nullptr) { - producer->token = this; - } - } - - inline ProducerToken& operator=(ProducerToken&& other) MOODYCAMEL_NOEXCEPT { - swap(other); - return *this; - } - - void swap(ProducerToken& other) MOODYCAMEL_NOEXCEPT { - std::swap(producer, other.producer); - if (producer != nullptr) { - producer->token = this; - } - if (other.producer != nullptr) { - other.producer->token = &other; - } - } - - // A token is always valid unless: - // 1) Memory allocation failed during construction - // 2) It was moved via the move constructor - // (Note: assignment does a swap, leaving both potentially valid) - // 3) The associated queue was destroyed - // Note that if valid() returns true, that only indicates - // that the token is valid for use with a specific queue, - // but not which one; that's up to the user to track. - inline bool valid() const { - return producer != nullptr; - } - - ~ProducerToken() { - if (producer != nullptr) { - producer->token = nullptr; - producer->inactive.store(true, std::memory_order_release); - } - } - - // Disable copying and assignment - ProducerToken(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION; - ProducerToken& operator=(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION; - - private: - template - friend class ConcurrentQueue; - friend class ConcurrentQueueTests; - - protected: - details::ConcurrentQueueProducerTypelessBase* producer; -}; - -struct ConsumerToken { - template - explicit ConsumerToken(ConcurrentQueue& q); - - template - explicit ConsumerToken(BlockingConcurrentQueue& q); - - ConsumerToken(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT : initialOffset(other.initialOffset), - lastKnownGlobalOffset(other.lastKnownGlobalOffset), - itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), - currentProducer(other.currentProducer), - desiredProducer(other.desiredProducer) { - } - - inline ConsumerToken& operator=(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT { - swap(other); - return *this; - } - - void swap(ConsumerToken& other) MOODYCAMEL_NOEXCEPT { - std::swap(initialOffset, other.initialOffset); - std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset); - std::swap(itemsConsumedFromCurrent, other.itemsConsumedFromCurrent); - std::swap(currentProducer, other.currentProducer); - std::swap(desiredProducer, other.desiredProducer); - } - - // Disable copying and assignment - ConsumerToken(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION; - ConsumerToken& operator=(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION; - - private: - template - friend class ConcurrentQueue; - friend class ConcurrentQueueTests; - - private: // but shared with ConcurrentQueue - std::uint32_t initialOffset; - std::uint32_t lastKnownGlobalOffset; - std::uint32_t itemsConsumedFromCurrent; - details::ConcurrentQueueProducerTypelessBase* currentProducer; - details::ConcurrentQueueProducerTypelessBase* desiredProducer; -}; - -// Need to forward-declare this swap because it's in a namespace. -// See http://stackoverflow.com/questions/4492062/why-does-a-c-friend-class-need-a-forward-declaration-only-in-other-namespaces -template -inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, - typename ConcurrentQueue::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT; - -template -class ConcurrentQueue { - public: - typedef ::moodycamel::ProducerToken producer_token_t; - typedef ::moodycamel::ConsumerToken consumer_token_t; - - typedef typename Traits::index_t index_t; - typedef typename Traits::size_t size_t; - - static const size_t BLOCK_SIZE = static_cast(Traits::BLOCK_SIZE); - static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = - static_cast(Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD); - static const size_t EXPLICIT_INITIAL_INDEX_SIZE = static_cast(Traits::EXPLICIT_INITIAL_INDEX_SIZE); - static const size_t IMPLICIT_INITIAL_INDEX_SIZE = static_cast(Traits::IMPLICIT_INITIAL_INDEX_SIZE); - static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = - static_cast(Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE); - static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = - static_cast(Traits::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE); -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4307) // + integral constant overflow (that's what the ternary expression is for!) -#pragma warning(disable : 4309) // static_cast: Truncation of constant value -#endif - static const size_t MAX_SUBQUEUE_SIZE = - (details::const_numeric_max::value - static_cast(Traits::MAX_SUBQUEUE_SIZE) < BLOCK_SIZE) - ? details::const_numeric_max::value - : ((static_cast(Traits::MAX_SUBQUEUE_SIZE) + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - static_assert(!std::numeric_limits::is_signed && std::is_integral::value, - "Traits::size_t must be an unsigned integral type"); - static_assert(!std::numeric_limits::is_signed && std::is_integral::value, - "Traits::index_t must be an unsigned integral type"); - static_assert(sizeof(index_t) >= sizeof(size_t), "Traits::index_t must be at least as wide as Traits::size_t"); - static_assert((BLOCK_SIZE > 1) && !(BLOCK_SIZE & (BLOCK_SIZE - 1)), - "Traits::BLOCK_SIZE must be a power of 2 (and at least 2)"); - static_assert((EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD > 1) && - !(EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD & (EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD - 1)), - "Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD must be a power of 2 (and greater than 1)"); - static_assert((EXPLICIT_INITIAL_INDEX_SIZE > 1) && !(EXPLICIT_INITIAL_INDEX_SIZE & (EXPLICIT_INITIAL_INDEX_SIZE - 1)), - "Traits::EXPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)"); - static_assert((IMPLICIT_INITIAL_INDEX_SIZE > 1) && !(IMPLICIT_INITIAL_INDEX_SIZE & (IMPLICIT_INITIAL_INDEX_SIZE - 1)), - "Traits::IMPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)"); - static_assert((INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) || - !(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE & (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - 1)), - "Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be a power of 2"); - static_assert(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0 || INITIAL_IMPLICIT_PRODUCER_HASH_SIZE >= 1, - "Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be at least 1 (or 0 to disable implicit enqueueing)"); - - public: - // Creates a queue with at least `capacity` element slots; note that the - // actual number of elements that can be inserted without additional memory - // allocation depends on the number of producers and the block size (e.g. if - // the block size is equal to `capacity`, only a single block will be allocated - // up-front, which means only a single producer will be able to enqueue elements - // without an extra allocation -- blocks aren't shared between producers). - // This method is not thread safe -- it is up to the user to ensure that the - // queue is fully constructed before it starts being used by other threads (this - // includes making the memory effects of construction visible, possibly with a - // memory barrier). - explicit ConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE) - : producerListTail(nullptr) - , producerCount(0) - , initialBlockPoolIndex(0) - , nextExplicitConsumerId(0) - , globalExplicitConsumerOffset(0) { - implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); - populate_initial_implicit_producer_hash(); - populate_initial_block_list(capacity / BLOCK_SIZE + ((capacity & (BLOCK_SIZE - 1)) == 0 ? 0 : 1)); - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - // Track all the producers using a fully-resolved typed list for - // each kind; this makes it possible to debug them starting from - // the root queue object (otherwise wacky casts are needed that - // don't compile in the debugger's expression evaluator). - explicitProducers.store(nullptr, std::memory_order_relaxed); - implicitProducers.store(nullptr, std::memory_order_relaxed); -#endif - } - - // Computes the correct amount of pre-allocated blocks for you based - // on the minimum number of elements you want available at any given - // time, and the maximum concurrent number of each type of producer. - ConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers) - : producerListTail(nullptr) - , producerCount(0) - , initialBlockPoolIndex(0) - , nextExplicitConsumerId(0) - , globalExplicitConsumerOffset(0) { - implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); - populate_initial_implicit_producer_hash(); - size_t blocks = (((minCapacity + BLOCK_SIZE - 1) / BLOCK_SIZE) - 1) * (maxExplicitProducers + 1) + - 2 * (maxExplicitProducers + maxImplicitProducers); - populate_initial_block_list(blocks); - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - explicitProducers.store(nullptr, std::memory_order_relaxed); - implicitProducers.store(nullptr, std::memory_order_relaxed); -#endif - } - - // Note: The queue should not be accessed concurrently while it's - // being deleted. It's up to the user to synchronize this. - // This method is not thread safe. - ~ConcurrentQueue() { - // Destroy producers - auto ptr = producerListTail.load(std::memory_order_relaxed); - while (ptr != nullptr) { - auto next = ptr->next_prod(); - if (ptr->token != nullptr) { - ptr->token->producer = nullptr; - } - destroy(ptr); - ptr = next; - } - - // Destroy implicit producer hash tables - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE != 0) { - auto hash = implicitProducerHash.load(std::memory_order_relaxed); - while (hash != nullptr) { - auto prev = hash->prev; - if (prev != nullptr) { // The last hash is part of this object and was not allocated dynamically - for (size_t i = 0; i != hash->capacity; ++i) { - hash->entries[i].~ImplicitProducerKVP(); - } - hash->~ImplicitProducerHash(); - (Traits::free)(hash); - } - hash = prev; - } - } - - // Destroy global free list - auto block = freeList.head_unsafe(); - while (block != nullptr) { - auto next = block->freeListNext.load(std::memory_order_relaxed); - if (block->dynamicallyAllocated) { - destroy(block); - } - block = next; - } - - // Destroy initial free list - destroy_array(initialBlockPool, initialBlockPoolSize); - } - - // Disable copying and copy assignment - ConcurrentQueue(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION; - ConcurrentQueue& operator=(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION; - - // Moving is supported, but note that it is *not* a thread-safe operation. - // Nobody can use the queue while it's being moved, and the memory effects - // of that move must be propagated to other threads before they can use it. - // Note: When a queue is moved, its tokens are still valid but can only be - // used with the destination queue (i.e. semantically they are moved along - // with the queue itself). - ConcurrentQueue(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT - : producerListTail(other.producerListTail.load(std::memory_order_relaxed)), - producerCount(other.producerCount.load(std::memory_order_relaxed)), - initialBlockPoolIndex(other.initialBlockPoolIndex.load(std::memory_order_relaxed)), - initialBlockPool(other.initialBlockPool), - initialBlockPoolSize(other.initialBlockPoolSize), - freeList(std::move(other.freeList)), - nextExplicitConsumerId(other.nextExplicitConsumerId.load(std::memory_order_relaxed)), - globalExplicitConsumerOffset(other.globalExplicitConsumerOffset.load(std::memory_order_relaxed)) { - // Move the other one into this, and leave the other one as an empty queue - implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); - populate_initial_implicit_producer_hash(); - swap_implicit_producer_hashes(other); - - other.producerListTail.store(nullptr, std::memory_order_relaxed); - other.producerCount.store(0, std::memory_order_relaxed); - other.nextExplicitConsumerId.store(0, std::memory_order_relaxed); - other.globalExplicitConsumerOffset.store(0, std::memory_order_relaxed); - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - explicitProducers.store(other.explicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed); - other.explicitProducers.store(nullptr, std::memory_order_relaxed); - implicitProducers.store(other.implicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed); - other.implicitProducers.store(nullptr, std::memory_order_relaxed); -#endif - - other.initialBlockPoolIndex.store(0, std::memory_order_relaxed); - other.initialBlockPoolSize = 0; - other.initialBlockPool = nullptr; - - reown_producers(); - } - - inline ConcurrentQueue& operator=(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT { - return swap_internal(other); - } - - // Swaps this queue's state with the other's. Not thread-safe. - // Swapping two queues does not invalidate their tokens, however - // the tokens that were created for one queue must be used with - // only the swapped queue (i.e. the tokens are tied to the - // queue's movable state, not the object itself). - inline void swap(ConcurrentQueue& other) MOODYCAMEL_NOEXCEPT { - swap_internal(other); - } - - private: - ConcurrentQueue& swap_internal(ConcurrentQueue& other) { - if (this == &other) { - return *this; - } - - details::swap_relaxed(producerListTail, other.producerListTail); - details::swap_relaxed(producerCount, other.producerCount); - details::swap_relaxed(initialBlockPoolIndex, other.initialBlockPoolIndex); - std::swap(initialBlockPool, other.initialBlockPool); - std::swap(initialBlockPoolSize, other.initialBlockPoolSize); - freeList.swap(other.freeList); - details::swap_relaxed(nextExplicitConsumerId, other.nextExplicitConsumerId); - details::swap_relaxed(globalExplicitConsumerOffset, other.globalExplicitConsumerOffset); - - swap_implicit_producer_hashes(other); - - reown_producers(); - other.reown_producers(); - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - details::swap_relaxed(explicitProducers, other.explicitProducers); - details::swap_relaxed(implicitProducers, other.implicitProducers); -#endif - - return *this; - } - - public: - // Enqueues a single item (by copying it). - // Allocates memory if required. Only fails if memory allocation fails (or implicit - // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0, - // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Thread-safe. - inline bool enqueue(T const& item) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue(item); - } - - // Enqueues a single item (by moving it, if possible). - // Allocates memory if required. Only fails if memory allocation fails (or implicit - // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0, - // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Thread-safe. - inline bool enqueue(T&& item) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue(std::move(item)); - } - - // Enqueues a single item (by copying it) using an explicit producer token. - // Allocates memory if required. Only fails if memory allocation fails (or - // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Thread-safe. - inline bool enqueue(producer_token_t const& token, T const& item) { - return inner_enqueue(token, item); - } - - // Enqueues a single item (by moving it, if possible) using an explicit producer token. - // Allocates memory if required. Only fails if memory allocation fails (or - // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Thread-safe. - inline bool enqueue(producer_token_t const& token, T&& item) { - return inner_enqueue(token, std::move(item)); - } - - // Enqueues several items. - // Allocates memory if required. Only fails if memory allocation fails (or - // implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - // is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Note: Use std::make_move_iterator if the elements should be moved instead of copied. - // Thread-safe. - template - bool enqueue_bulk(It itemFirst, size_t count) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue_bulk(itemFirst, count); - } - - // Enqueues several items using an explicit producer token. - // Allocates memory if required. Only fails if memory allocation fails - // (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). - // Note: Use std::make_move_iterator if the elements should be moved - // instead of copied. - // Thread-safe. - template - bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) { - return inner_enqueue_bulk(token, itemFirst, count); - } - - // Enqueues a single item (by copying it). - // Does not allocate memory. Fails if not enough room to enqueue (or implicit - // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - // is 0). - // Thread-safe. - inline bool try_enqueue(T const& item) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue(item); - } - - // Enqueues a single item (by moving it, if possible). - // Does not allocate memory (except for one-time implicit producer). - // Fails if not enough room to enqueue (or implicit production is - // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0). - // Thread-safe. - inline bool try_enqueue(T&& item) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue(std::move(item)); - } - - // Enqueues a single item (by copying it) using an explicit producer token. - // Does not allocate memory. Fails if not enough room to enqueue. - // Thread-safe. - inline bool try_enqueue(producer_token_t const& token, T const& item) { - return inner_enqueue(token, item); - } - - // Enqueues a single item (by moving it, if possible) using an explicit producer token. - // Does not allocate memory. Fails if not enough room to enqueue. - // Thread-safe. - inline bool try_enqueue(producer_token_t const& token, T&& item) { - return inner_enqueue(token, std::move(item)); - } - - // Enqueues several items. - // Does not allocate memory (except for one-time implicit producer). - // Fails if not enough room to enqueue (or implicit production is - // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0). - // Note: Use std::make_move_iterator if the elements should be moved - // instead of copied. - // Thread-safe. - template - bool try_enqueue_bulk(It itemFirst, size_t count) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return false; - return inner_enqueue_bulk(itemFirst, count); - } - - // Enqueues several items using an explicit producer token. - // Does not allocate memory. Fails if not enough room to enqueue. - // Note: Use std::make_move_iterator if the elements should be moved - // instead of copied. - // Thread-safe. - template - bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) { - return inner_enqueue_bulk(token, itemFirst, count); - } - - // Attempts to dequeue from the queue. - // Returns false if all producer streams appeared empty at the time they - // were checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - bool try_dequeue(U& item) { - // Instead of simply trying each producer in turn (which could cause needless contention on the first - // producer), we score them heuristically. - size_t nonEmptyCount = 0; - ProducerBase* best = nullptr; - size_t bestSize = 0; - for (auto ptr = producerListTail.load(std::memory_order_acquire); nonEmptyCount < 3 && ptr != nullptr; - ptr = ptr->next_prod()) { - auto size = ptr->size_approx(); - if (size > 0) { - if (size > bestSize) { - bestSize = size; - best = ptr; - } - ++nonEmptyCount; - } - } - - // If there was at least one non-empty queue but it appears empty at the time - // we try to dequeue from it, we need to make sure every queue's been tried - if (nonEmptyCount > 0) { - if ((details::likely)(best->dequeue(item))) { - return true; - } - for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - if (ptr != best && ptr->dequeue(item)) { - return true; - } - } - } - return false; - } - - // Attempts to dequeue from the queue. - // Returns false if all producer streams appeared empty at the time they - // were checked (so, the queue is likely but not guaranteed to be empty). - // This differs from the try_dequeue(item) method in that this one does - // not attempt to reduce contention by interleaving the order that producer - // streams are dequeued from. So, using this method can reduce overall throughput - // under contention, but will give more predictable results in single-threaded - // consumer scenarios. This is mostly only useful for internal unit tests. - // Never allocates. Thread-safe. - template - bool try_dequeue_non_interleaved(U& item) { - for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - if (ptr->dequeue(item)) { - return true; - } - } - return false; - } - - // Attempts to dequeue from the queue using an explicit consumer token. - // Returns false if all producer streams appeared empty at the time they - // were checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - bool try_dequeue(consumer_token_t& token, U& item) { - // The idea is roughly as follows: - // Every 256 items from one producer, make everyone rotate (increase the global offset) -> this means the highest efficiency consumer dictates the rotation speed of everyone else, more or less - // If you see that the global offset has changed, you must reset your consumption counter and move to your designated place - // If there's no items where you're supposed to be, keep moving until you find a producer with some items - // If the global offset has not changed but you've run out of items to consume, move over from your current position until you find an producer with something in it - - if (token.desiredProducer == nullptr || - token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) { - if (!update_current_producer_after_rotation(token)) { - return false; - } - } - - // If there was at least one non-empty queue but it appears empty at the time - // we try to dequeue from it, we need to make sure every queue's been tried - if (static_cast(token.currentProducer)->dequeue(item)) { - if (++token.itemsConsumedFromCurrent == EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) { - globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed); - } - return true; - } - - auto tail = producerListTail.load(std::memory_order_acquire); - auto ptr = static_cast(token.currentProducer)->next_prod(); - if (ptr == nullptr) { - ptr = tail; - } - while (ptr != static_cast(token.currentProducer)) { - if (ptr->dequeue(item)) { - token.currentProducer = ptr; - token.itemsConsumedFromCurrent = 1; - return true; - } - ptr = ptr->next_prod(); - if (ptr == nullptr) { - ptr = tail; - } - } - return false; - } - - // Attempts to dequeue several elements from the queue. - // Returns the number of items actually dequeued. - // Returns 0 if all producer streams appeared empty at the time they - // were checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - size_t try_dequeue_bulk(It itemFirst, size_t max) { - size_t count = 0; - for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - count += ptr->dequeue_bulk(itemFirst, max - count); - if (count == max) { - break; - } - } - return count; - } - - // Attempts to dequeue several elements from the queue using an explicit consumer token. - // Returns the number of items actually dequeued. - // Returns 0 if all producer streams appeared empty at the time they - // were checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max) { - if (token.desiredProducer == nullptr || - token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) { - if (!update_current_producer_after_rotation(token)) { - return 0; - } - } - - size_t count = static_cast(token.currentProducer)->dequeue_bulk(itemFirst, max); - if (count == max) { - if ((token.itemsConsumedFromCurrent += static_cast(max)) >= - EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) { - globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed); - } - return max; - } - token.itemsConsumedFromCurrent += static_cast(count); - max -= count; - - auto tail = producerListTail.load(std::memory_order_acquire); - auto ptr = static_cast(token.currentProducer)->next_prod(); - if (ptr == nullptr) { - ptr = tail; - } - while (ptr != static_cast(token.currentProducer)) { - auto dequeued = ptr->dequeue_bulk(itemFirst, max); - count += dequeued; - if (dequeued != 0) { - token.currentProducer = ptr; - token.itemsConsumedFromCurrent = static_cast(dequeued); - } - if (dequeued == max) { - break; - } - max -= dequeued; - ptr = ptr->next_prod(); - if (ptr == nullptr) { - ptr = tail; - } - } - return count; - } - - // Attempts to dequeue from a specific producer's inner queue. - // If you happen to know which producer you want to dequeue from, this - // is significantly faster than using the general-case try_dequeue methods. - // Returns false if the producer's queue appeared empty at the time it - // was checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - inline bool try_dequeue_from_producer(producer_token_t const& producer, U& item) { - return static_cast(producer.producer)->dequeue(item); - } - - // Attempts to dequeue several elements from a specific producer's inner queue. - // Returns the number of items actually dequeued. - // If you happen to know which producer you want to dequeue from, this - // is significantly faster than using the general-case try_dequeue methods. - // Returns 0 if the producer's queue appeared empty at the time it - // was checked (so, the queue is likely but not guaranteed to be empty). - // Never allocates. Thread-safe. - template - inline size_t try_dequeue_bulk_from_producer(producer_token_t const& producer, It itemFirst, size_t max) { - return static_cast(producer.producer)->dequeue_bulk(itemFirst, max); - } - - // Returns an estimate of the total number of elements currently in the queue. This - // estimate is only accurate if the queue has completely stabilized before it is called - // (i.e. all enqueue and dequeue operations have completed and their memory effects are - // visible on the calling thread, and no further operations start while this method is - // being called). - // Thread-safe. - size_t size_approx() const { - size_t size = 0; - for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - size += ptr->size_approx(); - } - return size; - } - - // Returns true if the underlying atomic variables used by - // the queue are lock-free (they should be on most platforms). - // Thread-safe. - static bool is_lock_free() { - return details::static_is_lock_free::value == 2 && details::static_is_lock_free::value == 2 && - details::static_is_lock_free::value == 2 && - details::static_is_lock_free::value == 2 && details::static_is_lock_free::value == 2 && - details::static_is_lock_free< - typename details::thread_id_converter::thread_id_numeric_size_t>::value == 2; - } - - private: - friend struct ProducerToken; - friend struct ConsumerToken; - struct ExplicitProducer; - friend struct ExplicitProducer; - struct ImplicitProducer; - friend struct ImplicitProducer; - friend class ConcurrentQueueTests; - - enum AllocationMode { CanAlloc, CannotAlloc }; - - /////////////////////////////// - // Queue methods - /////////////////////////////// - - template - inline bool inner_enqueue(producer_token_t const& token, U&& element) { - return static_cast(token.producer) - ->ConcurrentQueue::ExplicitProducer::template enqueue(std::forward(element)); - } - - template - inline bool inner_enqueue(U&& element) { - auto producer = get_or_add_implicit_producer(); - return producer == nullptr - ? false - : producer->ConcurrentQueue::ImplicitProducer::template enqueue(std::forward(element)); - } - - template - inline bool inner_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) { - return static_cast(token.producer) - ->ConcurrentQueue::ExplicitProducer::template enqueue_bulk(itemFirst, count); - } - - template - inline bool inner_enqueue_bulk(It itemFirst, size_t count) { - auto producer = get_or_add_implicit_producer(); - return producer == nullptr - ? false - : producer->ConcurrentQueue::ImplicitProducer::template enqueue_bulk(itemFirst, count); - } - - inline bool update_current_producer_after_rotation(consumer_token_t& token) { - // Ah, there's been a rotation, figure out where we should be! - auto tail = producerListTail.load(std::memory_order_acquire); - if (token.desiredProducer == nullptr && tail == nullptr) { - return false; - } - auto prodCount = producerCount.load(std::memory_order_relaxed); - auto globalOffset = globalExplicitConsumerOffset.load(std::memory_order_relaxed); - if ((details::unlikely)(token.desiredProducer == nullptr)) { - // Aha, first time we're dequeueing anything. - // Figure out our local position - // Note: offset is from start, not end, but we're traversing from end -- subtract from count first - std::uint32_t offset = prodCount - 1 - (token.initialOffset % prodCount); - token.desiredProducer = tail; - for (std::uint32_t i = 0; i != offset; ++i) { - token.desiredProducer = static_cast(token.desiredProducer)->next_prod(); - if (token.desiredProducer == nullptr) { - token.desiredProducer = tail; - } - } - } - - std::uint32_t delta = globalOffset - token.lastKnownGlobalOffset; - if (delta >= prodCount) { - delta = delta % prodCount; - } - for (std::uint32_t i = 0; i != delta; ++i) { - token.desiredProducer = static_cast(token.desiredProducer)->next_prod(); - if (token.desiredProducer == nullptr) { - token.desiredProducer = tail; - } - } - - token.lastKnownGlobalOffset = globalOffset; - token.currentProducer = token.desiredProducer; - token.itemsConsumedFromCurrent = 0; - return true; - } - - /////////////////////////// - // Free list - /////////////////////////// - - template - struct FreeListNode { - FreeListNode() : freeListRefs(0), freeListNext(nullptr) { - } - - std::atomic freeListRefs; - std::atomic freeListNext; - }; - - // A simple CAS-based lock-free free list. Not the fastest thing in the world under heavy contention, but - // simple and correct (assuming nodes are never freed until after the free list is destroyed), and fairly - // speedy under low contention. - template // N must inherit FreeListNode or have the same fields (and initialization of them) - struct FreeList { - FreeList() : freeListHead(nullptr) { - } - FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { - other.freeListHead.store(nullptr, std::memory_order_relaxed); - } - void swap(FreeList& other) { - details::swap_relaxed(freeListHead, other.freeListHead); - } - - FreeList(FreeList const&) MOODYCAMEL_DELETE_FUNCTION; - FreeList& operator=(FreeList const&) MOODYCAMEL_DELETE_FUNCTION; - - inline void add(N* node) { -#ifdef MCDBGQ_NOLOCKFREE_FREELIST - debug::DebugLock lock(mutex); -#endif - // We know that the should-be-on-freelist bit is 0 at this point, so it's safe to - // set it using a fetch_add - if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST, std::memory_order_acq_rel) == 0) { - // Oh look! We were the last ones referencing this node, and we know - // we want to add it to the free list, so let's do it! - add_knowing_refcount_is_zero(node); - } - } - - inline N* try_get() { -#ifdef MCDBGQ_NOLOCKFREE_FREELIST - debug::DebugLock lock(mutex); -#endif - auto head = freeListHead.load(std::memory_order_acquire); - while (head != nullptr) { - auto prevHead = head; - auto refs = head->freeListRefs.load(std::memory_order_relaxed); - if ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong( - refs, refs + 1, std::memory_order_acquire, std::memory_order_relaxed)) { - head = freeListHead.load(std::memory_order_acquire); - continue; - } - - // Good, reference count has been incremented (it wasn't at zero), which means we can read the - // next and not worry about it changing between now and the time we do the CAS - auto next = head->freeListNext.load(std::memory_order_relaxed); - if (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) { - // Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no - // matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on). - assert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0); - - // Decrease refcount twice, once for our ref, and once for the list's ref - head->freeListRefs.fetch_sub(2, std::memory_order_release); - return head; - } - - // OK, the head must have changed on us, but we still need to decrease the refcount we increased. - // Note that we don't need to release any memory effects, but we do need to ensure that the reference - // count decrement happens-after the CAS on the head. - refs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel); - if (refs == SHOULD_BE_ON_FREELIST + 1) { - add_knowing_refcount_is_zero(prevHead); - } - } - - return nullptr; - } - - // Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes) - N* head_unsafe() const { - return freeListHead.load(std::memory_order_relaxed); - } - - private: - inline void add_knowing_refcount_is_zero(N* node) { - // Since the refcount is zero, and nobody can increase it once it's zero (except us, and we run - // only one copy of this method per node at a time, i.e. the single thread case), then we know - // we can safely change the next pointer of the node; however, once the refcount is back above - // zero, then other threads could increase it (happens under heavy contention, when the refcount - // goes to zero in between a load and a refcount increment of a node in try_get, then back up to - // something non-zero, then the refcount increment is done by the other thread) -- so, if the CAS - // to add the node to the actual list fails, decrease the refcount and leave the add operation to - // the next thread who puts the refcount back at zero (which could be us, hence the loop). - auto head = freeListHead.load(std::memory_order_relaxed); - while (true) { - node->freeListNext.store(head, std::memory_order_relaxed); - node->freeListRefs.store(1, std::memory_order_release); - if (!freeListHead.compare_exchange_strong(head, node, std::memory_order_release, std::memory_order_relaxed)) { - // Hmm, the add failed, but we can only try again when the refcount goes back to zero - if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST - 1, std::memory_order_release) == 1) { - continue; - } - } - return; - } - } - - private: - // Implemented like a stack, but where node order doesn't matter (nodes are inserted out of order under contention) - std::atomic freeListHead; - - static const std::uint32_t REFS_MASK = 0x7FFFFFFF; - static const std::uint32_t SHOULD_BE_ON_FREELIST = 0x80000000; - -#ifdef MCDBGQ_NOLOCKFREE_FREELIST - debug::DebugMutex mutex; -#endif - }; - - /////////////////////////// - // Block - /////////////////////////// - - enum InnerQueueContext { implicit_context = 0, explicit_context = 1 }; - - struct Block { - Block() - : next(nullptr) - , elementsCompletelyDequeued(0) - , freeListRefs(0) - , freeListNext(nullptr) - , shouldBeOnFreeList(false) - , dynamicallyAllocated(true) { -#ifdef MCDBGQ_TRACKMEM - owner = nullptr; -#endif - } - - template - inline bool is_empty() const { - if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { - // Check flags - for (size_t i = 0; i < BLOCK_SIZE; ++i) { - if (!emptyFlags[i].load(std::memory_order_relaxed)) { - return false; - } - } - - // Aha, empty; make sure we have all other memory effects that happened before the empty flags were set - std::atomic_thread_fence(std::memory_order_acquire); - return true; - } else { - // Check counter - if (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) { - std::atomic_thread_fence(std::memory_order_acquire); - return true; - } - assert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE); - return false; - } - } - - // Returns true if the block is now empty (does not apply in explicit context) - template - inline bool set_empty(index_t i) { - if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { - // Set flag - assert(!emptyFlags[BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1))].load( - std::memory_order_relaxed)); - emptyFlags[BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1))].store( - true, std::memory_order_release); - return false; - } else { - // Increment counter - auto prevVal = elementsCompletelyDequeued.fetch_add(1, std::memory_order_release); - assert(prevVal < BLOCK_SIZE); - return prevVal == BLOCK_SIZE - 1; - } - } - - // Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0). - // Returns true if the block is now empty (does not apply in explicit context). - template - inline bool set_many_empty(index_t i, size_t count) { - if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { - // Set flags - std::atomic_thread_fence(std::memory_order_release); - i = BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1)) - count + 1; - for (size_t j = 0; j != count; ++j) { - assert(!emptyFlags[i + j].load(std::memory_order_relaxed)); - emptyFlags[i + j].store(true, std::memory_order_relaxed); - } - return false; - } else { - // Increment counter - auto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release); - assert(prevVal + count <= BLOCK_SIZE); - return prevVal + count == BLOCK_SIZE; - } - } - - template - inline void set_all_empty() { - if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { - // Set all flags - for (size_t i = 0; i != BLOCK_SIZE; ++i) { - emptyFlags[i].store(true, std::memory_order_relaxed); - } - } else { - // Reset counter - elementsCompletelyDequeued.store(BLOCK_SIZE, std::memory_order_relaxed); - } - } - - template - inline void reset_empty() { - if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { - // Reset flags - for (size_t i = 0; i != BLOCK_SIZE; ++i) { - emptyFlags[i].store(false, std::memory_order_relaxed); - } - } else { - // Reset counter - elementsCompletelyDequeued.store(0, std::memory_order_relaxed); - } - } - - inline T* operator[](index_t idx) MOODYCAMEL_NOEXCEPT { - return static_cast(static_cast(elements)) + - static_cast(idx & static_cast(BLOCK_SIZE - 1)); - } - inline T const* operator[](index_t idx) const MOODYCAMEL_NOEXCEPT { - return static_cast(static_cast(elements)) + - static_cast(idx & static_cast(BLOCK_SIZE - 1)); - } - - private: - // IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of - // addresses returned by malloc, that alignment will be preserved. Apparently clang actually - // generates code that uses this assumption for AVX instructions in some cases. Ideally, we - // should also align Block to the alignment of T in case it's higher than malloc's 16-byte - // alignment, but this is hard to do in a cross-platform way. Assert for this case: - static_assert(std::alignment_of::value <= std::alignment_of::value, - "The queue does not support super-aligned types at this time"); - // Additionally, we need the alignment of Block itself to be a multiple of max_align_t since - // otherwise the appropriate padding will not be added at the end of Block in order to make - // arrays of Blocks all be properly aligned (not just the first one). We use a union to force - // this. - union { - char elements[sizeof(T) * BLOCK_SIZE]; - details::max_align_t dummy; - }; - - public: - Block* next; - std::atomic elementsCompletelyDequeued; - std::atomic emptyFlags[BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD ? BLOCK_SIZE : 1]; - - public: - std::atomic freeListRefs; - std::atomic freeListNext; - std::atomic shouldBeOnFreeList; - bool dynamicallyAllocated; // Perhaps a better name for this would be 'isNotPartOfInitialBlockPool' - -#ifdef MCDBGQ_TRACKMEM - void* owner; -#endif - }; - static_assert(std::alignment_of::value >= std::alignment_of::value, - "Internal error: Blocks must be at least as aligned as the type they are wrapping"); - -#ifdef MCDBGQ_TRACKMEM - public: - struct MemStats; - - private: -#endif - - /////////////////////////// - // Producer base - /////////////////////////// - - struct ProducerBase : public details::ConcurrentQueueProducerTypelessBase { - ProducerBase(ConcurrentQueue* parent_, bool isExplicit_) - : tailIndex(0) - , headIndex(0) - , dequeueOptimisticCount(0) - , dequeueOvercommit(0) - , tailBlock(nullptr) - , isExplicit(isExplicit_) - , parent(parent_) { - } - - virtual ~ProducerBase(){}; - - template - inline bool dequeue(U& element) { - if (isExplicit) { - return static_cast(this)->dequeue(element); - } else { - return static_cast(this)->dequeue(element); - } - } - - template - inline size_t dequeue_bulk(It& itemFirst, size_t max) { - if (isExplicit) { - return static_cast(this)->dequeue_bulk(itemFirst, max); - } else { - return static_cast(this)->dequeue_bulk(itemFirst, max); - } - } - - inline ProducerBase* next_prod() const { - return static_cast(next); - } - - inline size_t size_approx() const { - auto tail = tailIndex.load(std::memory_order_relaxed); - auto head = headIndex.load(std::memory_order_relaxed); - return details::circular_less_than(head, tail) ? static_cast(tail - head) : 0; - } - - inline index_t getTail() const { - return tailIndex.load(std::memory_order_relaxed); - } - - protected: - std::atomic tailIndex; // Where to enqueue to next - std::atomic headIndex; // Where to dequeue from next - - std::atomic dequeueOptimisticCount; - std::atomic dequeueOvercommit; - - Block* tailBlock; - - public: - bool isExplicit; - ConcurrentQueue* parent; - - protected: -#ifdef MCDBGQ_TRACKMEM - friend struct MemStats; -#endif - }; - - /////////////////////////// - // Explicit queue - /////////////////////////// - - struct ExplicitProducer : public ProducerBase { - explicit ExplicitProducer(ConcurrentQueue* parent) - : ProducerBase(parent, true) - , blockIndex(nullptr) - , pr_blockIndexSlotsUsed(0) - , pr_blockIndexSize(EXPLICIT_INITIAL_INDEX_SIZE >> 1) - , pr_blockIndexFront(0) - , pr_blockIndexEntries(nullptr) - , pr_blockIndexRaw(nullptr) { - size_t poolBasedIndexSize = details::ceil_to_pow_2(parent->initialBlockPoolSize) >> 1; - if (poolBasedIndexSize > pr_blockIndexSize) { - pr_blockIndexSize = poolBasedIndexSize; - } - - new_block_index( - 0); // This creates an index with double the number of current entries, i.e. EXPLICIT_INITIAL_INDEX_SIZE - } - - ~ExplicitProducer() { - // Destruct any elements not yet dequeued. - // Since we're in the destructor, we can assume all elements - // are either completely dequeued or completely not (no halfways). - if (this->tailBlock != nullptr) { // Note this means there must be a block index too - // First find the block that's partially dequeued, if any - Block* halfDequeuedBlock = nullptr; - if ((this->headIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)) != 0) { - // The head's not on a block boundary, meaning a block somewhere is partially dequeued - // (or the head block is the tail block and was fully dequeued, but the head/tail are still not on a boundary) - size_t i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & (pr_blockIndexSize - 1); - while (details::circular_less_than(pr_blockIndexEntries[i].base + BLOCK_SIZE, - this->headIndex.load(std::memory_order_relaxed))) { - i = (i + 1) & (pr_blockIndexSize - 1); - } - assert(details::circular_less_than(pr_blockIndexEntries[i].base, - this->headIndex.load(std::memory_order_relaxed))); - halfDequeuedBlock = pr_blockIndexEntries[i].block; - } - - // Start at the head block (note the first line in the loop gives us the head from the tail on the first iteration) - auto block = this->tailBlock; - do { - block = block->next; - if (block->ConcurrentQueue::Block::template is_empty()) { - continue; - } - - size_t i = 0; // Offset into block - if (block == halfDequeuedBlock) { - i = static_cast(this->headIndex.load(std::memory_order_relaxed) & - static_cast(BLOCK_SIZE - 1)); - } - - // Walk through all the items in the block; if this is the tail block, we need to stop when we reach the tail index - auto lastValidIndex = - (this->tailIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)) == 0 - ? BLOCK_SIZE - : static_cast(this->tailIndex.load(std::memory_order_relaxed) & - static_cast(BLOCK_SIZE - 1)); - while (i != BLOCK_SIZE && (block != this->tailBlock || i != lastValidIndex)) { - (*block)[i++]->~T(); - } - } while (block != this->tailBlock); - } - - // Destroy all blocks that we own - if (this->tailBlock != nullptr) { - auto block = this->tailBlock; - do { - auto nextBlock = block->next; - if (block->dynamicallyAllocated) { - destroy(block); - } else { - this->parent->add_block_to_free_list(block); - } - block = nextBlock; - } while (block != this->tailBlock); - } - - // Destroy the block indices - auto header = static_cast(pr_blockIndexRaw); - while (header != nullptr) { - auto prev = static_cast(header->prev); - header->~BlockIndexHeader(); - (Traits::free)(header); - header = prev; - } - } - - template - inline bool enqueue(U&& element) { - index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed); - index_t newTailIndex = 1 + currentTailIndex; - if ((currentTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { - // We reached the end of a block, start a new one - auto startBlock = this->tailBlock; - auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed; - if (this->tailBlock != nullptr && - this->tailBlock->next->ConcurrentQueue::Block::template is_empty()) { - // We can re-use the block ahead of us, it's empty! - this->tailBlock = this->tailBlock->next; - this->tailBlock->ConcurrentQueue::Block::template reset_empty(); - - // We'll put the block on the block index (guaranteed to be room since we're conceptually removing the - // last block from it first -- except instead of removing then adding, we can just overwrite). - // Note that there must be a valid block index here, since even if allocation failed in the ctor, - // it would have been re-attempted when adding the first block to the queue; since there is such - // a block, a block index must have been successfully allocated. - } else { - // Whatever head value we see here is >= the last value we saw here (relatively), - // and <= its current value. Since we have the most recent tail, the head must be - // <= to it. - auto head = this->headIndex.load(std::memory_order_relaxed); - assert(!details::circular_less_than(currentTailIndex, head)); - if (!details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || - (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && - (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) { - // We can't enqueue in another block because there's not enough leeway -- the - // tail could surpass the head by the time the block fills up! (Or we'll exceed - // the size limit, if the second part of the condition was true.) - return false; - } - // We're going to need a new block; check that the block index has room - if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize) { - // Hmm, the circular block index is already full -- we'll need - // to allocate a new index. Note pr_blockIndexRaw can only be nullptr if - // the initial allocation failed in the constructor. - - if (allocMode == CannotAlloc || !new_block_index(pr_blockIndexSlotsUsed)) { - return false; - } - } - - // Insert a new block in the circular linked list - auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); - if (newBlock == nullptr) { - return false; - } -#ifdef MCDBGQ_TRACKMEM - newBlock->owner = this; -#endif - newBlock->ConcurrentQueue::Block::template reset_empty(); - if (this->tailBlock == nullptr) { - newBlock->next = newBlock; - } else { - newBlock->next = this->tailBlock->next; - this->tailBlock->next = newBlock; - } - this->tailBlock = newBlock; - ++pr_blockIndexSlotsUsed; - } - - if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { - // The constructor may throw. We want the element not to appear in the queue in - // that case (without corrupting the queue): - MOODYCAMEL_TRY { - new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); - } - MOODYCAMEL_CATCH(...) { - // Revert change to the current block, but leave the new block available - // for next time - pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; - this->tailBlock = startBlock == nullptr ? this->tailBlock : startBlock; - MOODYCAMEL_RETHROW; - } - } else { - (void)startBlock; - (void)originalBlockIndexSlotsUsed; - } - - // Add block to block index - auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; - entry.base = currentTailIndex; - entry.block = this->tailBlock; - blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release); - pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); - - if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - } - - // Enqueue - new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); - - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - - template - bool dequeue(U& element) { - auto tail = this->tailIndex.load(std::memory_order_relaxed); - auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); - if (details::circular_less_than( - this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) { - // Might be something to dequeue, let's give it a try - - // Note that this if is purely for performance purposes in the common case when the queue is - // empty and the values are eventually consistent -- we may enter here spuriously. - - // Note that whatever the values of overcommit and tail are, they are not going to change (unless we - // change them) and must be the same value at this point (inside the if) as when the if condition was - // evaluated. - - // We insert an acquire fence here to synchronize-with the release upon incrementing dequeueOvercommit below. - // This ensures that whatever the value we got loaded into overcommit, the load of dequeueOptisticCount in - // the fetch_add below will result in a value at least as recent as that (and therefore at least as large). - // Note that I believe a compiler (signal) fence here would be sufficient due to the nature of fetch_add (all - // read-modify-write operations are guaranteed to work on the latest value in the modification order), but - // unfortunately that can't be shown to be correct using only the C++11 standard. - // See http://stackoverflow.com/questions/18223161/what-are-the-c11-memory-ordering-guarantees-in-this-corner-case - std::atomic_thread_fence(std::memory_order_acquire); - - // Increment optimistic counter, then check if it went over the boundary - auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed); - - // Note that since dequeueOvercommit must be <= dequeueOptimisticCount (because dequeueOvercommit is only ever - // incremented after dequeueOptimisticCount -- this is enforced in the `else` block below), and since we now - // have a version of dequeueOptimisticCount that is at least as recent as overcommit (due to the release upon - // incrementing dequeueOvercommit and the acquire above that synchronizes with it), overcommit <= myDequeueCount. - // However, we can't assert this since both dequeueOptimisticCount and dequeueOvercommit may (independently) - // overflow; in such a case, though, the logic still holds since the difference between the two is maintained. - - // Note that we reload tail here in case it changed; it will be the same value as before or greater, since - // this load is sequenced after (happens after) the earlier load above. This is supported by read-read - // coherency (as defined in the standard), explained here: http://en.cppreference.com/w/cpp/atomic/memory_order - tail = this->tailIndex.load(std::memory_order_acquire); - if ((details::likely)(details::circular_less_than(myDequeueCount - overcommit, tail))) { - // Guaranteed to be at least one element to dequeue! - - // Get the index. Note that since there's guaranteed to be at least one element, this - // will never exceed tail. We need to do an acquire-release fence here since it's possible - // that whatever condition got us to this point was for an earlier enqueued element (that - // we already see the memory effects for), but that by the time we increment somebody else - // has incremented it, and we need to see the memory effects for *that* element, which is - // in such a case is necessarily visible on the thread that incremented it in the first - // place with the more current condition (they must have acquired a tail that is at least - // as recent). - auto index = this->headIndex.fetch_add(1, std::memory_order_acq_rel); - - // Determine which block the element is in - - auto localBlockIndex = blockIndex.load(std::memory_order_acquire); - auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire); - - // We need to be careful here about subtracting and dividing because of index wrap-around. - // When an index wraps, we need to preserve the sign of the offset when dividing it by the - // block size (in order to get a correct signed block count offset in all cases): - auto headBase = localBlockIndex->entries[localBlockIndexHead].base; - auto blockBaseIndex = index & ~static_cast(BLOCK_SIZE - 1); - auto offset = static_cast( - static_cast::type>(blockBaseIndex - headBase) / BLOCK_SIZE); - auto block = localBlockIndex->entries[(localBlockIndexHead + offset) & (localBlockIndex->size - 1)].block; - - // Dequeue - auto& el = *((*block)[index]); - if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) { - // Make sure the element is still fully dequeued and destroyed even if the assignment - // throws - struct Guard { - Block* block; - index_t index; - - ~Guard() { - (*block)[index]->~T(); - block->ConcurrentQueue::Block::template set_empty(index); - } - } guard = {block, index}; - - element = std::move(el); // NOLINT - } else { - element = std::move(el); // NOLINT - el.~T(); // NOLINT - block->ConcurrentQueue::Block::template set_empty(index); - } - - return true; - } else { - // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent - this->dequeueOvercommit.fetch_add( - 1, - std:: - memory_order_release); // Release so that the fetch_add on dequeueOptimisticCount is guaranteed to happen before this write - } - } - - return false; - } - - template - bool enqueue_bulk(It itemFirst, size_t count) { - // First, we need to make sure we have enough room to enqueue all of the elements; - // this means pre-allocating blocks and putting them in the block index (but only if - // all the allocations succeeded). - index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed); - auto startBlock = this->tailBlock; - auto originalBlockIndexFront = pr_blockIndexFront; - auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed; - - Block* firstAllocatedBlock = nullptr; - - // Figure out how many blocks we'll need to allocate, and do so - size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast(BLOCK_SIZE - 1)) - - ((startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1)); - index_t currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); - if (blockBaseDiff > 0) { - // Allocate as many blocks as possible from ahead - while (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && - this->tailBlock->next->ConcurrentQueue::Block::template is_empty()) { - blockBaseDiff -= static_cast(BLOCK_SIZE); - currentTailIndex += static_cast(BLOCK_SIZE); - - this->tailBlock = this->tailBlock->next; - firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock; - - auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; - entry.base = currentTailIndex; - entry.block = this->tailBlock; - pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); - } - - // Now allocate as many blocks as necessary from the block pool - while (blockBaseDiff > 0) { - blockBaseDiff -= static_cast(BLOCK_SIZE); - currentTailIndex += static_cast(BLOCK_SIZE); - - auto head = this->headIndex.load(std::memory_order_relaxed); - assert(!details::circular_less_than(currentTailIndex, head)); - bool full = !details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || - (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && - (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head)); - if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) { - if (allocMode == CannotAlloc || full || !new_block_index(originalBlockIndexSlotsUsed)) { - // Failed to allocate, undo changes (but keep injected blocks) - pr_blockIndexFront = originalBlockIndexFront; - pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; - this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; - return false; - } - - // pr_blockIndexFront is updated inside new_block_index, so we need to - // update our fallback value too (since we keep the new index even if we - // later fail) - originalBlockIndexFront = originalBlockIndexSlotsUsed; - } - - // Insert a new block in the circular linked list - auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); - if (newBlock == nullptr) { - pr_blockIndexFront = originalBlockIndexFront; - pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; - this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; - return false; - } - -#ifdef MCDBGQ_TRACKMEM - newBlock->owner = this; -#endif - newBlock->ConcurrentQueue::Block::template set_all_empty(); - if (this->tailBlock == nullptr) { - newBlock->next = newBlock; - } else { - newBlock->next = this->tailBlock->next; - this->tailBlock->next = newBlock; - } - this->tailBlock = newBlock; - firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock; - - ++pr_blockIndexSlotsUsed; - - auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; - entry.base = currentTailIndex; - entry.block = this->tailBlock; - pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); - } - - // Excellent, all allocations succeeded. Reset each block's emptiness before we fill them up, and - // publish the new block index front - auto block = firstAllocatedBlock; - while (true) { - block->ConcurrentQueue::Block::template reset_empty(); - if (block == this->tailBlock) { - break; - } - block = block->next; - } - - if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), - new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { - blockIndex.load(std::memory_order_relaxed) - ->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); - } - } - - // Enqueue, one block at a time - index_t newTailIndex = startTailIndex + static_cast(count); - currentTailIndex = startTailIndex; - auto endBlock = this->tailBlock; - this->tailBlock = startBlock; - assert((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || - count == 0); - if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) { - this->tailBlock = firstAllocatedBlock; - } - while (true) { - auto stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - if (details::circular_less_than(newTailIndex, stopIndex)) { - stopIndex = newTailIndex; - } - if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), - new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { - while (currentTailIndex != stopIndex) { - new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); - } - } else { - MOODYCAMEL_TRY { - while (currentTailIndex != stopIndex) { - // Must use copy constructor even if move constructor is available - // because we may have to revert if there's an exception. - // Sorry about the horrible templated next line, but it was the only way - // to disable moving *at compile time*, which is important because a type - // may only define a (noexcept) move constructor, and so calls to the - // cctor will not compile, even if they are in an if branch that will never - // be executed - new ((*this->tailBlock)[currentTailIndex]) - T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR( - T, decltype(*itemFirst), - new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); - ++currentTailIndex; - ++itemFirst; - } - } - MOODYCAMEL_CATCH(...) { - // Oh dear, an exception's been thrown -- destroy the elements that - // were enqueued so far and revert the entire bulk operation (we'll keep - // any allocated blocks in our linked list for later, though). - auto constructedStopIndex = currentTailIndex; - auto lastBlockEnqueued = this->tailBlock; - - pr_blockIndexFront = originalBlockIndexFront; - pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; - this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; - - if (!details::is_trivially_destructible::value) { - auto block = startBlock; - if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { - block = firstAllocatedBlock; - } - currentTailIndex = startTailIndex; - while (true) { - stopIndex = - (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - if (details::circular_less_than(constructedStopIndex, stopIndex)) { - stopIndex = constructedStopIndex; - } - while (currentTailIndex != stopIndex) { - (*block)[currentTailIndex++]->~T(); - } - if (block == lastBlockEnqueued) { - break; - } - block = block->next; - } - } - MOODYCAMEL_RETHROW; - } - } - - if (this->tailBlock == endBlock) { - assert(currentTailIndex == newTailIndex); - break; - } - this->tailBlock = this->tailBlock->next; - } - - if (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst))) && - firstAllocatedBlock != nullptr) { - blockIndex.load(std::memory_order_relaxed) - ->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); - } - - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - - template - size_t dequeue_bulk(It& itemFirst, size_t max) { - auto tail = this->tailIndex.load(std::memory_order_relaxed); - auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); - auto desiredCount = - static_cast(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit)); - if (details::circular_less_than(0, desiredCount)) { - desiredCount = desiredCount < max ? desiredCount : max; - std::atomic_thread_fence(std::memory_order_acquire); - - auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed); - ; - - tail = this->tailIndex.load(std::memory_order_acquire); - auto actualCount = static_cast(tail - (myDequeueCount - overcommit)); - if (details::circular_less_than(0, actualCount)) { - actualCount = desiredCount < actualCount ? desiredCount : actualCount; - if (actualCount < desiredCount) { - this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release); - } - - // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this - // will never exceed tail. - auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel); - - // Determine which block the first element is in - auto localBlockIndex = blockIndex.load(std::memory_order_acquire); - auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire); - - auto headBase = localBlockIndex->entries[localBlockIndexHead].base; - auto firstBlockBaseIndex = firstIndex & ~static_cast(BLOCK_SIZE - 1); - auto offset = static_cast( - static_cast::type>(firstBlockBaseIndex - headBase) / BLOCK_SIZE); - auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1); - - // Iterate the blocks and dequeue - auto index = firstIndex; - do { - auto firstIndexInBlock = index; - auto endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) - ? firstIndex + static_cast(actualCount) - : endIndex; - auto block = localBlockIndex->entries[indexIndex].block; - if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, - details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) { - while (index != endIndex) { - auto& el = *((*block)[index]); - *itemFirst++ = std::move(el); - el.~T(); - ++index; - } - } else { - MOODYCAMEL_TRY { - while (index != endIndex) { - auto& el = *((*block)[index]); - *itemFirst = std::move(el); - ++itemFirst; - el.~T(); - ++index; - } - } - MOODYCAMEL_CATCH(...) { - // It's too late to revert the dequeue, but we can make sure that all - // the dequeued objects are properly destroyed and the block index - // (and empty count) are properly updated before we propagate the exception - do { - block = localBlockIndex->entries[indexIndex].block; - while (index != endIndex) { - (*block)[index++]->~T(); - } - block->ConcurrentQueue::Block::template set_many_empty( - firstIndexInBlock, static_cast(endIndex - firstIndexInBlock)); - indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1); - - firstIndexInBlock = index; - endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - endIndex = - details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) - ? firstIndex + static_cast(actualCount) - : endIndex; - } while (index != firstIndex + actualCount); - - MOODYCAMEL_RETHROW; - } - } - block->ConcurrentQueue::Block::template set_many_empty( - firstIndexInBlock, static_cast(endIndex - firstIndexInBlock)); - indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1); - } while (index != firstIndex + actualCount); - - return actualCount; - } else { - // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent - this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release); - } - } - - return 0; - } - - private: - struct BlockIndexEntry { - index_t base; - Block* block; - }; - - struct BlockIndexHeader { - size_t size; - std::atomic front; // Current slot (not next, like pr_blockIndexFront) - BlockIndexEntry* entries; - void* prev; - }; - - bool new_block_index(size_t numberOfFilledSlotsToExpose) { - auto prevBlockSizeMask = pr_blockIndexSize - 1; - - // Create the new block - pr_blockIndexSize <<= 1; - auto newRawPtr = - static_cast((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of::value - 1 + - sizeof(BlockIndexEntry) * pr_blockIndexSize)); - if (newRawPtr == nullptr) { - pr_blockIndexSize >>= 1; // Reset to allow graceful retry - return false; - } - - auto newBlockIndexEntries = - reinterpret_cast(details::align_for(newRawPtr + sizeof(BlockIndexHeader))); - - // Copy in all the old indices, if any - size_t j = 0; - if (pr_blockIndexSlotsUsed != 0) { - auto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask; - do { - newBlockIndexEntries[j++] = pr_blockIndexEntries[i]; - i = (i + 1) & prevBlockSizeMask; - } while (i != pr_blockIndexFront); - } - - // Update everything - auto header = new (newRawPtr) BlockIndexHeader; - header->size = pr_blockIndexSize; - header->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed); - header->entries = newBlockIndexEntries; - header->prev = pr_blockIndexRaw; // we link the new block to the old one so we can free it later - - pr_blockIndexFront = j; - pr_blockIndexEntries = newBlockIndexEntries; - pr_blockIndexRaw = newRawPtr; - blockIndex.store(header, std::memory_order_release); - - return true; - } - - private: - std::atomic blockIndex; - - // To be used by producer only -- consumer must use the ones in referenced by blockIndex - size_t pr_blockIndexSlotsUsed; - size_t pr_blockIndexSize; - size_t pr_blockIndexFront; // Next slot (not current) - BlockIndexEntry* pr_blockIndexEntries; - void* pr_blockIndexRaw; - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - public: - ExplicitProducer* nextExplicitProducer; - - private: -#endif - -#ifdef MCDBGQ_TRACKMEM - friend struct MemStats; -#endif - }; - - ////////////////////////////////// - // Implicit queue - ////////////////////////////////// - - struct ImplicitProducer : public ProducerBase { - ImplicitProducer(ConcurrentQueue* parent) - : ProducerBase(parent, false), nextBlockIndexCapacity(IMPLICIT_INITIAL_INDEX_SIZE), blockIndex(nullptr) { - new_block_index(); - } - - ~ImplicitProducer() { - // Note that since we're in the destructor we can assume that all enqueue/dequeue operations - // completed already; this means that all undequeued elements are placed contiguously across - // contiguous blocks, and that only the first and last remaining blocks can be only partially - // empty (all other remaining blocks must be completely full). - -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - // Unregister ourselves for thread termination notification - if (!this->inactive.load(std::memory_order_relaxed)) { - details::ThreadExitNotifier::unsubscribe(&threadExitListener); - } -#endif - - // Destroy all remaining elements! - auto tail = this->tailIndex.load(std::memory_order_relaxed); - auto index = this->headIndex.load(std::memory_order_relaxed); - Block* block = nullptr; - assert(index == tail || details::circular_less_than(index, tail)); - bool forceFreeLastBlock = index != tail; // If we enter the loop, then the last (tail) block will not be freed - while (index != tail) { - if ((index & static_cast(BLOCK_SIZE - 1)) == 0 || block == nullptr) { - if (block != nullptr) { - // Free the old block - this->parent->add_block_to_free_list(block); - } - - block = get_block_index_entry_for_index(index)->value.load(std::memory_order_relaxed); - } - - ((*block)[index])->~T(); - ++index; - } - // Even if the queue is empty, there's still one block that's not on the free list - // (unless the head index reached the end of it, in which case the tail will be poised - // to create a new block). - if (this->tailBlock != nullptr && (forceFreeLastBlock || (tail & static_cast(BLOCK_SIZE - 1)) != 0)) { - this->parent->add_block_to_free_list(this->tailBlock); - } - - // Destroy block index - auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); - if (localBlockIndex != nullptr) { - for (size_t i = 0; i != localBlockIndex->capacity; ++i) { - localBlockIndex->index[i]->~BlockIndexEntry(); - } - do { - auto prev = localBlockIndex->prev; - localBlockIndex->~BlockIndexHeader(); - (Traits::free)(localBlockIndex); - localBlockIndex = prev; - } while (localBlockIndex != nullptr); - } - } - - template - inline bool enqueue(U&& element) { - index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed); - index_t newTailIndex = 1 + currentTailIndex; - if ((currentTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { - // We reached the end of a block, start a new one - auto head = this->headIndex.load(std::memory_order_relaxed); - assert(!details::circular_less_than(currentTailIndex, head)); - if (!details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || - (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && - (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) { - return false; - } -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - // Find out where we'll be inserting this block in the block index - BlockIndexEntry* idxEntry; - if (!insert_block_index_entry(idxEntry, currentTailIndex)) { - return false; - } - - // Get ahold of a new block - auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); - if (newBlock == nullptr) { - rewind_block_index_tail(); - idxEntry->value.store(nullptr, std::memory_order_relaxed); - return false; - } -#ifdef MCDBGQ_TRACKMEM - newBlock->owner = this; -#endif - newBlock->ConcurrentQueue::Block::template reset_empty(); - - if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { - // May throw, try to insert now before we publish the fact that we have this new block - MOODYCAMEL_TRY { - new ((*newBlock)[currentTailIndex]) T(std::forward(element)); - } - MOODYCAMEL_CATCH(...) { - rewind_block_index_tail(); - idxEntry->value.store(nullptr, std::memory_order_relaxed); - this->parent->add_block_to_free_list(newBlock); - MOODYCAMEL_RETHROW; - } - } - - // Insert the new block into the index - idxEntry->value.store(newBlock, std::memory_order_relaxed); - - this->tailBlock = newBlock; - - if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - } - - // Enqueue - new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); - - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - - template - bool dequeue(U& element) { - // See ExplicitProducer::dequeue for rationale and explanation - index_t tail = this->tailIndex.load(std::memory_order_relaxed); - index_t overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); - if (details::circular_less_than( - this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) { - std::atomic_thread_fence(std::memory_order_acquire); - - index_t myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed); - tail = this->tailIndex.load(std::memory_order_acquire); - if ((details::likely)(details::circular_less_than(myDequeueCount - overcommit, tail))) { - index_t index = this->headIndex.fetch_add(1, std::memory_order_acq_rel); - - // Determine which block the element is in - auto entry = get_block_index_entry_for_index(index); - - // Dequeue - auto block = entry->value.load(std::memory_order_relaxed); - auto& el = *((*block)[index]); - - if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - // Note: Acquiring the mutex with every dequeue instead of only when a block - // is released is very sub-optimal, but it is, after all, purely debug code. - debug::DebugLock lock(producer->mutex); -#endif - struct Guard { - Block* block; - index_t index; - BlockIndexEntry* entry; - ConcurrentQueue* parent; - - ~Guard() { - (*block)[index]->~T(); - if (block->ConcurrentQueue::Block::template set_empty(index)) { - entry->value.store(nullptr, std::memory_order_relaxed); - parent->add_block_to_free_list(block); - } - } - } guard = {block, index, entry, this->parent}; - - element = std::move(el); // NOLINT - } else { - element = std::move(el); // NOLINT - el.~T(); // NOLINT - - if (block->ConcurrentQueue::Block::template set_empty(index)) { - { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - // Add the block back into the global free pool (and remove from block index) - entry->value.store(nullptr, std::memory_order_relaxed); - } - this->parent->add_block_to_free_list(block); // releases the above store - } - } - - return true; - } else { - this->dequeueOvercommit.fetch_add(1, std::memory_order_release); - } - } - - return false; - } - - template - bool enqueue_bulk(It itemFirst, size_t count) { - // First, we need to make sure we have enough room to enqueue all of the elements; - // this means pre-allocating blocks and putting them in the block index (but only if - // all the allocations succeeded). - - // Note that the tailBlock we start off with may not be owned by us any more; - // this happens if it was filled up exactly to the top (setting tailIndex to - // the first index of the next block which is not yet allocated), then dequeued - // completely (putting it on the free list) before we enqueue again. - - index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed); - auto startBlock = this->tailBlock; - Block* firstAllocatedBlock = nullptr; - auto endBlock = this->tailBlock; - - // Figure out how many blocks we'll need to allocate, and do so - size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast(BLOCK_SIZE - 1)) - - ((startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1)); - index_t currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); - if (blockBaseDiff > 0) { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - do { - blockBaseDiff -= static_cast(BLOCK_SIZE); - currentTailIndex += static_cast(BLOCK_SIZE); - - // Find out where we'll be inserting this block in the block index - BlockIndexEntry* idxEntry = nullptr; // initialization here unnecessary but compiler can't always tell - Block* newBlock; - bool indexInserted = false; - auto head = this->headIndex.load(std::memory_order_relaxed); - assert(!details::circular_less_than(currentTailIndex, head)); - bool full = !details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || - (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && - (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head)); - if (full || !(indexInserted = insert_block_index_entry(idxEntry, currentTailIndex)) || - (newBlock = this->parent->ConcurrentQueue::template requisition_block()) == nullptr) { - // Index allocation or block allocation failed; revert any other allocations - // and index insertions done so far for this operation - if (indexInserted) { - rewind_block_index_tail(); - idxEntry->value.store(nullptr, std::memory_order_relaxed); - } - currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); - for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) { - currentTailIndex += static_cast(BLOCK_SIZE); - idxEntry = get_block_index_entry_for_index(currentTailIndex); - idxEntry->value.store(nullptr, std::memory_order_relaxed); - rewind_block_index_tail(); - } - this->parent->add_blocks_to_free_list(firstAllocatedBlock); - this->tailBlock = startBlock; - - return false; - } - -#ifdef MCDBGQ_TRACKMEM - newBlock->owner = this; -#endif - newBlock->ConcurrentQueue::Block::template reset_empty(); - newBlock->next = nullptr; - - // Insert the new block into the index - idxEntry->value.store(newBlock, std::memory_order_relaxed); - - // Store the chain of blocks so that we can undo if later allocations fail, - // and so that we can find the blocks when we do the actual enqueueing - if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr) { - assert(this->tailBlock != nullptr); - this->tailBlock->next = newBlock; - } - this->tailBlock = newBlock; - endBlock = newBlock; - firstAllocatedBlock = firstAllocatedBlock == nullptr ? newBlock : firstAllocatedBlock; - } while (blockBaseDiff > 0); - } - - // Enqueue, one block at a time - index_t newTailIndex = startTailIndex + static_cast(count); - currentTailIndex = startTailIndex; - this->tailBlock = startBlock; - assert((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || - count == 0); - if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) { - this->tailBlock = firstAllocatedBlock; - } - while (true) { - auto stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - if (details::circular_less_than(newTailIndex, stopIndex)) { - stopIndex = newTailIndex; - } - if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), - new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { - while (currentTailIndex != stopIndex) { - new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); - } - } else { - MOODYCAMEL_TRY { - while (currentTailIndex != stopIndex) { - new ((*this->tailBlock)[currentTailIndex]) - T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR( - T, decltype(*itemFirst), - new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); - ++currentTailIndex; - ++itemFirst; - } - } - MOODYCAMEL_CATCH(...) { - auto constructedStopIndex = currentTailIndex; - auto lastBlockEnqueued = this->tailBlock; - - if (!details::is_trivially_destructible::value) { - auto block = startBlock; - if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { - block = firstAllocatedBlock; - } - currentTailIndex = startTailIndex; - while (true) { - stopIndex = - (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - if (details::circular_less_than(constructedStopIndex, stopIndex)) { - stopIndex = constructedStopIndex; - } - while (currentTailIndex != stopIndex) { - (*block)[currentTailIndex++]->~T(); - } - if (block == lastBlockEnqueued) { - break; - } - block = block->next; - } - } - - currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); - for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) { - currentTailIndex += static_cast(BLOCK_SIZE); - auto idxEntry = get_block_index_entry_for_index(currentTailIndex); - idxEntry->value.store(nullptr, std::memory_order_relaxed); - rewind_block_index_tail(); - } - this->parent->add_blocks_to_free_list(firstAllocatedBlock); - this->tailBlock = startBlock; - MOODYCAMEL_RETHROW; - } - } - - if (this->tailBlock == endBlock) { - assert(currentTailIndex == newTailIndex); - break; - } - this->tailBlock = this->tailBlock->next; - } - this->tailIndex.store(newTailIndex, std::memory_order_release); - return true; - } - - template - size_t dequeue_bulk(It& itemFirst, size_t max) { - auto tail = this->tailIndex.load(std::memory_order_relaxed); - auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); - auto desiredCount = - static_cast(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit)); - if (details::circular_less_than(0, desiredCount)) { - desiredCount = desiredCount < max ? desiredCount : max; - std::atomic_thread_fence(std::memory_order_acquire); - - auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed); - - tail = this->tailIndex.load(std::memory_order_acquire); - auto actualCount = static_cast(tail - (myDequeueCount - overcommit)); - if (details::circular_less_than(0, actualCount)) { - actualCount = desiredCount < actualCount ? desiredCount : actualCount; - if (actualCount < desiredCount) { - this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release); - } - - // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this - // will never exceed tail. - auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel); - - // Iterate the blocks and dequeue - auto index = firstIndex; - BlockIndexHeader* localBlockIndex; - auto indexIndex = get_block_index_index_for_index(index, localBlockIndex); - do { - auto blockStartIndex = index; - auto endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) - ? firstIndex + static_cast(actualCount) - : endIndex; - - auto entry = localBlockIndex->index[indexIndex]; - auto block = entry->value.load(std::memory_order_relaxed); - if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, - details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) { - while (index != endIndex) { - auto& el = *((*block)[index]); - *itemFirst++ = std::move(el); - el.~T(); - ++index; - } - } else { - MOODYCAMEL_TRY { - while (index != endIndex) { - auto& el = *((*block)[index]); - *itemFirst = std::move(el); - ++itemFirst; - el.~T(); - ++index; - } - } - MOODYCAMEL_CATCH(...) { - do { - entry = localBlockIndex->index[indexIndex]; - block = entry->value.load(std::memory_order_relaxed); - while (index != endIndex) { - (*block)[index++]->~T(); - } - - if (block->ConcurrentQueue::Block::template set_many_empty( - blockStartIndex, static_cast(endIndex - blockStartIndex))) { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - entry->value.store(nullptr, std::memory_order_relaxed); - this->parent->add_block_to_free_list(block); - } - indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1); - - blockStartIndex = index; - endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); - endIndex = - details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) - ? firstIndex + static_cast(actualCount) - : endIndex; - } while (index != firstIndex + actualCount); - - MOODYCAMEL_RETHROW; - } - } - if (block->ConcurrentQueue::Block::template set_many_empty( - blockStartIndex, static_cast(endIndex - blockStartIndex))) { - { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - // Note that the set_many_empty above did a release, meaning that anybody who acquires the block - // we're about to free can use it safely since our writes (and reads!) will have happened-before then. - entry->value.store(nullptr, std::memory_order_relaxed); - } - this->parent->add_block_to_free_list(block); // releases the above store - } - indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1); - } while (index != firstIndex + actualCount); - - return actualCount; - } else { - this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release); - } - } - - return 0; - } - - private: - // The block size must be > 1, so any number with the low bit set is an invalid block base index - static const index_t INVALID_BLOCK_BASE = 1; - - struct BlockIndexEntry { - std::atomic key; - std::atomic value; - }; - - struct BlockIndexHeader { - size_t capacity; - std::atomic tail; - BlockIndexEntry* entries; - BlockIndexEntry** index; - BlockIndexHeader* prev; - }; - - template - inline bool insert_block_index_entry(BlockIndexEntry*& idxEntry, index_t blockStartIndex) { - auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); // We're the only writer thread, relaxed is OK - if (localBlockIndex == nullptr) { - return false; // this can happen if new_block_index failed in the constructor - } - auto newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); - idxEntry = localBlockIndex->index[newTail]; - if (idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE || - idxEntry->value.load(std::memory_order_relaxed) == nullptr) { - idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); - localBlockIndex->tail.store(newTail, std::memory_order_release); - return true; - } - - // No room in the old block index, try to allocate another one! - if (allocMode == CannotAlloc || !new_block_index()) { - return false; - } - localBlockIndex = blockIndex.load(std::memory_order_relaxed); - newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); - idxEntry = localBlockIndex->index[newTail]; - assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE); - idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); - localBlockIndex->tail.store(newTail, std::memory_order_release); - return true; - } - - inline void rewind_block_index_tail() { - auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); - localBlockIndex->tail.store( - (localBlockIndex->tail.load(std::memory_order_relaxed) - 1) & (localBlockIndex->capacity - 1), - std::memory_order_relaxed); - } - - inline BlockIndexEntry* get_block_index_entry_for_index(index_t index) const { - BlockIndexHeader* localBlockIndex; - auto idx = get_block_index_index_for_index(index, localBlockIndex); - return localBlockIndex->index[idx]; - } - - inline size_t get_block_index_index_for_index(index_t index, BlockIndexHeader*& localBlockIndex) const { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - debug::DebugLock lock(mutex); -#endif - index &= ~static_cast(BLOCK_SIZE - 1); - localBlockIndex = blockIndex.load(std::memory_order_acquire); - auto tail = localBlockIndex->tail.load(std::memory_order_acquire); - auto tailBase = localBlockIndex->index[tail]->key.load(std::memory_order_relaxed); - assert(tailBase != INVALID_BLOCK_BASE); - // Note: Must use division instead of shift because the index may wrap around, causing a negative - // offset, whose negativity we want to preserve - auto offset = - static_cast(static_cast::type>(index - tailBase) / BLOCK_SIZE); - size_t idx = (tail + offset) & (localBlockIndex->capacity - 1); - assert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && - localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr); - return idx; - } - - bool new_block_index() { - auto prev = blockIndex.load(std::memory_order_relaxed); - size_t prevCapacity = prev == nullptr ? 0 : prev->capacity; - auto entryCount = prev == nullptr ? nextBlockIndexCapacity : prevCapacity; - auto raw = static_cast( - (Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of::value - 1 + - sizeof(BlockIndexEntry) * entryCount + std::alignment_of::value - 1 + - sizeof(BlockIndexEntry*) * nextBlockIndexCapacity)); - if (raw == nullptr) { - return false; - } - - auto header = new (raw) BlockIndexHeader; - auto entries = - reinterpret_cast(details::align_for(raw + sizeof(BlockIndexHeader))); - auto index = reinterpret_cast(details::align_for( - reinterpret_cast(entries) + sizeof(BlockIndexEntry) * entryCount)); - if (prev != nullptr) { - auto prevTail = prev->tail.load(std::memory_order_relaxed); - auto prevPos = prevTail; - size_t i = 0; - do { - prevPos = (prevPos + 1) & (prev->capacity - 1); - index[i++] = prev->index[prevPos]; - } while (prevPos != prevTail); - assert(i == prevCapacity); - } - for (size_t i = 0; i != entryCount; ++i) { - new (entries + i) BlockIndexEntry; - entries[i].key.store(INVALID_BLOCK_BASE, std::memory_order_relaxed); - index[prevCapacity + i] = entries + i; - } - header->prev = prev; - header->entries = entries; - header->index = index; - header->capacity = nextBlockIndexCapacity; - header->tail.store((prevCapacity - 1) & (nextBlockIndexCapacity - 1), std::memory_order_relaxed); - - blockIndex.store(header, std::memory_order_release); - - nextBlockIndexCapacity <<= 1; - - return true; - } - - private: - size_t nextBlockIndexCapacity; - std::atomic blockIndex; - -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - public: - details::ThreadExitListener threadExitListener; - - private: -#endif - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - public: - ImplicitProducer* nextImplicitProducer; - - private: -#endif - -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX - mutable debug::DebugMutex mutex; -#endif -#ifdef MCDBGQ_TRACKMEM - friend struct MemStats; -#endif - }; - - ////////////////////////////////// - // Block pool manipulation - ////////////////////////////////// - - void populate_initial_block_list(size_t blockCount) { - initialBlockPoolSize = blockCount; - if (initialBlockPoolSize == 0) { - initialBlockPool = nullptr; - return; - } - - initialBlockPool = create_array(blockCount); - if (initialBlockPool == nullptr) { - initialBlockPoolSize = 0; - } - for (size_t i = 0; i < initialBlockPoolSize; ++i) { - initialBlockPool[i].dynamicallyAllocated = false; - } - } - - inline Block* try_get_block_from_initial_pool() { - if (initialBlockPoolIndex.load(std::memory_order_relaxed) >= initialBlockPoolSize) { - return nullptr; - } - - auto index = initialBlockPoolIndex.fetch_add(1, std::memory_order_relaxed); - - return index < initialBlockPoolSize ? (initialBlockPool + index) : nullptr; - } - - inline void add_block_to_free_list(Block* block) { -#ifdef MCDBGQ_TRACKMEM - block->owner = nullptr; -#endif - freeList.add(block); - } - - inline void add_blocks_to_free_list(Block* block) { - while (block != nullptr) { - auto next = block->next; - add_block_to_free_list(block); - block = next; - } - } - - inline Block* try_get_block_from_free_list() { - return freeList.try_get(); - } - - // Gets a free block from one of the memory pools, or allocates a new one (if applicable) - template - Block* requisition_block() { - auto block = try_get_block_from_initial_pool(); - if (block != nullptr) { - return block; - } - - block = try_get_block_from_free_list(); - if (block != nullptr) { - return block; - } - - if (canAlloc == CanAlloc) { - return create(); - } - - return nullptr; - } - -#ifdef MCDBGQ_TRACKMEM - public: - struct MemStats { - size_t allocatedBlocks; - size_t usedBlocks; - size_t freeBlocks; - size_t ownedBlocksExplicit; - size_t ownedBlocksImplicit; - size_t implicitProducers; - size_t explicitProducers; - size_t elementsEnqueued; - size_t blockClassBytes; - size_t queueClassBytes; - size_t implicitBlockIndexBytes; - size_t explicitBlockIndexBytes; - - friend class ConcurrentQueue; - - private: - static MemStats getFor(ConcurrentQueue* q) { - MemStats stats = {0}; - - stats.elementsEnqueued = q->size_approx(); - - auto block = q->freeList.head_unsafe(); - while (block != nullptr) { - ++stats.allocatedBlocks; - ++stats.freeBlocks; - block = block->freeListNext.load(std::memory_order_relaxed); - } - - for (auto ptr = q->producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - bool implicit = dynamic_cast(ptr) != nullptr; - stats.implicitProducers += implicit ? 1 : 0; - stats.explicitProducers += implicit ? 0 : 1; - - if (implicit) { - auto prod = static_cast(ptr); - stats.queueClassBytes += sizeof(ImplicitProducer); - auto head = prod->headIndex.load(std::memory_order_relaxed); - auto tail = prod->tailIndex.load(std::memory_order_relaxed); - auto hash = prod->blockIndex.load(std::memory_order_relaxed); - if (hash != nullptr) { - for (size_t i = 0; i != hash->capacity; ++i) { - if (hash->index[i]->key.load(std::memory_order_relaxed) != ImplicitProducer::INVALID_BLOCK_BASE && - hash->index[i]->value.load(std::memory_order_relaxed) != nullptr) { - ++stats.allocatedBlocks; - ++stats.ownedBlocksImplicit; - } - } - stats.implicitBlockIndexBytes += hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry); - for (; hash != nullptr; hash = hash->prev) { - stats.implicitBlockIndexBytes += sizeof(typename ImplicitProducer::BlockIndexHeader) + - hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry*); - } - } - for (; details::circular_less_than(head, tail); head += BLOCK_SIZE) { - //auto block = prod->get_block_index_entry_for_index(head); - ++stats.usedBlocks; - } - } else { - auto prod = static_cast(ptr); - stats.queueClassBytes += sizeof(ExplicitProducer); - auto tailBlock = prod->tailBlock; - bool wasNonEmpty = false; - if (tailBlock != nullptr) { - auto block = tailBlock; - do { - ++stats.allocatedBlocks; - if (!block->ConcurrentQueue::Block::template is_empty() || wasNonEmpty) { - ++stats.usedBlocks; - wasNonEmpty = wasNonEmpty || block != tailBlock; - } - ++stats.ownedBlocksExplicit; - block = block->next; - } while (block != tailBlock); - } - auto index = prod->blockIndex.load(std::memory_order_relaxed); - while (index != nullptr) { - stats.explicitBlockIndexBytes += sizeof(typename ExplicitProducer::BlockIndexHeader) + - index->size * sizeof(typename ExplicitProducer::BlockIndexEntry); - index = static_cast(index->prev); - } - } - } - - auto freeOnInitialPool = q->initialBlockPoolIndex.load(std::memory_order_relaxed) >= q->initialBlockPoolSize - ? 0 - : q->initialBlockPoolSize - q->initialBlockPoolIndex.load(std::memory_order_relaxed); - stats.allocatedBlocks += freeOnInitialPool; - stats.freeBlocks += freeOnInitialPool; - - stats.blockClassBytes = sizeof(Block) * stats.allocatedBlocks; - stats.queueClassBytes += sizeof(ConcurrentQueue); - - return stats; - } - }; - - // For debugging only. Not thread-safe. - MemStats getMemStats() { - return MemStats::getFor(this); - } - - private: - friend struct MemStats; -#endif - - ////////////////////////////////// - // Producer list manipulation - ////////////////////////////////// - - ProducerBase* recycle_or_create_producer(bool isExplicit) { - bool recycled; - return recycle_or_create_producer(isExplicit, recycled); - } - - ProducerBase* recycle_or_create_producer(bool isExplicit, bool& recycled) { -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH - debug::DebugLock lock(implicitProdMutex); -#endif - // Try to re-use one first - for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { - if (ptr->inactive.load(std::memory_order_relaxed) && ptr->isExplicit == isExplicit) { - bool expected = true; - if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, - std::memory_order_relaxed)) { - // We caught one! It's been marked as activated, the caller can have it - recycled = true; - return ptr; - } - } - } - - recycled = false; - return add_producer(isExplicit ? static_cast(create(this)) - : create(this)); - } - - ProducerBase* add_producer(ProducerBase* producer) { - // Handle failed memory allocation - if (producer == nullptr) { - return nullptr; - } - - producerCount.fetch_add(1, std::memory_order_relaxed); - - // Add it to the lock-free list - auto prevTail = producerListTail.load(std::memory_order_relaxed); - do { - producer->next = prevTail; - } while (!producerListTail.compare_exchange_weak(prevTail, producer, std::memory_order_release, - std::memory_order_relaxed)); - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - if (producer->isExplicit) { - auto prevTailExplicit = explicitProducers.load(std::memory_order_relaxed); - do { - static_cast(producer)->nextExplicitProducer = prevTailExplicit; - } while (!explicitProducers.compare_exchange_weak(prevTailExplicit, static_cast(producer), - std::memory_order_release, std::memory_order_relaxed)); - } else { - auto prevTailImplicit = implicitProducers.load(std::memory_order_relaxed); - do { - static_cast(producer)->nextImplicitProducer = prevTailImplicit; - } while (!implicitProducers.compare_exchange_weak(prevTailImplicit, static_cast(producer), - std::memory_order_release, std::memory_order_relaxed)); - } -#endif - - return producer; - } - - void reown_producers() { - // After another instance is moved-into/swapped-with this one, all the - // producers we stole still think their parents are the other queue. - // So fix them up! - for (auto ptr = producerListTail.load(std::memory_order_relaxed); ptr != nullptr; ptr = ptr->next_prod()) { - ptr->parent = this; - } - } - - ////////////////////////////////// - // Implicit producer hash - ////////////////////////////////// - - struct ImplicitProducerKVP { - std::atomic key; - ImplicitProducer* - value; // No need for atomicity since it's only read by the thread that sets it in the first place - - ImplicitProducerKVP() : value(nullptr) { - } - - ImplicitProducerKVP(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT { - key.store(other.key.load(std::memory_order_relaxed), std::memory_order_relaxed); - value = other.value; - } - - inline ImplicitProducerKVP& operator=(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT { - swap(other); - return *this; - } - - inline void swap(ImplicitProducerKVP& other) MOODYCAMEL_NOEXCEPT { - if (this != &other) { - details::swap_relaxed(key, other.key); - std::swap(value, other.value); - } - } - }; - - template - friend void moodycamel::swap(typename ConcurrentQueue::ImplicitProducerKVP&, - typename ConcurrentQueue::ImplicitProducerKVP&) MOODYCAMEL_NOEXCEPT; - - struct ImplicitProducerHash { - size_t capacity; - ImplicitProducerKVP* entries; - ImplicitProducerHash* prev; - }; - - inline void populate_initial_implicit_producer_hash() { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return; - - implicitProducerHashCount.store(0, std::memory_order_relaxed); - auto hash = &initialImplicitProducerHash; - hash->capacity = INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; - hash->entries = &initialImplicitProducerHashEntries[0]; - for (size_t i = 0; i != INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; ++i) { - initialImplicitProducerHashEntries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed); - } - hash->prev = nullptr; - implicitProducerHash.store(hash, std::memory_order_relaxed); - } - - void swap_implicit_producer_hashes(ConcurrentQueue& other) { - if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) - return; - - // Swap (assumes our implicit producer hash is initialized) - initialImplicitProducerHashEntries.swap(other.initialImplicitProducerHashEntries); - initialImplicitProducerHash.entries = &initialImplicitProducerHashEntries[0]; - other.initialImplicitProducerHash.entries = &other.initialImplicitProducerHashEntries[0]; - - details::swap_relaxed(implicitProducerHashCount, other.implicitProducerHashCount); - - details::swap_relaxed(implicitProducerHash, other.implicitProducerHash); - if (implicitProducerHash.load(std::memory_order_relaxed) == &other.initialImplicitProducerHash) { - implicitProducerHash.store(&initialImplicitProducerHash, std::memory_order_relaxed); - } else { - ImplicitProducerHash* hash; - for (hash = implicitProducerHash.load(std::memory_order_relaxed); - hash->prev != &other.initialImplicitProducerHash; hash = hash->prev) { - continue; - } - hash->prev = &initialImplicitProducerHash; - } - if (other.implicitProducerHash.load(std::memory_order_relaxed) == &initialImplicitProducerHash) { - other.implicitProducerHash.store(&other.initialImplicitProducerHash, std::memory_order_relaxed); - } else { - ImplicitProducerHash* hash; - for (hash = other.implicitProducerHash.load(std::memory_order_relaxed); - hash->prev != &initialImplicitProducerHash; hash = hash->prev) { - continue; - } - hash->prev = &other.initialImplicitProducerHash; - } - } - - // Only fails (returns nullptr) if memory allocation fails - ImplicitProducer* get_or_add_implicit_producer() { - // Note that since the data is essentially thread-local (key is thread ID), - // there's a reduced need for fences (memory ordering is already consistent - // for any individual thread), except for the current table itself. - - // Start by looking for the thread ID in the current and all previous hash tables. - // If it's not found, it must not be in there yet, since this same thread would - // have added it previously to one of the tables that we traversed. - - // Code and algorithm adapted from http://preshing.com/20130605/the-worlds-simplest-lock-free-hash-table - -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH - debug::DebugLock lock(implicitProdMutex); -#endif - - auto id = details::thread_id(); - auto hashedId = details::hash_thread_id(id); - - auto mainHash = implicitProducerHash.load(std::memory_order_acquire); - for (auto hash = mainHash; hash != nullptr; hash = hash->prev) { - // Look for the id in this hash - auto index = hashedId; - while (true) { // Not an infinite loop because at least one slot is free in the hash table - index &= hash->capacity - 1; - - auto probedKey = hash->entries[index].key.load(std::memory_order_relaxed); - if (probedKey == id) { - // Found it! If we had to search several hashes deep, though, we should lazily add it - // to the current main hash table to avoid the extended search next time. - // Note there's guaranteed to be room in the current hash table since every subsequent - // table implicitly reserves space for all previous tables (there's only one - // implicitProducerHashCount). - auto value = hash->entries[index].value; - if (hash != mainHash) { - index = hashedId; - while (true) { - index &= mainHash->capacity - 1; - probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); - auto empty = details::invalid_thread_id; -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - auto reusable = details::invalid_thread_id2; - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong( - empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || - (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong( - reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { -#else - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong( - empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { -#endif - mainHash->entries[index].value = value; - break; - } - ++index; - } - } - - return value; - } - if (probedKey == details::invalid_thread_id) { - break; // Not in this hash table - } - ++index; - } - } - - // Insert! - auto newCount = 1 + implicitProducerHashCount.fetch_add(1, std::memory_order_relaxed); - while (true) { - // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) - if (newCount >= (mainHash->capacity >> 1) && - !implicitProducerHashResizeInProgress.test_and_set(std::memory_order_acquire)) { - // We've acquired the resize lock, try to allocate a bigger hash table. - // Note the acquire fence synchronizes with the release fence at the end of this block, and hence when - // we reload implicitProducerHash it must be the most recent version (it only gets changed within this - // locked block). - mainHash = implicitProducerHash.load(std::memory_order_acquire); - if (newCount >= (mainHash->capacity >> 1)) { - auto newCapacity = mainHash->capacity << 1; - while (newCount >= (newCapacity >> 1)) { - newCapacity <<= 1; - } - auto raw = static_cast((Traits::malloc)(sizeof(ImplicitProducerHash) + - std::alignment_of::value - 1 + - sizeof(ImplicitProducerKVP) * newCapacity)); - if (raw == nullptr) { - // Allocation failed - implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); - implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); - return nullptr; - } - - auto newHash = new (raw) ImplicitProducerHash; - newHash->capacity = newCapacity; - newHash->entries = reinterpret_cast( - details::align_for(raw + sizeof(ImplicitProducerHash))); - for (size_t i = 0; i != newCapacity; ++i) { - new (newHash->entries + i) ImplicitProducerKVP; - newHash->entries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed); - } - newHash->prev = mainHash; - implicitProducerHash.store(newHash, std::memory_order_release); - implicitProducerHashResizeInProgress.clear(std::memory_order_release); - mainHash = newHash; - } else { - implicitProducerHashResizeInProgress.clear(std::memory_order_release); - } - } - - // If it's < three-quarters full, add to the old one anyway so that we don't have to wait for the next table - // to finish being allocated by another thread (and if we just finished allocating above, the condition will - // always be true) - if (newCount < (mainHash->capacity >> 1) + (mainHash->capacity >> 2)) { - bool recycled; - auto producer = static_cast(recycle_or_create_producer(false, recycled)); - if (producer == nullptr) { - implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); - return nullptr; - } - if (recycled) { - implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); - } - -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - producer->threadExitListener.callback = &ConcurrentQueue::implicit_producer_thread_exited_callback; - producer->threadExitListener.userData = producer; - details::ThreadExitNotifier::subscribe(&producer->threadExitListener); -#endif - - auto index = hashedId; - while (true) { - index &= mainHash->capacity - 1; - auto probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); - - auto empty = details::invalid_thread_id; -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - auto reusable = details::invalid_thread_id2; - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong( - empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || - (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong( - reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { -#else - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong( - empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { -#endif - mainHash->entries[index].value = producer; - break; - } - ++index; - } - return producer; - } - - // Hmm, the old hash is quite full and somebody else is busy allocating a new one. - // We need to wait for the allocating thread to finish (if it succeeds, we add, if not, - // we try to allocate ourselves). - mainHash = implicitProducerHash.load(std::memory_order_acquire); - } - } // namespace moodycamel - -#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED - void implicit_producer_thread_exited(ImplicitProducer* producer) { - // Remove from thread exit listeners - details::ThreadExitNotifier::unsubscribe(&producer->threadExitListener); - - // Remove from hash -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH - debug::DebugLock lock(implicitProdMutex); -#endif - auto hash = implicitProducerHash.load(std::memory_order_acquire); - assert(hash != - nullptr); // The thread exit listener is only registered if we were added to a hash in the first place - auto id = details::thread_id(); - auto hashedId = details::hash_thread_id(id); - details::thread_id_t probedKey; - - // We need to traverse all the hashes just in case other threads aren't on the current one yet and are - // trying to add an entry thinking there's a free slot (because they reused a producer) - for (; hash != nullptr; hash = hash->prev) { - auto index = hashedId; - do { - index &= hash->capacity - 1; - probedKey = hash->entries[index].key.load(std::memory_order_relaxed); - if (probedKey == id) { - hash->entries[index].key.store(details::invalid_thread_id2, std::memory_order_release); - break; - } - ++index; - } while ( - probedKey != - details:: - invalid_thread_id); // Can happen if the hash has changed but we weren't put back in it yet, or if we weren't added to this hash in the first place - } - - // Mark the queue as being recyclable - producer->inactive.store(true, std::memory_order_release); - } - - static void implicit_producer_thread_exited_callback(void* userData) { - auto producer = static_cast(userData); - auto queue = producer->parent; - queue->implicit_producer_thread_exited(producer); - } -#endif - - ////////////////////////////////// - // Utility functions - ////////////////////////////////// - - template - static inline U* create_array(size_t count) { - assert(count > 0); - auto p = static_cast((Traits::malloc)(sizeof(U) * count)); - if (p == nullptr) { - return nullptr; - } - - for (size_t i = 0; i != count; ++i) { - new (p + i) U(); - } - return p; - } - - template - static inline void destroy_array(U* p, size_t count) { - if (p != nullptr) { - assert(count > 0); - for (size_t i = count; i != 0;) { - (p + --i)->~U(); - } - (Traits::free)(p); - } - } - - template - static inline U* create() { - auto p = (Traits::malloc)(sizeof(U)); - return p != nullptr ? new (p) U : nullptr; - } - - template - static inline U* create(A1&& a1) { - auto p = (Traits::malloc)(sizeof(U)); - return p != nullptr ? new (p) U(std::forward(a1)) : nullptr; - } - - template - static inline void destroy(U* p) { - if (p != nullptr) { - p->~U(); - } - (Traits::free)(p); - } - - private: - std::atomic producerListTail; - std::atomic producerCount; - - std::atomic initialBlockPoolIndex; - Block* initialBlockPool; - size_t initialBlockPoolSize; - -#if !MCDBGQ_USEDEBUGFREELIST - FreeList freeList; -#else - debug::DebugFreeList freeList; -#endif - - std::atomic implicitProducerHash; - std::atomic implicitProducerHashCount; // Number of slots logically used - ImplicitProducerHash initialImplicitProducerHash; - std::array initialImplicitProducerHashEntries; - std::atomic_flag implicitProducerHashResizeInProgress; - - std::atomic nextExplicitConsumerId; - std::atomic globalExplicitConsumerOffset; - -#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH - debug::DebugMutex implicitProdMutex; -#endif - -#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG - std::atomic explicitProducers; - std::atomic implicitProducers; -#endif -}; - -template -ProducerToken::ProducerToken(ConcurrentQueue& queue) : producer(queue.recycle_or_create_producer(true)) { - if (producer != nullptr) { - producer->token = this; - } -} - -template -ProducerToken::ProducerToken(BlockingConcurrentQueue& queue) - : producer(reinterpret_cast*>(&queue)->recycle_or_create_producer(true)) { - if (producer != nullptr) { - producer->token = this; - } -} - -template -ConsumerToken::ConsumerToken(ConcurrentQueue& queue) - : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) { - initialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release); - lastKnownGlobalOffset = -1; -} - -template -ConsumerToken::ConsumerToken(BlockingConcurrentQueue& queue) - : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) { - initialOffset = reinterpret_cast*>(&queue)->nextExplicitConsumerId.fetch_add( - 1, std::memory_order_release); - lastKnownGlobalOffset = -1; -} - -template -inline void swap(ConcurrentQueue& a, ConcurrentQueue& b) MOODYCAMEL_NOEXCEPT { - a.swap(b); -} - -inline void swap(ProducerToken& a, ProducerToken& b) MOODYCAMEL_NOEXCEPT { - a.swap(b); -} - -inline void swap(ConsumerToken& a, ConsumerToken& b) MOODYCAMEL_NOEXCEPT { - a.swap(b); -} - -template -inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, - typename ConcurrentQueue::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT { - a.swap(b); -} - -} // namespace moodycamel - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.c b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.c deleted file mode 100644 index 8fcebbf1..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - This file is part of KittenDB-Engine Library. - - KittenDB-Engine Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - KittenDB-Engine Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with KittenDB-Engine Library. If not, see . - - Copyright 2014-2016 Telegraph Inc - 2014-2016 Nikolai Durov - 2014 Andrey Lopatin -*/ - -char disable_linker_warning_about_empty_file_mp_queue_cpp; - -#ifdef TG_LCR_QUEUE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mp-queue.h" - -#undef assert -#ifndef assert -#define assert(x) x -#endif - -volatile int mpq_blocks_allocated, mpq_blocks_allocated_max, mpq_blocks_allocations, mpq_blocks_true_allocations, - mpq_blocks_wasted, mpq_blocks_prepared; -volatile int mpq_small_blocks_allocated, mpq_small_blocks_allocated_max; - -__thread int mpq_this_thread_id; -__thread void **thread_hazard_pointers; -volatile int mpq_threads; - -struct mp_queue MqGarbageBlocks, MqPreparedBlocks; -struct mp_queue MqGarbageSmallBlocks, MqPreparedSmallBlocks; - -static inline void barrier(void) { - asm volatile("" : : : "memory"); -} -static inline void mfence(void) { - asm volatile("mfence" : : : "memory"); -} - -/* hazard pointers, one per thread */ - -void *mqb_hazard_ptr[MAX_MPQ_THREADS][THREAD_HPTRS] __attribute__((aligned(64))); - -int is_hazard_ptr(void *ptr, int a, int b) { - barrier(); - int k = mpq_threads, q = mpq_this_thread_id; - barrier(); - int i, j, r = 0; - for (j = a; j <= b; j++) { - if (mqb_hazard_ptr[q][j] == ptr) { - r = 1; - break; - } - } - for (i = 1; i <= k; i++) { - if (i == q) { - continue; - } - for (j = a; j <= b; j++) { - if (mqb_hazard_ptr[i][j] == ptr) { - barrier(); - return r + 2; - } - } - } - barrier(); - return r; -} - -void clear_thread_ids() { - mpq_threads = 0; - mpq_this_thread_id = 0; -} -/* initialize this thread id and return it */ -int get_this_thread_id(void) { - int i = mpq_this_thread_id; - if (i) { - return i; - } - i = __sync_fetch_and_add(&mpq_threads, 1) + 1; - assert(i > 0 && i < MAX_MPQ_THREADS); - thread_hazard_pointers = mqb_hazard_ptr[i]; - return mpq_this_thread_id = i; -} - -/* custom semaphore implementation using futexes */ - -int mp_sem_post(mp_sem_t *sem) { - __sync_fetch_and_add(&sem->value, 1); - if (sem->waiting > 0) { - syscall(__NR_futex, &sem->value, FUTEX_WAKE, 1, NULL, 0, 0); - } - return 0; -} - -int mp_sem_wait(mp_sem_t *sem) { - int v = sem->value, q = 0; - while (1) { - if (v > 0) { - v = __sync_fetch_and_add(&sem->value, -1); - if (v > 0) { - return 0; - } - v = __sync_add_and_fetch(&sem->value, 1); - } else { - if (v < 0 && q++ < 10) { - barrier(); - v = sem->value; - continue; - } - __sync_fetch_and_add(&sem->waiting, 1); - syscall(__NR_futex, &sem->value, FUTEX_WAIT, v, NULL, 0, 0); - __sync_fetch_and_add(&sem->waiting, -1); - v = sem->value; - q = 0; - } - } -} - -int mp_sem_trywait(mp_sem_t *sem) { - int v = sem->value; - if (v > 0) { - v = __sync_fetch_and_add(&sem->value, -1); - if (v > 0) { - return 0; - } - __sync_fetch_and_add(&sem->value, 1); - } - return -1; -} - -/* functions for one mp_queue_block */ - -// may invoke mpq_pop()/mpq_push() if allow_recursion=1 -struct mp_queue_block *alloc_mpq_block(mqn_value_t first_val, int allow_recursion, int is_small) { - is_small = 0; - struct mp_queue_block *QB = 0; - int prepared = 0, align_bytes = 0; - long size = (is_small ? MPQ_SMALL_BLOCK_SIZE : MPQ_BLOCK_SIZE); - if (allow_recursion) { - QB = mpq_pop(is_small ? &MqGarbageSmallBlocks : &MqGarbageBlocks, MPQF_RECURSIVE); - if (QB) { - if (!is_hazard_ptr(QB, 0, 2)) { - // reclaiming garbage - assert(QB->mqb_magic == MQ_BLOCK_GARBAGE_MAGIC); - __sync_fetch_and_add(&mpq_blocks_wasted, -1); - align_bytes = QB->mqb_align_bytes; - } else { - mpq_push(is_small ? &MqGarbageSmallBlocks : &MqGarbageBlocks, QB, MPQF_RECURSIVE); - QB = 0; - } - } - if (!QB) { - QB = mpq_pop(is_small ? &MqPreparedSmallBlocks : &MqPreparedBlocks, MPQF_RECURSIVE); - if (QB) { - assert(QB->mqb_magic == MQ_BLOCK_PREPARED_MAGIC); - prepared = 1; - __sync_fetch_and_add(&mpq_blocks_prepared, -1); - align_bytes = QB->mqb_align_bytes; - } - } - } - if (!QB) { - char *new_block = malloc(offsetof(struct mp_queue_block, mqb_nodes) + size * (2 * sizeof(void *)) + - MPQ_BLOCK_ALIGNMENT - sizeof(void *)); - assert(new_block); - assert(!((long)new_block & (sizeof(void *) - 1))); - align_bytes = -(int)(long)new_block & (MPQ_BLOCK_ALIGNMENT - 1); - QB = (struct mp_queue_block *)(new_block + align_bytes); - - __sync_fetch_and_add(&mpq_blocks_true_allocations, 1); - if (is_small) { - int t = __sync_fetch_and_add(&mpq_small_blocks_allocated, 1); - if (t >= mpq_small_blocks_allocated_max) { - __sync_bool_compare_and_swap(&mpq_small_blocks_allocated_max, mpq_small_blocks_allocated_max, t + 1); - } - } else { - int t = __sync_fetch_and_add(&mpq_blocks_allocated, 1); - if (t >= mpq_blocks_allocated_max) { - __sync_bool_compare_and_swap(&mpq_blocks_allocated_max, mpq_blocks_allocated_max, t + 1); - } - } - } else { - assert(QB->mqb_size == size); - } - __sync_fetch_and_add(&mpq_blocks_allocations, 1); - - memset(QB, 0, offsetof(struct mp_queue_block, mqb_nodes)); - QB->mqb_align_bytes = align_bytes; - QB->mqb_size = size; - - QB->mqb_nodes[0].idx = MQN_SAFE; - QB->mqb_nodes[0].val = first_val; - - if (!prepared) { - long i; - for (i = 1; i < size; i++) { - QB->mqb_nodes[i].idx = MQN_SAFE + i; - QB->mqb_nodes[i].val = 0; - } - } - - if (first_val) { - QB->mqb_tail = 1; - } - - QB->mqb_magic = MQ_BLOCK_USED_MAGIC; - return QB; -} - -void free_mpq_block(struct mp_queue_block *QB) { - assert(QB->mqb_magic == MQ_BLOCK_USED_MAGIC); - assert((unsigned)QB->mqb_align_bytes < MPQ_BLOCK_ALIGNMENT && !(QB->mqb_align_bytes & (sizeof(void *) - 1))); - QB->mqb_magic = MQ_BLOCK_FREE_MAGIC; - if (QB->mqb_size == MPQ_SMALL_BLOCK_SIZE) { - __sync_fetch_and_add(&mpq_small_blocks_allocated, -1); - } else { - assert(QB->mqb_size == MPQ_BLOCK_SIZE); - __sync_fetch_and_add(&mpq_blocks_allocated, -1); - } - free((char *)QB - QB->mqb_align_bytes); -} - -static inline void mpq_fix_state(struct mp_queue_block *QB) { - long h, t; - while (1) { - barrier(); - t = QB->mqb_tail; - barrier(); - h = QB->mqb_head; - barrier(); - if ((unsigned long)h <= (unsigned long)t) { - break; - } - if (QB->mqb_tail != t) { - continue; - } - // here tail < head ; try to advance tail to head - // (or to some value h such that tail < h <= head) - if (__sync_bool_compare_and_swap(&QB->mqb_tail, t, h)) { - break; - } - } -} - -mqn_value_t mpq_block_pop(struct mp_queue_block *QB) { - // fprintf (stderr, "%d:mpq_block_pop(%p)\n", mpq_this_thread_id, QB); - long size = QB->mqb_size; - while (1) { - long h = __sync_fetch_and_add(&QB->mqb_head, 1); - // fprintf (stderr, "%d: mpq_block_pop(%ld)\n", mpq_this_thread_id, h); - mpq_node_t *node = &QB->mqb_nodes[h & (size - 1)]; - while (1) { - mpq_node_t d, e; - barrier(); - mqn_value_t val = node->val; - barrier(); - long safe_idx = node->idx; - barrier(); - long idx = safe_idx & MQN_IDX_MASK; - if (idx > h) { - break; - } - d.val = val; - d.idx = safe_idx; - if (val) { - if (idx == h) { - e.idx = safe_idx + size; - e.val = 0; - if (__sync_bool_compare_and_swap(&node->pair, d.pair, e.pair)) { - // fprintf (stderr, "%d: mpq_block_pop(%ld) -> %lx\n", mpq_this_thread_id, h, (long) val); - return val; - } - } else { - e.val = val; - e.idx = idx; // clear 'safe' flag - if (__sync_bool_compare_and_swap(&node->pair, d.pair, e.pair)) { - break; - } - } - } else { - e.idx = (safe_idx & MQN_SAFE) + h + size; - e.val = 0; - if (__sync_bool_compare_and_swap(&node->pair, d.pair, e.pair)) { - break; - } - } - /* somebody changed this element while we were inspecting it, make another loop iteration */ - } - barrier(); - long t = QB->mqb_tail & MQN_IDX_MASK; - barrier(); - if (t <= h + 1) { - mpq_fix_state(QB); - return 0; - } - /* now try again with a new value of h */ - } -} - -long mpq_block_push(struct mp_queue_block *QB, mqn_value_t val) { - int iterations = 0; - long size = QB->mqb_size; - // fprintf (stderr, "%d:mpq_block_push(%p)\n", mpq_this_thread_id, QB); - while (1) { - long t = __sync_fetch_and_add(&QB->mqb_tail, 1); - // fprintf (stderr, "%d: mpq_block_push(%ld)\n", mpq_this_thread_id, t); - if (t & MQN_SAFE) { - return -1L; // bad luck - } - mpq_node_t *node = &QB->mqb_nodes[t & (size - 1)]; - barrier(); - mqn_value_t old_val = node->val; - barrier(); - long safe_idx = node->idx; - barrier(); - long idx = safe_idx & MQN_IDX_MASK; - if (!old_val && idx <= t && ((safe_idx & MQN_SAFE) || QB->mqb_head <= t)) { - mpq_node_t d, e; - d.idx = safe_idx; - d.val = 0; - e.idx = MQN_SAFE + t; - e.val = val; - if (__sync_bool_compare_and_swap(&node->pair, d.pair, e.pair)) { - // fprintf (stderr, "%d: mpq_block_push(%ld) <- %lx\n", mpq_this_thread_id, t, (long) val); - return t; // pushed OK - } - } - barrier(); - long h = QB->mqb_head; - barrier(); - if (t - h >= size || ++iterations > 10) { - __sync_fetch_and_or(&QB->mqb_tail, MQN_SAFE); // closing queue - return -1L; // bad luck - } - } -} - -/* functions for mp_queue = list of mp_queue_block's */ -void init_mp_queue(struct mp_queue *MQ) { - assert(MQ->mq_magic != MQ_MAGIC && MQ->mq_magic != MQ_MAGIC_SEM); - memset(MQ, 0, sizeof(struct mp_queue)); - MQ->mq_head = MQ->mq_tail = alloc_mpq_block(0, 0, 1); - MQ->mq_magic = MQ_MAGIC; - - if (!MqGarbageBlocks.mq_magic) { - init_mp_queue(&MqGarbageBlocks); - init_mp_queue(&MqGarbageSmallBlocks); - } else if (!MqPreparedBlocks.mq_magic) { - init_mp_queue(&MqPreparedBlocks); - init_mp_queue(&MqPreparedSmallBlocks); - } -} - -void init_mp_queue_w(struct mp_queue *MQ) { - init_mp_queue(MQ); -#if MPQ_USE_POSIX_SEMAPHORES - sem_init(&MQ->mq_sem, 0, 0); -#endif - MQ->mq_magic = MQ_MAGIC_SEM; -} - -struct mp_queue *alloc_mp_queue(void) { - struct mp_queue *MQ = NULL; - assert(!posix_memalign((void **)&MQ, 64, sizeof(*MQ))); - memset(MQ, 0, sizeof(*MQ)); - init_mp_queue(MQ); - return MQ; -} - -struct mp_queue *alloc_mp_queue_w(void) { - struct mp_queue *MQ = NULL; - assert(!posix_memalign((void **)&MQ, 64, sizeof(*MQ))); - memset(MQ, 0, sizeof(*MQ)); - init_mp_queue_w(MQ); - return MQ; -} - -/* invoke only if sure that nobody else may be using this mp_queue in parallel */ -void clear_mp_queue(struct mp_queue *MQ) { - assert(MQ->mq_magic == MQ_MAGIC || MQ->mq_magic == MQ_MAGIC_SEM); - assert(MQ->mq_head && MQ->mq_tail); - struct mp_queue_block *QB = MQ->mq_head, *QBN; - for (QB = MQ->mq_head; QB; QB = QBN) { - QBN = QB->mqb_next; - assert(QB->mqb_next || QB == MQ->mq_tail); - QB->mqb_next = 0; - free_mpq_block(QB); - } - MQ->mq_head = MQ->mq_tail = 0; - MQ->mq_magic = 0; -} - -void free_mp_queue(struct mp_queue *MQ) { - clear_mp_queue(MQ); - free(MQ); -} - -// may invoke mpq_push() to discard new empty block -mqn_value_t mpq_pop(struct mp_queue *MQ, int flags) { - void **hptr = &mqb_hazard_ptr[get_this_thread_id()][0]; - long r = ((flags & MPQF_RECURSIVE) != 0); - struct mp_queue_block *QB; - mqn_value_t v; - while (1) { - QB = MQ->mq_head; - barrier(); - hptr[r] = QB; - barrier(); - __sync_synchronize(); - if (MQ->mq_head != QB) { - continue; - } - - v = mpq_block_pop(QB); - if (v) { - break; - } - barrier(); - if (!QB->mqb_next) { - QB = 0; - break; - } - v = mpq_block_pop(QB); - if (v) { - break; - } - if (__sync_bool_compare_and_swap(&MQ->mq_head, QB, QB->mqb_next)) { - // want to free QB here, but this is complicated if somebody else holds a pointer - if (is_hazard_ptr(QB, 0, 2) <= 1) { - free_mpq_block(QB); - } else { - __sync_fetch_and_add(&mpq_blocks_wasted, 1); - // ... put QB into some GC queue? ... - QB->mqb_magic = MQ_BLOCK_GARBAGE_MAGIC; - mpq_push(QB->mqb_size == MPQ_SMALL_BLOCK_SIZE ? &MqGarbageSmallBlocks : &MqGarbageBlocks, QB, - flags & MPQF_RECURSIVE); - } - } - } - if (flags & MPQF_STORE_PTR) { - hptr[2] = QB; - } - hptr[r] = 0; - return v; -} - -/* 1 = definitely empty (for some serialization), 0 = possibly non-empty; - may invoke mpq_push() to discard empty block */ -int mpq_is_empty(struct mp_queue *MQ) { - void **hptr = &mqb_hazard_ptr[get_this_thread_id()][0]; - struct mp_queue_block *QB; - while (1) { - QB = MQ->mq_head; - barrier(); - *hptr = QB; - barrier(); - __sync_synchronize(); - if (MQ->mq_head != QB) { - continue; - } - barrier(); - long h = QB->mqb_head; - barrier(); - long t = QB->mqb_tail; - barrier(); - if (!(t & MQN_SAFE)) { - *hptr = 0; - return t <= h; - } - t &= MQN_IDX_MASK; - if (t > h) { - *hptr = 0; - return 0; - } - barrier(); - if (!QB->mqb_next) { - *hptr = 0; - return 1; - } - if (__sync_bool_compare_and_swap(&MQ->mq_head, QB, QB->mqb_next)) { - // want to free QB here, but this is complicated if somebody else holds a pointer - if (is_hazard_ptr(QB, 0, 2) <= 1) { - free_mpq_block(QB); - } else { - __sync_fetch_and_add(&mpq_blocks_wasted, 1); - // ... put QB into some GC queue? ... - QB->mqb_magic = MQ_BLOCK_GARBAGE_MAGIC; - mpq_push(QB->mqb_size == MPQ_SMALL_BLOCK_SIZE ? &MqGarbageSmallBlocks : &MqGarbageBlocks, QB, 0); - } - } - } - *hptr = 0; - return 0; -} - -/* may invoke mpq_alloc_block (which recursively invokes mpq_pop) - or mpq_push() (without needing to hold hazard pointer) to deal with blocks */ -long mpq_push(struct mp_queue *MQ, mqn_value_t val, int flags) { - void **hptr = mqb_hazard_ptr[get_this_thread_id()]; - long r = ((flags & MPQF_RECURSIVE) != 0); - while (1) { - struct mp_queue_block *QB = MQ->mq_tail; - barrier(); - hptr[r] = QB; - barrier(); - __sync_synchronize(); - if (MQ->mq_tail != QB) { - continue; - } - - if (QB->mqb_next) { - __sync_bool_compare_and_swap(&MQ->mq_tail, QB, QB->mqb_next); - continue; - } - long pos = mpq_block_push(QB, val); - if (pos >= 0) { - if (flags & MPQF_STORE_PTR) { - hptr[2] = QB; - } - hptr[r] = 0; - return pos; - } -#define DBG(c) // fprintf (stderr, "[%d] pushing %lx to %p,%p: %c\n", mpq_this_thread_id, (long) val, MQ, QB, c); - DBG('A'); - /* - if (__sync_fetch_and_add (&QB->mqb_next_allocators, 1)) { - // somebody else will allocate next block; busy wait instead of spuruous alloc/free - DBG('B') - while (!QB->mqb_next) { - barrier (); - } - DBG('C') - continue; - } - */ - int is_small = (QB == MQ->mq_head); - struct mp_queue_block *NQB; - if (!r) { - assert(!hptr[1]); - NQB = alloc_mpq_block(val, 1, is_small); - assert(!hptr[1]); - } else { - NQB = alloc_mpq_block(val, 0, is_small); - } - assert(hptr[r] == QB); - DBG('D') - if (__sync_bool_compare_and_swap(&QB->mqb_next, 0, NQB)) { - __sync_bool_compare_and_swap(&MQ->mq_tail, QB, NQB); - DBG('E') - if (flags & MPQF_STORE_PTR) { - hptr[2] = NQB; - } - hptr[r] = 0; - return 0; - } else { - DBG('F'); - NQB->mqb_magic = MQ_BLOCK_PREPARED_MAGIC; - mpq_push(is_small ? &MqPreparedSmallBlocks : &MqPreparedBlocks, NQB, 0); - __sync_fetch_and_add(&mpq_blocks_prepared, 1); - } - } -#undef DBG -} - -mqn_value_t mpq_pop_w(struct mp_queue *MQ, int flags) { - assert(MQ->mq_magic == MQ_MAGIC_SEM); - int s = -1, iterations = flags & MPQF_MAX_ITERATIONS; - while (iterations-- > 0) { -#if MPQ_USE_POSIX_SEMAPHORES - s = sem_trywait(&MQ->mq_sem); -#else - s = mp_sem_trywait(&MQ->mq_sem); -#endif - if (!s) { - break; - } -#if MPQ_USE_POSIX_SEMAPHORES - assert(errno == EAGAIN || errno == EINTR); -#endif - } - while (s < 0) { -#if MPQ_USE_POSIX_SEMAPHORES - s = sem_wait(&MQ->mq_sem); -#else - s = mp_sem_wait(&MQ->mq_sem); -#endif - if (!s) { - break; - } -#if MPQ_USE_POSIX_SEMAPHORES - assert(errno == EAGAIN); -#endif - } - mqn_value_t *v = mpq_pop(MQ, flags); - assert(v); - return v; -} - -mqn_value_t mpq_pop_nw(struct mp_queue *MQ, int flags) { - assert(MQ->mq_magic == MQ_MAGIC_SEM); - int s = -1, iterations = flags & MPQF_MAX_ITERATIONS; - while (iterations-- > 0) { -#if MPQ_USE_POSIX_SEMAPHORES - s = sem_trywait(&MQ->mq_sem); -#else - s = mp_sem_trywait(&MQ->mq_sem); -#endif - if (s >= 0) { - break; - } -#if MPQ_USE_POSIX_SEMAPHORES - assert(errno == EAGAIN || errno == EINTR); -#endif - } - if (s < 0) { - return 0; - } - mqn_value_t *v = mpq_pop(MQ, flags); - assert(v); - return v; -} - -long mpq_push_w(struct mp_queue *MQ, mqn_value_t v, int flags) { - assert(MQ->mq_magic == MQ_MAGIC_SEM); - long res = mpq_push(MQ, v, flags); -#if MPQ_USE_POSIX_SEMAPHORES - assert(sem_post(&MQ->mq_sem) >= 0); -#else - assert(mp_sem_post(&MQ->mq_sem) >= 0); -#endif - return res; -} - -void *get_ptr_multithread_copy(void **ptr, void (*incref)(void *ptr)) { - void **hptr = &mqb_hazard_ptr[get_this_thread_id()][COMMON_HAZARD_PTR_NUM]; - assert(*hptr == NULL); - - void *R; - while (1) { - R = *ptr; - barrier(); - *hptr = R; - barrier(); - mfence(); - - if (R != *ptr) { - continue; - } - - incref(R); - - barrier(); - *hptr = NULL; - - break; - } - return R; -} -#endif diff --git a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.h b/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.h deleted file mode 100644 index 52bd9f2c..00000000 --- a/submodules/ton/tonlib-src/tdactor/benchmark/third_party/mp-queue.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - This file is part of KittenDB-Engine Library. - - KittenDB-Engine Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - KittenDB-Engine Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with KittenDB-Engine Library. If not, see . - - Copyright 2014 Telegraph Inc - 2014 Nikolai Durov - 2014 Andrey Lopatin -*/ - -#ifndef __KDB_MP_QUEUE_H__ -#define __KDB_MP_QUEUE_H__ - -#define MPQ_USE_POSIX_SEMAPHORES 0 - -#if MPQ_USE_POSIX_SEMAPHORES -#include -#endif - -typedef struct mp_semaphore { - volatile int value; - volatile int waiting; -} mp_sem_t; - -#define THREAD_HPTRS 21 - -#define MPQ_SMALL_BLOCK_SIZE 64 -#define MPQ_BLOCK_SIZE 4096 // must be a power of 2 -#define MPQ_BLOCK_ALIGNMENT 64 - -#ifdef _LP64 -typedef int int128_t __attribute__((__mode__(TI))); -#define DLONG int128_t -// # define DLONG __int128 -#define MQN_SAFE (-1LL << 63) -#else -#define DLONG long long -#define MQN_SAFE (-1L << 31) -#endif - -#define MQN_IDX_MASK (~MQN_SAFE) - -typedef void *mqn_value_t; - -typedef struct mp_queue_node { - union { - struct { - long idx; - union { - long mqn_value; - void *mqn_ptr; - mqn_value_t val; - }; - }; - DLONG pair; - }; -} mpq_node_t; - -#define MQ_BLOCK_USED_MAGIC 0x1ebacaef -#define MQ_BLOCK_FREE_MAGIC 0x2e4afeda -#define MQ_BLOCK_GARBAGE_MAGIC 0x3a04dc7d -#define MQ_BLOCK_PREPARED_MAGIC 0x4b9b13cd - -#define MQ_MAGIC 0x1aed9b43 -#define MQ_MAGIC_SEM 0x1aedcd21 - -struct mp_queue_block { - long mqb_head __attribute__((aligned(64))); - int mqb_magic; - int mqb_align_bytes; - int mqb_size; // power of 2; one of MPQ_BLOCK_SIZE or MPQ_SMALL_BLOCK_SIZE - long mqb_tail __attribute__((aligned(64))); - struct mp_queue_block *mqb_next; - int mqb_next_allocators; - mpq_node_t mqb_nodes[MPQ_BLOCK_SIZE] __attribute__((aligned(64))); -}; - -struct mp_queue { - struct mp_queue_block *mq_head __attribute__((aligned(64))); - int mq_magic; - struct mp_queue_block *mq_tail __attribute__((aligned(64))); -#if MPQ_USE_POSIX_SEMAPHORES - sem_t mq_sem __attribute__((aligned(64))); -#else - mp_sem_t mq_sem __attribute__((aligned(64))); -#endif -}; - -extern volatile int mpq_blocks_allocated, mpq_blocks_allocated_max, mpq_blocks_allocations, mpq_blocks_true_allocations, - mpq_blocks_wasted, mpq_blocks_prepared; -extern volatile int mpq_small_blocks_allocated, mpq_small_blocks_allocated_max; - -#define MAX_MPQ_THREADS 22 -extern __thread int mpq_this_thread_id; -extern __thread void **thread_hazard_pointers; -extern volatile int mpq_threads; - -/* initialize this thread id and return it */ -void clear_thread_ids(void); -int get_this_thread_id(void); - -/* functions for one mp_queue_block */ -struct mp_queue_block *alloc_mpq_block(mqn_value_t first_val, int allow_recursion, int is_small); -void free_mpq_block(struct mp_queue_block *QB); - -mqn_value_t mpq_block_pop(struct mp_queue_block *QB); -long mpq_block_push(struct mp_queue_block *QB, mqn_value_t val); - -/* functions for mp_queue = list of mp_queue_block's */ -void init_mp_queue(struct mp_queue *MQ); -struct mp_queue *alloc_mp_queue(void); -struct mp_queue *alloc_mp_queue_w(void); -void init_mp_queue_w(struct mp_queue *MQ); -void clear_mp_queue(struct mp_queue *MQ); // frees all mpq block chain; invoke only if nobody else is using mp-queue -void free_mp_queue(struct mp_queue *MQ); // same + invoke free() - -// flags for mpq_push / mpq_pop functions -#define MPQF_RECURSIVE 8192 -#define MPQF_STORE_PTR 4096 -#define MPQF_MAX_ITERATIONS (MPQF_STORE_PTR - 1) - -long mpq_push(struct mp_queue *MQ, mqn_value_t val, int flags); -mqn_value_t mpq_pop(struct mp_queue *MQ, int flags); -int mpq_is_empty(struct mp_queue *MQ); - -long mpq_push_w(struct mp_queue *MQ, mqn_value_t val, int flags); -mqn_value_t mpq_pop_w(struct mp_queue *MQ, int flags); -mqn_value_t mpq_pop_nw(struct mp_queue *MQ, int flags); - -int mp_sem_post(mp_sem_t *sem); -int mp_sem_wait(mp_sem_t *sem); -int mp_sem_trywait(mp_sem_t *sem); - -#define COMMON_HAZARD_PTR_NUM 3 -int is_hazard_ptr(void *ptr, int a, int b); -extern void *mqb_hazard_ptr[MAX_MPQ_THREADS][THREAD_HPTRS]; -void *get_ptr_multithread_copy(void **ptr, void (*incref)(void *ptr)); -#endif diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/ActorId.h b/submodules/ton/tonlib-src/tdactor/td/actor/ActorId.h deleted file mode 100644 index 248a5f68..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/ActorId.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/common.h" - -namespace td { -namespace actor { -template -class ActorId; -template -class ActorOwn; -template -class ActorShared; -namespace core { -template -ActorId actor_id(SelfT *self); -} - -// Essentially ActorInfoWeakPtr with Type -template -class ActorId { - public: - using ActorT = ActorType; - ActorId() = default; - ActorId(const ActorId &) = default; - ActorId &operator=(const ActorId &) = default; - ActorId(ActorId &&other) = default; - ActorId &operator=(ActorId &&other) = default; - - // allow only conversion from child to parent - template ::value>> - operator ActorId() const { - return ActorId(ptr_); - } - - template - friend ActorId actor_dynamic_cast(ActorId from); - - ActorType &get_actor_unsafe() const { - return static_cast(actor_info().actor()); - } - bool empty() const { - return !ptr_; - } - - bool is_alive() const { - return !empty() && actor_info().is_alive(); - } - - template - static ActorId create(ActorOptions &options, ArgsT &&... args) { - return ActorId(detail::create_actor(options, std::forward(args)...)); - } - - template - bool operator==(const ActorId &other) const { - return ptr_ == other.ptr_; - } - - detail::ActorRef as_actor_ref() const { - CHECK(!empty()); - return detail::ActorRef(*actor_info_ptr()); - } - - const core::ActorInfoPtr &actor_info_ptr() const { - return ptr_; - } - - core::ActorInfo &actor_info() const { - CHECK(ptr_); - return *ptr_; - } - - private: - core::ActorInfoPtr ptr_; - - template - friend class ActorId; - template - friend class ActorOwn; - template - friend class ActorShared; - - explicit ActorId(core::ActorInfoPtr ptr) : ptr_(std::move(ptr)) { - } - - template - friend ActorId core::actor_id(SelfT *self); -}; -template -ActorId actor_dynamic_cast(ActorId from) { - static_assert( - std::is_base_of::value || std::is_base_of::value, - "Invalid actor dynamic conversion"); - auto res = ActorId(std::move(from.ptr_)); - CHECK(dynamic_cast(&res.actor_info().actor()) == &res.get_actor_unsafe()); - return res; -} -namespace core { // for ADL -template -ActorId actor_id(SelfT *self) { - CHECK(self); - CHECK(static_cast(self) == &core::ActorExecuteContext::get()->actor()); - return ActorId(core::ActorExecuteContext::get()->actor().get_actor_info_ptr()); -} - -inline ActorId<> actor_id() { - return actor_id(&core::ActorExecuteContext::get()->actor()); -} -} // namespace core -using core::actor_id; -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/ActorOwn.h b/submodules/ton/tonlib-src/tdactor/td/actor/ActorOwn.h deleted file mode 100644 index 01ceef54..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/ActorOwn.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/common.h" -#include "td/actor/ActorId.h" - -namespace td { -namespace actor { -template -class ActorOwn { - public: - using ActorT = ActorType; - ActorOwn() = default; - explicit ActorOwn(ActorId id) : id_(std::move(id)) { - } - template - explicit ActorOwn(ActorId id) : id_(std::move(id)) { - } - template - ActorOwn(ActorOwn &&other) : id_(other.release()) { - } - template - ActorOwn &operator=(ActorOwn &&other) { - reset(other.release()); - return *this; - } - ActorOwn(ActorOwn &&other) : id_(other.release()) { - } - ActorOwn &operator=(ActorOwn &&other) { - reset(other.release()); - return *this; - } - ActorOwn(const ActorOwn &) = delete; - ActorOwn &operator=(const ActorOwn &) = delete; - ~ActorOwn() { - reset(); - } - - bool empty() const { - return id_.empty(); - } - bool is_alive() const { - return id_.is_alive(); - } - ActorId get() const { - return id_; - } - ActorType &get_actor_unsafe() const { - return (*this)->get_actor_unsafe(); - } - ActorId release() { - return std::move(id_); - } - void reset(ActorId other = ActorId()) { - static_assert(sizeof(ActorType) > 0, "Can't use ActorOwn with incomplete type"); - hangup(); - id_ = std::move(other); - } - const ActorId *operator->() const { - return &id_; - } - - detail::ActorRef as_actor_ref() const { - CHECK(!empty()); - return detail::ActorRef(*id_.actor_info_ptr(), 0); - } - - private: - ActorId id_; - void hangup() const { - if (empty()) { - return; - } - detail::send_message(as_actor_ref(), detail::ActorMessageCreator::hangup()); - } -}; - -template -ActorOwn actor_dynamic_cast(ActorOwn from) { - return ActorOwn(td::actor::actor_dynamic_cast(from.release())); -} - -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/ActorShared.h b/submodules/ton/tonlib-src/tdactor/td/actor/ActorShared.h deleted file mode 100644 index ffc4176b..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/ActorShared.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/common.h" -#include "td/actor/ActorId.h" - -namespace td { -namespace actor { - -template -class ActorShared { - public: - using ActorT = ActorType; - ActorShared() = default; - template - ActorShared(ActorId id, uint64 token) : id_(std::move(id)), token_(token) { - CHECK(token_ != 0); - } - template - ActorShared(ActorShared &&other) : id_(other.release()), token_(other.token()) { - } - template - ActorShared(ActorOwn &&other) : id_(other.release()), token_(other.token()) { - } - template - ActorShared &operator=(ActorShared &&other) { - reset(other.release(), other.token()); - } - ActorShared(ActorShared &&other) : id_(other.release()), token_(other.token()) { - } - ActorShared &operator=(ActorShared &&other) { - reset(other.release(), other.token()); - return *this; - } - ActorShared(const ActorShared &) = delete; - ActorShared &operator=(const ActorShared &) = delete; - ~ActorShared() { - reset(); - } - - uint64 token() const { - return token_; - } - bool empty() const { - return id_.empty(); - } - bool is_alive() const { - return id_.is_alive(); - } - ActorId get() const { - return id_; - } - ActorId release() { - return std::move(id_); - } - ActorType &get_actor_unsafe() const { - return (*this)->get_actor_unsafe(); - } - void reset(ActorId other = ActorId(), uint64 link_token = core::EmptyLinkToken) { - static_assert(sizeof(ActorType) > 0, "Can't use ActorShared with incomplete type"); - hangup(); - id_ = other; - token_ = link_token; - } - const ActorId *operator->() const { - return &id_; - } - - detail::ActorRef as_actor_ref() const { - CHECK(!empty()); - return detail::ActorRef(*id_.actor_info_ptr(), token_); - } - - private: - ActorId id_; - uint64 token_; - - void hangup() const { - if (empty()) { - return; - } - detail::send_message(as_actor_ref(), detail::ActorMessageCreator::hangup_shared()); - } -}; - -template -ActorShared actor_dynamic_cast(ActorShared from) { - return ActorShared(td::actor::actor_dynamic_cast(from.release()), from.token()); -} - -// common interface -namespace core { // for ADL -template -ActorShared actor_shared(SelfT *self, uint64 id = static_cast(-1)) { - return ActorShared(actor_id(self), id); -} - -inline ActorShared<> actor_shared() { - return actor_shared(&core::ActorExecuteContext::get()->actor()); -} -} // namespace core -using core::actor_shared; -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.cpp deleted file mode 100644 index 7ef534cd..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/MultiPromise.h" - -#include - -namespace td { -namespace detail { -class MultiPromiseImpl { - public: - explicit MultiPromiseImpl(MultiPromise::Options options) : options_(options) { - } - ~MultiPromiseImpl() { - for (auto &promise : pending_) { - promise.set_value(Unit()); - } - } - - void on_status(Status status) { - if (status.is_ok() || options_.ignore_errors) { - return; - } - std::vector> promises; - { - std::unique_lock lock(mutex_); - if (pending_error_.is_ok()) { - pending_error_ = status.clone(); - std::swap(promises, pending_); - } else { - CHECK(pending_.empty()); - } - } - for (auto &promise : promises) { - promise.set_error(status.clone()); - } - } - void add_promise(Promise<> promise) { - if (options_.ignore_errors) { - pending_.push_back(std::move(promise)); - } - Status status; - { - std::unique_lock lock(mutex_); - if (pending_error_.is_error()) { - status = pending_error_.clone(); - } else { - pending_.push_back(std::move(promise)); - } - } - if (status.is_error()) { - promise.set_error(std::move(status)); - } - } - - private: - std::mutex mutex_; - std::vector> pending_; - MultiPromise::Options options_; - Status pending_error_; -}; -} // namespace detail -void MultiPromise::InitGuard::add_promise(Promise<> promise) { - impl_->add_promise(std::move(promise)); -} -Promise<> MultiPromise::InitGuard::get_promise() { - return [impl = impl_](Result result) { - if (result.is_ok()) { - impl->on_status(Status::OK()); - } else { - impl->on_status(result.move_as_error()); - } - }; -} -bool MultiPromise::InitGuard::empty() const { - return !impl_; -} -MultiPromise::InitGuard::operator bool() const { - return !empty(); -} -MultiPromise::InitGuard MultiPromise::init_guard() { - CHECK(!impl_.lock()); - auto impl = std::make_shared(options_); - impl_ = impl; - return InitGuard(std::move(impl)); -} -MultiPromise::InitGuard MultiPromise::add_promise_or_init(Promise<> promise) { - auto impl = impl_.lock(); - if (!impl) { - auto guard = init_guard(); - guard.add_promise(std::move(promise)); - return guard; - } - impl->add_promise(std::move(promise)); - return {}; -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.h b/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.h deleted file mode 100644 index 954ec8d5..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/MultiPromise.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/PromiseFuture.h" - -namespace td { -namespace detail { -class MultiPromiseImpl; -} - -class MultiPromise { - using Impl = detail::MultiPromiseImpl; - - public: - struct Options { - Options() { - } - bool ignore_errors{false}; - }; - explicit MultiPromise(Options options = Options{}) : options_(options) { - } - - struct InitGuard { - public: - InitGuard() = default; - InitGuard(std::shared_ptr impl) : impl_(std::move(impl)) { - } - InitGuard(InitGuard &&other) = default; - InitGuard &operator=(InitGuard &&other) = default; - InitGuard(const InitGuard &other) = delete; - InitGuard &operator=(const InitGuard &other) = delete; - - void add_promise(Promise<> promise); - Promise<> get_promise(); - bool empty() const; - explicit operator bool() const; - - private: - std::shared_ptr impl_; - }; - - TD_WARN_UNUSED_RESULT InitGuard init_guard(); - TD_WARN_UNUSED_RESULT InitGuard add_promise_or_init(Promise<> promise); - - private: - Options options_; - std::weak_ptr impl_; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h b/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h deleted file mode 100644 index 2b8890d3..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/Closure.h" -#include "td/utils/common.h" -#include "td/utils/invoke.h" // for tuple_for_each -#include "td/utils/logging.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Status.h" - -#include -#include -#include - -namespace td { -namespace detail { -template -struct GetArg : public GetArg {}; - -template -class GetArg { - public: - using type = Arg; -}; -template -class GetArg { - public: - using type = Arg; -}; - -template -struct GetRet : public GetRet {}; - -template -class GetRet { - public: - using type = R; -}; -template -class GetRet { - public: - using type = R; -}; - -template -using get_arg_t = std::decay_t::type>; -template -using get_ret_t = std::decay_t::type>; - -template -struct DropResult { - using type = T; -}; - -template -struct DropResult> { - using type = T; -}; - -template -using drop_result_t = typename DropResult::type; -} // namespace detail - -template -class PromiseInterface { - public: - using ValueType = T; - PromiseInterface() = default; - PromiseInterface(const PromiseInterface &) = delete; - PromiseInterface &operator=(const PromiseInterface &) = delete; - PromiseInterface(PromiseInterface &&) = default; - PromiseInterface &operator=(PromiseInterface &&) = default; - virtual ~PromiseInterface() = default; - - virtual void set_value(T &&value) { - set_result(std::move(value)); - } - virtual void set_error(Status &&error) { - set_result(std::move(error)); - } - virtual void set_result(Result &&result) { - if (result.is_ok()) { - set_value(result.move_as_ok()); - } else { - set_error(result.move_as_error()); - } - } - - void operator()(T &&value) { - set_value(std::move(value)); - } - void operator()(Status &&error) { - set_error(std::move(error)); - } - void operator()(Result &&result) { - set_result(std::move(result)); - } -}; -template -class Promise; - -constexpr std::false_type is_promise_interface(...) { - return {}; -} -template -constexpr std::true_type is_promise_interface(const PromiseInterface &promise) { - return {}; -} -template -constexpr std::true_type is_promise_interface(const Promise &promise) { - return {}; -} - -template -constexpr bool is_promise_interface() { - return decltype(is_promise_interface(std::declval()))::value; -} - -constexpr std::false_type is_promise_interface_ptr(...) { - return {}; -} -template -constexpr std::true_type is_promise_interface_ptr(const unique_ptr &promise) { - return {}; -} - -template -constexpr bool is_promise_interface_ptr() { - return decltype(is_promise_interface_ptr(std::declval()))::value; -} -template -class LambdaPromise : public PromiseInterface { - public: - using ArgT = ValueT; - void set_value(ValueT &&value) override { - CHECK(has_lambda_.get()); - do_ok(std::move(value)); - has_lambda_ = false; - } - void set_error(Status &&error) override { - CHECK(has_lambda_.get()); - do_error(std::move(error)); - has_lambda_ = false; - } - - LambdaPromise(const LambdaPromise &other) = delete; - LambdaPromise &operator=(const LambdaPromise &other) = delete; - LambdaPromise(LambdaPromise &&other) = default; - LambdaPromise &operator=(LambdaPromise &&other) = default; - ~LambdaPromise() override { - if (has_lambda_.get()) { - do_error(Status::Error("Lost promise")); - } - } - - template - explicit LambdaPromise(FromOkT &&ok) : ok_(std::forward(ok)), has_lambda_(true) { - } - - private: - FunctionT ok_; - MovableValue has_lambda_{false}; - - template - std::enable_if_t>::value, void> do_error(Status &&status) { - ok_(Result(std::move(status))); - } - template - std::enable_if_t>::value, void> do_error(Y &&status) { - ok_(Auto()); - } - template - std::enable_if_t>::value, void> do_ok(ValueT &&result) { - ok_(Result(std::move(result))); - } - template - std::enable_if_t>::value, void> do_ok(ValueT &&result) { - ok_(std::move(result)); - } -}; - -template ::value, bool> has_t = false> -auto lambda_promise(F &&f) { - return LambdaPromise>>, std::decay_t>(std::forward(f)); -} -template ::value, bool> has_t = true> -auto lambda_promise(F &&f) { - return LambdaPromise>(std::forward(f)); -} - -template (), bool> from_promise_inerface = true> -auto &&promise_interface(F &&f) { - return std::forward(f); -} - -template (), bool> from_promise_inerface = false> -auto promise_interface(F &&f) { - return lambda_promise(std::forward(f)); -} - -template (), bool> from_promise_inerface = true> -auto promise_interface_ptr(F &&f) { - return std::forward(f); -} -template (), bool> from_promise_inerface = false> -auto promise_interface_ptr(F &&f) { - return std::make_unique(std::forward(f)))>>( - promise_interface(std::forward(f))); -} - -template -class Promise { - public: - using ArgT = T; - void set_value(T &&value) { - if (!promise_) { - return; - } - promise_->set_value(std::move(value)); - promise_.reset(); - } - void set_error(Status &&error) { - if (!promise_) { - return; - } - promise_->set_error(std::move(error)); - promise_.reset(); - } - - void set_result(Result &&result) { - if (!promise_) { - return; - } - promise_->set_result(std::move(result)); - promise_.reset(); - } - template - void operator()(S &&result) { - if (!promise_) { - return; - } - promise_->operator()(std::forward(result)); - promise_.reset(); - } - void reset() { - promise_.reset(); - } - std::unique_ptr> release() { - return std::move(promise_); - } - - Promise() = default; - explicit Promise(std::unique_ptr> promise) : promise_(std::move(promise)) { - } - - Promise &operator=(Promise &&) = default; - Promise(Promise &&) = default; - template - Promise(F &&f) : promise_(promise_interface_ptr(std::forward(f))) { - } - - explicit operator bool() { - return static_cast(promise_); - } - template - auto do_wrap(V &&value, F &&func) { - if (value.is_ok()) { - set_result(func(value.move_as_ok())); - } else { - set_error(value.move_as_error()); - } - } - - template - auto do_wrap(td::Status status, F &&func) { - set_error(std::move(status)); - } - - template - auto wrap(F &&func) { - return [promise = std::move(*this), func = std::move(func)](auto &&res) mutable { - promise.do_wrap(std::move(res), std::move(func)); - }; - } - template - auto send_closure(ArgsT &&... args); - - private: - std::unique_ptr> promise_; -}; - -namespace detail { -template -class JoinPromise : public PromiseInterface { - public: - explicit JoinPromise(ArgsT &&... arg) : promises_(std::forward(arg)...) { - } - void set_value(Unit &&) override { - tuple_for_each(promises_, [](auto &promise) { promise.set_value(Unit()); }); - } - void set_error(Status &&error) override { - tuple_for_each(promises_, [&error](auto &promise) { promise.set_error(error.clone()); }); - } - - private: - std::tuple...> promises_; -}; -} // namespace detail - -class PromiseCreator { - public: - struct Ignore { - void operator()(Status &&error) { - error.ignore(); - } - }; - - template - static auto lambda(OkT &&ok) { - return lambda_promise(std::forward(ok)); - } - - template - static Promise<> join(ArgsT &&... args) { - return Promise<>(std::make_unique>(std::forward(args)...)); - } -}; - -template -auto make_promise(F &&f) { - using ValueT = typename decltype(PromiseCreator::lambda(std::move(f)))::ArgT; - return Promise(PromiseCreator::lambda(std::move(f))); -} -template -auto make_promise(Promise &&f) { - return std::move(f); -} - -template -class SafePromise { - public: - SafePromise(Promise promise, Result result) : promise_(std::move(promise)), result_(std::move(result)) { - } - SafePromise(const SafePromise &other) = delete; - SafePromise &operator=(const SafePromise &other) = delete; - SafePromise(SafePromise &&other) = default; - SafePromise &operator=(SafePromise &&other) = default; - ~SafePromise() { - if (promise_) { - promise_.set_result(std::move(result_)); - } - } - Promise release() { - return std::move(promise_); - } - operator Promise() && { - return release(); - } - - private: - Promise promise_; - Result result_; -}; - -template -class PromiseMerger; - -template -struct SplitPromise { - using PromiseT = decltype(make_promise(std::declval())); - using ArgT = typename PromiseT::ArgT; - - template - static std::pair, Promise> split(std::pair); - template - static std::tuple...> split(std::tuple); - using SplittedT = decltype(split(std::declval())); - - template - static PromiseMerger merger(std::pair); - template - static PromiseMerger merger(std::tuple); - using MergerT = decltype(merger(std::declval())); -}; - -template -class PromiseMerger : public std::enable_shared_from_this> { - public: - std::tuple...> args_; - PromiseT promise_; - - PromiseMerger(PromiseT promise) : promise_(std::move(promise)) { - } - ~PromiseMerger() { - td::Status status; - tuple_for_each(args_, [&status](auto &&arg) { - if (status.is_error()) { - return; - } - if (arg.is_error()) { - status = arg.move_as_error(); - } - }); - if (status.is_error()) { - promise_.set_error(std::move(status)); - return; - } - call_tuple([this](auto &&... args) { promise_.set_value({args.move_as_ok()...}); }, std::move(args_)); - } - - template - Promise make_promise(T &arg) { - return [&arg, self = this->shared_from_this()](auto res) { arg = std::move(res); }; - } - - template - auto split() { - return call_tuple([this](auto &&... arg) { return R{this->make_promise(arg)...}; }, std::move(args_)); - } -}; - -template -auto split_promise(F &&f) { - auto merger = std::make_shared::MergerT>(std::move(f)); - return merger->template split::SplittedT>(); -} - -template -struct PromiseFuture { - Result> promise_; - Result result_; - ~PromiseFuture() { - if (promise_.is_ok()) { - promise_.move_as_ok().set_result(std::move(result_)); - } else { - LOG(ERROR) << "Lost PromiseFuture"; - } - } -}; -template -struct Future; - -template -std::pair, Future> make_promise_future(); - -template -struct Future { - Promise> promise_; - Future(Promise> promise) : promise_(std::move(promise)) { - } - - void finish(Promise promise) { - promise_.set_value(std::move(promise)); - } - - template - auto map(F &&f) { - using R = detail::drop_result_t()))>; - auto pf = make_promise_future(); - promise_.set_value([p = std::move(pf.first), f = std::move(f)](Result res) mutable { - TRY_RESULT_PROMISE(p, x, std::move(res)); - p.set_result(f(std::move(x))); - }); - - return std::move(pf.second); - } - - template - auto fmap(F &&f) { - return flatten(map(std::move(f))); - } - - template - static Future flatten(Future> ff) { - auto pf = make_promise_future(); - ff.promise_.set_value([p = std::move(pf.first)](Result> r_f) mutable { - TRY_RESULT_PROMISE(p, f, std::move(r_f)); - // Promise p - // Future f - f.promise_.set_value(std::move(p)); - }); - return std::move(pf.second); - } -}; - -template -Future make_future(T &&value) { - return Future([value = std::move(value)](Result> r_promise) mutable { - if (r_promise.is_ok()) { - r_promise.move_as_ok().set_value(std::move(value)); - } else { - LOG(ERROR) << "Lost future"; - } - }); -} - -template -std::pair, Future> make_promise_future() { - auto pf = std::make_shared>(); - Future future([pf](Result> res) mutable { pf->promise_ = std::move(res); }); - Promise promise = [pf = std::move(pf)](Result res) mutable { pf->result_ = std::move(res); }; - return std::make_pair(std::move(promise), std::move(future)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/actor.h b/submodules/ton/tonlib-src/tdactor/td/actor/actor.h deleted file mode 100644 index 1f4f6e99..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/actor.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/common.h" -#include "td/actor/ActorId.h" -#include "td/actor/ActorOwn.h" -#include "td/actor/ActorShared.h" - -namespace td { -namespace actor { - -template -TD_WARN_UNUSED_RESULT ActorOwn create_actor(ActorOptions options, ArgsT &&... args) { - return ActorOwn(ActorId::create(options, std::forward(args)...)); -} - -template -TD_WARN_UNUSED_RESULT ActorOwn create_actor(Slice name, ArgsT &&... args) { - return ActorOwn(ActorId::create(ActorOptions().with_name(name), std::forward(args)...)); -} - -#define SEND_CLOSURE_LATER 1 -#ifndef SEND_CLOSURE_LATER - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = false> -void send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure(id.as_actor_ref(), function, std::forward(args)...); -} - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = true> -void send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure_with_promise(id.as_actor_ref(), - call_n_arguments( - [&function](auto &&... nargs) { - return create_immediate_closure(function, - std::forward(nargs)...); - }, - std::forward(args)...), - get_last_argument(std::forward(args)...)); -} - -#else - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = false> -void send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure_later(id.as_actor_ref(), function, std::forward(args)...); -} - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = true> -void send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure_with_promise_later(id.as_actor_ref(), - call_n_arguments( - [&function](auto &&... nargs) { - return create_delayed_closure(function, - std::forward(nargs)...); - }, - std::forward(args)...), - get_last_argument(std::forward(args)...)); -} - -#endif - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = false> -auto future_send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using R = ::td::detail::get_ret_t>; - auto pf = make_promise_future(); - send_closure(std::forward(actor_id), std::move(function), std::forward(args)..., - std::move(pf.first)); - return std::move(pf.second); -} - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = true> -Future future_send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - auto pf = make_promise_future(); - send_closure(std::forward(actor_id), std::move(function), std::forward(args)..., - std::move(pf.first)); - return std::move(pf.second); -} - -template -bool send_closure_bool(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - send_closure(std::forward(actor_id), function, std::forward(args)...); - return true; -} - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = false> -void send_closure_later(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure_later(id.as_actor_ref(), function, std::forward(args)...); -} - -template , - size_t argument_count = member_function_argument_count(), - std::enable_if_t with_promise = true> -void send_closure_later(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - using ActorT = typename std::decay_t::ActorT; - static_assert(std::is_base_of::value, "unsafe send_closure"); - - ActorIdT id = std::forward(actor_id); - detail::send_closure_with_promise_later(id.as_actor_ref(), - call_n_arguments( - [&function](auto &&... nargs) { - return create_delayed_closure(function, - std::forward(nargs)...); - }, - std::forward(args)...), - get_last_argument(std::forward(args)...)); -} - -template -bool send_closure_later_bool(ActorIdT &&actor_id, FunctionT function, ArgsT &&... args) { - send_closure_later(std::forward(actor_id), function, std::forward(args)...); - return true; -} - -template -void send_lambda(ActorIdT &&actor_id, ArgsT &&... args) { - ActorIdT id = std::forward(actor_id); - detail::send_lambda(id.as_actor_ref(), std::forward(args)...); -} -template -void send_lambda_later(ActorIdT &&actor_id, ArgsT &&... args) { - ActorIdT id = std::forward(actor_id); - detail::send_lambda_later(id.as_actor_ref(), std::forward(args)...); -} -template -void send_signals(ActorIdT &&actor_id, ActorSignals signals) { - ActorIdT id = std::forward(actor_id); - detail::send_signals(id.as_actor_ref(), signals); -} -template -void send_signals_later(ActorIdT &&actor_id, ActorSignals signals) { - ActorIdT id = std::forward(actor_id); - detail::send_signals_later(id.as_actor_ref(), signals); -} -} // namespace actor - -class SendClosure { - public: - template - void operator()(ArgsT &&... args) const { - td::actor::send_closure(std::forward(args)...); - } -}; - -template -template -auto Promise::send_closure(ArgsT &&... args) { - return [promise = std::move(*this), t = std::make_tuple(std::forward(args)...)](auto &&r_res) mutable { - TRY_RESULT_PROMISE(promise, res, std::move(r_res)); - td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res), std::move(promise)))); - }; -} - -template -auto promise_send_closure(ArgsT &&... args) { - return [t = std::make_tuple(std::forward(args)...)](auto &&res) mutable { - td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res)))); - }; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/common.h b/submodules/ton/tonlib-src/tdactor/td/actor/common.h deleted file mode 100644 index eacc6192..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/common.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/core/Actor.h" -#include "td/actor/core/ActorSignals.h" -#include "td/actor/core/SchedulerId.h" -#include "td/actor/core/SchedulerContext.h" -#include "td/actor/core/Scheduler.h" - -#include "td/actor/PromiseFuture.h" - -#include "td/utils/Timer.h" - -namespace td { -namespace actor { -using core::ActorOptions; - -// Replacement for core::ActorSignals. Easier to use and do not allow internal signals -class ActorSignals { - public: - static ActorSignals pause() { - return ActorSignals(core::ActorSignals::one(core::ActorSignals::Pause)); - } - static ActorSignals kill() { - return ActorSignals(core::ActorSignals::one(core::ActorSignals::Kill)); - } - static ActorSignals wakeup() { - return ActorSignals(core::ActorSignals::one(core::ActorSignals::Wakeup)); - } - friend ActorSignals operator|(ActorSignals a, ActorSignals b) { - a.raw_.add_signals(b.raw_); - return a; - } - ActorSignals() = default; - - core::ActorSignals raw() const { - return raw_; - } - - private: - ActorSignals(core::ActorSignals raw) : raw_(raw) { - } - core::ActorSignals raw_; -}; - -// TODO: proper interface -using core::Actor; -using core::SchedulerContext; -using core::SchedulerId; -using core::set_debug; - -struct Debug { - public: - Debug() = default; - Debug(std::shared_ptr group_info) : group_info_(std::move(group_info)) { - } - template - void for_each(F &&f) { - for (auto &scheduler : group_info_->schedulers) { - f(scheduler.io_worker->debug); - for (auto &cpu : scheduler.cpu_workers) { - f(cpu->debug); - } - } - } - - void dump() { - for_each([](core::Debug &debug) { - core::DebugInfo info; - debug.read(info); - if (info.is_active) { - LOG(ERROR) << info.name << " " << td::format::as_time(Time::now() - info.start_at); - } - }); - } - - private: - std::shared_ptr group_info_; -}; - -class Scheduler { - public: - struct NodeInfo { - NodeInfo(size_t cpu_threads) : cpu_threads_(cpu_threads) { - } - NodeInfo(size_t cpu_threads, size_t io_threads) : cpu_threads_(cpu_threads), io_threads_(io_threads) { - } - size_t cpu_threads_; - size_t io_threads_{1}; - }; - - enum Mode { Running, Paused }; - Scheduler(std::vector infos, Mode mode = Paused) : infos_(std::move(infos)) { - init(); - if (mode == Running) { - start(); - } - } - - ~Scheduler() { - stop(); - } - Scheduler(const Scheduler &) = delete; - Scheduler(Scheduler &&) = delete; - Scheduler &operator=(const Scheduler &) = delete; - Scheduler &operator=(Scheduler &&) = delete; - - void start() { - if (is_started_) { - return; - } - is_started_ = true; - for (size_t it = 0; it < schedulers_.size(); it++) { - auto &scheduler = schedulers_[it]; - scheduler->start(); - if (it != 0) { - auto thread = td::thread([&] { - while (scheduler->run(10)) { - } - }); - thread.set_name(PSLICE() << "#" << it << ":io"); - thread.detach(); - } - } - } - - Debug get_debug() { - return Debug{group_info_}; - } - - bool run() { - start(); - while (schedulers_[0]->run(10)) { - } - return false; - } - - bool run(double timeout) { - start(); - return schedulers_[0]->run(timeout); - } - - template - void run_in_context(F &&f) { - schedulers_[0]->run_in_context(std::forward(f)); - } - - template - void run_in_context_external(F &&f) { - schedulers_[0]->run_in_context_external(std::forward(f)); - } - - void stop() { - if (!group_info_) { - return; - } - if (!is_started_) { - start(); - } - schedulers_[0]->stop(); - run(); - core::Scheduler::close_scheduler_group(*group_info_); - group_info_.reset(); - } - - private: - std::vector infos_{td::thread::hardware_concurrency()}; - std::shared_ptr group_info_; - std::vector> schedulers_; - bool is_started_{false}; - - void init() { - CHECK(infos_.size() < 256); - CHECK(!group_info_); - group_info_ = std::make_shared(infos_.size()); - td::uint8 id = 0; - for (const auto &info : infos_) { - schedulers_.emplace_back(td::make_unique(group_info_, core::SchedulerId{id}, info.cpu_threads_)); - id++; - } - } -}; - -// Some helper functions. Not part of public interface and not part -// of namespace core -namespace detail { -template -class ActorMessageLambda : public core::ActorMessageImpl { - public: - template - explicit ActorMessageLambda(FromLambdaT &&lambda) : lambda_(std::forward(lambda)) { - } - void run() override { - //delivery_warning_.reset(); - lambda_(); - } - - private: - LambdaT lambda_; - //PerfWarningTimer delivery_warning_{"Long message delivery", 2}; -}; - -class ActorMessageCreator { - public: - template - static auto lambda(F &&f) { - return core::ActorMessage(std::make_unique>>(std::forward(f))); - } - - static auto hangup() { - return core::ActorMessage(std::make_unique()); - } - - static auto hangup_shared() { - return core::ActorMessage(std::make_unique()); - } - - // Use faster allocation? -}; -struct ActorRef { - ActorRef(core::ActorInfo &actor_info, uint64 link_token = core::EmptyLinkToken) - : actor_info(actor_info), link_token(link_token) { - } - - core::ActorInfo &actor_info; - uint64 link_token; -}; - -template -T ¤t_actor() { - return static_cast(core::ActorExecuteContext::get()->actor()); -} - -inline void send_message(core::ActorInfo &actor_info, core::ActorMessage message) { - auto scheduler_context_ptr = core::SchedulerContext::get(); - if (scheduler_context_ptr == nullptr) { - LOG(ERROR) << "send to actor is silently ignored"; - return; - } - auto &scheduler_context = *scheduler_context_ptr; - core::ActorExecutor executor(actor_info, scheduler_context, - core::ActorExecutor::Options().with_has_poll(scheduler_context.has_poll())); - executor.send(std::move(message)); -} - -inline void send_message(ActorRef actor_ref, core::ActorMessage message) { - message.set_link_token(actor_ref.link_token); - send_message(actor_ref.actor_info, std::move(message)); -} -inline void send_message_later(core::ActorInfo &actor_info, core::ActorMessage message) { - auto scheduler_context_ptr = core::SchedulerContext::get(); - if (scheduler_context_ptr == nullptr) { - LOG(ERROR) << "send to actor is silently ignored"; - return; - } - auto &scheduler_context = *scheduler_context_ptr; - core::ActorExecutor executor(actor_info, scheduler_context, - core::ActorExecutor::Options().with_has_poll(scheduler_context.has_poll())); - message.set_big(); - executor.send(std::move(message)); -} - -inline void send_message_later(ActorRef actor_ref, core::ActorMessage message) { - message.set_link_token(actor_ref.link_token); - send_message_later(actor_ref.actor_info, std::move(message)); -} - -template -void send_immediate(ActorRef actor_ref, ExecuteF &&execute, ToMessageF &&to_message) { - auto scheduler_context_ptr = core::SchedulerContext::get(); - if (scheduler_context_ptr == nullptr) { - LOG(ERROR) << "send to actor is silently ignored"; - return; - } - auto &scheduler_context = *scheduler_context_ptr; - core::ActorExecutor executor(actor_ref.actor_info, scheduler_context, - core::ActorExecutor::Options().with_has_poll(scheduler_context.has_poll())); - if (executor.can_send_immediate()) { - return executor.send_immediate(execute, actor_ref.link_token); - } - auto message = to_message(); - message.set_link_token(actor_ref.link_token); - executor.send(std::move(message)); -} - -template -void send_lambda(ActorRef actor_ref, F &&lambda) { - send_immediate(actor_ref, lambda, [&lambda]() mutable { return ActorMessageCreator::lambda(std::move(lambda)); }); -} -template -void send_lambda_later(ActorRef actor_ref, F &&lambda) { - send_message_later(actor_ref, ActorMessageCreator::lambda(std::move(lambda))); -} - -template -void send_closure_impl(ActorRef actor_ref, ClosureT &&closure) { - using ActorType = typename ClosureT::ActorType; - send_immediate( - actor_ref, [&closure]() mutable { closure.run(¤t_actor()); }, - [&closure]() mutable { - return ActorMessageCreator::lambda( - [closure = to_delayed_closure(std::move(closure))]() mutable { closure.run(¤t_actor()); }); - }); -} - -template -void send_closure(ActorRef actor_ref, ArgsT &&... args) { - send_closure_impl(actor_ref, create_immediate_closure(std::forward(args)...)); -} - -template -void send_closure_later_impl(ActorRef actor_ref, ClosureT &&closure) { - using ActorType = typename ClosureT::ActorType; - send_message_later(actor_ref, - ActorMessageCreator::lambda([closure = to_delayed_closure(std::move(closure))]() mutable { - closure.run(¤t_actor()); - })); -} - -template -void send_closure_with_promise(ActorRef actor_ref, ClosureT &&closure, PromiseT &&promise) { - using ActorType = typename ClosureT::ActorType; - using ResultType = decltype(closure.run(¤t_actor())); - auto &&promise_i = promise_interface(std::forward(promise)); - send_immediate( - actor_ref, [&closure, &promise = promise_i]() mutable { promise(closure.run(¤t_actor())); }, - [&closure, &promise = promise_i]() mutable { - return ActorMessageCreator::lambda( - [closure = to_delayed_closure(std::move(closure)), promise = std::move(promise)]() mutable { - promise(closure.run(¤t_actor())); - }); - }); -} - -template -void send_closure_with_promise_later(ActorRef actor_ref, ClosureT &&closure, PromiseT &&promise) { - using ActorType = typename ClosureT::ActorType; - using ResultType = decltype(closure.run(¤t_actor())); - send_message_later( - actor_ref, - ActorMessageCreator::lambda([closure = to_delayed_closure(std::move(closure)), - promise = promise_interface(std::forward(promise))]() mutable { - promise(closure.run(¤t_actor())); - })); -} - -template -void send_closure_later(ActorRef actor_ref, ArgsT &&... args) { - send_closure_later_impl(actor_ref, create_delayed_closure(std::forward(args)...)); -} - -inline void send_signals(ActorRef actor_ref, ActorSignals signals) { - auto scheduler_context_ptr = core::SchedulerContext::get(); - if (scheduler_context_ptr == nullptr) { - LOG(ERROR) << "send to actor is silently ignored"; - return; - } - auto &scheduler_context = *scheduler_context_ptr; - core::ActorExecutor executor(actor_ref.actor_info, scheduler_context, - core::ActorExecutor::Options().with_has_poll(scheduler_context.has_poll())); - if (executor.can_send_immediate()) { - return executor.send_immediate(signals.raw()); - } - executor.send(signals.raw()); -} - -inline void send_signals_later(ActorRef actor_ref, ActorSignals signals) { - auto scheduler_context_ptr = core::SchedulerContext::get(); - if (scheduler_context_ptr == nullptr) { - LOG(ERROR) << "send to actor is silently ignored"; - return; - } - auto &scheduler_context = *scheduler_context_ptr; - core::ActorExecutor executor(actor_ref.actor_info, scheduler_context, - core::ActorExecutor::Options().with_has_poll(scheduler_context.has_poll())); - executor.send((signals | ActorSignals::pause()).raw()); -} - -inline void register_actor_info_ptr(core::ActorInfoPtr actor_info_ptr) { - auto state = actor_info_ptr->state().get_flags_unsafe(); - core::SchedulerContext::get()->add_to_queue(std::move(actor_info_ptr), state.get_scheduler_id(), !state.is_shared()); -} - -template -core::ActorInfoPtr create_actor(core::ActorOptions &options, ArgsT &&... args) noexcept { - auto *scheduler_context = core::SchedulerContext::get(); - if (!options.has_scheduler()) { - options.on_scheduler(scheduler_context->get_scheduler_id()); - } - auto res = - scheduler_context->get_actor_info_creator().create(std::make_unique(std::forward(args)...), options); - register_actor_info_ptr(res); - return res; -} -} // namespace detail -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/Actor.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/Actor.h deleted file mode 100644 index 3d581fe5..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/Actor.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/core/ActorInfo.h" - -#include "td/utils/SharedObjectPool.h" - -namespace td { -namespace actor { -namespace core { -class Actor { - public: - Actor() = default; - Actor(const Actor &) = delete; - Actor &operator=(const Actor &) = delete; - Actor(Actor &&other) = delete; - Actor &operator=(Actor &&other) = delete; - virtual ~Actor() = default; - - void set_actor_info_ptr(ActorInfoPtr actor_info_ptr) { - actor_info_ptr_ = std::move(actor_info_ptr); - } - const ActorInfoPtr &get_actor_info_ptr() const { - return actor_info_ptr_; - } - - td::Unit dummy() { - return td::Unit(); - } - - protected: - // Signal handlers - virtual void start_up() { // StartUp signal handler - yield(); - } - virtual void tear_down() { // TearDown signal handler (or Kill) - //noop - } - virtual void hangup() { // HangUp signal handler - stop(); - } - virtual void hangup_shared() { // HangUp signal handler - loop(); - } - virtual void wake_up() { // WakeUp signal handler - loop(); - } - virtual void alarm() { // Alarm signal handler - loop(); - } - - virtual void loop() { // default handler - //noop - } - - // Useful functions - void yield() { // send wakeup signal to itself - ActorExecuteContext::get()->set_yield(); - } - void stop() { // send Kill signal to itself - ActorExecuteContext::get()->set_stop(); - } - Timestamp &alarm_timestamp() { - return ActorExecuteContext::get()->alarm_timestamp(); - } - Timestamp get_alarm_timestamp() { - return ActorExecuteContext::get()->get_alarm_timestamp(); - } - - CSlice get_name() { - return actor_info_ptr_->get_name(); - } - uint64 get_link_token() { - return ActorExecuteContext::get()->get_link_token(); - } - - //set context that will be inherited by all childrens - //void set_context(std::shared_ptr context); - - //void do_stop(); // process Kill signal immediately - - private: - friend class ActorExecutor; - friend class ActorMessageHangup; - friend class ActorMessageHangupShared; - - ActorInfoPtr actor_info_ptr_; -}; - -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecuteContext.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecuteContext.h deleted file mode 100644 index 37f7d856..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecuteContext.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/Context.h" - -#include "td/utils/logging.h" -#include "td/utils/Time.h" - -#include - -namespace td { -namespace actor { -namespace core { -class Actor; - -enum : uint64 { EmptyLinkToken = std::numeric_limits::max() }; - -class ActorExecuteContext : public Context { - public: - explicit ActorExecuteContext(Actor *actor, Timestamp alarm_timestamp = Timestamp::never()) - : actor_(actor), alarm_timestamp_(alarm_timestamp) { - } - void set_actor(Actor *actor) { - actor_ = actor; - } - Actor &actor() const { - CHECK(actor_); - return *actor_; - } - bool has_flags() const { - return flags_ != 0; - } - bool has_immediate_flags() const { - return (flags_ & ~(1 << Alarm)) != 0; - } - void set_stop() { - flags_ |= 1 << Stop; - } - bool get_stop() const { - return (flags_ & (1 << Stop)) != 0; - } - void set_pause() { - flags_ |= 1 << Pause; - } - bool get_pause() const { - return (flags_ & (1 << Pause)) != 0; - } - void clear_actor() { - actor_ = nullptr; - } - void set_link_token(uint64 link_token) { - link_token_ = link_token; - } - uint64 get_link_token() const { - return link_token_; - } - Timestamp &alarm_timestamp() { - flags_ |= 1 << Alarm; - return alarm_timestamp_; - } - bool get_alarm_flag() const { - return (flags_ & (1 << Alarm)) != 0; - } - Timestamp get_alarm_timestamp() const { - return alarm_timestamp_; - } - void set_yield() { - flags_ |= 1 << Yield; - } - bool get_yield() { - return (flags_ & (1 << Yield)) != 0; - } - - private: - Actor *actor_; - uint32 flags_{0}; - uint64 link_token_{EmptyLinkToken}; - Timestamp alarm_timestamp_; - enum { Stop, Pause, Alarm, Yield }; -}; - -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp deleted file mode 100644 index 8c5fde62..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/core/ActorExecutor.h" - -#include "td/utils/ScopeGuard.h" - -namespace td { -namespace actor { -namespace core { -void ActorExecutor::send_immediate(ActorMessage message) { - CHECK(can_send_immediate()); - if (is_closed()) { - return; - } - if (message.is_big()) { - actor_info_.mailbox().reader().delay(std::move(message)); - pending_signals_.add_signal(ActorSignals::Message); - actor_execute_context_.set_pause(); - return; - } - actor_execute_context_.set_link_token(message.get_link_token()); - message.run(); -} - -void ActorExecutor::send_immediate(ActorSignals signals) { - CHECK(can_send_immediate()); - if (is_closed()) { - return; - } - SCOPE_EXIT { - pending_signals_.add_signals(signals); - }; - while (flush_one_signal(signals) && !actor_execute_context_.has_immediate_flags()) { - } -} - -void ActorExecutor::send(ActorMessage message) { - if (is_closed()) { - return; - } - if (can_send_immediate()) { - //LOG(ERROR) << "AE::send immediate"; - return send_immediate(std::move(message)); - } - //LOG(ERROR) << "AE::send delayed"; - actor_info_.mailbox().push(std::move(message)); - pending_signals_.add_signal(ActorSignals::Message); -} - -void ActorExecutor::send(ActorSignals signals) { - if (is_closed()) { - return; - } - - if (can_send_immediate()) { - return send_immediate(signals); - } - - pending_signals_.add_signals(signals); -} - -void ActorExecutor::start() noexcept { - //LOG(ERROR) << "START " << actor_info_.get_name() << " " << tag("from_queue", options_.from_queue); - if (is_closed()) { - return; - } - - ActorSignals signals; - SCOPE_EXIT { - pending_signals_.add_signals(signals); - }; - - if (options_.from_queue) { - signals.add_signal(ActorSignals::Pop); - } - - actor_locker_.try_lock(); - flags_ = actor_locker_.flags(); - - if (!actor_locker_.own_lock()) { - return; - } - - if (!actor_locker_.can_execute()) { - CHECK(!options_.from_queue); - return; - } - - signals.add_signals(flags().get_signals()); - if (options_.from_queue) { - signals.clear_signal(ActorSignals::Pause); - } - flags().clear_signals(); - - if (flags_.is_closed()) { - return; - } - - actor_execute_context_.set_actor(&actor_info_.actor()); - - while (flush_one_signal(signals)) { - if (actor_execute_context_.has_immediate_flags()) { - return; - } - } - while (flush_one_message()) { - if (actor_execute_context_.has_immediate_flags()) { - return; - } - } -} - -void ActorExecutor::finish() noexcept { - //LOG(ERROR) << "FINISH " << actor_info_.get_name() << " " << tag("own_lock", actor_locker_.own_lock()); - if (!actor_locker_.own_lock()) { - if (!pending_signals_.empty() && actor_locker_.add_signals(pending_signals_)) { - flags_ = actor_locker_.flags(); - //LOG(ERROR) << "Own after finish " << actor_info_.get_name() << " " << format::as_binary(flags().raw()); - } else { - //LOG(ERROR) << "DO FINISH " << actor_info_.get_name() << " " << flags(); - return; - } - } else { - flags_.add_signals(pending_signals_); - } - - CHECK(actor_locker_.own_lock()); - - if (td::unlikely(actor_execute_context_.has_flags())) { - flush_context_flags(); - } - - bool add_to_queue = false; - while (true) { - // Drop InQueue flag if has pop signal - // Can't delay or ignore this signal - auto signals = flags().get_signals(); - if (signals.has_signal(ActorSignals::Pop)) { - signals.clear_signal(ActorSignals::Pop); - flags().set_signals(signals); - flags().set_in_queue(false); - //LOG(ERROR) << "clear in_queue " << format::as_binary(flags().raw()); - } - - //LOG(ERROR) << tag("in_queue", flags().is_in_queue()) << tag("has_signals", flags().has_signals()); - if (flags_.is_closed()) { - // Writing to mailbox and closing actor may happen concurrently - // We must ensure that all messages in mailbox will be deleted - // Note that an ActorExecute may have to delete messages that was added by itself. - actor_info_.mailbox().clear(); - } else { - // No need to add closed actor into queue. - if (flags().has_signals() && !flags().is_in_queue()) { - add_to_queue = true; - flags().set_in_queue(true); - } - } - ActorInfoPtr actor_info_ptr; - if (add_to_queue) { - actor_info_ptr = actor_info_.actor().get_actor_info_ptr(); - } - if (actor_locker_.try_unlock(flags())) { - if (add_to_queue) { - dispatcher_.add_to_queue(std::move(actor_info_ptr), flags().get_scheduler_id(), !flags().is_shared()); - } - break; - } - flags_ = actor_locker_.flags(); - } - //LOG(ERROR) << "DO FINISH " << actor_info_.get_name() << " " << flags(); -} - -bool ActorExecutor::flush_one_signal(ActorSignals &signals) { - auto signal = signals.first_signal(); - if (!signal) { - return false; - } - switch (signal) { - //NB: Signals will be handled in order of their value. - // For clarity it conincides with order in this switch - case ActorSignals::Pause: - actor_execute_context_.set_pause(); - break; - case ActorSignals::Kill: - actor_execute_context_.set_stop(); - break; - case ActorSignals::StartUp: - actor_info_.actor().start_up(); - break; - case ActorSignals::Wakeup: - actor_info_.actor().wake_up(); - break; - case ActorSignals::Alarm: - if (actor_execute_context_.get_alarm_timestamp() && actor_execute_context_.get_alarm_timestamp().is_in_past()) { - actor_execute_context_.alarm_timestamp() = Timestamp::never(); - actor_info_.actor().alarm(); - } - break; - case ActorSignals::Io: - case ActorSignals::Cpu: - LOG(FATAL) << "TODO"; - break; - case ActorSignals::Message: - pending_signals_.add_signal(ActorSignals::Message); - actor_info_.mailbox().pop_all(); - break; - case ActorSignals::Pop: - flags().set_in_queue(false); - break; - default: - UNREACHABLE(); - } - signals.clear_signal(signal); - return true; -} - -bool ActorExecutor::flush_one_message() { - auto message = actor_info_.mailbox().reader().read(); - //LOG(ERROR) << "flush one message " << !!message << " " << actor_info_.get_name(); - if (!message) { - pending_signals_.clear_signal(ActorSignals::Message); - return false; - } - if (message.is_big() && !options_.from_queue) { - actor_info_.mailbox().reader().delay(std::move(message)); - actor_execute_context_.set_pause(); - return false; - } - - actor_execute_context_.set_link_token(message.get_link_token()); - message.run(); - return true; -} - -void ActorExecutor::flush_context_flags() { - if (actor_execute_context_.get_stop()) { - if (actor_info_.get_alarm_timestamp()) { - actor_info_.set_alarm_timestamp(Timestamp::never()); - dispatcher_.set_alarm_timestamp(actor_info_.actor().get_actor_info_ptr()); - } - flags_.set_closed(true); - if (!flags_.get_signals().has_signal(ActorSignals::Signal::StartUp)) { - actor_info_.actor().tear_down(); - } - actor_info_.destroy_actor(); - } else { - if (actor_execute_context_.get_pause()) { - flags_.add_signals(ActorSignals::one(ActorSignals::Pause)); - } - if (actor_execute_context_.get_yield()) { - flags_.add_signals(ActorSignals::one(ActorSignals::Wakeup)); - } - if (actor_execute_context_.get_alarm_flag()) { - auto old_timestamp = actor_info_.get_alarm_timestamp(); - auto new_timestamp = actor_execute_context_.get_alarm_timestamp(); - if (!(old_timestamp == new_timestamp)) { - actor_info_.set_alarm_timestamp(new_timestamp); - dispatcher_.set_alarm_timestamp(actor_info_.actor().get_actor_info_ptr()); - } - } - } -} -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.h deleted file mode 100644 index 9a2c5d29..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorExecuteContext.h" -#include "td/actor/core/ActorInfo.h" -#include "td/actor/core/ActorLocker.h" -#include "td/actor/core/ActorMessage.h" -#include "td/actor/core/ActorSignals.h" -#include "td/actor/core/ActorState.h" -#include "td/actor/core/SchedulerContext.h" - -#include "td/utils/format.h" - -namespace td { -namespace actor { -namespace core { -class ActorExecutor { - public: - struct Options { - Options &with_from_queue() { - from_queue = true; - return *this; - } - Options &with_has_poll(bool new_has_poll) { - this->has_poll = new_has_poll; - return *this; - } - bool from_queue{false}; - bool has_poll{false}; - }; - - ActorExecutor(ActorInfo &actor_info, SchedulerDispatcher &dispatcher, Options options) - : actor_info_(actor_info), dispatcher_(dispatcher), options_(options) { - old_log_tag_ = LOG_TAG2; - LOG_TAG2 = actor_info.get_name().c_str(); - start(); - } - ActorExecutor(const ActorExecutor &) = delete; - ActorExecutor &operator=(const ActorExecutor &) = delete; - ActorExecutor(ActorExecutor &&other) = delete; - ActorExecutor &operator=(ActorExecutor &&other) = delete; - ~ActorExecutor() { - finish(); - LOG_TAG2 = old_log_tag_; - } - - // our best guess if actor is closed or not - bool is_closed() { - return flags().is_closed(); - } - - bool can_send_immediate() { - return actor_locker_.own_lock() && !actor_execute_context_.has_immediate_flags() && actor_locker_.can_execute(); - } - - template - void send_immediate(F &&f, uint64 link_token) { - CHECK(can_send_immediate()); - if (is_closed()) { - return; - } - actor_execute_context_.set_link_token(link_token); - f(); - } - - void send_immediate(ActorMessage message); - void send_immediate(ActorSignals signals); - void send(ActorMessage message); - void send(ActorSignals signals); - - private: - ActorInfo &actor_info_; - SchedulerDispatcher &dispatcher_; - Options options_; - ActorLocker actor_locker_{&actor_info_.state(), ActorLocker::Options() - .with_can_execute_paused(options_.from_queue) - .with_is_shared(!options_.has_poll) - .with_scheduler_id(dispatcher_.get_scheduler_id())}; - - ActorExecuteContext actor_execute_context_{nullptr, actor_info_.get_alarm_timestamp()}; - ActorExecuteContext::Guard guard{&actor_execute_context_}; - - ActorState::Flags flags_; - ActorSignals pending_signals_; - - const char *old_log_tag_; - - ActorState::Flags &flags() { - return flags_; - } - - void start() noexcept; - void finish() noexcept; - - bool flush_one(ActorSignals &signals); - bool flush_one_signal(ActorSignals &signals); - bool flush_one_message(); - void flush_context_flags(); -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfo.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfo.h deleted file mode 100644 index 97419293..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfo.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorState.h" -#include "td/actor/core/ActorMailbox.h" - -#include "td/utils/Heap.h" -#include "td/utils/List.h" -#include "td/utils/Time.h" -#include "td/utils/SharedObjectPool.h" - -namespace td { -namespace actor { -namespace core { -class Actor; -class ActorInfo; -using ActorInfoPtr = SharedObjectPool::Ptr; -class ActorInfo : private HeapNode, private ListNode { - public: - ActorInfo(std::unique_ptr actor, ActorState::Flags state_flags, Slice name) - : actor_(std::move(actor)), name_(name.begin(), name.size()) { - state_.set_flags_unsafe(state_flags); - VLOG(actor) << "Create actor [" << name_ << "]"; - } - ~ActorInfo() { - VLOG(actor) << "Destroy actor [" << name_ << "]"; - CHECK(!actor_); - } - - bool is_alive() const { - return !state_.get_flags_unsafe().is_closed(); - } - - bool has_actor() const { - return bool(actor_); - } - Actor &actor() { - CHECK(has_actor()); - return *actor_; - } - Actor *actor_ptr() const { - return actor_.get(); - } - void destroy_actor() { - actor_.reset(); - } - ActorState &state() { - return state_; - } - ActorMailbox &mailbox() { - return mailbox_; - } - CSlice get_name() const { - return name_; - } - - HeapNode *as_heap_node() { - return this; - } - static ActorInfo *from_heap_node(HeapNode *node) { - return static_cast(node); - } - - Timestamp get_alarm_timestamp() const { - return Timestamp::at(alarm_timestamp_at_.load(std::memory_order_relaxed)); - } - void set_alarm_timestamp(Timestamp timestamp) { - alarm_timestamp_at_.store(timestamp.at(), std::memory_order_relaxed); - } - - void pin(ActorInfoPtr ptr) { - CHECK(pin_.empty()); - CHECK(&*ptr == this); - pin_ = std::move(ptr); - } - ActorInfoPtr unpin() { - CHECK(!pin_.empty()); - return std::move(pin_); - } - - private: - std::unique_ptr actor_; - ActorState state_; - ActorMailbox mailbox_; - std::string name_; - std::atomic alarm_timestamp_at_{0}; - - ActorInfoPtr pin_; -}; - -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfoCreator.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfoCreator.h deleted file mode 100644 index 49c7611a..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorInfoCreator.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/core/ActorInfo.h" -#include "td/actor/core/Actor.h" - -namespace td { -namespace actor { -namespace core { -class ActorInfoCreator { - public: - class Options { - public: - Options() = default; - - Options &with_name(Slice new_name) { - name = new_name; - return *this; - } - - Options &on_scheduler(SchedulerId new_scheduler_id) { - scheduler_id = new_scheduler_id; - return *this; - } - bool has_scheduler() const { - return scheduler_id.is_valid(); - } - Options &with_poll(bool has_poll = true) { - is_shared = !has_poll; - return *this; - } - - private: - friend class ActorInfoCreator; - Slice name; - SchedulerId scheduler_id; - bool is_shared{true}; - bool in_queue{true}; - //TODO: rename - }; - - //Create unlocked actor. One must send StartUp signal immediately. - ActorInfoPtr create(std::unique_ptr actor, const Options &args) { - ActorState::Flags flags; - flags.set_scheduler_id(args.scheduler_id); - if (allow_shared_) { - flags.set_shared(args.is_shared); - } - flags.set_in_queue(args.in_queue); - flags.set_signals(ActorSignals::one(ActorSignals::StartUp)); - - auto actor_info_ptr = pool_.alloc(std::move(actor), flags, args.name); - actor_info_ptr->actor().set_actor_info_ptr(actor_info_ptr); - return actor_info_ptr; - } - - ActorInfoCreator() = default; - explicit ActorInfoCreator(bool allow_shared) : allow_shared_(allow_shared) { - } - ActorInfoCreator(const ActorInfoCreator &) = delete; - ActorInfoCreator &operator=(const ActorInfoCreator &) = delete; - ActorInfoCreator(ActorInfoCreator &&other) = delete; - ActorInfoCreator &operator=(ActorInfoCreator &&other) = delete; - void clear() { - pool_.for_each([](auto &actor_info) { actor_info.destroy_actor(); }); - } - ~ActorInfoCreator() { - clear(); - } - void ensure_empty() { - pool_.for_each([](auto &actor_info) { LOG(ERROR) << actor_info.get_name(); }); - } - - private: - SharedObjectPool pool_; - bool allow_shared_{true}; -}; - -using ActorOptions = ActorInfoCreator::Options; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorLocker.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorLocker.h deleted file mode 100644 index f0811bea..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorLocker.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorSignals.h" -#include "td/actor/core/ActorState.h" - -#include "td/utils/logging.h" - -#include - -namespace td { -namespace actor { -namespace core { -class ActorLocker { - public: - struct Options { - Options() { - } - bool can_execute_paused = false; - bool is_shared = true; - SchedulerId scheduler_id; - - Options &with_can_execute_paused(bool new_can_execute_paused) { - can_execute_paused = new_can_execute_paused; - return *this; - } - Options &with_is_shared(bool new_is_shared) { - is_shared = new_is_shared; - return *this; - } - Options &with_scheduler_id(SchedulerId id) { - scheduler_id = id; - return *this; - } - }; - explicit ActorLocker(ActorState *state, Options options = {}) - : state_(state), flags_(state->get_flags_unsafe()), new_flags_{}, options_{options} { - } - bool try_lock() { - CHECK(!own_lock()); - while (!can_try_add_signals()) { - new_flags_ = flags_; - new_flags_.set_locked(true); - new_flags_.clear_signals(); - if (state_->state_.compare_exchange_strong(flags_.raw_ref(), new_flags_.raw(), std::memory_order_acq_rel)) { - own_lock_ = true; - return true; - } - } - return false; - } - bool try_unlock(ActorState::Flags flags) { - CHECK(!flags.is_locked()); - CHECK(own_lock()); - // can't unlock with signals set - //CHECK(!flags.has_signals()); - - flags_ = flags; - // try to unlock - if (state_->state_.compare_exchange_strong(new_flags_.raw_ref(), flags.raw(), std::memory_order_acq_rel)) { - own_lock_ = false; - return true; - } - - // read all signals - flags.set_locked(true); - flags.clear_signals(); - do { - flags_.add_signals(new_flags_.get_signals()); - } while (!state_->state_.compare_exchange_strong(new_flags_.raw_ref(), flags.raw(), std::memory_order_acq_rel)); - new_flags_ = flags; - return false; - } - - bool try_add_signals(ActorSignals signals) { - CHECK(!own_lock()); - CHECK(can_try_add_signals()); - new_flags_ = flags_; - new_flags_.add_signals(signals); - - // This is not an optimization. - // Sometimes it helps sometimes it makes things worse - // It there are a lot of threads concurrently sending signals to an actor it helps - // Buf it threre is only one thread, CAS without conficts is much cheaper than full - // barrier. - if (false && flags_.raw() == new_flags_.raw()) { - std::atomic_thread_fence(std::memory_order_seq_cst); - auto actual_flags = state_->get_flags_unsafe(); - if (actual_flags.raw() == new_flags_.raw()) { - return true; - } - } - - return state_->state_.compare_exchange_strong(flags_.raw_ref(), new_flags_.raw(), std::memory_order_acq_rel); - } - bool add_signals(ActorSignals signals) { - CHECK(!own_lock()); - while (true) { - if (can_try_add_signals()) { - if (try_add_signals(signals)) { - return false; - } - } else { - if (try_lock()) { - flags_.add_signals(signals); - return true; - } - } - } - } - bool own_lock() const { - return own_lock_; - } - ActorState::Flags flags() const { - return flags_; - } - bool can_execute() const { - return flags_.is_shared() == options_.is_shared && flags_.get_scheduler_id() == options_.scheduler_id && - (options_.can_execute_paused || !flags_.get_signals().has_signal(ActorSignals::Pause)); - } - - private: - ActorState *state_{nullptr}; - ActorState::Flags flags_; - ActorState::Flags new_flags_; - bool own_lock_{false}; - Options options_; - - bool can_try_add_signals() const { - return flags_.is_locked() || (flags_.is_in_queue() && !can_execute()); - } -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMailbox.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMailbox.h deleted file mode 100644 index 9e8b0309..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMailbox.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorMessage.h" -#include "td/utils/MpscLinkQueue.h" - -namespace td { -namespace actor { -namespace core { -class ActorMailbox { - public: - ActorMailbox() = default; - ActorMailbox(const ActorMailbox &) = delete; - ActorMailbox &operator=(const ActorMailbox &) = delete; - ActorMailbox(ActorMailbox &&other) = delete; - ActorMailbox &operator=(ActorMailbox &&other) = delete; - ~ActorMailbox() { - clear(); - } - void push(ActorMessage message) { - queue_.push(std::move(message)); - } - void push_unsafe(ActorMessage message) { - queue_.push_unsafe(std::move(message)); - } - - td::MpscLinkQueue::Reader &reader() { - return reader_; - } - - void pop_all() { - queue_.pop_all(reader_); - } - void pop_all_unsafe() { - queue_.pop_all_unsafe(reader_); - } - - void clear() { - pop_all(); - while (reader_.read()) { - // skip - } - } - - private: - td::MpscLinkQueue queue_; - td::MpscLinkQueue::Reader reader_; -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMessage.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMessage.h deleted file mode 100644 index e8a1b659..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorMessage.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorExecuteContext.h" - -#include "td/utils/MpscLinkQueue.h" - -namespace td { -namespace actor { -namespace core { -class ActorMessageImpl : private MpscLinkQueueImpl::Node { - public: - ActorMessageImpl() = default; - ActorMessageImpl(const ActorMessageImpl &) = delete; - ActorMessageImpl &operator=(const ActorMessageImpl &) = delete; - ActorMessageImpl(ActorMessageImpl &&other) = delete; - ActorMessageImpl &operator=(ActorMessageImpl &&other) = delete; - - virtual ~ActorMessageImpl() = default; - virtual void run() = 0; - - private: - friend class ActorMessage; - - // ActorMessage <--> MpscLintQueue::Node - // Each actor's mailbox will be a queue - static ActorMessageImpl *from_mpsc_link_queue_node(MpscLinkQueueImpl::Node *node) { - return static_cast(node); - } - MpscLinkQueueImpl::Node *to_mpsc_link_queue_node() { - return static_cast(this); - } - - uint64 link_token_{EmptyLinkToken}; - bool is_big_{false}; -}; - -class ActorMessage { - public: - ActorMessage() = default; - explicit ActorMessage(std::unique_ptr impl) : impl_(std::move(impl)) { - } - void run() { - CHECK(impl_); - impl_->run(); - } - explicit operator bool() { - return bool(impl_); - } - friend class ActorMailbox; - - void set_link_token(uint64 link_token) { - impl_->link_token_ = link_token; - } - uint64 get_link_token() const { - return impl_->link_token_; - } - bool is_big() const { - return impl_->is_big_; - } - void set_big() { - impl_->is_big_ = true; - } - - private: - std::unique_ptr impl_; - - template - friend class td::MpscLinkQueue; - - static ActorMessage from_mpsc_link_queue_node(MpscLinkQueueImpl::Node *node) { - return ActorMessage(std::unique_ptr(ActorMessageImpl::from_mpsc_link_queue_node(node))); - } - MpscLinkQueueImpl::Node *to_mpsc_link_queue_node() { - return impl_.release()->to_mpsc_link_queue_node(); - } -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorSignals.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorSignals.h deleted file mode 100644 index c6247843..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorSignals.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/bits.h" -#include "td/utils/format.h" - -namespace td { -namespace actor { -namespace core { -class ActorSignals { - public: - ActorSignals() = default; - uint32 raw() const { - return raw_; - } - static ActorSignals create_raw(uint32 raw) { - return ActorSignals(raw); - } - bool empty() const { - return raw_ == 0; - } - bool has_signal(uint32 signal) const { - return (raw_ & (1u << signal)) != 0; - } - void add_signal(uint32 signal) { - raw_ |= (1u << signal); - } - void add_signals(ActorSignals signals) { - raw_ |= signals.raw(); - } - void clear_signal(uint32 signal) { - raw_ &= ~(1u << signal); - } - uint32 first_signal() { - if (!raw_) { - return 0; - } - return td::count_trailing_zeroes_non_zero32(raw_); - } - friend StringBuilder &operator<<(StringBuilder &sb, ActorSignals signals) { - sb << "S{"; - bool was = false; - auto add_signal = [&](int signal, auto name) { - if (signals.has_signal(signal)) { - if (was) { - sb << ","; - } else { - was = true; - } - sb << name; - } - }; - add_signal(Wakeup, "Wakeup"); - add_signal(Alarm, "Alarm"); - add_signal(Kill, "Kill"); - add_signal(Io, "Io"); - add_signal(Cpu, "Cpu"); - add_signal(StartUp, "StartUp"); - add_signal(Pop, "Pop"); - add_signal(Message, "Message"); - add_signal(Pause, "Pause"); - sb << "}"; - return sb; - } - enum Signal : uint32 { - // Signals in order of priority - Pause = 1, - Kill = 2, // immediate kill - StartUp = 3, - Wakeup = 4, - Alarm = 5, - Io = 6, // move to io thread - Cpu = 7, // move to cpu thread - // Two signals for mpmc queue logic - // - // PopSignal is set after actor is popped from queue - // When processed it should set InQueue and Pause flags to false. - // - // MessagesSignal is set after new messages was added to actor - // If owner of actor wish to delay message handling, she should set InQueue flag to true and - // add actor into mpmc queue. - Pop = 8, // got popped from queue - Message = 9, // got new message - }; - - static ActorSignals one(uint32 signal) { - ActorSignals res; - res.add_signal(signal); - return res; - } - - private: - uint32 raw_{0}; - friend class ActorState; - explicit ActorSignals(uint32 raw) : raw_(raw) { - } -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorState.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorState.h deleted file mode 100644 index 5719b816..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorState.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorSignals.h" -#include "td/actor/core/SchedulerId.h" - -#include "td/utils/common.h" -#include "td/utils/format.h" - -#include - -namespace td { -namespace actor { -namespace core { -class ActorState { - public: - class Flags { - public: - Flags() = default; - uint32 raw() const { - return raw_; - } - uint32 &raw_ref() { - return raw_; - } - SchedulerId get_scheduler_id() const { - return SchedulerId{static_cast(raw_ & SchedulerMask)}; - } - void set_scheduler_id(SchedulerId id) { - raw_ = (raw_ & ~SchedulerMask) | id.value(); - } - - bool is_shared() const { - return check_flag(SharedFlag); - } - void set_shared(bool shared) { - set_flag(SharedFlag, shared); - } - - bool is_locked() const { - return check_flag(LockFlag); - } - void set_locked(bool locked) { - set_flag(LockFlag, locked); - } - - bool is_migrate() const { - return check_flag(MigrateFlag); - } - void set_migrate(bool migrate) { - set_flag(MigrateFlag, migrate); - } - - bool is_closed() const { - return check_flag(ClosedFlag); - } - void set_closed(bool closed) { - set_flag(ClosedFlag, closed); - } - - bool is_in_queue() const { - return check_flag(InQueueFlag); - } - void set_in_queue(bool in_queue) { - set_flag(InQueueFlag, in_queue); - } - - bool has_signals() const { - return check_flag(SignalMask); - } - void clear_signals() { - set_flag(SignalMask, false); - } - void set_signals(ActorSignals signals) { - raw_ = (raw_ & ~SignalMask) | (signals.raw() << SignalOffset); - } - void add_signals(ActorSignals signals) { - raw_ = raw_ | (signals.raw() << SignalOffset); - } - ActorSignals get_signals() const { - return ActorSignals{(raw_ & SignalMask) >> SignalOffset}; - } - friend StringBuilder &operator<<(StringBuilder &sb, Flags flags) { - sb << "ActorFlags{" << flags.get_scheduler_id().value() << ", " << (flags.is_shared() ? "cpu " : "io ") - << (flags.is_migrate() ? "migrate " : "") << (flags.is_closed() ? "closed " : "") - << (flags.is_in_queue() ? "in_queue " : "") << flags.get_signals() << "}"; - - return sb; - } - - private: - uint32 raw_{0}; - - friend class ActorState; - Flags(uint32 raw) : raw_(raw) { - } - - bool check_flag(uint32 mask) const { - return (raw_ & mask) != 0; - } - void set_flag(uint32 mask, bool flag) { - raw_ = (raw_ & ~mask) | (flag * mask); - } - }; - - Flags get_flags_unsafe() const { - return Flags(state_.load(std::memory_order_relaxed)); - } - void set_flags_unsafe(Flags flags) { - state_.store(flags.raw(), std::memory_order_relaxed); - } - - private: - friend class ActorLocker; - std::atomic state_{0}; - enum : uint32 { - SchedulerMask = 255, - - // Actors can be shared or not. - // If actor is shared, than any thread may try to lock it - // If actor is not shared, than it is owned by its scheduler, and only - // its scheduler is allowed to access it - // This flag may NOT change during the lifetime of an actor - SharedFlag = 1 << 9, - - // Only shared actors need lock - // Lock if somebody is going to unlock it eventually. - // For example actor is locked, when some scheduler is executing its mailbox - // Or it is locked when it is in Mpmc queue, so someone will pop it eventually. - LockFlag = 1 << 10, - - // While actor is migrating from one scheduler to another no one is allowed to change it - // Could not be set for shared actors. - MigrateFlag = 1 << 11, - - // While set all messages are delayed - // Dropped from flush_maibox - // PauseFlag => InQueueFlag - PauseFlag = 1 << 12, - - ClosedFlag = 1 << 13, - - InQueueFlag = 1 << 14, - - // Signals - SignalOffset = 15, - Signal = 1 << SignalOffset, - WakeupSignalFlag = Signal << ActorSignals::Wakeup, - AlarmSignalFlag = Signal << ActorSignals::Alarm, - KillSignalFlag = Signal << ActorSignals::Kill, // immediate kill - IoSignalFlag = Signal << ActorSignals::Io, // move to io thread - CpuSignalFlag = Signal << ActorSignals::Cpu, // move to cpu thread - StartUpSignalFlag = Signal << ActorSignals::StartUp, - MessageSignalFlag = Signal << ActorSignals::Message, - PopSignalFlag = Signal << ActorSignals::Pop, - PauseSignalFlag = Signal << ActorSignals::Pause, - - SignalMask = WakeupSignalFlag | AlarmSignalFlag | KillSignalFlag | IoSignalFlag | CpuSignalFlag | - StartUpSignalFlag | MessageSignalFlag | PopSignalFlag | PauseSignalFlag - }; -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/Context.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/Context.h deleted file mode 100644 index bb32f668..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/Context.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/thread_local.h" - -namespace td { -namespace actor { -namespace core { -template -class Context { - public: - static Impl *get() { - return context_; - } - class Guard { - public: - explicit Guard(Impl *new_context) { - old_context_ = context_; - context_ = new_context; - } - ~Guard() { - context_ = old_context_; - } - Guard(const Guard &) = delete; - Guard &operator=(const Guard &) = delete; - Guard(Guard &&) = delete; - Guard &operator=(Guard &&) = delete; - - private: - Impl *old_context_; - }; - - private: - static TD_THREAD_LOCAL Impl *context_; -}; - -template -TD_THREAD_LOCAL Impl *Context::context_; - -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.cpp deleted file mode 100644 index d78660c6..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/core/CpuWorker.h" - -#include "td/actor/core/ActorExecutor.h" -#include "td/actor/core/SchedulerContext.h" - -#include "td/actor/core/Scheduler.h" // FIXME: afer LocalQueue is in a separate file - -namespace td { -namespace actor { -namespace core { -void CpuWorker::run() { - auto thread_id = get_thread_id(); - auto &dispatcher = *SchedulerContext::get(); - - MpmcWaiter::Slot slot; - waiter_.init_slot(slot, thread_id); - auto &debug = dispatcher.get_debug(); - while (true) { - SchedulerMessage message; - if (try_pop(message, thread_id)) { - waiter_.stop_wait(slot); - if (!message) { - return; - } - auto lock = debug.start(message->get_name()); - ActorExecutor executor(*message, dispatcher, ActorExecutor::Options().with_from_queue()); - } else { - waiter_.wait(slot); - } - } -} - -bool CpuWorker::try_pop_local(SchedulerMessage &message) { - SchedulerMessage::Raw *raw_message; - if (local_queues_[id_].try_pop(raw_message)) { - message = SchedulerMessage(SchedulerMessage::acquire_t{}, raw_message); - return true; - } - return false; -} - -bool CpuWorker::try_pop_global(SchedulerMessage &message, size_t thread_id) { - SchedulerMessage::Raw *raw_message; - if (queue_.try_pop(raw_message, thread_id)) { - message = SchedulerMessage(SchedulerMessage::acquire_t{}, raw_message); - return true; - } - return false; -} - -bool CpuWorker::try_pop(SchedulerMessage &message, size_t thread_id) { - if (++cnt_ == 51) { - cnt_ = 0; - if (try_pop_global(message, thread_id) || try_pop_local(message)) { - return true; - } - } else { - if (try_pop_local(message) || try_pop_global(message, thread_id)) { - return true; - } - } - - for (size_t i = 1; i < local_queues_.size(); i++) { - size_t pos = (i + id_) % local_queues_.size(); - SchedulerMessage::Raw *raw_message; - if (local_queues_[id_].steal(raw_message, local_queues_[pos])) { - message = SchedulerMessage(SchedulerMessage::acquire_t{}, raw_message); - return true; - } - } - - return false; -} - -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.h deleted file mode 100644 index d9f32513..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/CpuWorker.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/SchedulerMessage.h" - -#include "td/utils/MpmcQueue.h" -#include "td/utils/MpmcWaiter.h" -#include "td/utils/Span.h" - -namespace td { -namespace actor { -namespace core { -template -struct LocalQueue; -class CpuWorker { - public: - CpuWorker(MpmcQueue &queue, MpmcWaiter &waiter, size_t id, - MutableSpan> local_queues) - : queue_(queue), waiter_(waiter), id_(id), local_queues_(local_queues) { - } - void run(); - - private: - MpmcQueue &queue_; - MpmcWaiter &waiter_; - size_t id_; - MutableSpan> local_queues_; - size_t cnt_{0}; - - bool try_pop(SchedulerMessage &message, size_t thread_id); - - bool try_pop_local(SchedulerMessage &message); - bool try_pop_global(SchedulerMessage &message, size_t thread_id); -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.cpp deleted file mode 100644 index ee3576bd..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/core/IoWorker.h" - -#include "td/actor/core/ActorExecutor.h" -#include "td/actor/core/Scheduler.h" - -namespace td { -namespace actor { -namespace core { -void IoWorker::start_up() { -#if TD_PORT_POSIX - auto &poll = SchedulerContext::get()->get_poll(); - poll.subscribe(queue_.reader_get_event_fd().get_poll_info().extract_pollable_fd(nullptr), PollFlags::Read()); -#endif -} -void IoWorker::tear_down() { -#if TD_PORT_POSIX - auto &poll = SchedulerContext::get()->get_poll(); - poll.unsubscribe(queue_.reader_get_event_fd().get_poll_info().get_pollable_fd_ref()); -#endif -} - -bool IoWorker::run_once(double timeout) { - auto &dispatcher = *SchedulerContext::get(); -#if TD_PORT_POSIX - auto &poll = SchedulerContext::get()->get_poll(); -#endif - auto &heap = SchedulerContext::get()->get_heap(); - auto &debug = SchedulerContext::get()->get_debug(); - - auto now = Time::now(); // update Time::now_cached() - while (!heap.empty() && heap.top_key() <= now) { - auto *heap_node = heap.pop(); - auto *actor_info = ActorInfo::from_heap_node(heap_node); - - auto id = actor_info->unpin(); - auto lock = debug.start(actor_info->get_name()); - ActorExecutor executor(*actor_info, dispatcher, ActorExecutor::Options().with_has_poll(true)); - if (executor.can_send_immediate()) { - executor.send_immediate(ActorSignals::one(ActorSignals::Alarm)); - } else { - executor.send(ActorSignals::one(ActorSignals::Alarm)); - } - } - - const int size = queue_.reader_wait_nonblock(); - for (int i = 0; i < size; i++) { - auto message = queue_.reader_get_unsafe(); - if (!message) { - return false; - } - if (message->state().get_flags_unsafe().is_shared()) { - // should check actors timeout - dispatcher.set_alarm_timestamp(message); - continue; - } - auto lock = debug.start(message->get_name()); - ActorExecutor executor(*message, dispatcher, ActorExecutor::Options().with_from_queue().with_has_poll(true)); - } - queue_.reader_flush(); - - bool can_sleep = size == 0 && timeout != 0; - int32 timeout_ms = 0; - if (can_sleep) { - auto wakeup_timestamp = Timestamp::in(timeout); - if (!heap.empty()) { - wakeup_timestamp.relax(Timestamp::at(heap.top_key())); - } - timeout_ms = static_cast(wakeup_timestamp.in() * 1000) + 1; - if (timeout_ms < 0) { - timeout_ms = 0; - } - //const int thirty_seconds = 30 * 1000; - //if (timeout_ms > thirty_seconds) { - //timeout_ms = thirty_seconds; - //} - } -#if TD_PORT_POSIX - poll.run(timeout_ms); -#elif TD_PORT_WINDOWS - queue_.reader_get_event_fd().wait(timeout_ms); -#endif - return true; -} -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.h deleted file mode 100644 index 529a01f8..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/IoWorker.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/SchedulerContext.h" -#include "td/actor/core/SchedulerMessage.h" -#include "td/utils/MpscPollableQueue.h" - -namespace td { -namespace actor { -namespace core { -class IoWorker { - public: - explicit IoWorker(MpscPollableQueue &queue) : queue_(queue) { - } - - void start_up(); - void tear_down(); - - bool run_once(double timeout); - - private: - MpscPollableQueue &queue_; -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp deleted file mode 100644 index f79620d9..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/core/Scheduler.h" - -#include "td/actor/core/CpuWorker.h" -#include "td/actor/core/IoWorker.h" - -namespace td { -namespace actor { -namespace core { - -std::atomic debug; -void set_debug(bool flag) { - debug = flag; -} - -bool need_debug() { - return debug.load(std::memory_order_relaxed); -} - -Scheduler::Scheduler(std::shared_ptr scheduler_group_info, SchedulerId id, size_t cpu_threads_count) - : scheduler_group_info_(std::move(scheduler_group_info)), cpu_threads_(cpu_threads_count) { - scheduler_group_info_->active_scheduler_count++; - info_ = &scheduler_group_info_->schedulers.at(id.value()); - info_->id = id; - if (cpu_threads_count != 0) { - info_->cpu_threads_count = cpu_threads_count; - info_->cpu_queue = std::make_unique>(1024, max_thread_count()); - info_->cpu_queue_waiter = std::make_unique(); - - info_->cpu_local_queue = std::vector>(cpu_threads_count); - } - info_->io_queue = std::make_unique>(); - info_->io_queue->init(); - - info_->cpu_workers.resize(cpu_threads_count); - td::uint8 cpu_worker_id = 0; - for (auto &worker : info_->cpu_workers) { - worker = std::make_unique(WorkerInfo::Type::Cpu, true, CpuWorkerId{cpu_worker_id}); - cpu_worker_id++; - } - info_->io_worker = std::make_unique(WorkerInfo::Type::Io, !info_->cpu_workers.empty(), CpuWorkerId{}); - - poll_.init(); - io_worker_ = std::make_unique(*info_->io_queue); - -#if TD_PORT_WINDOWS - if (info_->id.value() == 0) { - scheduler_group_info_->iocp.init(); - } -#endif -} - -Scheduler::~Scheduler() { - // should stop - stop(); - do_stop(); -} - -void Scheduler::start() { - for (size_t i = 0; i < cpu_threads_.size(); i++) { - cpu_threads_[i] = td::thread([this, i] { - this->run_in_context_impl(*this->info_->cpu_workers[i], [this, i] { - CpuWorker(*info_->cpu_queue, *info_->cpu_queue_waiter, i, info_->cpu_local_queue).run(); - }); - }); - cpu_threads_[i].set_name(PSLICE() << "#" << info_->id.value() << ":cpu#" << i); - } -#if TD_PORT_WINDOWS - // FIXME: use scheduler_id - if (info_->id.value() == 0) { - scheduler_group_info_->iocp_thread = td::thread([this] { - WorkerInfo info; - info.type = WorkerInfo::Type::Cpu; - this->run_in_context_impl(info, [this] { scheduler_group_info_->iocp.loop(); }); - }); - } -#endif - this->run_in_context([this] { this->io_worker_->start_up(); }); -} - -bool Scheduler::run(double timeout) { - bool res; - run_in_context_impl(*info_->io_worker, [this, timeout, &res] { - if (SchedulerContext::get()->is_stop_requested()) { - res = false; - } else { - res = io_worker_->run_once(timeout); - } - if (!res) { - if (!is_stopped_) { - io_worker_->tear_down(); - } - } - }); - if (!res) { - do_stop(); - } - return res; -} - -void Scheduler::do_stop() { - if (is_stopped_) { - return; - } - // wait other threads to finish - for (auto &thread : cpu_threads_) { - thread.join(); - } - // Can't do anything else, other schedulers may send queries to this one. - // Must wait till every scheduler is stopped first.. - is_stopped_ = true; - - io_worker_.reset(); - poll_.clear(); - heap_.for_each([](auto &key, auto &node) { ActorInfo::from_heap_node(node)->unpin(); }); - - std::unique_lock lock(scheduler_group_info_->active_scheduler_count_mutex); - scheduler_group_info_->active_scheduler_count--; - scheduler_group_info_->active_scheduler_count_condition_variable.notify_all(); -} - -Scheduler::ContextImpl::ContextImpl(ActorInfoCreator *creator, SchedulerId scheduler_id, CpuWorkerId cpu_worker_id, - SchedulerGroupInfo *scheduler_group, Poll *poll, KHeap *heap, Debug *debug) - : creator_(creator) - , scheduler_id_(scheduler_id) - , cpu_worker_id_(cpu_worker_id) - , scheduler_group_(scheduler_group) - , poll_(poll) - , heap_(heap) - , debug_(debug) { -} - -SchedulerId Scheduler::ContextImpl::get_scheduler_id() const { - return scheduler_id_; -} -void Scheduler::ContextImpl::add_to_queue(ActorInfoPtr actor_info_ptr, SchedulerId scheduler_id, bool need_poll) { - if (!scheduler_id.is_valid()) { - scheduler_id = get_scheduler_id(); - } - //LOG(ERROR) << "Add to queue: " << actor_info_ptr->get_name() << " " << scheduler_id.value(); - auto &info = scheduler_group()->schedulers.at(scheduler_id.value()); - if (need_poll || !info.cpu_queue) { - info.io_queue->writer_put(std::move(actor_info_ptr)); - } else { - if (scheduler_id == get_scheduler_id() && cpu_worker_id_.is_valid()) { - // may push local - CHECK(actor_info_ptr); - auto raw = actor_info_ptr.release(); - auto should_notify = info.cpu_local_queue[cpu_worker_id_.value()].push( - raw, [&](auto value) { info.cpu_queue->push(value, get_thread_id()); }); - if (should_notify) { - info.cpu_queue_waiter->notify(); - } - return; - } - info.cpu_queue->push(actor_info_ptr.release(), get_thread_id()); - info.cpu_queue_waiter->notify(); - } -} - -ActorInfoCreator &Scheduler::ContextImpl::get_actor_info_creator() { - return *creator_; -} - -bool Scheduler::ContextImpl::has_poll() { - return poll_ != nullptr; -} -Poll &Scheduler::ContextImpl::get_poll() { - CHECK(has_poll()); - return *poll_; -} - -bool Scheduler::ContextImpl::has_heap() { - return heap_ != nullptr; -} -KHeap &Scheduler::ContextImpl::get_heap() { - CHECK(has_heap()); - return *heap_; -} -Debug &Scheduler::ContextImpl::get_debug() { - return *debug_; -} - -void Scheduler::ContextImpl::set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) { - // Ideas for optimization - // 1. Several cpu actors with separate heaps. They ask io worker to update timeout only when it has been changed - // 2. Update timeout only when it has increased - // 3. Use signal-like logic to combile multiple timeout updates into one - if (!has_heap()) { - add_to_queue(actor_info_ptr, {}, true); - return; - } - // we are in PollWorker - CHECK(has_heap()); - auto &heap = get_heap(); - auto *heap_node = actor_info_ptr->as_heap_node(); - auto timestamp = actor_info_ptr->get_alarm_timestamp(); - if (timestamp) { - if (heap_node->in_heap()) { - heap.fix(timestamp.at(), heap_node); - } else { - actor_info_ptr->pin(actor_info_ptr); - heap.insert(timestamp.at(), heap_node); - } - } else { - if (heap_node->in_heap()) { - actor_info_ptr->unpin(); - heap.erase(heap_node); - } - } -} - -bool Scheduler::ContextImpl::is_stop_requested() { - return scheduler_group()->is_stop_requested; -} - -void Scheduler::ContextImpl::stop() { - bool expect_false = false; - // Trying to set close_flag_ to true with CAS - auto &group = *scheduler_group(); - if (!group.is_stop_requested.compare_exchange_strong(expect_false, true)) { - return; - } - - // Notify all workers of all schedulers - for (auto &scheduler_info : group.schedulers) { - scheduler_info.io_queue->writer_put({}); - for (size_t i = 0; i < scheduler_info.cpu_threads_count; i++) { - scheduler_info.cpu_queue->push({}, get_thread_id()); - scheduler_info.cpu_queue_waiter->notify(); - } - } -} -void Scheduler::close_scheduler_group(SchedulerGroupInfo &group_info) { - //LOG(DEBUG) << "close scheduler group"; - // Cannot close scheduler group before somebody asked to stop them - CHECK(group_info.is_stop_requested); - { - std::unique_lock lock(group_info.active_scheduler_count_mutex); - group_info.active_scheduler_count_condition_variable.wait(lock, - [&] { return group_info.active_scheduler_count == 0; }); - } - - //FIXME - //ContextImpl context(&group_info.schedulers[0].io_worker->actor_info_creator, SchedulerId{0}, &group_info, nullptr, - // nullptr); - //SchedulerContext::Guard guard(&context); - -#if TD_PORT_WINDOWS - detail::Iocp::Guard iocp_guard(&group_info.iocp); - group_info.iocp.interrupt_loop(); - group_info.iocp_thread.join(); -#endif - - // Drain all queues - int it = 0; - for (bool queues_are_empty = false; !queues_are_empty;) { - queues_are_empty = true; - for (auto &scheduler_info : group_info.schedulers) { - // Drain io queue - auto &io_queue = *scheduler_info.io_queue; - while (true) { - int n = io_queue.reader_wait_nonblock(); - if (n == 0) { - break; - } - while (n-- > 0) { - auto message = io_queue.reader_get_unsafe(); - // message's destructor is called - queues_are_empty = false; - } - } - - // Drain cpu queue - for (auto &q : scheduler_info.cpu_local_queue) { - auto &cpu_queue = q; - while (true) { - SchedulerMessage::Raw *raw_message; - if (!cpu_queue.try_pop(raw_message)) { - break; - } - SchedulerMessage(SchedulerMessage::acquire_t{}, raw_message); - // message's destructor is called - queues_are_empty = false; - } - } - if (scheduler_info.cpu_queue) { - auto &cpu_queue = *scheduler_info.cpu_queue; - while (true) { - SchedulerMessage::Raw *raw_message; - if (!cpu_queue.try_pop(raw_message, get_thread_id())) { - break; - } - SchedulerMessage(SchedulerMessage::acquire_t{}, raw_message); - // message's destructor is called - queues_are_empty = false; - } - } - } - if (++it > 100) { - LOG(FATAL) << "Failed to drain all queues"; - } - } - LOG_IF(ERROR, it > 2) << "It took more than one iteration to drain queues"; - - // Just to destroy all elements should be ok. - for (auto &scheduler_info : group_info.schedulers) { - scheduler_info.io_queue.reset(); - scheduler_info.cpu_queue.reset(); - - // Do not destroy worker infos. run_in_context will crash if they are empty - scheduler_info.io_worker->actor_info_creator.clear(); - for (auto &worker : scheduler_info.cpu_workers) { - worker->actor_info_creator.clear(); - } - } - //for (auto &scheduler : group_info.schedulers) { - //scheduler.io_worker->actor_info_creator.ensure_empty(); - //for (auto &worker : scheduler.cpu_workers) { - //worker->actor_info_creator.ensure_empty(); - //} - //} -} -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.h deleted file mode 100644 index 377d835f..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorExecuteContext.h" -#include "td/actor/core/ActorExecutor.h" -#include "td/actor/core/Actor.h" -#include "td/actor/core/ActorInfo.h" -#include "td/actor/core/ActorInfoCreator.h" -#include "td/actor/core/ActorLocker.h" -#include "td/actor/core/ActorMailbox.h" -#include "td/actor/core/ActorMessage.h" -#include "td/actor/core/Context.h" -#include "td/actor/core/SchedulerContext.h" -#include "td/actor/core/SchedulerId.h" -#include "td/actor/core/SchedulerMessage.h" - -#include "td/utils/AtomicRead.h" -#include "td/utils/Closure.h" -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/Heap.h" -#include "td/utils/List.h" -#include "td/utils/logging.h" -#include "td/utils/MpmcQueue.h" -#include "td/utils/StealingQueue.h" -#include "td/utils/MpmcWaiter.h" -#include "td/utils/MpscLinkQueue.h" -#include "td/utils/MpscPollableQueue.h" -#include "td/utils/optional.h" -#include "td/utils/port/Poll.h" -#include "td/utils/port/detail/Iocp.h" -#include "td/utils/port/thread.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Slice.h" -#include "td/utils/Time.h" -#include "td/utils/type_traits.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace td { -namespace actor { -namespace core { -class IoWorker; - -struct DebugInfo { - bool is_active{false}; - double start_at{0}; - static constexpr size_t name_size{32}; - char name[name_size] = {}; - void set_name(td::Slice from) { - from.truncate(name_size - 1); - std::memcpy(name, from.data(), from.size()); - name[from.size()] = 0; - } -}; - -void set_debug(bool flag); -bool need_debug(); - -struct Debug { - public: - bool is_on() const { - return need_debug(); - } - struct Destructor { - void operator()(Debug *info) { - info->info_.lock().value().is_active = false; - } - }; - - void read(DebugInfo &info) { - info_.read(info); - } - - std::unique_ptr start(td::Slice name) { - if (!is_on()) { - return {}; - } - { - auto lock = info_.lock(); - auto &value = lock.value(); - value.is_active = true; - value.start_at = Time::now(); - value.set_name(name); - } - return std::unique_ptr(this); - } - - private: - AtomicRead info_; -}; - -struct WorkerInfo { - enum class Type { Io, Cpu } type{Type::Io}; - WorkerInfo() = default; - explicit WorkerInfo(Type type, bool allow_shared, CpuWorkerId cpu_worker_id) - : type(type), actor_info_creator(allow_shared), cpu_worker_id(cpu_worker_id) { - } - ActorInfoCreator actor_info_creator; - CpuWorkerId cpu_worker_id; - Debug debug; -}; - -template -struct LocalQueue { - public: - template - bool push(T value, F &&overflow_f) { - auto res = std::move(next_); - next_ = std::move(value); - if (res) { - queue_.local_push(res.unwrap(), overflow_f); - return true; - } - return false; - } - bool try_pop(T &message) { - if (!next_) { - return queue_.local_pop(message); - } - message = next_.unwrap(); - return true; - } - bool steal(T &message, LocalQueue &other) { - return queue_.steal(message, other.queue_); - } - - private: - td::optional next_; - StealingQueue queue_; - char pad[TD_CONCURRENCY_PAD - sizeof(optional)]; -}; - -struct SchedulerInfo { - SchedulerId id; - // will be read by all workers is any thread - std::unique_ptr> cpu_queue; - std::unique_ptr cpu_queue_waiter; - - std::vector> cpu_local_queue; - //std::vector> cpu_stealing_queue; - - // only scheduler itself may read from io_queue_ - std::unique_ptr> io_queue; - size_t cpu_threads_count{0}; - - std::unique_ptr io_worker; - std::vector> cpu_workers; -}; - -struct SchedulerGroupInfo { - explicit SchedulerGroupInfo(size_t n) : schedulers(n) { - } - std::atomic is_stop_requested{false}; - - int active_scheduler_count{0}; - std::mutex active_scheduler_count_mutex; - std::condition_variable active_scheduler_count_condition_variable; - -#if TD_PORT_WINDOWS - td::detail::Iocp iocp; - td::thread iocp_thread; -#endif - std::vector schedulers; -}; - -class Scheduler { - public: - static constexpr int32 max_thread_count() { - return 256; - } - - static int32 get_thread_id() { - auto thread_id = ::td::get_thread_id(); - CHECK(thread_id < max_thread_count()); - return thread_id; - } - - Scheduler(std::shared_ptr scheduler_group_info, SchedulerId id, size_t cpu_threads_count); - - Scheduler(const Scheduler &) = delete; - Scheduler &operator=(const Scheduler &) = delete; - Scheduler(Scheduler &&other) = delete; - Scheduler &operator=(Scheduler &&other) = delete; - ~Scheduler(); - - void start(); - - template - void run_in_context(F &&f) { - run_in_context_impl(*info_->io_worker, std::forward(f)); - } - - template - void run_in_context_external(F &&f) { - WorkerInfo info; - info.type = WorkerInfo::Type::Cpu; - run_in_context_impl(*info_->io_worker, std::forward(f)); - } - - bool run(double timeout); - - // Just syntactic sugar - void stop() { - run_in_context([] { SchedulerContext::get()->stop(); }); - } - - SchedulerId get_scheduler_id() const { - return info_->id; - } - - private: - std::shared_ptr scheduler_group_info_; - SchedulerInfo *info_; - std::vector cpu_threads_; - bool is_stopped_{false}; - Poll poll_; - KHeap heap_; - std::unique_ptr io_worker_; - - class ContextImpl : public SchedulerContext { - public: - ContextImpl(ActorInfoCreator *creator, SchedulerId scheduler_id, CpuWorkerId cpu_worker_id, - SchedulerGroupInfo *scheduler_group, Poll *poll, KHeap *heap, Debug *debug); - - SchedulerId get_scheduler_id() const override; - void add_to_queue(ActorInfoPtr actor_info_ptr, SchedulerId scheduler_id, bool need_poll) override; - - ActorInfoCreator &get_actor_info_creator() override; - - bool has_poll() override; - Poll &get_poll() override; - - bool has_heap() override; - KHeap &get_heap() override; - - Debug &get_debug() override; - - void set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) override; - - bool is_stop_requested() override; - void stop() override; - - private: - SchedulerGroupInfo *scheduler_group() const { - return scheduler_group_; - } - - ActorInfoCreator *creator_; - SchedulerId scheduler_id_; - CpuWorkerId cpu_worker_id_; - SchedulerGroupInfo *scheduler_group_; - Poll *poll_; - - KHeap *heap_; - - Debug *debug_; - }; - - template - void run_in_context_impl(WorkerInfo &worker_info, F &&f) { -#if TD_PORT_WINDOWS - td::detail::Iocp::Guard iocp_guard(&scheduler_group_info_->iocp); -#endif - bool is_io_worker = worker_info.type == WorkerInfo::Type::Io; - ContextImpl context(&worker_info.actor_info_creator, info_->id, worker_info.cpu_worker_id, - scheduler_group_info_.get(), is_io_worker ? &poll_ : nullptr, is_io_worker ? &heap_ : nullptr, - &worker_info.debug); - SchedulerContext::Guard guard(&context); - f(); - } - - void do_stop(); - - public: - static void close_scheduler_group(SchedulerGroupInfo &group_info); -}; - -// Actor messages -class ActorMessageHangup : public core::ActorMessageImpl { - public: - void run() override { - ActorExecuteContext::get()->actor().hangup(); - } -}; -class ActorMessageHangupShared : public core::ActorMessageImpl { - public: - void run() override { - ActorExecuteContext::get()->actor().hangup_shared(); - } -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerContext.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerContext.h deleted file mode 100644 index e46aef7d..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerContext.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/actor/core/Context.h" -#include "td/actor/core/SchedulerId.h" -#include "td/actor/core/ActorInfo.h" -#include "td/actor/core/ActorInfoCreator.h" - -#include "td/utils/port/Poll.h" -#include "td/utils/Heap.h" - -namespace td { -namespace actor { -namespace core { -class SchedulerDispatcher { - public: - virtual ~SchedulerDispatcher() = default; - - virtual SchedulerId get_scheduler_id() const = 0; - virtual void add_to_queue(ActorInfoPtr actor_info_ptr, SchedulerId scheduler_id, bool need_poll) = 0; - virtual void set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) = 0; -}; - -struct Debug; -class SchedulerContext : public Context, public SchedulerDispatcher { - public: - virtual ~SchedulerContext() = default; - - // ActorCreator Interface - virtual ActorInfoCreator &get_actor_info_creator() = 0; - - // Poll interface - virtual bool has_poll() = 0; - virtual Poll &get_poll() = 0; - - // Timeout interface - virtual bool has_heap() = 0; - virtual KHeap &get_heap() = 0; - - // Stop all schedulers - virtual bool is_stop_requested() = 0; - virtual void stop() = 0; - - // Debug - virtual Debug &get_debug() = 0; -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerId.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerId.h deleted file mode 100644 index 289adbd4..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerId.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" - -namespace td { -namespace actor { -namespace core { -class SchedulerId { - public: - SchedulerId() = default; - explicit SchedulerId(uint8 id) : id_(id) { - } - bool is_valid() const { - return id_ >= 0; - } - uint8 value() const { - CHECK(is_valid()); - return static_cast(id_); - } - bool operator==(SchedulerId scheduler_id) const { - return id_ == scheduler_id.id_; - } - - private: - int32 id_{-1}; -}; - -class CpuWorkerId { - public: - CpuWorkerId() = default; - explicit CpuWorkerId(uint8 id) : id_(id) { - } - bool is_valid() const { - return id_ >= 0; - } - uint8 value() const { - CHECK(is_valid()); - return static_cast(id_); - } - bool operator==(CpuWorkerId other) const { - return id_ == other.id_; - } - - private: - int32 id_{-1}; -}; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerMessage.h b/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerMessage.h deleted file mode 100644 index 936d965d..00000000 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/SchedulerMessage.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/core/ActorInfo.h" - -namespace td { -namespace actor { -namespace core { -using SchedulerMessage = ActorInfoPtr; -} // namespace core -} // namespace actor -} // namespace td diff --git a/submodules/ton/tonlib-src/tdactor/test/actors_core.cpp b/submodules/ton/tonlib-src/tdactor/test/actors_core.cpp deleted file mode 100644 index ae10eb9b..00000000 --- a/submodules/ton/tonlib-src/tdactor/test/actors_core.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/core/ActorLocker.h" -#include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/StringBuilder.h" -#include "td/utils/tests.h" -#include "td/utils/Time.h" - -#include -#include -#include -#include - -TEST(Actor2, signals) { - using td::actor::core::ActorSignals; - ActorSignals signals; - signals.add_signal(ActorSignals::Wakeup); - signals.add_signal(ActorSignals::Cpu); - signals.add_signal(ActorSignals::Kill); - signals.clear_signal(ActorSignals::Cpu); - - bool was_kill = false; - bool was_wakeup = false; - while (!signals.empty()) { - auto s = signals.first_signal(); - if (s == ActorSignals::Kill) { - was_kill = true; - } else if (s == ActorSignals::Wakeup) { - was_wakeup = true; - } else { - UNREACHABLE(); - } - signals.clear_signal(s); - } - CHECK(was_kill && was_wakeup); -} - -TEST(Actors2, flags) { - using namespace td::actor::core; - ActorState::Flags flags; - CHECK(!flags.is_locked()); - flags.set_locked(true); - CHECK(flags.is_locked()); - flags.set_locked(false); - CHECK(!flags.is_locked()); - - flags.set_scheduler_id(SchedulerId{123}); - - auto signals = flags.get_signals(); - CHECK(signals.empty()); - signals.add_signal(ActorSignals::Cpu); - signals.add_signal(ActorSignals::Kill); - CHECK(signals.has_signal(ActorSignals::Cpu)); - CHECK(signals.has_signal(ActorSignals::Kill)); - flags.set_signals(signals); - LOG_CHECK(flags.get_signals().raw() == signals.raw()) << flags.get_signals().raw() << " " << signals.raw(); - - auto wakeup = ActorSignals{}; - wakeup.add_signal(ActorSignals::Wakeup); - - flags.add_signals(wakeup); - signals.add_signal(ActorSignals::Wakeup); - CHECK(flags.get_signals().raw() == signals.raw()); - - flags.clear_signals(); - CHECK(flags.get_signals().empty()); - - flags.add_signals(ActorSignals::one(ActorSignals::Pause)); - CHECK(flags.get_scheduler_id().value() == 123); - CHECK(flags.get_signals().has_signal(ActorSignals::Pause)); -} - -TEST(Actor2, locker) { - using namespace td::actor::core; - ActorState state; - - ActorSignals kill_signal; - kill_signal.add_signal(ActorSignals::Kill); - - ActorSignals wakeup_signal; - wakeup_signal.add_signal(ActorSignals::Wakeup); - - ActorSignals cpu_signal; - cpu_signal.add_signal(ActorSignals::Cpu); - - { - ActorLocker lockerA(&state); - ActorLocker lockerB(&state); - ActorLocker lockerC(&state); - - CHECK(lockerA.try_lock()); - CHECK(lockerA.own_lock()); - auto flagsA = lockerA.flags(); - CHECK(lockerA.try_unlock(flagsA)); - CHECK(!lockerA.own_lock()); - - CHECK(lockerA.try_lock()); - CHECK(!lockerB.try_lock()); - CHECK(!lockerC.try_lock()); - - CHECK(lockerB.try_add_signals(kill_signal)); - CHECK(!lockerC.try_add_signals(wakeup_signal)); - CHECK(lockerC.try_add_signals(wakeup_signal)); - CHECK(!lockerC.add_signals(cpu_signal)); - CHECK(!lockerA.flags().has_signals()); - CHECK(!lockerA.try_unlock(lockerA.flags())); - { - auto flags = lockerA.flags(); - auto signals = flags.get_signals(); - bool was_kill = false; - bool was_wakeup = false; - bool was_cpu = false; - while (!signals.empty()) { - auto s = signals.first_signal(); - if (s == ActorSignals::Kill) { - was_kill = true; - } else if (s == ActorSignals::Wakeup) { - was_wakeup = true; - } else if (s == ActorSignals::Cpu) { - was_cpu = true; - } else { - UNREACHABLE(); - } - signals.clear_signal(s); - } - CHECK(was_kill && was_wakeup && was_cpu); - flags.clear_signals(); - CHECK(lockerA.try_unlock(flags)); - } - } - - { - ActorLocker lockerB(&state); - CHECK(lockerB.try_lock()); - CHECK(lockerB.try_unlock(lockerB.flags())); - CHECK(lockerB.add_signals(kill_signal)); - CHECK(lockerB.flags().get_signals().has_signal(ActorSignals::Kill)); - auto flags = lockerB.flags(); - flags.clear_signals(); - ActorLocker lockerA(&state); - CHECK(!lockerA.add_signals(kill_signal)); - CHECK(!lockerB.try_unlock(flags)); - CHECK(!lockerA.add_signals(kill_signal)); // do not loose this signal! - CHECK(!lockerB.try_unlock(flags)); - CHECK(lockerB.flags().get_signals().has_signal(ActorSignals::Kill)); - CHECK(lockerB.try_unlock(flags)); - } - - { - ActorLocker lockerA(&state); - CHECK(lockerA.try_lock()); - auto flags = lockerA.flags(); - flags.add_signals(ActorSignals::one(ActorSignals::Pause)); - CHECK(lockerA.try_unlock(flags)); - //We have to lock, though we can't execute. - CHECK(lockerA.add_signals(wakeup_signal)); - } -} - -#if !TD_THREAD_UNSUPPORTED -TEST(Actor2, locker_stress) { - using namespace td::actor::core; - ActorState state; - - constexpr size_t threads_n = 5; - auto stage = [&](std::atomic &value, int need) { - value.fetch_add(1, std::memory_order_release); - while (value.load(std::memory_order_acquire) < need) { - td::this_thread::yield(); - } - }; - - struct Node { - std::atomic request{0}; - td::uint32 response = 0; - char pad[64]; - }; - std::array nodes; - auto do_work = [&]() { - for (auto &node : nodes) { - auto query = node.request.load(std::memory_order_acquire); - if (query) { - node.response = query * query; - node.request.store(0, std::memory_order_relaxed); - } - } - }; - - std::atomic begin{0}; - std::atomic ready{0}; - std::atomic check{0}; - std::vector threads; - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = i] { - for (size_t i = 1; i < 1000000; i++) { - ActorLocker locker(&state); - auto need = static_cast(threads_n * i); - auto query = static_cast(id + need); - stage(begin, need); - nodes[id].request = 0; - nodes[id].response = 0; - stage(ready, need); - if (locker.try_lock()) { - nodes[id].response = query * query; - } else { - auto cpu = ActorSignals::one(ActorSignals::Cpu); - nodes[id].request.store(query, std::memory_order_release); - locker.add_signals(cpu); - } - while (locker.own_lock()) { - auto flags = locker.flags(); - auto signals = flags.get_signals(); - if (!signals.empty()) { - do_work(); - } - flags.clear_signals(); - locker.try_unlock(flags); - } - - stage(check, need); - if (id == 0) { - CHECK(locker.add_signals(ActorSignals{})); - CHECK(!locker.flags().has_signals()); - CHECK(locker.try_unlock(locker.flags())); - for (size_t thread_id = 0; thread_id < threads_n; thread_id++) { - LOG_CHECK(nodes[thread_id].response == - static_cast(thread_id + need) * static_cast(thread_id + need)) - << td::tag("thread", thread_id) << " " << nodes[thread_id].response << " " - << nodes[thread_id].request.load(); - } - } - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} - -namespace { -const size_t BUF_SIZE = 1024 * 1024; -char buf[BUF_SIZE]; -td::StringBuilder sb(td::MutableSlice(buf, BUF_SIZE - 1)); -} // namespace - -TEST(Actor2, executor_simple) { - using namespace td::actor::core; - using namespace td::actor; - using td::actor::detail::ActorMessageCreator; - struct Dispatcher : public SchedulerDispatcher { - void add_to_queue(ActorInfoPtr ptr, SchedulerId scheduler_id, bool need_poll) override { - queue.push_back(std::move(ptr)); - } - void set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) override { - UNREACHABLE(); - } - SchedulerId get_scheduler_id() const override { - return SchedulerId{0}; - } - std::deque queue; - }; - Dispatcher dispatcher; - - class TestActor : public Actor { - public: - void close() { - stop(); - } - - private: - void start_up() override { - sb << "StartUp"; - } - void tear_down() override { - sb << "TearDown"; - } - }; - { - ActorInfoCreator actor_info_creator; - auto actor = actor_info_creator.create( - std::make_unique(), ActorInfoCreator::Options().on_scheduler(SchedulerId{0}).with_name("TestActor")); - dispatcher.add_to_queue(actor, SchedulerId{0}, false); - - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - CHECK(!executor.is_closed()); - CHECK(executor.can_send_immediate()); - LOG_CHECK(sb.as_cslice() == "StartUp") << sb.as_cslice(); - sb.clear(); - executor.send(ActorMessageCreator::lambda([&] { sb << "A"; })); - LOG_CHECK(sb.as_cslice() == "A") << sb.as_cslice(); - sb.clear(); - auto big_message = ActorMessageCreator::lambda([&] { sb << "big"; }); - big_message.set_big(); - executor.send(std::move(big_message)); - LOG_CHECK(sb.as_cslice() == "") << sb.as_cslice(); - executor.send(ActorMessageCreator::lambda([&] { sb << "B"; })); - LOG_CHECK(sb.as_cslice() == "") << sb.as_cslice(); - } - CHECK(dispatcher.queue.size() == 1); - { ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options().with_from_queue()); } - CHECK(dispatcher.queue.size() == 1); - dispatcher.queue.clear(); - LOG_CHECK(sb.as_cslice() == "bigB") << sb.as_cslice(); - sb.clear(); - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - executor.send( - ActorMessageCreator::lambda([&] { static_cast(ActorExecuteContext::get()->actor()).close(); })); - } - LOG_CHECK(sb.as_cslice() == "TearDown") << sb.as_cslice(); - sb.clear(); - CHECK(!actor->has_actor()); - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - executor.send( - ActorMessageCreator::lambda([&] { static_cast(ActorExecuteContext::get()->actor()).close(); })); - } - CHECK(dispatcher.queue.empty()); - CHECK(sb.as_cslice() == ""); - } - - { - ActorInfoCreator actor_info_creator; - auto actor = actor_info_creator.create( - std::make_unique(), ActorInfoCreator::Options().on_scheduler(SchedulerId{0}).with_name("TestActor")); - dispatcher.add_to_queue(actor, SchedulerId{0}, false); - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - CHECK(!executor.is_closed()); - CHECK(executor.can_send_immediate()); - LOG_CHECK(sb.as_cslice() == "StartUp") << sb.as_cslice(); - sb.clear(); - auto a_msg = ActorMessageCreator::lambda([&] { - sb << "big pause"; - ActorExecuteContext::get()->set_pause(); - }); - a_msg.set_big(); - executor.send(std::move(a_msg)); - executor.send(ActorMessageCreator::lambda([&] { sb << "A"; })); - LOG_CHECK(sb.as_cslice() == "") << sb.as_cslice(); - } - { - CHECK(dispatcher.queue.size() == 1); - dispatcher.queue.clear(); - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options().with_from_queue()); - CHECK(!executor.is_closed()); - CHECK(!executor.can_send_immediate()); - LOG_CHECK(sb.as_cslice() == "big pause") << sb.as_cslice(); - sb.clear(); - } - { - CHECK(dispatcher.queue.size() == 1); - dispatcher.queue.clear(); - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options().with_from_queue()); - CHECK(!executor.is_closed()); - CHECK(executor.can_send_immediate()); - LOG_CHECK(sb.as_cslice() == "A") << sb.as_cslice(); - sb.clear(); - } - { - ActorExecutor executor(*actor, dispatcher, ActorExecutor::Options()); - executor.send( - ActorMessageCreator::lambda([&] { static_cast(ActorExecuteContext::get()->actor()).close(); })); - } - LOG_CHECK(sb.as_cslice() == "TearDown") << sb.as_cslice(); - sb.clear(); - dispatcher.queue.clear(); - } -} - -using namespace td::actor; -using td::uint32; -static std::atomic global_cnt; -class Worker : public Actor { - public: - void query(uint32 x, core::ActorInfoPtr master); - void close() { - stop(); - } -}; -class Master : public Actor { - public: - void on_result(uint32 x, uint32 y) { - loop(); - } - - private: - uint32 l = 0; - uint32 r = 1000; - core::ActorInfoPtr worker; - void start_up() override { - worker = detail::create_actor(ActorOptions().with_name("Master")); - loop(); - } - void loop() override { - l++; - if (l == r) { - if (!--global_cnt) { - SchedulerContext::get()->stop(); - } - detail::send_closure(*worker, &Worker::close); - stop(); - return; - } - detail::send_lambda(*worker, - [x = l, self = get_actor_info_ptr()] { detail::current_actor().query(x, self); }); - } -}; - -void Worker::query(uint32 x, core::ActorInfoPtr master) { - auto y = x; - for (int i = 0; i < 100; i++) { - y = y * y; - } - detail::send_lambda(*master, [result = y, x] { detail::current_actor().on_result(x, result); }); -} - -TEST(Actor2, scheduler_simple) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 2}; - scheduler.start(); - scheduler.run_in_context([] { - global_cnt = 1000; - for (int i = 0; i < global_cnt; i++) { - detail::create_actor(ActorOptions().with_name("Master")); - } - }); - while (scheduler.run(1000)) { - } - core::Scheduler::close_scheduler_group(*group_info); -} - -TEST(Actor2, actor_id_simple) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 2}; - sb.clear(); - scheduler.start(); - - scheduler.run_in_context([] { - class A : public Actor { - public: - A(int value) : value_(value) { - sb << "A" << value_; - } - void hello() { - sb << "hello"; - } - ~A() { - sb << "~A"; - if (--global_cnt <= 0) { - SchedulerContext::get()->stop(); - } - } - - private: - int value_; - }; - global_cnt = 1; - auto id = create_actor("A", 123); - CHECK(sb.as_cslice() == "A123"); - sb.clear(); - send_closure(id, &A::hello); - }); - while (scheduler.run(1000)) { - } - CHECK(sb.as_cslice() == "hello~A"); - core::Scheduler::close_scheduler_group(*group_info); - sb.clear(); -} - -TEST(Actor2, actor_creation) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 1}; - scheduler.start(); - - scheduler.run_in_context([] { - class B; - class A : public Actor { - public: - void f() { - check(); - stop(); - } - - private: - void start_up() override { - check(); - create_actor("Simple", actor_id(this)).release(); - } - - void check() { - auto &context = *SchedulerContext::get(); - CHECK(context.has_poll()); - context.get_poll(); - } - - void tear_down() override { - if (--global_cnt <= 0) { - SchedulerContext::get()->stop(); - } - } - }; - - class B : public Actor { - public: - B(ActorId a) : a_(a) { - } - - private: - void start_up() override { - auto &context = *SchedulerContext::get(); - CHECK(!context.has_poll()); - send_closure(a_, &A::f); - stop(); - } - void tear_down() override { - if (--global_cnt <= 0) { - SchedulerContext::get()->stop(); - } - } - ActorId a_; - }; - global_cnt = 2; - create_actor(ActorOptions().with_name("Poll").with_poll()).release(); - }); - while (scheduler.run(1000)) { - } - scheduler.stop(); - core::Scheduler::close_scheduler_group(*group_info); -} - -TEST(Actor2, actor_timeout_simple) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 2}; - sb.clear(); - scheduler.start(); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - scheduler.run_in_context([watcher = std::move(watcher)] { - class A : public Actor { - public: - A(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void start_up() override { - set_timeout(); - } - void alarm() override { - double diff = td::Time::now() - expected_timeout_; - LOG_CHECK(-0.001 < diff && diff < 0.1) << diff; - if (cnt_-- > 0) { - set_timeout(); - } else { - stop(); - } - } - - private: - std::shared_ptr watcher_; - double expected_timeout_; - int cnt_ = 5; - void set_timeout() { - auto wakeup_timestamp = td::Timestamp::in(0.1); - expected_timeout_ = wakeup_timestamp.at(); - alarm_timestamp() = wakeup_timestamp; - } - }; - create_actor(core::ActorInfoCreator::Options().with_name("A").with_poll(), watcher).release(); - create_actor(core::ActorInfoCreator::Options().with_name("B"), watcher).release(); - }); - watcher.reset(); - while (scheduler.run(1000)) { - } - core::Scheduler::close_scheduler_group(*group_info); - sb.clear(); -} - -TEST(Actor2, actor_timeout_simple2) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 2}; - sb.clear(); - scheduler.start(); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - scheduler.run_in_context([watcher = std::move(watcher)] { - class A : public Actor { - public: - A(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void start_up() override { - set_timeout(); - } - void alarm() override { - set_timeout(); - } - - private: - std::shared_ptr watcher_; - void set_timeout() { - auto wakeup_timestamp = td::Timestamp::in(0.001); - alarm_timestamp() = wakeup_timestamp; - } - }; - class B : public Actor { - public: - B(std::shared_ptr watcher, ActorOwn<> actor_own) - : watcher_(std::move(watcher)), actor_own_(std::move(actor_own)) { - } - void start_up() override { - set_timeout(); - } - void alarm() override { - stop(); - } - - private: - std::shared_ptr watcher_; - ActorOwn<> actor_own_; - void set_timeout() { - auto wakeup_timestamp = td::Timestamp::in(0.005); - alarm_timestamp() = wakeup_timestamp; - } - }; - auto actor_own = create_actor(core::ActorInfoCreator::Options().with_name("A").with_poll(), watcher); - create_actor(core::ActorInfoCreator::Options().with_name("B"), watcher, std::move(actor_own)).release(); - }); - watcher.reset(); - while (scheduler.run(1000)) { - } - core::Scheduler::close_scheduler_group(*group_info); - sb.clear(); -} - -TEST(Actor2, actor_function_result) { - auto group_info = std::make_shared(1); - core::Scheduler scheduler{group_info, SchedulerId{0}, 2}; - sb.clear(); - scheduler.start(); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - scheduler.run_in_context([watcher = std::move(watcher)] { - class B : public Actor { - public: - uint32 query(uint32 x) { - return x * x; - } - void query_async(uint32 x, td::Promise promise) { - promise(x * x); - } - }; - class A : public Actor { - public: - A(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void on_result(uint32 x, td::Result r_y) { - auto y = r_y.move_as_ok(); - LOG_CHECK(x * x == y) << x << " " << y; - if (--cnt_ == 0) { - stop(); - } - } - void start_up() { - b_ = create_actor(ActorOptions().with_name("B")); - cnt_ = 5; - send_closure(b_, &B::query, 3, [a = std::make_unique(), self = actor_id(this)](td::Result y) { - LOG_IF(ERROR, y.is_error()) << y.error(); - send_closure(self, &A::on_result, 3, y.ok()); - }); - send_closure(b_, &B::query_async, 2, [self = actor_id(this)](uint32 y) { - CHECK(!self.empty()); - send_closure(self, &A::on_result, 2, y); - }); - send_closure_later(b_, &B::query_async, 5, [self = actor_id(this)](uint32 y) { - CHECK(!self.empty()); - send_closure(self, &A::on_result, 5, y); - }); - auto future = future_send_closure(b_, &B::query, 7); - future.finish(td::promise_send_closure(actor_id(this), &A::on_result, 7)); - //TODO: deduce Future type (i.e. Future) - auto future2 = future_send_closure(b_, &B::query_async, 7); - future2.finish(td::promise_send_closure(actor_id(this), &A::on_result, 7)); - } - - private: - int cnt_{0}; - std::shared_ptr watcher_; - td::actor::ActorOwn b_; - }; - create_actor(core::ActorInfoCreator::Options().with_name("A").with_poll(), watcher).release(); - create_actor(core::ActorInfoCreator::Options().with_name("B"), watcher).release(); - }); - watcher.reset(); - while (scheduler.run(1000)) { - } - core::Scheduler::close_scheduler_group(*group_info); - sb.clear(); -} - -TEST(Actor2, actor_ping_pong) { - Scheduler scheduler{{3}, Scheduler::Paused}; - sb.clear(); - scheduler.start(); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - td::actor::set_debug(true); - for (int i = 0; i < 2000; i++) { - scheduler.run_in_context([watcher] { - class PingPong : public Actor { - public: - PingPong(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void query(td::int32 left, ActorOwn<> data) { - if (td::Random::fast(0, 4) == 0) { - alarm_timestamp() = td::Timestamp::in(0.01 * td::Random::fast(0, 10)); - } - if (left <= 0) { - return; - } - auto dest = td::Random::fast(0, (int)next_.size() - 1); - if (td::Random::fast(0, 1) == 0) { - send_closure(next_[dest], &PingPong::query, left - 1, std::move(data)); - } else { - send_closure_later(next_[dest], &PingPong::query, left - 1, std::move(data)); - } - } - void add_next(ActorId p) { - next_.push_back(std::move(p)); - } - void start_up() override { - } - void store_data(ActorOwn<> data) { - data_.push_back(std::move(data)); - } - - private: - std::vector> next_; - std::vector> data_; - std::shared_ptr watcher_; - }; - - int N = td::Random::fast(2, 100); - //N = 2; - std::vector> actors; - for (int i = 0; i < N; i++) { - actors.push_back( - create_actor(core::ActorInfoCreator::Options().with_name(PSLICE() << "Worker#" << i), watcher)); - } - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - send_closure(actors[i], &PingPong::add_next, actors[j].get()); - } - } - int nn = td::Random::fast(1, N); - //nn = 2; - auto first = actors[0].get(); - for (int i = 0; i < N; i++) { - auto to = actors[i].get(); - if (i < nn) { - send_closure(to, &PingPong::query, td::Random::fast(10, 1000), std::move(actors[i])); - } else { - send_closure(first, &PingPong::store_data, std::move(actors[i])); - } - } - }); - } - watcher.reset(); - while (scheduler.run(0.1)) { - //scheduler.get_debug().dump(); - } - sb.clear(); -} - -TEST(Actor2, Schedulers) { - for (auto mode : {Scheduler::Running, Scheduler::Paused}) { - for (auto start_count : {0, 1, 2}) { - for (auto run_count : {0, 1, 2}) { - for (auto stop_count : {0, 1, 2}) { - for (size_t threads : {0, 1}) { - Scheduler scheduler({threads}, mode); - for (int i = 0; i < start_count; i++) { - scheduler.start(); - } - for (int i = 0; i < run_count; i++) { - scheduler.run(0); - } - for (int i = 0; i < stop_count; i++) { - scheduler.stop(); - } - } - } - } - } - } -} -TEST(Actor2, SchedulerZeroCpuThreads) { - Scheduler scheduler({0}); - scheduler.run_in_context([] { - class A : public Actor { - void start_up() override { - SchedulerContext::get()->stop(); - } - }; - create_actor(ActorOptions().with_name("A").with_poll(false)).release(); - }); - scheduler.run(); -} -TEST(Actor2, SchedulerTwo) { - Scheduler scheduler({0, 0}); - scheduler.run_in_context([] { - class B : public Actor { - public: - void start_up() override { - CHECK(SchedulerContext::get()->get_scheduler_id() == SchedulerId{1}); - } - void close() { - CHECK(SchedulerContext::get()->get_scheduler_id() == SchedulerId{1}); - SchedulerContext::get()->stop(); - } - }; - class A : public Actor { - void start_up() override { - CHECK(SchedulerContext::get()->get_scheduler_id() == SchedulerId{0}); - auto id = - create_actor(ActorOptions().with_name("B").with_poll(false).on_scheduler(SchedulerId{1})).release(); - send_closure(id, &B::close); - } - }; - create_actor(ActorOptions().with_name("A").with_poll(false).on_scheduler(SchedulerId{0})).release(); - }); - scheduler.run(); -} -TEST(Actor2, ActorIdDynamicCast) { - Scheduler scheduler({0}); - scheduler.run_in_context([] { - class A : public Actor { - public: - void close() { - CHECK(actor_id().actor_info_ptr() == get_actor_info_ptr()); - SchedulerContext::get()->stop(); - } - }; - auto actor_own_a = create_actor(ActorOptions().with_name("A").with_poll(false)); - auto actor = &actor_own_a.get_actor_unsafe(); - ActorOwn<> actor_own = actor_dynamic_cast(std::move(actor_own_a)); - CHECK(actor_own_a.empty()); - actor_own_a = actor_dynamic_cast(std::move(actor_own)); - CHECK(actor_own.empty()); - CHECK(&actor_own_a.get_actor_unsafe() == actor); - - auto actor_id_a = actor_own_a.release(); - ActorId<> actor_id = actor_dynamic_cast(actor_id_a); - actor_id_a = actor_dynamic_cast(actor_id); - CHECK(&actor_id_a.get_actor_unsafe() == actor); - - auto actor_shared_a = ActorShared(actor_id_a, 123); - ActorShared<> actor_shared = actor_dynamic_cast(std::move(actor_shared_a)); - CHECK(actor_shared_a.empty()); - CHECK(actor_shared.token() == 123); - actor_shared_a = actor_dynamic_cast(std::move(actor_shared)); - CHECK(actor_shared.empty()); - CHECK(&actor_shared_a.get_actor_unsafe() == actor); - CHECK(actor_shared_a.token() == 123); - - send_closure(actor_shared_a, &A::close); - }); - scheduler.run(); -} - -TEST(Actor2, send_vs_close) { - for (int it = 0; it < 100; it++) { - Scheduler scheduler({8}); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - scheduler.run_in_context([watcher = std::move(watcher)] { - class To : public Actor { - public: - class Callback { - public: - virtual ~Callback() { - } - virtual void on_closed(ActorId to) = 0; - }; - To(int cnt, std::shared_ptr watcher) : cnt_(cnt), watcher_(std::move(watcher)) { - } - void on_event() { - if (--cnt_ <= 0) { - stop(); - } - } - void add_callback(std::unique_ptr callback) { - callbacks_.push_back(std::move(callback)); - } - void start_up() override { - alarm_timestamp() = td::Timestamp::in(td::Random::fast(0, 4) * 0.001); - } - void tear_down() override { - if (td::Random::fast(0, 4) == 0) { - send_closure(actor_id(this), &To::self_ref, actor_id(this)); - } - for (auto &callback : callbacks_) { - callback->on_closed(actor_id(this)); - } - } - void self_ref(ActorId) { - } - void alarm() override { - stop(); - } - - private: - int cnt_; - std::shared_ptr watcher_; - std::vector> callbacks_; - }; - class From : public Actor { - public: - From(std::vector> to, std::shared_ptr watcher) - : to_(std::move(to)), watcher_(std::move(watcher)) { - } - void start_up() override { - yield(); - } - void on_closed(ActorId) { - } - void loop() override { - while (!to_.empty()) { - if (td::Random::fast(0, 3) == 0) { - break; - } - auto id = to_.back(); - to_.pop_back(); - if (td::Random::fast(0, 4) == 0) { - class Callback : public To::Callback { - public: - Callback(ActorId from) : from_(std::move(from)) { - } - void on_closed(ActorId id) override { - send_closure(from_, &From::on_closed, std::move(id)); - } - - private: - ActorId from_; - }; - send_closure(id, &To::add_callback, std::make_unique(actor_id(this))); - } - send_closure(id, &To::on_event); - } - if (to_.empty()) { - stop(); - } else { - yield(); - } - } - - private: - std::vector> to_; - std::shared_ptr watcher_; - }; - - class Master : public Actor { - public: - Master(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - - private: - std::shared_ptr watcher_; - int cnt_ = 10; - void loop() override { - if (cnt_-- < 0) { - return stop(); - } - int from_n = 5; - int to_n = 5; - std::vector>> from(from_n); - for (int i = 0; i < to_n; i++) { - int cnt = td::Random::fast(1, 10); - int to_cnt = td::Random::fast(1, cnt); - auto to = - td::actor::create_actor( - td::actor::ActorOptions().with_name(PSLICE() << "To#" << i).with_poll(td::Random::fast(0, 4) == 0), - to_cnt, watcher_) - .release(); - for (int j = 0; j < cnt; j++) { - auto from_i = td::Random::fast(0, from_n - 1); - from[from_i].push_back(to); - } - } - for (int i = 0; i < from_n; i++) { - td::actor::create_actor( - td::actor::ActorOptions().with_name(PSLICE() << "From#" << i).with_poll(td::Random::fast(0, 4) == 0), - std::move(from[i]), watcher_) - .release(); - } - alarm_timestamp() = td::Timestamp::in(td::Random::fast(0, 10) * 0.01 / 30); - } - }; - td::actor::create_actor("Master", watcher).release(); - }); - - scheduler.run(); - } -} -TEST(Actor2, send_vs_close2) { - for (int it = 0; it < 100; it++) { - Scheduler scheduler({8}); - - auto watcher = td::create_shared_destructor([] { SchedulerContext::get()->stop(); }); - //std::shared_ptr watcher; - scheduler.run_in_context([watcher = std::move(watcher)] { - class To : public Actor { - public: - To(int cnt, std::shared_ptr watcher) : cnt_(cnt), watcher_(std::move(watcher)) { - } - void start_up() override { - alarm_timestamp() = td::Timestamp::in(td::Random::fast(0, 4) * 0.001 / 30); - } - void alarm() override { - stop(); - } - - private: - int cnt_; - std::shared_ptr watcher_; - }; - class From : public Actor { - public: - From(std::vector> to, std::shared_ptr watcher) - : to_(std::move(to)), watcher_(std::move(watcher)) { - } - void start_up() override { - stop(); - } - - private: - std::vector> to_; - std::shared_ptr watcher_; - }; - - class Master : public Actor { - public: - Master(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - - private: - std::shared_ptr watcher_; - int cnt_ = 5; - void loop() override { - if (cnt_-- < 0) { - return stop(); - } - int from_n = 2; - int to_n = 2; - std::vector>> from(from_n); - for (int i = 0; i < to_n; i++) { - int cnt = td::Random::fast(1, 2); - int to_cnt = td::Random::fast(1, cnt); - auto to = - td::actor::create_actor( - td::actor::ActorOptions().with_name(PSLICE() << "To#" << i).with_poll(td::Random::fast(0, 4) == 0), - to_cnt, watcher_) - .release(); - for (int j = 0; j < cnt; j++) { - auto from_i = td::Random::fast(0, from_n - 1); - from[from_i].push_back(to); - } - } - for (int i = 0; i < from_n; i++) { - td::actor::create_actor( - td::actor::ActorOptions().with_name(PSLICE() << "From#" << i).with_poll(td::Random::fast(0, 4) == 0), - std::move(from[i]), watcher_) - .release(); - } - alarm_timestamp() = td::Timestamp::in(td::Random::fast(0, 10) * 0.01 / 30); - } - }; - td::actor::create_actor("Master", watcher).release(); - }); - - scheduler.run(); - } -} -#endif //!TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdactor/test/actors_promise.cpp b/submodules/ton/tonlib-src/tdactor/test/actors_promise.cpp deleted file mode 100644 index f1d57069..00000000 --- a/submodules/ton/tonlib-src/tdactor/test/actors_promise.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" -#include "td/actor/MultiPromise.h" -#include "td/utils/MovableValue.h" -#include "td/utils/tests.h" - -template -class X { - public: - X() = default; - X(X &&) = default; - template - X(S s) : t(s) { - } - T t; -}; - -TEST(Actor, promise) { - using Int = td::MovableValue; - using td::Promise; - using td::Result; - - auto set_int = [](td::Result &destination) { - return [&destination](Int value) { destination = std::move(value); }; - }; - auto set_result_int = [](Result &destination) { - return [&destination](Result value) { destination = std::move(value); }; - }; - - { - Result result{2}; - { - Promise promise = set_int(result); - promise.set_value(Int{3}); - } - ASSERT_TRUE(result.is_ok()); - ASSERT_EQ(result.ok().get(), 3); - } - - { - Result result{2}; - { - Promise promise = set_int(result); - (void)promise; - // will set Int{} on destruction - } - ASSERT_TRUE(result.is_ok()); - ASSERT_EQ(result.ok().get(), 0); - } - - { - Result result{2}; - { - Promise promise = set_result_int(result); - promise.set_value(Int{3}); - } - ASSERT_TRUE(result.is_ok()); - ASSERT_EQ(result.ok().get(), 3); - } - - { - Result result{2}; - { - Promise promise = set_result_int(result); - (void)promise; - // will set Status::Error() on destruction - } - ASSERT_TRUE(result.is_error()); - } - - { - std::unique_ptr res; - Promise x = [a = std::make_unique(5), &res](td::Unit) mutable { res = std::move(a); }; - x(td::Unit()); - CHECK(*res == 5); - } - - {//{ - //Promise promise; - //std::tuple &&> f(std::move(promise)); - //std::tuple> x = std::move(f); - //} - - { - //using T = Result; - //using T = std::unique_ptr; - //using T = std::function; - //using T = std::vector; - //using T = X; - ////using T = Promise; - //T f; - //std::tuple g(std::move(f)); - //std::tuple h = std::move(g); - }} - - { - int result = 0; - auto promise = td::lambda_promise([&](auto x) { result = x.move_as_ok(); }); - promise.set_value(5); - ASSERT_EQ(5, result); - - Promise promise2 = [&](auto x) { result = x.move_as_ok(); }; - promise2.set_value(6); - ASSERT_EQ(6, result); - } -} - -TEST(Actor, safe_promise) { - int res = 0; - { - td::Promise promise = td::PromiseCreator::lambda([&](int x) { res = x; }); - auto safe_promise = td::SafePromise(std::move(promise), 2); - promise = std::move(safe_promise); - ASSERT_EQ(res, 0); - auto safe_promise2 = td::SafePromise(std::move(promise), 3); - } - ASSERT_EQ(res, 3); -} - -TEST(Actor, split_promise) { - using td::Promise; - using td::Result; - using td::split_promise; - using td::SplitPromise; - { - td::optional> x; - auto pair = [&](Result> res) { x = res.move_as_ok(); }; - static_assert(std::is_same::ArgT, std::pair>::value, "A"); - static_assert( - std::is_same::SplittedT, std::pair, Promise>>::value, "A"); - auto splitted = split_promise(pair); - static_assert(std::is_same, Promise>>::value, "A"); - - splitted.first.set_value(1); - splitted.second.set_value(2.0); - CHECK(x.unwrap() == std::make_pair(1, 2.0)); - } // namespace td - { - td::optional> x; - auto triple = [&](Result> res) { x = res.move_as_ok(); }; - static_assert(std::is_same::ArgT, std::tuple>::value, "A"); - static_assert(std::is_same::SplittedT, - std::tuple, Promise, Promise>>::value, - "A"); - auto splitted = split_promise(triple); - static_assert( - std::is_same, Promise, Promise>>::value, "A"); - std::get<0>(splitted).set_value(1); - std::get<1>(splitted).set_value(2.0); - std::get<2>(splitted).set_value("hello"); - CHECK(x.unwrap() == std::make_tuple(1, 2.0, "hello")); - } - { - int code = 0; - auto pair = [&](Result> res) { - res.ensure_error(); - code = res.error().code(); - }; - auto splitted = split_promise(td::Promise>(pair)); - splitted.second.set_error(td::Status::Error(123, "123")); - CHECK(code == 0); - splitted.first.set_value(1); - CHECK(code == 123); - } -} - -TEST(Actor, promise_future) { - using td::make_promise_future; - { - auto pf = make_promise_future(); - td::optional res; - pf.second.map([](int x) { return x * 2; }).map([](int x) { return x + 10; }).map([&](int x) { - res = x; - return td::Unit(); - }); - CHECK(!res); - pf.first.set_value(6); - ASSERT_EQ(22, res.unwrap()); - } - { - LOG(ERROR) << "Second test"; - td::optional res; - td::make_future(6) - .map([](int x) { return x * 2; }) - .map([](int x) { return x + 10; }) - .fmap([&](int x) { return td::make_future(x * 2); }) - .finish([&](int x) { res = x; }); - ASSERT_EQ(44, res.unwrap()); - } -} - -TEST(Actor2, actor_lost_promise) { - using namespace td::actor; - using namespace td; - Scheduler scheduler({1}, Scheduler::Paused); - - auto watcher = td::create_shared_destructor([] { - LOG(ERROR) << "STOP"; - SchedulerContext::get()->stop(); - }); - scheduler.run_in_context([watcher = std::move(watcher)] { - class B : public Actor { - public: - void start_up() override { - stop(); - } - uint32 query(uint32 x) { - return x * x; - } - }; - class A : public Actor { - public: - A(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - void start_up() { - b_ = create_actor(ActorOptions().with_name("B")); - //send_closure(b_, &B::query, 2, [self = actor_id(this)](uint32 y) { send_closure(self, &A::on_result, 2, y); }); - send_closure_later(b_, &B::query, 2, - [self = actor_id(this), a = std::make_unique()](Result y) mutable { - LOG(ERROR) << "!"; - CHECK(y.is_error()); - send_closure(self, &A::finish); - }); - send_closure(b_, &B::query, 2, [self = actor_id(this), a = std::make_unique()](Result y) mutable { - LOG(ERROR) << "!"; - CHECK(y.is_error()); - send_closure(self, &A::finish); - }); - } - void finish() { - LOG(ERROR) << "FINISH"; - stop(); - } - - private: - std::shared_ptr watcher_; - td::actor::ActorOwn b_; - }; - create_actor(ActorOptions().with_name("A").with_poll(), watcher).release(); - }); - scheduler.run(); -} - -TEST(Actor2, MultiPromise) { - using namespace td; - MultiPromise::Options fail_on_error; - fail_on_error.ignore_errors = false; - MultiPromise::Options ignore_errors; - ignore_errors.ignore_errors = true; - - std::string str; - auto log = [&](Result res) { - if (res.is_ok()) { - str += "OK;"; - } else { - str += PSTRING() << "E" << res.error().code() << ";"; - } - }; - auto clear = [&] { str = ""; }; - - { - clear(); - MultiPromise mp(ignore_errors); - { - auto mp_init = mp.init_guard(); - mp_init.add_promise(log); - ASSERT_EQ("", str); - } - ASSERT_EQ("OK;", str); - } - - { - clear(); - MultiPromise mp(ignore_errors); - { - auto mp_init = mp.init_guard(); - mp_init.add_promise(log); - mp_init.get_promise().set_error(Status::Error(1)); - ASSERT_EQ("", str); - } - ASSERT_EQ("OK;", str); - } - - { - clear(); - MultiPromise mp(ignore_errors); - Promise<> promise; - { - auto mp_init = mp.init_guard(); - mp_init.add_promise(log); - promise = mp_init.get_promise(); - } - ASSERT_EQ("", str); - { - auto mp_init = mp.add_promise_or_init(log); - ASSERT_TRUE(!mp_init); - } - promise.set_error(Status::Error(2)); - ASSERT_EQ("OK;OK;", str); - clear(); - { - auto mp_init = mp.add_promise_or_init(log); - ASSERT_TRUE(mp_init); - ASSERT_EQ("", str); - } - ASSERT_EQ("OK;", str); - } - - { - clear(); - MultiPromise mp(fail_on_error); - { - auto mp_init = mp.init_guard(); - mp_init.get_promise().set_value(Unit()); - mp_init.add_promise(log); - ASSERT_EQ("", str); - } - ASSERT_EQ("OK;", str); - } - - { - clear(); - MultiPromise mp(fail_on_error); - { - auto mp_init = mp.init_guard(); - mp_init.get_promise().set_value(Unit()); - mp_init.add_promise(log); - mp_init.get_promise().set_error(Status::Error(1)); - ASSERT_EQ("E1;", str); - clear(); - mp_init.get_promise().set_error(Status::Error(2)); - ASSERT_EQ("", str); - mp_init.add_promise(log); - ASSERT_EQ("E1;", str); - } - ASSERT_EQ("E1;", str); - } - - { - clear(); - MultiPromise mp(fail_on_error); - Promise<> promise; - { - auto mp_init = mp.init_guard(); - mp_init.get_promise().set_value(Unit()); - mp_init.add_promise(log); - promise = mp_init.get_promise(); - } - ASSERT_EQ("", str); - { - auto mp_init = mp.add_promise_or_init(log); - ASSERT_TRUE(mp_init.empty()); - } - promise.set_error(Status::Error(2)); - ASSERT_EQ("E2;E2;", str); - clear(); - - { - auto mp_init = mp.add_promise_or_init(log); - ASSERT_TRUE(!mp_init.empty()); - } - ASSERT_EQ("OK;", str); - } -} - -#if TD_HAVE_COROUTINES -#include -namespace td { -template -struct task { - struct final_awaiter { - bool await_ready() const noexcept { - return false; - } - template - std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle

continuation) noexcept { - return continuation.promise().continuation_; - } - void await_resume() noexcept { - } - }; - struct promise_type { - task get_return_object() { - return task{*this}; - } - std::experimental::suspend_always initial_suspend() { - return {}; - } - final_awaiter final_suspend() { - return final_awaiter{}; - } - void return_value(T v) { - value_ = v; - } - T move_value() { - return std::move(value_.value()); - } - void unhandled_exception() { - } - - optional value_; - std::experimental::coroutine_handle<> continuation_; - }; - - // awaiter - std::experimental::coroutine_handle coroutine_handle_; - task(task &&other) = default; - task(promise_type &promise) - : coroutine_handle_(std::experimental::coroutine_handle::from_promise(promise)) { - } - - bool await_ready() const noexcept { - return !coroutine_handle_ || coroutine_handle_.done(); - } - std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle<> continuation) noexcept { - coroutine_handle_.promise().continuation_ = continuation; - return coroutine_handle_; - } - T await_resume() noexcept { - return coroutine_handle_.promise().move_value(); - } -}; - -task f() { - co_return 1; -} -task g() { - co_return 2; -} -task h() { - auto a = co_await f(); - auto b = co_await g(); - co_return a + b; -} - -struct immediate_task { - struct promise_type { - immediate_task get_return_object() { - return {}; - } - std::experimental::suspend_never initial_suspend() { - return {}; - } - std::experimental::suspend_never final_suspend() { - return {}; - } - void return_void() { - } - void unhandled_exception() { - } - }; -}; - -struct OnActor { - public: - template - OnActor(T &&actor_id) : actor_id_(actor_id.as_actor_ref()) { - } - bool await_ready() const noexcept { - return false; - } - void await_suspend(std::experimental::coroutine_handle<> continuation) noexcept { - //TODO: destroy if lambda is lost - send_lambda(actor_id_, [continuation]() mutable { continuation.resume(); }); - } - void await_resume() noexcept { - } - - private: - actor::detail::ActorRef actor_id_; -}; - -immediate_task check_h() { - LOG(ERROR) << "check_h: call h"; - auto c = co_await h(); - LOG(ERROR) << "check_h: after call h"; - ASSERT_EQ(3, c); -} - -TEST(ActorCoro, Task) { - check_h(); -} -namespace actor { -class AsyncQuery {}; - -class Printer : public Actor { - public: - void f(); - void print_a() { - LOG(ERROR) << "a"; - } - void print_b() { - LOG(ERROR) << "b"; - } -}; - -class SampleActor : public Actor { - public: - SampleActor(std::shared_ptr watcher) : watcher_(std::move(watcher)) { - } - - private: - std::shared_ptr watcher_; - ActorOwn printer_; - void start_up() override { - printer_ = create_actor("Printer"); - run_coroutine(); - } - task print_a() { - auto self = actor_id(this); - LOG(ERROR) << "enter print_a"; - co_await OnActor(printer_); - detail::current_actor().print_a(); - co_await OnActor(self); - LOG(ERROR) << "exit print_a"; - co_return {}; - } - task print_b() { - auto self = actor_id(this); - LOG(ERROR) << "enter print_b"; - co_await OnActor(printer_); - detail::current_actor().print_b(); - co_await OnActor(self); - LOG(ERROR) << "exit print_b"; - co_return {}; - } - - immediate_task run_coroutine() { - co_await print_a(); - co_await print_b(); - stop(); - } -}; -} // namespace actor - -TEST(ActorCoro, Simple) { - using namespace td::actor; - using namespace td; - Scheduler scheduler({1}); - - auto watcher = td::create_shared_destructor([] { - LOG(ERROR) << "STOP"; - SchedulerContext::get()->stop(); - }); - scheduler.run_in_context([watcher = std::move(watcher)] { - create_actor(ActorOptions().with_name("SampleActor").with_poll(), watcher).release(); - }); - scheduler.run(); -} - -} // namespace td -#endif diff --git a/submodules/ton/tonlib-src/tddb/CMakeLists.txt b/submodules/ton/tonlib-src/tddb/CMakeLists.txt deleted file mode 100644 index 960703b6..00000000 --- a/submodules/ton/tonlib-src/tddb/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -#SOURCE SETS -set(TDDB_SOURCE - td/db/MemoryKeyValue.cpp - - td/db/KeyValue.h - td/db/KeyValueAsync.h - td/db/MemoryKeyValue.h - - td/db/utils/ChainBuffer.cpp - td/db/utils/CyclicBuffer.cpp - td/db/utils/FileSyncState.cpp - td/db/utils/StreamInterface.cpp - td/db/utils/StreamToFileActor.cpp - td/db/utils/FileToStreamActor.cpp - - td/db/utils/ChainBuffer.h - td/db/utils/CyclicBuffer.h - td/db/utils/FileSyncState.h - td/db/utils/StreamInterface.h - td/db/utils/StreamToFileActor.h - td/db/utils/FileToStreamActor.h - - td/db/binlog/Binlog.cpp - td/db/binlog/BinlogReaderHelper.cpp - - td/db/binlog/Binlog.h - td/db/binlog/BinlogReaderHelper.h - td/db/binlog/BinlogReaderInterface.h -) - -set(TDDB_ROCKSDB_SOURCE - td/db/RocksDb.cpp - td/db/RocksDb.h -) - -set(TDDB_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/key_value.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/binlog.cpp - PARENT_SCOPE -) - -#RULES - -#LIBRARIES - -add_library(tddb STATIC ${TDDB_SOURCE}) -target_include_directories(tddb PUBLIC $) -target_link_libraries(tddb PUBLIC tdutils tdactor) - -if (TDDB_USE_ROCKSDB) - target_sources(tddb PRIVATE ${TDDB_ROCKSDB_SOURCE}) - target_compile_definitions(tddb PUBLIC -DTDDB_USE_ROCKSDB) - target_link_libraries(tddb PRIVATE rocksdb) - target_include_directories(tddb PRIVATE $) -endif() - -add_executable(io-bench test/io-bench.cpp) -target_link_libraries(io-bench tdutils tdactor tddb) - -# BEGIN-INTERNAL -#add_subdirectory(benchmark) - -# END-INTERNAL -install(TARGETS tddb EXPORT TdTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include -) diff --git a/submodules/ton/tonlib-src/tddb/td/db/KeyValue.h b/submodules/ton/tonlib-src/tddb/td/db/KeyValue.h deleted file mode 100644 index 4e0d8538..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/KeyValue.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/Status.h" -#include "td/utils/logging.h" -namespace td { -class KeyValueReader { - public: - virtual ~KeyValueReader() = default; - enum class GetStatus : int32 { Ok, NotFound }; - - virtual Result get(Slice key, std::string &value) = 0; - virtual Result count(Slice prefix) = 0; -}; - -class PrefixedKeyValueReader : public KeyValueReader { - public: - PrefixedKeyValueReader(std::shared_ptr reader, Slice prefix) - : reader_(std::move(reader)), prefix_(prefix.str()) { - } - Result get(Slice key, std::string &value) override { - return reader_->get(PSLICE() << prefix_ << key, value); - } - Result count(Slice prefix) override { - return reader_->count(PSLICE() << prefix_ << prefix); - } - - private: - std::shared_ptr reader_; - std::string prefix_; -}; - -class KeyValueUtils { - public: -}; - -class KeyValue : public KeyValueReader { - public: - virtual Status set(Slice key, Slice value) = 0; - virtual Status erase(Slice key) = 0; - - virtual Status begin_write_batch() = 0; - virtual Status commit_write_batch() = 0; - virtual Status abort_write_batch() = 0; - - virtual Status begin_transaction() = 0; - virtual Status commit_transaction() = 0; - virtual Status abort_transaction() = 0; - // Desctructor will abort transaction - - virtual std::unique_ptr snapshot() = 0; - - virtual std::string stats() const { - return ""; - } - virtual Status flush() { - return Status::OK(); - } -}; -class PrefixedKeyValue : public KeyValue { - public: - PrefixedKeyValue(std::shared_ptr kv, Slice prefix) : kv_(std::move(kv)), prefix_(prefix.str()) { - } - Result get(Slice key, std::string &value) override { - return kv_->get(PSLICE() << prefix_ << key, value); - } - Result count(Slice prefix) override { - return kv_->count(PSLICE() << prefix_ << prefix); - } - Status set(Slice key, Slice value) override { - return kv_->set(PSLICE() << prefix_ << key, value); - } - Status erase(Slice key) override { - return kv_->erase(PSLICE() << prefix_ << key); - } - - Status begin_write_batch() override { - return kv_->begin_write_batch(); - } - Status commit_write_batch() override { - return kv_->commit_write_batch(); - } - Status abort_write_batch() override { - return kv_->abort_write_batch(); - } - - Status begin_transaction() override { - return kv_->begin_transaction(); - } - Status commit_transaction() override { - return kv_->commit_transaction(); - } - Status abort_transaction() override { - return kv_->abort_transaction(); - } - // Desctructor will abort transaction - - std::unique_ptr snapshot() override { - return kv_->snapshot(); - } - - std::string stats() const override { - return kv_->stats(); - } - Status flush() override { - return kv_->flush(); - } - - private: - std::shared_ptr kv_; - std::string prefix_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/KeyValueAsync.h b/submodules/ton/tonlib-src/tddb/td/db/KeyValueAsync.h deleted file mode 100644 index 98d2ec3b..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/KeyValueAsync.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" - -#include "td/db/KeyValue.h" - -namespace td { - -template -class KeyValueActor; - -template -class KeyValueAsync { - public: - using ActorType = KeyValueActor; - struct GetResult { - KeyValue::GetStatus status; - ValueT value; - }; - KeyValueAsync(std::shared_ptr key_value); - void get(KeyT key, Promise promise = {}); - void set(KeyT key, ValueT value, Promise promise = {}, double sync_delay = 0); - void erase(KeyT key, Promise promise = {}, double sync_delay = 0); - - KeyValueAsync(); - KeyValueAsync(KeyValueAsync &&); - KeyValueAsync &operator=(KeyValueAsync &&); - ~KeyValueAsync(); - - private: - actor::ActorOwn actor_; -}; - -template -class KeyValueActor : public actor::Actor { - public: - KeyValueActor(std::shared_ptr key_value) : key_value_(std::move(key_value)) { - } - - void get(KeyT key, Promise::GetResult> promise) { - std::string value; - auto r_status = key_value_->get(as_slice(key), value); - if (r_status.is_error()) { - promise.set_error(r_status.move_as_error()); - return; - } - typename KeyValueAsync::GetResult result; - result.status = r_status.move_as_ok(); - if (result.status == KeyValue::GetStatus::Ok) { - result.value = ValueT(std::move(value)); - } - promise.set_value(std::move(result)); - } - void set(KeyT key, ValueT value, Promise promise, double sync_delay) { - schedule_sync(std::move(promise), sync_delay); - key_value_->set(as_slice(key), as_slice(value)); - } - void erase(KeyT key, Promise promise, double sync_delay) { - schedule_sync(std::move(promise), sync_delay); - key_value_->erase(as_slice(key)); - } - - private: - std::shared_ptr key_value_; - std::vector> pending_promises_; - bool need_sync_ = false; - bool sync_active_ = false; - - void tear_down() override { - sync(); - } - void sync() { - if (!need_sync_) { - return; - } - need_sync_ = false; - sync_active_ = false; - key_value_->commit_transaction(); - for (auto &promise : pending_promises_) { - promise.set_value(Unit()); - } - pending_promises_.clear(); - } - void schedule_sync(Promise promise, double sync_delay) { - if (!need_sync_) { - key_value_->begin_transaction(); - need_sync_ = true; - } - - if (!sync_active_) { - if (sync_delay == 0) { - send_sync(); - } else { - alarm_timestamp().relax(Timestamp::in(sync_delay)); - } - } - if (promise) { - pending_promises_.push_back(std::move(promise)); - } - } - void alarm() override { - if (need_sync_ && !sync_active_) { - send_sync(); - } - } - void send_sync() { - sync_active_ = true; - alarm_timestamp() = Timestamp::never(); - send_closure(actor_id(this), &KeyValueActor::sync); - } -}; - -template -KeyValueAsync::KeyValueAsync() = default; -template -KeyValueAsync::KeyValueAsync(KeyValueAsync &&) = default; -template -KeyValueAsync &KeyValueAsync::operator=(KeyValueAsync &&) = default; -template -KeyValueAsync::~KeyValueAsync() = default; - -template -KeyValueAsync::KeyValueAsync(std::shared_ptr key_value) { - actor_ = actor::create_actor("KeyValueActor", std::move(key_value)); -} -template -void KeyValueAsync::get(KeyT key, Promise promise) { - send_closure_later(actor_, &ActorType::get, std::move(key), std::move(promise)); -} -template -void KeyValueAsync::set(KeyT key, ValueT value, Promise promise, double sync_delay) { - send_closure_later(actor_, &ActorType::set, std::move(key), std::move(value), std::move(promise), sync_delay); -} -template -void KeyValueAsync::erase(KeyT key, Promise promise, double sync_delay) { - send_closure_later(actor_, &ActorType::erase, std::move(key), std::move(promise), sync_delay); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.cpp b/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.cpp deleted file mode 100644 index aaf5472d..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/db/MemoryKeyValue.h" - -#include "td/utils/format.h" - -namespace td { -Result MemoryKeyValue::get(Slice key, std::string &value) { - auto it = map_.find(key); - if (it == map_.end()) { - return GetStatus::NotFound; - } - value = it->second; - return GetStatus::Ok; -} -Status MemoryKeyValue::set(Slice key, Slice value) { - map_[key.str()] = value.str(); - return Status::OK(); -} -Status MemoryKeyValue::erase(Slice key) { - auto it = map_.find(key); - if (it != map_.end()) { - map_.erase(it); - } - return Status::OK(); -} - -Result MemoryKeyValue::count(Slice prefix) { - size_t res = 0; - for (auto it = map_.lower_bound(prefix); it != map_.end(); it++) { - if (Slice(it->first).truncate(prefix.size()) != prefix) { - break; - } - res++; - } - return res; -} - -std::unique_ptr MemoryKeyValue::snapshot() { - auto res = std::make_unique(); - res->map_ = map_; - return std::move(res); -} - -std::string MemoryKeyValue::stats() const { - return PSTRING() << "MemoryKeyValueStats{" << tag("get_count", get_count_) << "}"; -} -Status MemoryKeyValue::begin_write_batch() { - UNREACHABLE(); -} -Status MemoryKeyValue::commit_write_batch() { - UNREACHABLE(); -} -Status MemoryKeyValue::abort_write_batch() { - UNREACHABLE(); -} - -Status MemoryKeyValue::begin_transaction() { - UNREACHABLE(); -} -Status MemoryKeyValue::commit_transaction() { - UNREACHABLE(); -} -Status MemoryKeyValue::abort_transaction() { - UNREACHABLE(); -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.h b/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.h deleted file mode 100644 index c9d584bc..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/MemoryKeyValue.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/db/KeyValue.h" - -#include - -namespace td { -class MemoryKeyValue : public KeyValue { - public: - Result get(Slice key, std::string &value) override; - Status set(Slice key, Slice value) override; - Status erase(Slice key) override; - Result count(Slice prefix) override; - - Status begin_write_batch() override; - Status commit_write_batch() override; - Status abort_write_batch() override; - - Status begin_transaction() override; - Status commit_transaction() override; - Status abort_transaction() override; - - std::unique_ptr snapshot() override; - - std::string stats() const override; - - private: - std::map> map_; - int64 get_count_{0}; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/RocksDb.cpp b/submodules/ton/tonlib-src/tddb/td/db/RocksDb.cpp deleted file mode 100644 index 500985e2..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/RocksDb.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/db/RocksDb.h" - -#include "rocksdb/db.h" -#include "rocksdb/table.h" -#include "rocksdb/statistics.h" -#include "rocksdb/write_batch.h" -#include "rocksdb/utilities/optimistic_transaction_db.h" -#include "rocksdb/utilities/transaction.h" - -namespace td { -namespace { -static Status from_rocksdb(rocksdb::Status status) { - if (status.ok()) { - return Status::OK(); - } - return Status::Error(status.ToString()); -} -static Slice from_rocksdb(rocksdb::Slice slice) { - return Slice(slice.data(), slice.size()); -} -static rocksdb::Slice to_rocksdb(Slice slice) { - return rocksdb::Slice(slice.data(), slice.size()); -} -} // namespace - -Status RocksDb::destroy(Slice path) { - return from_rocksdb(rocksdb::DestroyDB(path.str(), {})); -} - -RocksDb::RocksDb(RocksDb &&) = default; -RocksDb &RocksDb::operator=(RocksDb &&) = default; - -RocksDb::~RocksDb() { - if (!db_) { - return; - } - end_snapshot().ensure(); -} - -RocksDb RocksDb::clone() const { - return RocksDb{db_, statistics_}; -} - -Result RocksDb::open(std::string path) { - rocksdb::OptimisticTransactionDB *db; - auto statistics = rocksdb::CreateDBStatistics(); - { - rocksdb::Options options; - - static auto cache = rocksdb::NewLRUCache(1 << 30); - - rocksdb::BlockBasedTableOptions table_options; - table_options.block_cache = cache; - options.table_factory.reset(rocksdb::NewBlockBasedTableFactory(table_options)); - - options.manual_wal_flush = true; - options.create_if_missing = true; - options.max_background_compactions = 4; - options.max_background_flushes = 2; - options.bytes_per_sync = 1 << 20; - options.writable_file_max_buffer_size = 2 << 14; - options.statistics = statistics; - rocksdb::OptimisticTransactionDBOptions occ_options; - occ_options.validate_policy = rocksdb::OccValidationPolicy::kValidateSerial; - rocksdb::ColumnFamilyOptions cf_options(options); - std::vector column_families; - column_families.push_back(rocksdb::ColumnFamilyDescriptor(rocksdb::kDefaultColumnFamilyName, cf_options)); - std::vector handles; - TRY_STATUS(from_rocksdb( - rocksdb::OptimisticTransactionDB::Open(options, occ_options, std::move(path), column_families, &handles, &db))); - CHECK(handles.size() == 1); - // i can delete the handle since DBImpl is always holding a reference to - // default column family - delete handles[0]; - } - return RocksDb(std::shared_ptr(db), std::move(statistics)); -} - -std::unique_ptr RocksDb::snapshot() { - auto res = std::make_unique(clone()); - res->begin_snapshot().ensure(); - return std::move(res); -} - -std::string RocksDb::stats() const { - std::string out; - db_->GetProperty("rocksdb.stats", &out); - //db_->GetProperty("rocksdb.cur-size-all-mem-tables", &out); - return out; - return statistics_->ToString(); -} - -Result RocksDb::get(Slice key, std::string &value) { - //LOG(ERROR) << "GET"; - rocksdb::Status status; - if (snapshot_) { - rocksdb::ReadOptions options; - options.snapshot = snapshot_.get(); - status = db_->Get(options, to_rocksdb(key), &value); - } else if (transaction_) { - status = transaction_->Get({}, to_rocksdb(key), &value); - } else { - status = db_->Get({}, to_rocksdb(key), &value); - } - if (status.ok()) { - return GetStatus::Ok; - } - if (status.code() == rocksdb::Status::kNotFound) { - return GetStatus::NotFound; - } - return from_rocksdb(status); -} - -Status RocksDb::set(Slice key, Slice value) { - if (write_batch_) { - return from_rocksdb(write_batch_->Put(to_rocksdb(key), to_rocksdb(value))); - } - if (transaction_) { - return from_rocksdb(transaction_->Put(to_rocksdb(key), to_rocksdb(value))); - } - return from_rocksdb(db_->Put({}, to_rocksdb(key), to_rocksdb(value))); -} - -Status RocksDb::erase(Slice key) { - if (write_batch_) { - return from_rocksdb(write_batch_->Delete(to_rocksdb(key))); - } - if (transaction_) { - return from_rocksdb(transaction_->Delete(to_rocksdb(key))); - } - return from_rocksdb(db_->Delete({}, to_rocksdb(key))); -} - -Result RocksDb::count(Slice prefix) { - rocksdb::ReadOptions options; - options.snapshot = snapshot_.get(); - std::unique_ptr iterator; - if (snapshot_ || !transaction_) { - iterator.reset(db_->NewIterator(options)); - } else { - iterator.reset(transaction_->GetIterator(options)); - } - - size_t res = 0; - for (iterator->Seek(to_rocksdb(prefix)); iterator->Valid(); iterator->Next()) { - if (from_rocksdb(iterator->key()).truncate(prefix.size()) != prefix) { - break; - } - res++; - } - if (!iterator->status().ok()) { - return from_rocksdb(iterator->status()); - } - return res; -} - -Status RocksDb::begin_write_batch() { - CHECK(!transaction_); - write_batch_ = std::make_unique(); - return Status::OK(); -} - -Status RocksDb::begin_transaction() { - CHECK(!write_batch_); - rocksdb::WriteOptions options; - options.sync = true; - transaction_.reset(db_->BeginTransaction(options, {})); - return Status::OK(); -} - -Status RocksDb::commit_write_batch() { - CHECK(write_batch_); - auto write_batch = std::move(write_batch_); - rocksdb::WriteOptions options; - options.sync = true; - return from_rocksdb(db_->Write(options, write_batch.get())); -} - -Status RocksDb::commit_transaction() { - CHECK(transaction_); - auto transaction = std::move(transaction_); - return from_rocksdb(transaction->Commit()); -} - -Status RocksDb::abort_write_batch() { - CHECK(write_batch_); - write_batch_.reset(); - return Status::OK(); -} - -Status RocksDb::abort_transaction() { - CHECK(transaction_); - transaction_.reset(); - return Status::OK(); -} - -Status RocksDb::flush() { - return from_rocksdb(db_->Flush({})); -} - -Status RocksDb::begin_snapshot() { - snapshot_.reset(db_->GetSnapshot()); - return td::Status::OK(); -} - -Status RocksDb::end_snapshot() { - if (snapshot_) { - db_->ReleaseSnapshot(snapshot_.release()); - } - return td::Status::OK(); -} - -RocksDb::RocksDb(std::shared_ptr db, std::shared_ptr statistics) - : db_(std::move(db)), statistics_(std::move(statistics)) { -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/RocksDb.h b/submodules/ton/tonlib-src/tddb/td/db/RocksDb.h deleted file mode 100644 index b8bfaf9d..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/RocksDb.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#if !TDDB_USE_ROCKSDB -#error "RocksDb is not supported" -#endif - -#include "td/db/KeyValue.h" -#include "td/utils/Status.h" - -namespace rocksdb { -class OptimisticTransactionDB; -class Transaction; -class WriteBatch; -class Snapshot; -class Statistics; -} // namespace rocksdb - -namespace td { -class RocksDb : public KeyValue { - public: - static Status destroy(Slice path); - RocksDb clone() const; - static Result open(std::string path); - - Result get(Slice key, std::string &value) override; - Status set(Slice key, Slice value) override; - Status erase(Slice key) override; - Result count(Slice prefix) override; - - Status begin_write_batch() override; - Status commit_write_batch() override; - Status abort_write_batch() override; - - Status begin_transaction() override; - Status commit_transaction() override; - Status abort_transaction() override; - Status flush() override; - - Status begin_snapshot(); - Status end_snapshot(); - - std::unique_ptr snapshot() override; - std::string stats() const override; - - RocksDb(RocksDb &&); - RocksDb &operator=(RocksDb &&); - ~RocksDb(); - - std::shared_ptr raw_db() const { - return db_; - }; - - private: - std::shared_ptr db_; - std::shared_ptr statistics_; - - std::unique_ptr transaction_; - std::unique_ptr write_batch_; - class UnreachableDeleter { - public: - template - void operator()(T *) { - UNREACHABLE(); - } - }; - std::unique_ptr snapshot_; - - explicit RocksDb(std::shared_ptr db, - std::shared_ptr statistics); -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.cpp b/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.cpp deleted file mode 100644 index 7c60b113..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "Binlog.h" - -#include "BinlogReaderHelper.h" - -#include "td/db/utils/StreamInterface.h" -#include "td/db/utils/ChainBuffer.h" -#include "td/db/utils/CyclicBuffer.h" -#include "td/db/utils/FileSyncState.h" -#include "td/db/utils/StreamToFileActor.h" -#include "td/db/utils/FileToStreamActor.h" - -#include "td/actor/actor.h" - -#include "td/utils/misc.h" -#include "td/utils/port/path.h" -#include "td/utils/VectorQueue.h" - -namespace td { -namespace { -class BinlogReplayActor : public actor::Actor { - public: - BinlogReplayActor(StreamReader stream_reader, actor::ActorOwn file_to_stream, - std::shared_ptr binlog_reader, Promise promise) - : stream_reader_(std::move(stream_reader)) - , file_to_stream_(std::move(file_to_stream)) - , binlog_reader_(std::move(binlog_reader)) - , promise_(std::move(promise)) { - } - - private: - StreamReader stream_reader_; - actor::ActorOwn file_to_stream_; - std::shared_ptr binlog_reader_; - Promise promise_; - - bool is_writer_closed_{false}; - BinlogReaderHelper binlog_reader_helper_; - - unique_ptr create_callback() { - class Callback : public FileToStreamActor::Callback { - public: - Callback(actor::ActorShared<> actor) : actor_(std::move(actor)) { - } - void got_more() override { - send_signals_later(actor_, actor::ActorSignals::wakeup()); - } - - private: - actor::ActorShared<> actor_; - }; - return make_unique(actor_shared(this)); - } - - void start_up() override { - send_closure_later(file_to_stream_, &FileToStreamActor::set_callback, create_callback()); - } - void notify_writer() { - send_signals_later(file_to_stream_, actor::ActorSignals::wakeup()); - } - - void loop() override { - auto status = do_loop(); - if (status.is_error()) { - stream_reader_.close_reader(status.clone()); - promise_.set_error(std::move(status)); - return stop(); - } - if (is_writer_closed_) { - stream_reader_.close_reader(Status::OK()); - promise_.set_value(Unit()); - return stop(); - } - } - Status do_loop() { - is_writer_closed_ = stream_reader_.is_writer_closed(); - if (is_writer_closed_) { - TRY_STATUS(std::move(stream_reader_.writer_status())); - } - - // TODO: watermark want_more/got_more logic - int64 got_size = stream_reader_.reader_size(); - while (got_size > 0) { - auto slice = stream_reader_.prepare_read(); - TRY_STATUS(binlog_reader_helper_.parse(*binlog_reader_, slice)); - stream_reader_.confirm_read(slice.size()); - got_size -= slice.size(); - } - notify_writer(); - - if (is_writer_closed_) { - if (binlog_reader_helper_.unparsed_size() != 0) { - return Status::Error(PSLICE() << "Got " << binlog_reader_helper_.unparsed_size() - << " unparsed bytes in binlog"); - } - } - - return Status::OK(); - } -}; -} // namespace -Binlog::Binlog(string path) : path_(std::move(path)) { -} - -Status Binlog::replay_sync(BinlogReaderInterface& binlog_reader) { - TRY_RESULT(fd, FileFd::open(path_, FileFd::Flags::Read)); - // No need to use Cyclic buffer, but CyclicBuffer is important for async version - CyclicBuffer::Options options; - options.chunk_size = 256; - options.count = 1; - auto reader_writer = CyclicBuffer::create(options); - - auto buf_reader = std::move(reader_writer.first); - auto buf_writer = std::move(reader_writer.second); - - TRY_RESULT(fd_size, fd.get_size()); - - BinlogReaderHelper helper; - while (fd_size != 0) { - auto read_to = buf_writer.prepare_write(); - if (static_cast(read_to.size()) > fd_size) { - read_to.truncate(narrow_cast(fd_size)); - } - TRY_RESULT(read, fd.read(read_to)); - if (read == 0) { - return Status::Error("Unexpected end of file"); - } - fd_size -= read; - buf_writer.confirm_write(read); - - auto data = buf_reader.prepare_read(); - CHECK(data.size() == read); - TRY_STATUS(helper.parse(binlog_reader, data)); - buf_reader.confirm_read(data.size()); - } - - if (helper.unparsed_size() != 0) { - return Status::Error(PSLICE() << "Got " << helper.unparsed_size() << " unparsed bytes in binlog"); - } - - //TODO: check crc32 - //TODO: allow binlog truncate - return Status::OK(); -} - -void Binlog::replay_async(std::shared_ptr binlog_reader, Promise promise) { - auto r_fd = FileFd::open(path_, FileFd::Flags::Read); - if (r_fd.is_error()) { - promise.set_error(r_fd.move_as_error()); - return; - } - auto fd = r_fd.move_as_ok(); - CyclicBuffer::Options buf_options; - buf_options.chunk_size = 256; - auto reader_writer = CyclicBuffer::create(buf_options); - - auto buf_reader = std::move(reader_writer.first); - auto buf_writer = std::move(reader_writer.second); - - auto r_fd_size = fd.get_size(); - if (r_fd_size.is_error()) { - promise.set_error(r_fd_size.move_as_error()); - } - auto options = FileToStreamActor::Options{}; - options.limit = r_fd_size.move_as_ok(); - auto file_to_stream = - actor::create_actor("FileToStream", std::move(fd), std::move(buf_writer), options); - auto stream_to_binlog = actor::create_actor( - "BinlogReplay", std::move(buf_reader), std::move(file_to_stream), std::move(binlog_reader), std::move(promise)); - stream_to_binlog.release(); -} - -void Binlog::destroy(CSlice path) { - td::unlink(path).ignore(); -} - -void Binlog::destroy() { - destroy(path_); -} - -BinlogWriter::BinlogWriter(std::string path) : path_(std::move(path)) { -} - -Status BinlogWriter::open() { - TRY_RESULT(fd, FileFd::open(path_, FileFd::Flags::Write | FileFd::Flags::Append | FileFd::Create)); - fd_ = std::move(fd); - ChainBuffer::Options buf_options; - buf_options.max_io_slices = 128; - buf_options.chunk_size = 256; - auto reader_writer = ChainBuffer::create(buf_options); - buf_reader_ = std::move(reader_writer.first); - buf_writer_ = std::move(reader_writer.second); - return Status::OK(); -} - -Status BinlogWriter::lazy_flush() { - if (buf_reader_.reader_size() < 512) { - return Status::OK(); - } - return flush(); -} - -Status BinlogWriter::flush() { - while (buf_reader_.reader_size() != 0) { - TRY_RESULT(written, fd_.writev(buf_reader_.prepare_readv())); - buf_reader_.confirm_read(written); - } - return Status::OK(); -} -Status BinlogWriter::sync() { - flush(); - return fd_.sync(); -} - -Status BinlogWriter::close() { - sync(); - fd_.close(); - return Status::OK(); -} - -namespace detail { -class FlushHelperActor : public actor::Actor { - public: - FlushHelperActor(FileSyncState::Reader sync_state_reader, actor::ActorOwn actor) - : sync_state_reader_(std::move(sync_state_reader)), actor_(std::move(actor)) { - } - void flush() { - //TODO; - } - void sync(size_t position, Promise promise) { - sync_state_reader_.set_requested_sync_size(position); - if (promise) { - queries_.emplace(position, std::move(promise)); - } - send_signals_later(actor_, actor::ActorSignals::wakeup()); - } - - void close(Promise<> promise) { - close_promise_ = std::move(promise); - actor_.reset(); - } - - private: - FileSyncState::Reader sync_state_reader_; - actor::ActorOwn actor_; - Promise<> close_promise_; - - struct Query { - Query(size_t position, Promise promise) : position(position), promise(std::move(promise)) { - } - size_t position; - Promise promise; - }; - VectorQueue queries_; - - unique_ptr create_callback() { - class Callback : public StreamToFileActor::Callback { - public: - Callback(actor::ActorShared<> actor) : actor_(std::move(actor)) { - } - void on_sync_state_changed() override { - send_signals_later(actor_, actor::ActorSignals::wakeup()); - } - - private: - actor::ActorShared<> actor_; - }; - return make_unique(actor_shared(this)); - } - - void start_up() override { - send_closure_later(actor_, &StreamToFileActor::set_callback, create_callback()); - } - - void loop() override { - auto synced_position = sync_state_reader_.synced_size(); - while (!queries_.empty() && queries_.front().position <= synced_position) { - queries_.front().promise.set_value(Unit()); - queries_.pop(); - } - } - - void hangup_shared() override { - stop(); - } - void tear_down() override { - if (close_promise_) { - close_promise_.set_value(Unit()); - } - } -}; -} // namespace detail -BinlogWriterAsync::BinlogWriterAsync(std::string path) : path_(std::move(path)) { -} -BinlogWriterAsync::~BinlogWriterAsync() = default; - -Status BinlogWriterAsync::open() { - TRY_RESULT(fd, FileFd::open(path_, FileFd::Flags::Write | FileFd::Flags::Append | FileFd::Create)); - ChainBuffer::Options buf_options; - buf_options.max_io_slices = 128; - buf_options.chunk_size = 256; - auto reader_writer = ChainBuffer::create(buf_options); - buf_writer_ = std::move(reader_writer.second); - - auto sync_state_reader_writer = td::FileSyncState::create(); - auto writer_actor = actor::create_actor("StreamToFile", std::move(reader_writer.first), - std::move(fd), std::move(sync_state_reader_writer.second)); - writer_actor_ = writer_actor.get(); - sync_state_reader_ = std::move(sync_state_reader_writer.first); - - flush_helper_actor_ = - actor::create_actor("FlushHelperActor", sync_state_reader_, std::move(writer_actor)); - - return Status::OK(); -} - -void BinlogWriterAsync::close(Promise<> promise) { - send_closure(std::move(flush_helper_actor_), &detail::FlushHelperActor::close, std::move(promise)); - writer_actor_ = {}; -} -void BinlogWriterAsync::lazy_flush() { - send_signals_later(writer_actor_, actor::ActorSignals::wakeup()); -} - -void BinlogWriterAsync::flush() { - send_closure(flush_helper_actor_, &detail::FlushHelperActor::flush); -} -void BinlogWriterAsync::sync(Promise promise) { - send_closure(flush_helper_actor_, &detail::FlushHelperActor::sync, buf_writer_.writer_size(), std::move(promise)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.h b/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.h deleted file mode 100644 index 86eb3691..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/binlog/Binlog.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "BinlogReaderInterface.h" - -#include "td/db/utils/FileSyncState.h" -#include "td/db/utils/StreamInterface.h" - -#include "td/actor/actor.h" - -#include "td/utils/misc.h" -#include "td/utils/port/FileFd.h" - -namespace td { -class BinlogReaderInterface; -class StreamToFileActor; -namespace detail { -class FlushHelperActor; -} // namespace detail -class Binlog { - public: - explicit Binlog(string path); - - Status replay_sync(BinlogReaderInterface& binlog_reader); - void replay_async(std::shared_ptr binlog_reader, Promise promise); - - static void destroy(CSlice path); - void destroy(); - - private: - string path_; -}; - -class BinlogWriter { - public: - BinlogWriter(std::string path); - - Status open(); - - template - Status write_event(EventT&& event, BinlogReaderInterface* binlog_reader); - Status lazy_flush(); - Status flush(); - Status sync(); - - Status close(); - - private: - string path_; - FileFd fd_; - - StreamReader buf_reader_; - StreamWriter buf_writer_; -}; - -class BinlogWriterAsync { - public: - BinlogWriterAsync(std::string path); - ~BinlogWriterAsync(); - - Status open(); - - template - Status write_event(EventT&& event, BinlogReaderInterface* binlog_reader); - - void close(Promise<> promise); - - void lazy_flush(); - - void flush(); - void sync(Promise promise = {}); - - private: - std::string path_; - StreamWriter buf_writer_; - actor::ActorId writer_actor_; - actor::ActorOwn flush_helper_actor_; - - FileSyncState::Reader sync_state_reader_; -}; - -template -Status BinlogWriter::write_event(EventT&& event, BinlogReaderInterface* binlog_reader) { - int64 need_size = -event.serialize({}); - auto dest = - buf_writer_.prepare_write_at_least(narrow_cast(need_size)).truncate(narrow_cast(need_size)); - auto written = event.serialize(dest); - CHECK(written == need_size); - - if (binlog_reader != nullptr) { - TRY_RESULT(parsed, binlog_reader->parse(dest)); - binlog_reader->flush(); - CHECK(parsed == written); - } - - buf_writer_.confirm_write(narrow_cast(written)); - return lazy_flush(); -} - -template -Status BinlogWriterAsync::write_event(EventT&& event, BinlogReaderInterface* binlog_reader) { - int64 need_size = -event.serialize({}); - auto dest = - buf_writer_.prepare_write_at_least(narrow_cast(need_size)).truncate(narrow_cast(need_size)); - auto written = event.serialize(dest); - CHECK(written == need_size); - - if (binlog_reader != nullptr) { - TRY_RESULT(parsed, binlog_reader->parse(dest)); - CHECK(parsed == written); - } - - buf_writer_.confirm_write(narrow_cast(written)); - lazy_flush(); - return Status::OK(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.cpp b/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.cpp deleted file mode 100644 index 5ea45f64..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "BinlogReaderHelper.h" -#include "BinlogReaderInterface.h" - -#include "td/utils/misc.h" - -namespace td { -td::Status BinlogReaderHelper::parse(BinlogReaderInterface& reader, td::Slice data) { - SCOPE_EXIT { - reader.flush(); - }; - while (true) { - if (expected_prefix_size_ > 0 && expected_prefix_size_ == prefix_size_) { - TRY_RESULT(size, reader.parse(MutableSlice(buf_.data(), prefix_size_))); - if (size < 0) { - if (expected_prefix_size_ > td::narrow_cast(-size)) { - return td::Status::Error("BinlogReader decreased logevent size estimation (1)"); - } - expected_prefix_size_ = static_cast(-size); - } else { - if (expected_prefix_size_ != td::narrow_cast(size)) { - return td::Status::Error("BinlogReader changed logevent"); - } - prefix_size_ = 0; - expected_prefix_size_ = 0; - } - } - - if (data.empty()) { - break; - } - - if (expected_prefix_size_ > 0) { - CHECK(expected_prefix_size_ < buf_.size()); - CHECK(prefix_size_ < expected_prefix_size_); - auto got = data.copy().truncate(expected_prefix_size_ - prefix_size_); - reader.flush(); - auto dest = td::MutableSlice(buf_.data(), buf_.size()).substr(prefix_size_); - if (dest.size() < got.size()) { - return td::Status::Error("Too big logevent"); - } - dest.copy_from(got); - prefix_size_ += got.size(); - data = data.substr(got.size()); - continue; - } - - CHECK(!data.empty()); - - TRY_RESULT(size, reader.parse(data)); - if (size < 0) { - expected_prefix_size_ = td::narrow_cast(-size); - prefix_size_ = data.size(); - if (expected_prefix_size_ < prefix_size_) { - return td::Status::Error("BinlogReader waits for less data than it already has"); - } - if (expected_prefix_size_ > buf_.size()) { - return td::Status::Error("BinlogReader waits for too big logevent"); - } - reader.flush(); - td::MutableSlice(buf_.data(), prefix_size_).copy_from(data); - break; - } - if (size == 0) { - return td::Status::Error("BinlogReader parseed nothing and asked for nothing"); - } - if (td::narrow_cast(size) > data.size()) { - return td::Status::Error("BinlogReader parseed more than was given"); - } - data = data.substr(static_cast(size)); - } - return td::Status::OK(); -} - -size_t BinlogReaderHelper::unparsed_size() const { - return prefix_size_; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.h b/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.h deleted file mode 100644 index 19f6a586..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderHelper.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Status.h" -#include "td/utils/Slice.h" - -namespace td { - -class BinlogReaderInterface; - -// Usually we have data available in chunks and we can't control chunk's sizes -// And some events will be in multiple chunks. -// We suggest that all events are small, chunks are big and only small -// portion of events will lie on chunk's border. -// This helper will store this rare events locally and will feed them -// to BinlogReaderInterface as single memory chunk each. -class BinlogReaderHelper { - public: - td::Status parse(BinlogReaderInterface& reader, td::Slice data); - - size_t unparsed_size() const; - - private: - alignas(16) std::array buf_; - size_t prefix_size_{0}; - size_t expected_prefix_size_{0}; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderInterface.h b/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderInterface.h deleted file mode 100644 index 2cea8f6f..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/binlog/BinlogReaderInterface.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -class BinlogReaderInterface { - public: - virtual ~BinlogReaderInterface() { - } - // returns error or size - // negative size means reader expects data.size() to be at least -size - // positive size means first size bytes of data are processed and could be skipped - virtual td::Result parse(td::Slice data) = 0; - - // called when all passed slices are invalidated - // Till it is called reader may resue all slices given to it. - // It makes possible to calculate crc32c in larger chunks - // TODO: maybe we should just process all data that we can at once - virtual void flush() { - } -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.cpp deleted file mode 100644 index 7478eed8..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "ChainBuffer.h" - -#include "td/utils/buffer.h" -#include "td/db/utils/StreamInterface.h" - -namespace td { -namespace detail { -class ChainBuffer : public StreamWriterInterface, public StreamReaderInterface { - public: - using Options = ::td::ChainBuffer::Options; - - ChainBuffer(Options options) { - shared_.options_ = options; - reader_.io_slices_.reserve(options.max_io_slices); - reader_.buf_ = writer_.buf_.extract_reader(); - } - - // StreamReaderInterface - size_t reader_size() override { - reader_.buf_.sync_with_writer(); - return reader_.buf_.size(); - } - - Slice prepare_read() override { - return reader_.buf_.prepare_read(); - } - Span prepare_readv() override { - reader_.io_slices_.clear(); - auto it = reader_.buf_.clone(); - while (!it.empty() && reader_.io_slices_.size() < reader_.io_slices_.capacity()) { - auto slice = it.prepare_read(); - reader_.io_slices_.push_back(as_io_slice(slice)); - it.confirm_read(slice.size()); - } - return reader_.io_slices_; - } - void confirm_read(size_t size) override { - reader_.buf_.advance(size); - } - - void close_reader(Status error) override { - CHECK(!reader_.is_closed_); - reader_.status_ = std::move(error); - reader_.is_closed_.store(true, std::memory_order_release); - } - bool is_writer_closed() const override { - return writer_.is_closed_.load(std::memory_order_acquire); - } - Status &writer_status() override { - CHECK(is_writer_closed()); - return writer_.status_; - } - - // StreamWriterInterface - size_t writer_size() override { - return writer_.size_; - } - MutableSlice prepare_write() override { - return writer_.buf_.prepare_append(shared_.options_.chunk_size); - } - MutableSlice prepare_write_at_least(size_t size) override { - return writer_.buf_.prepare_append_at_least(size); - } - void confirm_write(size_t size) override { - writer_.buf_.confirm_append(size); - writer_.size_ += size; - } - void append(Slice data) override { - writer_.buf_.append(data, shared_.options_.chunk_size); - writer_.size_ += data.size(); - } - void append(BufferSlice data) override { - writer_.size_ += data.size(); - writer_.buf_.append(std::move(data)); - } - void append(std::string data) override { - append(Slice(data)); - } - void close_writer(Status error) override { - CHECK(!writer_.is_closed_); - writer_.status_ = std::move(error); - writer_.is_closed_.store(true, std::memory_order_release); - } - bool is_reader_closed() const override { - return reader_.is_closed_.load(std::memory_order_acquire); - } - Status &reader_status() override { - CHECK(is_reader_closed()); - return reader_.status_; - } - - private: - struct SharedData { - Options options_; - } shared_; - - char pad1[128]; - - struct ReaderData { - ChainBufferReader buf_; - std::atomic is_closed_{false}; - Status status_; - std::vector io_slices_; - } reader_; - - char pad2[128]; - - struct WriterData { - ChainBufferWriter buf_; - std::atomic is_closed_{false}; - Status status_; - size_t size_{0}; - } writer_; -}; -} // namespace detail - -std::pair ChainBuffer::create(Options options) { - auto impl = std::make_shared(options); - return {Reader(impl), Writer(impl)}; -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.h b/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.h deleted file mode 100644 index af690693..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/ChainBuffer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/common.h" - -#include "StreamInterface.h" - -namespace td { -class ChainBuffer { - public: - struct Options { - Options() { - } - size_t chunk_size{1024 * 1024 / 8}; // default size of one chunk in chain buffer - size_t max_io_slices{128}; // size of buffer for writev - }; - using Reader = StreamReader; - using Writer = StreamWriter; - static std::pair create(Options options = {}); -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.cpp deleted file mode 100644 index ea3b2c6c..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "CyclicBuffer.h" - -#include "td/utils/misc.h" -#include "td/utils/Slice.h" - -#include -#include -#include - -namespace td { -namespace detail { -class CyclicBuffer : public StreamWriterInterface, public StreamReaderInterface { - public: - using Options = ::td::CyclicBuffer::Options; - - CyclicBuffer(Options options) { - CHECK(options.chunk_size != 0); - CHECK(options.count != 0); - CHECK(options.alignment != 0); - CHECK(options.chunk_size < (std::numeric_limits::max() - options.alignment) / options.count); - shared_.options_ = options; - shared_.raw_data_ = std::make_unique(options.size() + options.alignment - 1); - auto pos = reinterpret_cast(shared_.raw_data_.get()); - auto offset = (options.alignment - static_cast(pos % options.alignment)) % options.alignment; - CHECK(offset < options.alignment); - shared_.data_ = MutableSlice(shared_.raw_data_.get() + offset, options.size()); - } - - // StreamReaderInterface - size_t reader_size() override { - auto offset = reader_.pos_.load(std::memory_order_relaxed); - auto size = writer_.pos_.load(std::memory_order_acquire) - offset; - return narrow_cast(size); - } - Slice prepare_read() override { - auto offset = reader_.pos_.load(std::memory_order_relaxed); - auto size = narrow_cast(writer_.pos_.load(std::memory_order_acquire) - offset); - if (size == 0) { - return {}; - } - offset %= (shared_.options_.chunk_size * shared_.options_.count); - return shared_.data_.substr(narrow_cast(offset)).truncate(size).truncate(shared_.options_.chunk_size); - } - Span prepare_readv() override { - reader_.io_slice_ = as_io_slice(prepare_read()); - return Span(&reader_.io_slice_, 1); - } - void confirm_read(size_t size) override { - reader_.pos_.store(reader_.pos_.load(std::memory_order_relaxed) + size); - } - - void close_reader(Status error) override { - CHECK(!reader_.is_closed_); - reader_.status_ = std::move(error); - reader_.is_closed_.store(true, std::memory_order_release); - } - bool is_writer_closed() const override { - return writer_.is_closed_.load(std::memory_order_acquire); - } - Status &writer_status() override { - CHECK(is_writer_closed()); - return writer_.status_; - } - - // StreamWriterInterface - size_t writer_size() override { - auto offset = reader_.pos_.load(std::memory_order_acquire); - auto size = writer_.pos_.load(std::memory_order_relaxed) - offset; - return narrow_cast(size); - } - MutableSlice prepare_write() override { - auto max_offset = - reader_.pos_.load(std::memory_order_acquire) + shared_.options_.chunk_size * (shared_.options_.count - 1); - auto offset = writer_.pos_.load(std::memory_order_relaxed); - if (offset > max_offset) { - return {}; - } - offset %= (shared_.options_.chunk_size * shared_.options_.count); - return shared_.data_.substr(narrow_cast(offset), shared_.options_.chunk_size); - } - MutableSlice prepare_write_at_least(size_t size) override { - UNREACHABLE(); - } - void confirm_write(size_t size) override { - writer_.pos_.store(writer_.pos_.load(std::memory_order_relaxed) + size); - } - void append(Slice data) override { - UNREACHABLE(); - } - void append(BufferSlice data) override { - UNREACHABLE(); - } - void append(std::string data) override { - UNREACHABLE(); - } - void close_writer(Status error) override { - CHECK(!writer_.is_closed_); - writer_.status_ = std::move(error); - writer_.is_closed_.store(true, std::memory_order_release); - } - bool is_reader_closed() const override { - return reader_.is_closed_.load(std::memory_order_acquire); - } - Status &reader_status() override { - CHECK(is_reader_closed()); - return reader_.status_; - } - - private: - struct SharedData { - std::unique_ptr raw_data_; - MutableSlice data_; - Options options_; - } shared_; - - struct ReaderData { - std::atomic pos_{0}; - std::atomic is_closed_{false}; - Status status_; - IoSlice io_slice_; - } reader_; - - char pad[128]; - - struct WriterData { - std::atomic pos_{0}; - std::atomic is_closed_{false}; - Status status_; - } writer_; -}; -} // namespace detail - -std::pair CyclicBuffer::create(Options options) { - auto impl = std::make_shared(options); - return {Reader(impl), Writer(impl)}; -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.h b/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.h deleted file mode 100644 index c82a1e5b..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/CyclicBuffer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "StreamInterface.h" - -#include - -namespace td { - -class CyclicBuffer { - public: - struct Options { - Options() { - } - size_t chunk_size{1024 * 1024 / 8}; - size_t count{16}; - size_t alignment{1024}; - - size_t size() const { - return chunk_size * count; - } - size_t max_writable_size() { - return size() - chunk_size; - } - }; - using Reader = StreamReader; - using Writer = StreamWriter; - static std::pair create(Options options = {}); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.cpp deleted file mode 100644 index 667c70c0..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ - -#include "FileSyncState.h" -namespace td { -std::pair FileSyncState::create() { - auto self = std::make_shared(); - return {Reader(self), Writer(self)}; -} - -FileSyncState::Reader::Reader(std::shared_ptr self) : self(std::move(self)) { -} -bool FileSyncState::Reader::set_requested_sync_size(size_t size) const { - if (self->requested_synced_size.load(std::memory_order_relaxed) == size) { - return false; - } - self->requested_synced_size.store(size, std::memory_order_release); - return true; -} - -size_t FileSyncState::Reader::synced_size() const { - return self->synced_size; -} -size_t FileSyncState::Reader::flushed_size() const { - return self->flushed_size; -} - -FileSyncState::Writer::Writer(std::shared_ptr self) : self(std::move(self)) { -} - -size_t FileSyncState::Writer::get_requested_synced_size() { - return self->requested_synced_size.load(std::memory_order_acquire); -} - -bool FileSyncState::Writer::set_synced_size(size_t size) { - if (self->synced_size.load(std::memory_order_relaxed) == size) { - return false; - } - self->synced_size.store(size, std::memory_order_release); - return true; -} - -bool FileSyncState::Writer::set_flushed_size(size_t size) { - if (self->flushed_size.load(std::memory_order_relaxed) == size) { - return false; - } - self->flushed_size.store(size, std::memory_order_release); - return true; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.h b/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.h deleted file mode 100644 index fcd23514..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/FileSyncState.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include -#include -#include - -#include "td/utils/common.h" - -namespace td { -class FileSyncState { - struct Self; - - public: - class Reader { - public: - Reader() = default; - Reader(std::shared_ptr self); - bool set_requested_sync_size(size_t size) const; - size_t synced_size() const; - size_t flushed_size() const; - - private: - std::shared_ptr self; - }; - - class Writer { - public: - Writer() = default; - Writer(std::shared_ptr self); - size_t get_requested_synced_size(); - bool set_synced_size(size_t size); - bool set_flushed_size(size_t size); - - private: - std::shared_ptr self; - }; - - static std::pair create(); - - private: - struct Self { - std::atomic requested_synced_size{0}; - - std::atomic synced_size{0}; - std::atomic flushed_size{0}; - }; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.cpp deleted file mode 100644 index bef5b94f..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "FileToStreamActor.h" - -namespace td { -FileToStreamActor::FileToStreamActor(FileFd fd, StreamWriter writer, Options options) - : fd_(std::move(fd)), writer_(std::move(writer)), options_(options) { -} - -void FileToStreamActor::set_callback(td::unique_ptr callback) { - callback_ = std::move(callback); - got_more(); -} - -void FileToStreamActor::got_more() { - if (!callback_) { - return; - } - callback_->got_more(); -} -void FileToStreamActor::loop() { - auto dest = writer_.prepare_write(); - if (options_.limit != -1) { - if (static_cast(dest.size()) > options_.limit) { - dest.truncate(narrow_cast(options_.limit)); - } - } - if (dest.empty()) { - //NB: Owner of CyclicBufer::Reader should notify this actor after each chunk is readed - return; - } - - auto r_size = fd_.read(dest); - if (r_size.is_error()) { - writer_.close_writer(r_size.move_as_error()); - got_more(); - return stop(); - } - auto size = r_size.move_as_ok(); - writer_.confirm_write(size); - got_more(); - if (options_.limit != -1) { - options_.limit -= narrow_cast(size); - } - if (options_.limit == 0) { - writer_.close_writer(td::Status::OK()); - got_more(); - return stop(); - } - if (size == 0) { - if (options_.read_tail_each < 0) { - writer_.close_writer(td::Status::OK()); - got_more(); - return stop(); - } - alarm_timestamp() = Timestamp::in(options_.read_tail_each); - return; - } - yield(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.h b/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.h deleted file mode 100644 index 0d09392e..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/FileToStreamActor.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "StreamInterface.h" - -#include "td/actor/actor.h" -#include "td/utils/port/FileFd.h" - -namespace td { -class FileToStreamActor : public td::actor::Actor { - public: - struct Options { - Options() { - } - int64 limit{-1}; - double read_tail_each{-1}; - }; - class Callback { - public: - virtual ~Callback() { - } - virtual void got_more() = 0; - }; - FileToStreamActor(FileFd fd, StreamWriter writer, Options options = {}); - - void set_callback(td::unique_ptr callback); - - private: - void got_more(); - void loop() override; - FileFd fd_; - StreamWriter writer_; - td::unique_ptr callback_; - Options options_; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.cpp deleted file mode 100644 index 923d7be2..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "StreamInterface.h" -namespace td { -StreamReader::StreamReader(std::shared_ptr self) : self(std::move(self)) { -} -size_t StreamReader::reader_size() { - return self->reader_size(); -} -Slice StreamReader::prepare_read() { - return self->prepare_read(); -} -Span StreamReader::prepare_readv() { - return self->prepare_readv(); -} -void StreamReader::confirm_read(size_t size) { - return self->confirm_read(size); -} - -void StreamReader::close_reader(Status error) { - return self->close_reader(std::move(error)); -} -bool StreamReader::is_writer_closed() const { - return self->is_writer_closed(); -} -Status &StreamReader::writer_status() { - return self->writer_status(); -} - -StreamWriter::StreamWriter(std::shared_ptr self) : self(std::move(self)) { -} -size_t StreamWriter::writer_size() { - return self->writer_size(); -} -MutableSlice StreamWriter::prepare_write() { - return self->prepare_write(); -} -MutableSlice StreamWriter::prepare_write_at_least(size_t size) { - return self->prepare_write_at_least(size); -} -void StreamWriter::confirm_write(size_t size) { - return self->confirm_write(size); -} -void StreamWriter::append(Slice data) { - return self->append(data); -} -void StreamWriter::append(BufferSlice data) { - return self->append(std::move(data)); -} -void StreamWriter::append(std::string data) { - return self->append(std::move(data)); -} - -void StreamWriter::close_writer(Status error) { - return self->close_writer(std::move(error)); -} -bool StreamWriter::is_reader_closed() const { - return self->is_reader_closed(); -} -Status &StreamWriter::reader_status() { - return self->reader_status(); -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.h b/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.h deleted file mode 100644 index 68b853c4..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamInterface.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "td/utils/buffer.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/port/IoSlice.h" - -namespace td { -// Generic stream interface -// Will to hide implementations details. -// CyclicBuffer, ChainBuffer, Bounded ChainBuffer, some clever writers. They all should be interchangable -// Most implementaions will assume that reading and writing may happen concurrently - -class StreamReaderInterface { - public: - virtual ~StreamReaderInterface() { - } - virtual size_t reader_size() = 0; - virtual Slice prepare_read() = 0; - virtual Span prepare_readv() = 0; - virtual void confirm_read(size_t size) = 0; - - virtual void close_reader(Status error) = 0; - virtual bool is_writer_closed() const = 0; - virtual Status &writer_status() = 0; -}; - -class StreamWriterInterface { - public: - virtual ~StreamWriterInterface() { - } - virtual size_t writer_size() = 0; - virtual MutableSlice prepare_write() = 0; - virtual MutableSlice prepare_write_at_least(size_t size) = 0; - virtual void confirm_write(size_t size) = 0; - virtual void append(Slice data) = 0; - virtual void append(BufferSlice data) { - append(data.as_slice()); - } - virtual void append(std::string data) { - append(Slice(data)); - } - - virtual void close_writer(Status error) = 0; - virtual bool is_reader_closed() const = 0; - virtual Status &reader_status() = 0; -}; - -// Hide shared_ptr -class StreamReader : public StreamReaderInterface { - public: - StreamReader() = default; - StreamReader(std::shared_ptr self); - size_t reader_size() override; - Slice prepare_read() override; - Span prepare_readv() override; - void confirm_read(size_t size) override; - void close_reader(Status error) override; - bool is_writer_closed() const override; - Status &writer_status() override; - - private: - std::shared_ptr self; -}; - -class StreamWriter : public StreamWriterInterface { - public: - StreamWriter() = default; - StreamWriter(std::shared_ptr self); - size_t writer_size() override; - MutableSlice prepare_write() override; - MutableSlice prepare_write_at_least(size_t size) override; - void confirm_write(size_t size) override; - void append(Slice data) override; - void append(BufferSlice data) override; - void append(std::string data) override; - void close_writer(Status error) override; - bool is_reader_closed() const override; - Status &reader_status() override; - - private: - std::shared_ptr self; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.cpp b/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.cpp deleted file mode 100644 index 24202da4..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "StreamToFileActor.h" - -namespace td { -StreamToFileActor::StreamToFileActor(StreamReader reader, FileFd fd, FileSyncState::Writer sync_state, Options options) - : reader_(std::move(reader)), fd_(std::move(fd)), sync_state_(std::move(sync_state)) { -} -void StreamToFileActor::set_callback(td::unique_ptr callback) { - callback_ = std::move(callback); - callback_->on_sync_state_changed(); -} - -Result StreamToFileActor::is_closed() { - if (!reader_.is_writer_closed()) { - return false; - } - return reader_.writer_status().clone(); -} - -Status StreamToFileActor::do_flush_once() { - auto size = reader_.reader_size(); - size_t total_written = 0; - while (total_written < size) { - auto io_slices = reader_.prepare_readv(); - TRY_RESULT(written, fd_.writev(io_slices)); - reader_.confirm_read(written); - flushed_size_ += written; - total_written += written; - } - return Status::OK(); -} - -Status StreamToFileActor::do_sync() { - if (flushed_size_ == synced_size_) { - return Status::OK(); - } - TRY_STATUS(fd_.sync()); - synced_size_ = flushed_size_; - return Status::OK(); -} - -void StreamToFileActor::schedule_sync() { - if (synced_size_ == flushed_size_) { - return; - } - if (sync_state_.get_requested_synced_size() > synced_size_) { - sync_at_.relax(Timestamp::in(options_.immediate_sync_delay)); - } else { - sync_at_.relax(Timestamp::in(options_.lazy_sync_delay)); - } -} - -Result StreamToFileActor::do_loop() { - // We must first check if writer is closed and then drain all data from reader - // Otherwise there will be a race and some of data could be lost. - // Also it could be useful to check error and stop immediately. - TRY_RESULT(is_closed, is_closed()); - - // Flush all data that is awailable on the at the beginning of loop - TRY_STATUS(do_flush_once()); - - if ((sync_at_ && sync_at_.is_in_past()) || is_closed) { - TRY_STATUS(do_sync()); - sync_at_ = {}; - } - - bool need_update = sync_state_.set_synced_size(synced_size_) | sync_state_.set_flushed_size(flushed_size_); - if (need_update && callback_) { - callback_->on_sync_state_changed(); - } - - if (reader_.reader_size() == 0 && is_closed) { - return true; - } - - schedule_sync(); - return false; -} - -void StreamToFileActor::start_up() { - schedule_sync(); -} - -void StreamToFileActor::loop() { - auto r_is_closed = do_loop(); - if (r_is_closed.is_error()) { - reader_.close_reader(r_is_closed.move_as_error()); - return stop(); - } else if (r_is_closed.ok()) { - reader_.close_reader(Status::OK()); - return stop(); - } - alarm_timestamp() = sync_at_; -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.h b/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.h deleted file mode 100644 index 2037cc43..00000000 --- a/submodules/ton/tonlib-src/tddb/td/db/utils/StreamToFileActor.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once -#include "StreamInterface.h" -#include "FileSyncState.h" - -#include "td/utils/Time.h" -#include "td/utils/port/FileFd.h" - -#include "td/actor/actor.h" - -namespace td { -class StreamToFileActor : public actor::Actor { - public: - struct Options { - Options() { - } - double lazy_sync_delay = 10; - double immediate_sync_delay = 0.001; - }; - - class Callback { - public: - virtual ~Callback() { - } - virtual void on_sync_state_changed() = 0; - }; - - StreamToFileActor(StreamReader reader, FileFd fd, FileSyncState::Writer sync_state, Options options = {}); - void set_callback(td::unique_ptr callback); - - private: - StreamReader reader_; - FileFd fd_; - Timestamp sync_at_; - Options options_; - FileSyncState::Writer sync_state_; - unique_ptr callback_; - - size_t flushed_size_{0}; - size_t synced_size_{0}; - - TD_WARN_UNUSED_RESULT Result is_closed(); - - Status do_flush_once(); - - Status do_sync(); - - void schedule_sync(); - - TD_WARN_UNUSED_RESULT Result do_loop(); - - void start_up() override; - - void loop() override; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tddb/test/binlog.cpp b/submodules/ton/tonlib-src/tddb/test/binlog.cpp deleted file mode 100644 index d3cc6c9b..00000000 --- a/submodules/ton/tonlib-src/tddb/test/binlog.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/utils/as.h" -#include "td/utils/base64.h" -#include "td/utils/benchmark.h" -#include "td/utils/buffer.h" -#include "td/utils/crypto.h" -#include "td/utils/filesystem.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/misc.h" -#include "td/utils/overloaded.h" -#include "td/utils/optional.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/path.h" -#include "td/utils/port/IoSlice.h" -#include "td/utils/UInt.h" -#include "td/utils/Variant.h" -#include "td/utils/VectorQueue.h" - -#include "td/actor/actor.h" - -#include "td/db/utils/StreamInterface.h" -#include "td/db/utils/ChainBuffer.h" -#include "td/db/utils/CyclicBuffer.h" -#include "td/db/binlog/BinlogReaderHelper.h" - -#include "td/db/binlog/Binlog.h" - -#include - -// Toy Binlog Implementation -using td::int64; -using td::MutableSlice; -using td::Result; -using td::Slice; -using td::Status; - -using RootHash = td::UInt256; -using FileHash = td::UInt256; -struct BlockId { - int workchain; - unsigned seqno; - unsigned long long shard; -}; - -template -Result memcpy_parse(Slice data, T* res) { - if (data.size() < sizeof(T)) { - return -static_cast(sizeof(T)); - } - std::memcpy(res, data.data(), sizeof(T)); - if (res->tag_field != res->tag) { - return Status::Error("Tag mismatch"); - } - return sizeof(T); -} -template -int64 memcpy_serialize(MutableSlice data, const T& res) { - if (data.size() < sizeof(T)) { - return -static_cast(sizeof(T)); - } - std::memcpy(data.data(), &res, sizeof(T)); - return sizeof(T); -} - -#pragma pack(push, 4) -struct LogEventCrc32C { - static constexpr unsigned tag = 0x473a830a; - - unsigned tag_field; - td::uint32 crc32c; - LogEventCrc32C() = default; - LogEventCrc32C(td::uint32 crc32c) : tag_field(tag), crc32c(crc32c) { - } - static Result parse(Slice data, LogEventCrc32C* res) { - return memcpy_parse(data, res); - } - int64 serialize(MutableSlice data) const { - return memcpy_serialize(data, *this); - } - auto key() const { - return crc32c; - } - bool operator==(const LogEventCrc32C& other) const { - return key() == other.key(); - } - bool operator!=(const LogEventCrc32C& other) const { - return !(*this == other); - } -}; - -struct LogEventStart { - static constexpr unsigned tag = 0x0442446b; - static constexpr unsigned log_type = 0x290100; - unsigned tag_field; - unsigned type_field; - unsigned created_at; - unsigned char zerostate_root_hash[32]; - LogEventStart() = default; - LogEventStart(const RootHash& hash, unsigned _now = 0) - : tag_field(tag), type_field(log_type), created_at(_now ? _now : (unsigned)std::time(nullptr)) { - td::as(zerostate_root_hash) = hash; - } - static Result parse(Slice data, LogEventStart* res) { - return memcpy_parse(data, res); - } - int64 serialize(MutableSlice data) const { - return memcpy_serialize(data, *this); - } - auto key() const { - return std::make_tuple(tag_field, type_field, created_at, Slice(zerostate_root_hash, 32)); - } - bool operator==(const LogEventStart& other) const { - return key() == other.key(); - } - bool operator!=(const LogEventStart& other) const { - return !(*this == other); - } -}; - -struct LogEventSetZeroState { - static constexpr unsigned tag = 0x63ab3cd9; - unsigned tag_field; - unsigned flags; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - LogEventSetZeroState() = default; - LogEventSetZeroState(const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, unsigned _flags = 0) - : tag_field(tag), flags(_flags), file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - } - static Result parse(Slice data, LogEventSetZeroState* res) { - return memcpy_parse(data, res); - } - int64 serialize(MutableSlice data) const { - return memcpy_serialize(data, *this); - } - auto key() const { - return std::make_tuple(tag_field, flags, file_size, Slice(file_hash, 32), Slice(root_hash, 32)); - } - bool operator==(const LogEventSetZeroState& other) const { - return key() == other.key(); - } - bool operator!=(const LogEventSetZeroState& other) const { - return !(*this == other); - } -}; - -struct LogEventNewBlock { - static constexpr unsigned tag = 0x19f4bc63; - unsigned tag_field; - unsigned flags; // lower 8 bits = authority - int workchain; - unsigned seqno; - unsigned long long shard; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - unsigned char last_bytes[8]; - LogEventNewBlock() = default; - LogEventNewBlock(const BlockId& block, const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, - unsigned _flags) - : tag_field(tag) - , flags(_flags) - , workchain(block.workchain) - , seqno(block.seqno) - , shard(block.shard) - , file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - td::as(last_bytes) = 0; - } - static Result parse(Slice data, LogEventNewBlock* res) { - return memcpy_parse(data, res); - } - int64 serialize(MutableSlice data) const { - return memcpy_serialize(data, *this); - } - auto key() const { - return std::make_tuple(tag_field, flags, workchain, seqno, shard, file_size, Slice(file_hash, 32), - Slice(root_hash, 32), Slice(last_bytes, 8)); - } - bool operator==(const LogEventNewBlock& other) const { - return key() == other.key(); - } - bool operator!=(const LogEventNewBlock& other) const { - return !(*this == other); - } -}; - -struct LogEventNewState { - static constexpr unsigned tag = 0x4190a21f; - unsigned tag_field; - unsigned flags; // lower 8 bits = authority - int workchain; - unsigned seqno; - unsigned long long shard; - long long file_size; - unsigned char file_hash[32]; - unsigned char root_hash[32]; - unsigned char last_bytes[8]; - LogEventNewState() = default; - LogEventNewState(const BlockId& state, const RootHash& rhash, const FileHash& fhash, unsigned long long _fsize, - unsigned _flags) - : tag_field(tag) - , flags(_flags) - , workchain(state.workchain) - , seqno(state.seqno) - , shard(state.shard) - , file_size(_fsize) { - td::as(file_hash) = fhash; - td::as(root_hash) = rhash; - td::as(last_bytes) = 0; - } - static Result parse(Slice data, LogEventNewState* res) { - return memcpy_parse(data, res); - } - int64 serialize(MutableSlice data) const { - return memcpy_serialize(data, *this); - } - auto key() const { - return std::make_tuple(tag_field, flags, workchain, seqno, shard, file_size, Slice(file_hash, 32), - Slice(root_hash, 32), Slice(last_bytes, 8)); - } - bool operator==(const LogEventNewState& other) const { - return key() == other.key(); - } - bool operator!=(const LogEventNewState& other) const { - return !(*this == other); - } -}; -#pragma pack(pop) - -struct LogEventString { - static constexpr unsigned tag = 0xabcdabcd; - - std::string data; - - bool operator==(const LogEventString& other) const { - return data == other.data; - } - bool operator!=(const LogEventString& other) const { - return !(*this == other); - } - - int64 serialize(MutableSlice dest) const { - size_t need_size = 8 + data.size(); - if (dest.size() < need_size) { - return -static_cast(need_size); - } - dest.truncate(need_size); - td::as(dest.data()) = tag; - td::as(dest.data() + 4) = td::narrow_cast(data.size()); - dest.substr(8).copy_from(data); - return dest.size(); - } - - static Result parse(Slice data, LogEventString* res) { - if (data.size() < 4) { - return -4; - } - unsigned got_tag = td::as(data.data()); - if (got_tag != tag) { - return Status::Error(PSLICE() << "tag mismatch " << td::format::as_hex(got_tag)); - } - data = data.substr(4); - if (data.size() < 4) { - return -8; - } - td::int64 length = td::as(data.data()); - data = data.substr(4); - if (static_cast(data.size()) < length) { - return -length - 8; - } - res->data = data.substr(0, td::narrow_cast(length)).str(); - return length + 8; - } -}; - -struct LogEvent { - td::Variant - event_{LogEventStart{}}; - - bool operator==(const LogEvent& other) const { - return event_ == other.event_; - } - bool operator!=(const LogEvent& other) const { - return !(*this == other); - } - - LogEvent() = default; - LogEvent(LogEvent&& other) = default; - template - LogEvent(T&& e) : event_(std::forward(e)) { - } - - int64 serialize(MutableSlice data) const { - int64 res; - event_.visit([&](auto& e) { res = e.serialize(data); }); - return res; - } - - static Result parse(Slice data, LogEvent* res) { - if (data.size() < 4) { - return -4; - } - //LOG(ERROR) << td::format::as_hex_dump<4>(data); - unsigned got_tag = td::as(data.data()); - switch (got_tag) { - case LogEventCrc32C::tag: { - LogEventCrc32C e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - case LogEventStart::tag: { - LogEventStart e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - case LogEventSetZeroState::tag: { - LogEventSetZeroState e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - case LogEventNewBlock::tag: { - LogEventNewBlock e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - case LogEventNewState::tag: { - LogEventNewState e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - case LogEventString::tag: { - LogEventString e; - TRY_RESULT(x, e.parse(data, &e)); - if (x >= 0) { - res->event_ = e; - } - return x; - } - default: - return Status::Error(PSLICE() << "Unknown tag: " << td::format::as_hex(got_tag)); - } - } -}; - -static td::CSlice test_binlog_path("test.binlog"); - -class BinlogReader : public td::BinlogReaderInterface { - public: - td::Span logevents() const { - return logevents_; - } - - td::Result parse(td::Slice data) override { - if (data.size() < 4) { - return -4; - } - LogEvent res; - TRY_RESULT(size, res.parse(data, &res)); - if (size > 0) { - if (res.event_.get_offset() == res.event_.offset()) { - auto crc = res.event_.get().crc32c; - flush_crc(); - if (crc != crc_) { - return Status::Error("Crc mismatch"); - } - } else { - logevents_.emplace_back(std::move(res)); - } - lazy_crc_extend(data.substr(0, td::narrow_cast(size))); - } - return size; - } - - td::uint32 crc32c() { - flush_crc(); - return crc_; - } - - void flush() override { - flush_crc(); - } - - private: - std::vector logevents_; - td::uint32 crc_{0}; - td::Slice suffix_; - - void flush_crc() { - crc_ = td::crc32c_extend(crc_, suffix_); - suffix_ = Slice(); - } - void lazy_crc_extend(Slice slice) { - if (suffix_.empty()) { - suffix_ = slice; - return; - } - if (suffix_.end() == slice.begin()) { - suffix_ = Slice(suffix_.begin(), slice.end()); - return; - } - flush_crc(); - suffix_ = slice; - } -}; - -class RandomBinlog { - public: - RandomBinlog() { - size_t logevent_count = 1000; - for (size_t i = 0; i < logevent_count; i++) { - add_logevent(create_random_logevent()); - } - } - - Slice data() const { - return data_; - } - td::Span logevents() const { - return logevents_; - } - - private: - std::vector logevents_; - std::string data_; - - template - void add_logevent(T event) { - int64 size = -event.serialize({}); - std::string data(td::narrow_cast(size), '\0'); - int64 new_size = event.serialize(data); - CHECK(new_size == size); - data_ += data; - logevents_.emplace_back(std::move(event)); - } - - LogEvent create_random_logevent() { - auto rand_uint256 = [] { - td::UInt256 res; - td::Random::secure_bytes(as_slice(res)); - return res; - }; - auto rand_block_id = [] { - BlockId res; - res.workchain = td::Random::fast(0, 100); - res.shard = td::Random::fast(0, 100); - res.seqno = td::Random::fast(0, 100); - return res; - }; - - auto type = td::Random::fast(0, 4); - switch (type) { - case 0: { - auto size = td::Random::fast(0, 10); - LogEventString event; - event.data = td::rand_string('a', 'z', size); - return event; - } - case 1: { - return LogEventStart(rand_uint256(), 12); - } - case 2: { - return LogEventSetZeroState(rand_uint256(), rand_uint256(), td::Random::fast(0, 1000), - td::Random::fast(0, 1000)); - } - case 3: { - return LogEventNewBlock(rand_block_id(), rand_uint256(), rand_uint256(), 12, 17); - } - case 4: { - return LogEventNewState(rand_block_id(), rand_uint256(), rand_uint256(), 12, 17); - } - } - UNREACHABLE(); - } -}; - -void test_binlog(td::Slice data, td::optional> events = {}) { - auto splitted_binlog = td::rand_split(data); - - std::string new_binlog_data; - - BinlogReader reader; - td::BinlogReaderHelper reader_impl; - for (auto& chunk : splitted_binlog) { - reader_impl.parse(reader, chunk).ensure(); - } - - //Binlog write sync - { - td::Binlog::destroy(test_binlog_path); - td::BinlogWriter binlog_writer(test_binlog_path.str()); - binlog_writer.open().ensure(); - - BinlogReader new_reader; - size_t i = 0; - for (auto& logevent : reader.logevents()) { - binlog_writer.write_event(logevent, &new_reader).ensure(); - i++; - if (i % 10 == 0) { - binlog_writer.write_event(LogEvent(LogEventCrc32C(new_reader.crc32c())), &new_reader).ensure(); - } - } - binlog_writer.sync(); - binlog_writer.close().ensure(); - - auto file_data = read_file(test_binlog_path).move_as_ok(); - ASSERT_TRUE(reader.logevents() == new_reader.logevents()); - new_binlog_data = file_data.as_slice().str(); - data = new_binlog_data; - //ASSERT_EQ(data, file_data); - } - - //Binlog write async - { - td::Binlog::destroy(test_binlog_path); - td::BinlogWriterAsync binlog_writer(test_binlog_path.str()); - - td::actor::Scheduler scheduler({2}); - - BinlogReader new_reader; - scheduler.run_in_context([&]() mutable { - binlog_writer.open().ensure(); - for (auto& logevent : reader.logevents()) { - binlog_writer.write_event(logevent, &new_reader).ensure(); - } - binlog_writer.sync([&](Result res) { - res.ensure(); - binlog_writer.close([&](Result res) { - res.ensure(); - td::actor::SchedulerContext::get()->stop(); - }); - }); - }); - - scheduler.run(); - scheduler.stop(); - - auto file_data = read_file(test_binlog_path).move_as_ok(); - ASSERT_TRUE(reader.logevents() == new_reader.logevents()); - //ASSERT_EQ(data, file_data); - } - - ASSERT_TRUE(!events || events.value() == reader.logevents()); - - std::string new_data; - for (auto& event : reader.logevents()) { - int64 size = -event.serialize({}); - std::string event_data(td::narrow_cast(size), '\0'); - int64 new_size = event.serialize(event_data); - CHECK(new_size == size); - new_data += event_data; - } - //ASSERT_EQ(data, new_data); - - // Binlog::read_sync - { - td::CSlice path("test.binlog"); - td::Binlog::destroy(path); - td::write_file(path, data).ensure(); - - td::Binlog binlog(path.str()); - BinlogReader binlog_reader; - binlog.replay_sync(binlog_reader).ensure(); - - ASSERT_EQ(reader.logevents().size(), binlog_reader.logevents().size()); - ASSERT_TRUE(reader.logevents() == binlog_reader.logevents()); - } - - // Binlog::read_async - { - td::Binlog::destroy(test_binlog_path); - td::write_file(test_binlog_path, data).ensure(); - - td::Binlog binlog(test_binlog_path.str()); - auto binlog_reader = std::make_shared(); - - td::actor::Scheduler scheduler({2}); - scheduler.run_in_context([&]() mutable { - binlog.replay_async(binlog_reader, [](Result res) { - res.ensure(); - td::actor::SchedulerContext::get()->stop(); - }); - }); - - scheduler.run(); - scheduler.stop(); - - ASSERT_EQ(reader.logevents().size(), binlog_reader->logevents().size()); - ASSERT_TRUE(reader.logevents() == binlog_reader->logevents()); - } -} - -TEST(Binlog, Reader) { - RandomBinlog binlog; - test_binlog(binlog.data(), binlog.logevents()); -} - -TEST(Binlog, Hands) { - std::string binlog = td::base64_decode( - "a0RCBAABKQCRMn1c2DaJhwrptxburpRtrWI2sjGhVbG29bFO0r8DDtAAExjZPKtjAAAAALwGAAAA" - "AAAAFvJq3qfzFCDWap+LUrgBI8sWFayIOQSxkBjV3CWgizHYNomHCum3Fu6ulG2tYjayMaFVsbb1" - "sU7SvwMO0AATGGO89BmAAAAA/////wEAAAAAAAAAAAAAgN4RAAAAAAAAa53L4ziGleZ7K+StAsBd" - "txMxbHHfuB9SJRFp+BMzXfnGnt8TsgFnig7j/xVRjtIsYUVw0rQZJUC0sWQROj0SHvplIkBV9vMp") - .move_as_ok(); - test_binlog(binlog); -} - -TEST(Buffers, CyclicBufferSimple) { - { - auto reader_writer = td::CyclicBuffer::create(); - auto reader = std::move(reader_writer.first); - auto writer = std::move(reader_writer.second); - - ASSERT_TRUE(!writer.is_reader_closed()); - reader.close_reader(td::Status::Error(2)); - ASSERT_TRUE(!reader.is_writer_closed()); - ASSERT_TRUE(writer.is_reader_closed()); - ASSERT_EQ(2, writer.reader_status().code()); - } - { - auto reader_writer = td::CyclicBuffer::create(); - auto reader = std::move(reader_writer.first); - auto writer = std::move(reader_writer.second); - - ASSERT_TRUE(!reader.is_writer_closed()); - writer.close_writer(td::Status::Error(2)); - ASSERT_TRUE(!writer.is_reader_closed()); - ASSERT_TRUE(reader.is_writer_closed()); - ASSERT_EQ(2, reader.writer_status().code()); - } - { - td::CyclicBuffer::Options options; - options.chunk_size = 14; - options.count = 10; - options.alignment = 7; - auto reader_writer = td::CyclicBuffer::create(options); - auto reader = std::move(reader_writer.first); - auto writer = std::move(reader_writer.second); - - auto data = td::rand_string('a', 'z', 100001); - td::Slice write_slice = data; - td::Slice read_slice = data; - for (size_t i = 1; i < options.count; i++) { - ASSERT_EQ((i - 1) * options.chunk_size, reader.reader_size()); - ASSERT_EQ((i - 1) * options.chunk_size, writer.writer_size()); - auto slice = writer.prepare_write(); - ASSERT_EQ(0u, reinterpret_cast(slice.data()) % options.alignment); - auto to_copy = write_slice; - to_copy.truncate(options.chunk_size); - slice.copy_from(to_copy); - write_slice = write_slice.substr(to_copy.size()); - writer.confirm_write(to_copy.size()); - ASSERT_EQ(i * options.chunk_size, reader.reader_size()); - ASSERT_EQ(i * options.chunk_size, writer.writer_size()); - } - bool is_writer_closed = false; - while (true) { - { - bool is_closed = reader.is_writer_closed(); - auto slice = reader.prepare_read(); - ASSERT_EQ(read_slice.substr(0, slice.size()), slice); - read_slice = read_slice.substr(slice.size()); - reader.confirm_read(slice.size()); - if (is_closed && slice.empty()) { - break; - } - } - - if (!is_writer_closed) { - auto slice = writer.prepare_write(); - auto to_copy = write_slice; - to_copy.truncate(options.chunk_size); - if (to_copy.empty()) { - writer.close_writer(td::Status::OK()); - is_writer_closed = true; - } else { - slice.copy_from(to_copy); - write_slice = write_slice.substr(to_copy.size()); - writer.confirm_write(to_copy.size()); - } - } - } - ASSERT_EQ(0u, write_slice.size()); - ASSERT_EQ(0u, read_slice.size()); - } -} - -TEST(Buffers, CyclicBuffer) { - for (int t = 0; t < 20; t++) { - td::CyclicBuffer::Options options; - options.chunk_size = 14; - options.count = 10; - options.alignment = 7; - auto reader_writer = td::CyclicBuffer::create(options); - auto reader = std::move(reader_writer.first); - auto writer = std::move(reader_writer.second); - auto data = td::rand_string('a', 'z', 100001); - auto chunks = td::rand_split(data); - - size_t chunk_i = 0; - std::string res; - while (true) { - if (td::Random::fast(0, 1) == 0) { - bool is_closed = reader.is_writer_closed(); - auto slice = reader.prepare_read(); - res += slice.str(); - reader.confirm_read(slice.size()); - if (slice.empty() && is_closed) { - reader.writer_status().ensure(); - break; - } - } - if (chunk_i < chunks.size() && td::Random::fast(0, 1) == 0) { - auto slice = writer.prepare_write(); - auto from = Slice(chunks[chunk_i]); - auto copy = from.substr(0, slice.size()); - slice.copy_from(copy); - writer.confirm_write(copy.size()); - auto left = from.substr(copy.size()); - if (!left.empty()) { - chunks[chunk_i] = left.str(); - } else { - chunk_i++; - if (chunk_i == chunks.size()) { - writer.close_writer(td::Status::OK()); - } - } - } - } - ASSERT_EQ(data, res); - } -} - -TEST(Buffers, ChainBuffer) { - for (int t = 0; t < 20; t++) { - td::ChainBuffer::Options options; - options.chunk_size = 14; - auto reader_writer = td::ChainBuffer::create(options); - auto reader = std::move(reader_writer.first); - auto writer = std::move(reader_writer.second); - auto data = td::rand_string('a', 'z', 100001); - auto chunks = td::rand_split(data); - - size_t chunk_i = 0; - std::string res; - while (true) { - if (td::Random::fast(0, 1) == 0) { - bool is_closed = reader.is_writer_closed(); - Slice slice; - if (reader.reader_size() != 0) { - slice = reader.prepare_read(); - res += slice.str(); - reader.confirm_read(slice.size()); - } - if (slice.empty() && is_closed) { - reader.writer_status().ensure(); - break; - } - } - if (chunk_i < chunks.size() && td::Random::fast(0, 1) == 0) { - writer.append(chunks[chunk_i]); - chunk_i++; - if (chunk_i == chunks.size()) { - writer.close_writer(td::Status::OK()); - } - } - } - ASSERT_EQ(data.size(), res.size()); - ASSERT_EQ(data, res); - } -} diff --git a/submodules/ton/tonlib-src/tddb/test/io-bench.cpp b/submodules/ton/tonlib-src/tddb/test/io-bench.cpp deleted file mode 100644 index 084e7c6c..00000000 --- a/submodules/ton/tonlib-src/tddb/test/io-bench.cpp +++ /dev/null @@ -1,685 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/OptionsParser.h" -#include "td/utils/filesystem.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Timer.h" -#include "td/utils/crypto.h" -#include "td/utils/BufferedReader.h" -#include "td/utils/optional.h" -#include "td/actor/actor.h" - -#include "td/db/utils/StreamInterface.h" -#include "td/db/utils/ChainBuffer.h" -#include "td/db/utils/CyclicBuffer.h" -#include "td/db/utils/FileSyncState.h" -#include "td/db/utils/StreamToFileActor.h" -#include "td/db/utils/FileToStreamActor.h" - -#include - -namespace td { -class AsyncCyclicBufferReader : public td::actor::Actor { - public: - class Callback { - public: - virtual ~Callback() { - } - virtual void want_more() = 0; - virtual Status process(Slice data) = 0; - virtual void on_closed(Status status) = 0; - }; - AsyncCyclicBufferReader(CyclicBuffer::Reader reader, td::unique_ptr callback) - : reader_(std::move(reader)), callback_(std::move(callback)) { - } - - private: - CyclicBuffer::Reader reader_; - td::unique_ptr callback_; - - void loop() override { - while (true) { - auto data = reader_.prepare_read(); - if (data.empty()) { - if (reader_.is_writer_closed()) { - callback_->on_closed(std::move(reader_.writer_status())); - return stop(); - } - callback_->want_more(); - return; - } - auto status = callback_->process(data); - if (status.is_error()) { - callback_->on_closed(std::move(status)); - } - reader_.confirm_read(data.size()); - //TODO: better condition for want_more. May be reader should decide if it is ready for more writes - callback_->want_more(); - } - } -}; - -} // namespace td - -class Processor { - public: - void process(td::Slice slice) { - res = crc32c_extend(res, slice); - res2 = crc32c_extend(res2, slice); - } - auto result() { - return res * res2; - } - - private: - td::uint32 res{0}; - td::uint32 res2{0}; -}; - -void read_baseline(td::CSlice path) { - LOG(ERROR) << "BASELINE"; - td::PerfWarningTimer timer("read file"); - auto data = td::read_file(path).move_as_ok(); - timer.reset(); - - td::PerfWarningTimer process_timer("process file", 0); - Processor processor; - processor.process(data.as_slice()); - process_timer.reset(); - LOG(ERROR) << processor.result(); -} - -void read_buffered(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "BufferedReader"; - auto fd = td::FileFd::open(path, td::FileFd::Read).move_as_ok(); - td::BufferedReader reader(fd, buffer_size); - std::vector buf(buffer_size); - Processor processor; - while (true) { - auto slice = td::MutableSlice(&buf[0], buf.size()); - auto size = reader.read(slice).move_as_ok(); - if (size == 0) { - break; - } - processor.process(slice.truncate(size)); - } - LOG(ERROR) << processor.result(); -} - -void read_async(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Async"; - auto fd = td::FileFd::open(path, td::FileFd::Read).move_as_ok(); - td::actor::Scheduler scheduler({2}); - scheduler.run_in_context([&] { - auto reader_writer = td::CyclicBuffer::create(); - //TODO: hide actor - auto reader = - td::actor::create_actor("Reader", std::move(fd), std::move(reader_writer.second)); - class Callback : public td::AsyncCyclicBufferReader::Callback { - public: - Callback(td::actor::ActorOwn<> reader) : reader_(std::move(reader)) { - } - void want_more() override { - td::actor::send_signals_later(reader_, td::actor::ActorSignals::wakeup()); - } - td::Status process(td::Slice data) override { - processor.process(data); - return td::Status::OK(); - } - void on_closed(td::Status status) override { - LOG(ERROR) << processor.result(); - td::actor::SchedulerContext::get()->stop(); - } - - private: - td::actor::ActorOwn<> reader_; - Processor processor; - }; - auto reader_copy = reader.get(); - auto callback = td::make_unique(std::move(reader)); - auto processor = td::actor::create_actor( - "BufferReader", std::move(reader_writer.first), std::move(callback)); - class ReaderCallback : public td::FileToStreamActor::Callback { - public: - ReaderCallback(td::actor::ActorId<> actor) : actor_(std::move(actor)) { - } - void got_more() override { - td::actor::send_signals_later(actor_, td::actor::ActorSignals::wakeup()); - } - - private: - td::actor::ActorId<> actor_; - }; - send_closure(reader_copy, &td::FileToStreamActor::set_callback, - td::make_unique(processor.release())); - }); - scheduler.run(); -} - -static char o_direct_buf[100000000]; -void read_o_direct(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Direct"; - auto fd = td::FileFd::open(path, td::FileFd::Read | td::FileFd::Direct).move_as_ok(); - size_t align = 4096; - auto *ptr = - reinterpret_cast((reinterpret_cast(o_direct_buf) + align - 1) & td::bits_negate64(align)); - - td::BufferedReader reader(fd, buffer_size); - Processor processor; - while (true) { - auto slice = td::MutableSlice(ptr, buffer_size); - auto size = reader.read(slice).move_as_ok(); - if (size == 0) { - break; - } - processor.process(slice.truncate(size)); - } - LOG(ERROR) << processor.result(); -} - -class DataGenerator { - public: - operator bool() const { - return generated_size < total_size; - } - - td::string next() { - auto res = words_[2]; - generated_size += res.size(); - return res; - } - - private: - std::vector words_{"a", "fjdksalfdfs", std::string(20, 'b'), std::string(1000, 'a')}; - size_t total_size = (1 << 20) * 600; - size_t generated_size = 0; -}; - -void write_baseline(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Baseline"; - auto fd = td::FileFd::open(path, td::FileFd::Flags::Create | td::FileFd::Flags::Truncate | td::FileFd::Flags::Write) - .move_as_ok(); - std::vector buf(buffer_size); - - DataGenerator generator; - while (generator) { - auto slice = generator.next(); - fd.write(slice).ensure(); - } - fd.sync().ensure(); -} -void write_buffered(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Buffered"; - auto fd = td::FileFd::open(path, td::FileFd::Flags::Create | td::FileFd::Flags::Truncate | td::FileFd::Flags::Write) - .move_as_ok(); - std::vector buf(buffer_size); - size_t data_size{0}; - - auto flush = [&]() { - auto slice = td::Slice(buf.data(), data_size); - fd.write(slice).ensure(); - //auto io_slice = as_io_slice(slice); - //fd.writev({&io_slice, 1}).ensure(); - data_size = 0; - }; - auto append = [&](td::Slice slice) { - if (data_size + slice.size() > buffer_size) { - flush(); - } - - td::MutableSlice(buf.data(), buffer_size).substr(data_size).copy_from(slice); - data_size += slice.size(); - }; - - DataGenerator generator; - while (generator) { - auto slice = generator.next(); - append(slice); - } - flush(); - fd.sync().ensure(); -} - -namespace td { - -class FileWriter { - public: - FileWriter(FileFd fd, size_t buffer_size) : fd_(std::move(fd)), raw_buffer_(buffer_size) { - reset(); - buffer_slices_.reserve(1024); - strings_.reserve(1024); - ios_slices_.reserve(1024); - } - - void append(std::string data) { - cached_size_ += data.size(); - if (data.size() <= max_copy_size) { - append_copy(data); - } else { - CHECK(strings_.size() < strings_.capacity()); - strings_.push_back(std::move(data)); - ios_slices_.push_back(as_io_slice(strings_.back())); - should_merge_ = false; - } - try_flush(); - } - - void append(BufferSlice data) { - cached_size_ += data.size(); - if (data.size() <= max_copy_size) { - append_copy(data); - } else { - buffer_slices_.push_back(std::move(data)); - ios_slices_.push_back(as_io_slice(strings_.back())); - should_merge_ = false; - } - try_flush(); - } - - void append(Slice data) { - if (data.size() <= max_copy_size) { - append_copy(data); - try_flush(); - } else if (data.size() > min_immediate_write_size) { - ios_slices_.push_back(as_io_slice(data)); - flush(); - } else { - append(BufferSlice(data)); - } - } - - void flush() { - if (ios_slices_.empty()) { - return; - } - flushed_size_ += cached_size_; - fd_.writev(ios_slices_).ensure(); - reset(); - } - - void sync() { - flush(); - synced_size_ = flushed_size_; - fd_.sync().ensure(); - } - - bool may_flush() const { - return cached_size_ != 0; - } - size_t total_size() const { - return flushed_size() + cached_size_; - } - size_t flushed_size() const { - return flushed_size_; - } - size_t synced_size() const { - return synced_size_; - } - - private: - static constexpr size_t max_cached_size = 256 * (1 << 10); - static constexpr size_t min_immediate_write_size = 32 * (1 << 10); - - FileFd fd_; - - std::vector raw_buffer_; - size_t max_copy_size = min(raw_buffer_.size() / 8, size_t(4096u)); - MutableSlice buffer_; - bool should_merge_ = false; - - std::vector buffer_slices_; - std::vector strings_; - std::vector ios_slices_; - size_t cached_size_{0}; - size_t flushed_size_{0}; - size_t synced_size_{0}; - - void append_copy(Slice data) { - buffer_.copy_from(data); - if (should_merge_) { - auto back = as_slice(ios_slices_.back()); - back = Slice(back.data(), back.size() + data.size()); - ios_slices_.back() = as_io_slice(back); - } else { - ios_slices_.push_back(as_io_slice(buffer_.substr(0, data.size()))); - should_merge_ = true; - } - buffer_ = buffer_.substr(data.size()); - } - - void reset() { - buffer_ = MutableSlice(raw_buffer_.data(), raw_buffer_.size()); - buffer_slices_.clear(); - strings_.clear(); - ios_slices_.clear(); - should_merge_ = false; - cached_size_ = 0; - } - - bool must_flush() const { - return buffer_.size() < max_copy_size || ios_slices_.size() == ios_slices_.capacity() || - cached_size_ >= max_cached_size; - } - void try_flush() { - if (!must_flush()) { - return; - } - flush(); - } -}; - -class AsyncFileWriterActor : public actor::Actor { - public: - AsyncFileWriterActor(FileSyncState::Reader state) : state_(std::move(state)) { - io_slices_.reserve(100); - } - - private: - FileFd fd_; - ChainBufferReader reader_; - FileSyncState::Reader state_; - std::vector io_slices_; - - size_t flushed_size_{0}; - size_t synced_size_{0}; - - void flush() { - reader_.sync_with_writer(); - while (!reader_.empty()) { - auto it = reader_.clone(); - size_t io_slices_size = 0; - while (!it.empty() && io_slices_.size() < io_slices_.capacity()) { - auto slice = it.prepare_read(); - io_slices_.push_back(as_io_slice(slice)); - io_slices_size += slice.size(); - it.confirm_read(slice.size()); - } - if (!io_slices_.empty()) { - auto r_written = fd_.writev(io_slices_); - LOG_IF(FATAL, r_written.is_error()) << r_written.error(); - auto written = r_written.move_as_ok(); - CHECK(written == io_slices_size); - flushed_size_ += written; - io_slices_.clear(); - } - reader_ = std::move(it); - } - } - - void loop() override { - reader_.sync_with_writer(); - flush(); - } -}; - -} // namespace td - -void write_vector(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "io vector"; - auto fd = td::FileFd::open(path, td::FileFd::Flags::Create | td::FileFd::Flags::Truncate | td::FileFd::Flags::Write) - .move_as_ok(); - td::FileWriter writer(std::move(fd), buffer_size); - - DataGenerator generator; - while (generator) { - auto slice = generator.next(); - writer.append(std::move(slice)); - } - writer.sync(); -} - -void write_async(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Async"; - auto fd = td::FileFd::open(path, td::FileFd::Flags::Create | td::FileFd::Flags::Truncate | td::FileFd::Flags::Write) - .move_as_ok(); - td::actor::Scheduler scheduler({1}); - scheduler.run_in_context([&] { - class Writer : public td::actor::Actor { - public: - Writer(td::FileFd fd, size_t buffer_size) : fd_(std::move(fd)), buffer_size_(buffer_size) { - } - class Callback : public td::StreamToFileActor::Callback { - public: - Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) { - } - void on_sync_state_changed() override { - td::actor::send_signals_later(parent_, td::actor::ActorSignals::wakeup()); - } - - private: - td::actor::ActorShared<> parent_; - }; - - void start_up() override { - auto buffer_reader_writer = td::ChainBuffer::create(); - buffer_writer_ = std::move(buffer_reader_writer.second); - auto buffer_reader = std::move(buffer_reader_writer.first); - - auto sync_state_reader_writer = td::FileSyncState::create(); - fd_sync_state_ = std::move(sync_state_reader_writer.first); - auto sync_state_writer = std::move(sync_state_reader_writer.second); - auto options = td::StreamToFileActor::Options{}; - writer_ = td::actor::create_actor(td::actor::ActorOptions().with_name("FileWriterActor"), - std::move(buffer_reader), std::move(fd_), - std::move(sync_state_writer), options); - send_closure(writer_, &td::StreamToFileActor::set_callback, td::make_unique(actor_shared(this))); - loop(); - } - - private: - td::FileFd fd_; - td::optional buffer_writer_; - td::optional fd_sync_state_; - td::actor::ActorOwn writer_; - size_t buffer_size_; - DataGenerator generator_; - size_t total_size_{0}; - bool was_sync_{false}; - - void loop() override { - auto flushed_size = fd_sync_state_.value().flushed_size(); - while (generator_ && total_size_ < flushed_size + buffer_size_ * 10) { - auto str = generator_.next(); - total_size_ += str.size(); - buffer_writer_.value().append(str); - } - td::actor::send_signals_later(writer_, td::actor::ActorSignals::wakeup()); - if (generator_) { - return; - } else if (!was_sync_) { - was_sync_ = true; - fd_sync_state_.value().set_requested_sync_size(total_size_); - td::actor::send_signals_later(writer_, td::actor::ActorSignals::wakeup()); - } - if (fd_sync_state_.value().synced_size() == total_size_) { - writer_.reset(); - } - } - void hangup_shared() override { - td::actor::SchedulerContext::get()->stop(); - stop(); - } - }; - td::actor::create_actor("Writer", std::move(fd), buffer_size).release(); - }); - scheduler.run(); -} - -void write_async2(td::CSlice path, size_t buffer_size) { - LOG(ERROR) << "Async2"; - auto fd = td::FileFd::open(path, td::FileFd::Flags::Create | td::FileFd::Flags::Truncate | td::FileFd::Flags::Write) - .move_as_ok(); - td::actor::Scheduler scheduler({1}); - scheduler.run_in_context([&] { - class Worker : public td::actor::Actor { - public: - Worker(td::FileFd fd, td::ChainBufferReader reader, td::actor::ActorShared<> parent) - : fd_(std::move(fd)), reader_(std::move(reader)), parent_(std::move(parent)) { - } - - private: - td::FileFd fd_; - td::ChainBufferReader reader_; - td::actor::ActorShared<> parent_; - void loop() override { - reader_.sync_with_writer(); - while (!reader_.empty()) { - auto slice = reader_.prepare_read(); - fd_.write(slice).ensure(); - reader_.confirm_read(slice.size()); - } - } - void hangup() override { - loop(); - fd_.sync().ensure(); - stop(); - } - }; - class Writer : public td::actor::Actor { - public: - Writer(td::FileFd fd) : fd_(std::move(fd)) { - } - - private: - td::FileFd fd_; - td::actor::ActorOwn<> worker_; - td::ChainBufferWriter writer_; - DataGenerator generator_; - - void start_up() override { - worker_ = - td::actor::create_actor("Worker", std::move(fd_), writer_.extract_reader(), actor_shared(this)); - while (generator_) { - writer_.append(generator_.next(), 65536); - send_signals_later(worker_, td::actor::ActorSignals::wakeup()); - } - worker_.reset(); - } - void hangup_shared() override { - td::actor::SchedulerContext::get()->stop(); - stop(); - } - }; - td::actor::create_actor(td::actor::ActorOptions().with_name("Writer").with_poll(), std::move(fd)).release(); - }); - scheduler.run(); -} - -int main(int argc, char **argv) { - std::string from; - enum Type { Read, Write }; - Type type{Write}; - enum Mode { Baseline, Buffered, Direct, Async, WriteV, Async2 }; - Mode mode = Baseline; - size_t buffer_size = 1024; - - td::OptionsParser options_parser; - options_parser.add_option('f', td::Slice("from"), td::Slice("read from file"), [&](td::Slice arg) -> td::Status { - from = arg.str(); - return td::Status::OK(); - }); - options_parser.add_option('m', td::Slice("mode"), td::Slice("mode"), [&](td::Slice arg) -> td::Status { - TRY_RESULT(x, td::to_integer_safe(arg)); - switch (x) { - case 0: - mode = Baseline; - return td::Status::OK(); - case 1: - mode = Buffered; - return td::Status::OK(); - case 2: - mode = Direct; - return td::Status::OK(); - case 3: - mode = Async; - return td::Status::OK(); - case 4: - mode = WriteV; - return td::Status::OK(); - case 5: - mode = Async2; - return td::Status::OK(); - } - return td::Status::Error("unknown mode"); - }); - options_parser.add_option('b', td::Slice("buffer"), td::Slice("buffer size"), [&](td::Slice arg) -> td::Status { - TRY_RESULT(x, td::to_integer_safe(arg)); - buffer_size = x; - return td::Status::OK(); - }); - - auto status = options_parser.run(argc, argv); - if (status.is_error()) { - LOG(ERROR) << status.error() << "\n" << options_parser; - return 0; - } - - switch (type) { - case Read: - switch (mode) { - case Baseline: - read_baseline(from); - break; - case Buffered: - read_buffered(from, buffer_size); - break; - case Direct: - read_o_direct(from, buffer_size); - break; - case Async: - read_async(from, buffer_size); - break; - case Async2: - case WriteV: - LOG(FATAL) << "Not supported mode for Read test"; - } - break; - case Write: - switch (mode) { - case Baseline: - write_baseline(from, buffer_size); - break; - case Buffered: - write_buffered(from, buffer_size); - break; - case WriteV: - write_vector(from, buffer_size); - break; - case Async: - write_async(from, buffer_size); - break; - case Async2: - write_async2(from, buffer_size); - break; - case Direct: - LOG(FATAL) << "Unimplemented"; - } - } - - return 0; -} diff --git a/submodules/ton/tonlib-src/tddb/test/key_value.cpp b/submodules/ton/tonlib-src/tddb/test/key_value.cpp deleted file mode 100644 index e04e7ee9..00000000 --- a/submodules/ton/tonlib-src/tddb/test/key_value.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/db/KeyValueAsync.h" -#include "td/db/KeyValue.h" -#include "td/db/RocksDb.h" - -#include "td/utils/benchmark.h" -#include "td/utils/buffer.h" -#include "td/utils/optional.h" -#include "td/utils/UInt.h" - -TEST(KeyValue, simple) { - td::Slice db_name = "testdb"; - td::RocksDb::destroy(db_name).ignore(); - - std::unique_ptr kv = std::make_unique(td::RocksDb::open(db_name.str()).move_as_ok()); - auto set_value = [&](td::Slice key, td::Slice value) { - kv->begin_transaction(); - kv->set(key, value); - kv->commit_transaction(); - }; - auto ensure_value = [&](td::Slice key, td::Slice value) { - std::string kv_value; - auto status = kv->get(key, kv_value).move_as_ok(); - ASSERT_EQ(td::int32(status), td::int32(td::KeyValue::GetStatus::Ok)); - ASSERT_EQ(kv_value, value); - }; - auto ensure_no_value = [&](td::Slice key) { - std::string kv_value; - auto status = kv->get(key, kv_value).move_as_ok(); - ASSERT_EQ(td::int32(status), td::int32(td::KeyValue::GetStatus::NotFound)); - }; - - ensure_no_value("A"); - set_value("A", "HELLO"); - ensure_value("A", "HELLO"); - - td::UInt128 x; - std::fill(as_slice(x).begin(), as_slice(x).end(), '1'); - x.raw[5] = 0; - set_value(as_slice(x), as_slice(x)); - ensure_value(as_slice(x), as_slice(x)); - - kv.reset(); - kv = std::make_unique(td::RocksDb::open(db_name.str()).move_as_ok()); - ensure_value("A", "HELLO"); - ensure_value(as_slice(x), as_slice(x)); -}; - -TEST(KeyValue, async_simple) { - td::Slice db_name = "testdb"; - td::RocksDb::destroy(db_name).ignore(); - - td::actor::Scheduler scheduler({6}); - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher, std::string db_name) - : watcher_(std::move(watcher)), db_name_(std::move(db_name)) { - } - void start_up() override { - loop(); - } - void tear_down() override { - } - void loop() override { - if (!kv_) { - kv_ = td::KeyValueAsync( - std::make_unique(td::RocksDb::open(db_name_).move_as_ok())); - set_start_at_ = td::Timestamp::now(); - } - if (next_set_ && next_set_.is_in_past()) { - for (size_t i = 0; i < 10 && left_cnt_ > 0; i++, left_cnt_--) { - do_set(); - } - if (left_cnt_ > 0) { - next_set_ = td::Timestamp::in(0.001); - alarm_timestamp() = next_set_; - } else { - next_set_ = td::Timestamp::never(); - set_finish_at_ = td::Timestamp::now(); - } - } - } - - private: - std::shared_ptr watcher_; - td::optional> kv_; - std::string db_name_; - int left_cnt_ = 10000; - int pending_cnt_ = left_cnt_; - td::Timestamp next_set_ = td::Timestamp::now(); - td::Timestamp set_start_at_; - td::Timestamp set_finish_at_; - - void do_set() { - td::UInt128 key; - td::Random::secure_bytes(as_slice(key)); - td::BufferSlice data(1024); - td::Random::secure_bytes(as_slice(data)); - kv_.value().set(key, std::move(data), [actor_id = actor_id(this)](td::Result res) { - res.ensure(); - send_closure(actor_id, &Worker::on_stored); - }); - } - - void on_stored() { - pending_cnt_--; - if (pending_cnt_ == 0) { - auto now = td::Timestamp::now(); - LOG(ERROR) << (now.at() - set_finish_at_.at()); - LOG(ERROR) << (set_finish_at_.at() - set_start_at_.at()); - stop(); - } - } - }; - - scheduler.run_in_context([watcher = std::move(watcher), &db_name]() mutable { - td::actor::create_actor("Worker", watcher, db_name.str()).release(); - watcher.reset(); - }); - - scheduler.run(); -}; - -class KeyValueBenchmark : public td::Benchmark { - public: - std::string get_description() const override { - return "kv transation benchmark"; - } - - void start_up() override { - td::RocksDb::destroy("ttt"); - db_ = td::RocksDb::open("ttt").move_as_ok(); - } - void tear_down() override { - db_ = {}; - } - void run(int n) override { - for (int i = 0; i < n; i++) { - db_.value().begin_transaction(); - db_.value().set(PSLICE() << i, PSLICE() << i); - db_.value().commit_transaction(); - } - } - - private: - td::optional db_; -}; - -TEST(KeyValue, Bench) { - td::bench(KeyValueBenchmark()); -} - -TEST(KeyValue, Stress) { - return; - td::Slice db_name = "testdb"; - size_t N = 20; - auto db_name_i = [&](size_t i) { return PSTRING() << db_name << i; }; - for (size_t i = 0; i < N; i++) { - td::RocksDb::destroy(db_name_i(i)).ignore(); - } - - td::actor::Scheduler scheduler({6}); - auto watcher = td::create_shared_destructor([] { td::actor::SchedulerContext::get()->stop(); }); - - class Worker : public td::actor::Actor { - public: - Worker(std::shared_ptr watcher, std::string db_name) - : watcher_(std::move(watcher)), db_name_(std::move(db_name)) { - } - void start_up() override { - loop(); - } - void tear_down() override { - } - void loop() override { - if (stat_at_.is_in_past()) { - stat_at_ = td::Timestamp::in(10); - LOG(ERROR) << db_->stats(); - } - if (!kv_) { - db_ = std::make_shared(td::RocksDb::open(db_name_).move_as_ok()); - kv_ = td::KeyValueAsync(db_); - set_start_at_ = td::Timestamp::now(); - } - if (next_set_ && next_set_.is_in_past()) { - for (size_t i = 0; i < 10 && left_cnt_ > 0; i++, left_cnt_--) { - do_set(); - } - if (left_cnt_ > 0) { - next_set_ = td::Timestamp::in(0.01); - alarm_timestamp() = next_set_; - } else { - next_set_ = td::Timestamp::never(); - set_finish_at_ = td::Timestamp::now(); - } - } - } - - private: - std::shared_ptr watcher_; - std::shared_ptr db_; - td::optional> kv_; - std::string db_name_; - int left_cnt_ = 1000000000; - int pending_cnt_ = left_cnt_; - td::Timestamp next_set_ = td::Timestamp::now(); - td::Timestamp set_start_at_; - td::Timestamp set_finish_at_; - td::Timestamp stat_at_ = td::Timestamp::in(10); - - void do_set() { - td::UInt128 key = td::UInt128::zero(); - td::Random::secure_bytes(as_slice(key).substr(0, 1)); - td::BufferSlice data(1024); - td::Random::secure_bytes(as_slice(data)); - kv_.value().set(key, std::move(data), [actor_id = actor_id(this)](td::Result res) { - res.ensure(); - send_closure(actor_id, &Worker::on_stored); - }); - } - - void on_stored() { - pending_cnt_--; - if (pending_cnt_ == 0) { - auto now = td::Timestamp::now(); - LOG(ERROR) << (now.at() - set_finish_at_.at()); - LOG(ERROR) << (set_finish_at_.at() - set_start_at_.at()); - stop(); - } - } - }; - scheduler.run_in_context([watcher = std::move(watcher), &db_name_i, &N]() mutable { - for (size_t i = 0; i < N; i++) { - td::actor::create_actor("Worker", watcher, db_name_i(i)).release(); - } - watcher.reset(); - }); - - scheduler.run(); -} diff --git a/submodules/ton/tonlib-src/tdnet/CMakeLists.txt b/submodules/ton/tonlib-src/tdnet/CMakeLists.txt deleted file mode 100644 index d5ae7086..00000000 --- a/submodules/ton/tonlib-src/tdnet/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -set(TDNET_SOURCE - td/net/FdListener.cpp - td/net/TcpListener.cpp - td/net/UdpServer.cpp - - td/net/FdListener.h - td/net/TcpListener.h - td/net/UdpServer.h -) - -add_library(tdnet STATIC ${TDNET_SOURCE}) -target_include_directories(tdnet PUBLIC $) -target_link_libraries(tdnet PUBLIC tdactor) - -add_executable(tcp_ping_pong example/tcp_ping_pong.cpp) -target_link_libraries(tcp_ping_pong PRIVATE tdactor tdnet) - -add_executable(udp_ping_pong example/udp_ping_pong.cpp) -target_link_libraries(udp_ping_pong PRIVATE tdactor tdnet) - -set(NET_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/net-test.cpp - PARENT_SCOPE -) diff --git a/submodules/ton/tonlib-src/tdnet/example/tcp_ping_pong.cpp b/submodules/ton/tonlib-src/tdnet/example/tcp_ping_pong.cpp deleted file mode 100644 index 9bcbee99..00000000 --- a/submodules/ton/tonlib-src/tdnet/example/tcp_ping_pong.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/actor.h" - -#include "td/utils/BufferedFd.h" -#include "td/utils/OptionsParser.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/port/ServerSocketFd.h" -#include "td/utils/Observer.h" - -#include "td/net/TcpListener.h" - -class PingClient : public td::actor::Actor, td::ObserverBase { - public: - PingClient(td::SocketFd fd) : buffered_fd_(std::move(fd)) { - } - - private: - td::BufferedFd buffered_fd_; - td::actor::ActorId self_; - void notify() override { - // NB: Interface will be changed - send_closure_later(self_, &PingClient::on_net); - } - void on_net() { - loop(); - } - - void start_up() override { - self_ = actor_id(this); - LOG(INFO) << "Start"; - // Subscribe for socket updates - // NB: Interface will be changed - td::actor::SchedulerContext::get()->get_poll().subscribe(buffered_fd_.get_poll_info().extract_pollable_fd(this), - td::PollFlags::ReadWrite()); - - alarm_timestamp() = td::Timestamp::now(); - } - - void tear_down() override { - LOG(INFO) << "Close"; - // unsubscribe from socket updates - // nb: interface will be changed - td::actor::SchedulerContext::get()->get_poll().unsubscribe(buffered_fd_.get_poll_info().get_pollable_fd_ref()); - } - - void loop() override { - auto status = [&] { - TRY_STATUS(buffered_fd_.flush_read()); - auto &input = buffered_fd_.input_buffer(); - while (input.size() >= 12) { - auto query = input.cut_head(12).move_as_buffer_slice(); - LOG(INFO) << "Got query " << td::format::escaped(query.as_slice()); - if (query[5] == 'i') { - LOG(INFO) << "Send ping"; - buffered_fd_.output_buffer().append("magkpongpong"); - } else { - LOG(INFO) << "Got pong"; - } - } - - TRY_STATUS(buffered_fd_.flush_write()); - if (td::can_close(buffered_fd_)) { - stop(); - } - return td::Status::OK(); - }(); - if (status.is_error()) { - LOG(ERROR) << "Client got error " << status; - stop(); - } - } - - void alarm() override { - alarm_timestamp() = td::Timestamp::in(5); - LOG(INFO) << "Send ping"; - buffered_fd_.output_buffer().append("magkpingping"); - loop(); - } -}; - -int main(int argc, char *argv[]) { - td::OptionsParser options_parser; - options_parser.set_description("Tcp ping server/client (based on td::actors2)"); - - int port = 8081; - bool is_client = false; - options_parser.add_option('p', "port", "listen/connect to tcp port (8081 by default)", [&](td::Slice arg) { - port = td::to_integer(arg); - return td::Status::OK(); - }); - options_parser.add_option('c', "client", "Work as client (server by default)", [&]() { - is_client = true; - return td::Status::OK(); - }); - auto status = options_parser.run(argc, argv); - if (status.is_error()) { - LOG(ERROR) << status.error(); - LOG(INFO) << options_parser; - return 1; - } - - // NB: Interface will be changed - td::actor::Scheduler scheduler({2}); - scheduler.run_in_context([&] { - if (is_client) { - td::IPAddress ip_address; - ip_address.init_ipv4_port("127.0.0.1", port).ensure(); - td::actor::create_actor(td::actor::ActorOptions().with_name("TcpClient").with_poll(), - td::SocketFd::open(ip_address).move_as_ok()) - .release(); - } else { - class Callback : public td::TcpListener::Callback { - public: - void accept(td::SocketFd fd) override { - td::actor::create_actor(td::actor::ActorOptions().with_name("TcpClient").with_poll(), - std::move(fd)) - .release(); - } - }; - td::actor::create_actor(td::actor::ActorOptions().with_name("TcpServer").with_poll(), port, - std::make_unique()) - .release(); - } - }); - scheduler.run(); - return 0; -} diff --git a/submodules/ton/tonlib-src/tdnet/example/udp_ping_pong.cpp b/submodules/ton/tonlib-src/tdnet/example/udp_ping_pong.cpp deleted file mode 100644 index 069380a7..00000000 --- a/submodules/ton/tonlib-src/tdnet/example/udp_ping_pong.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/actor.h" - -#include "td/utils/OptionsParser.h" -#include "td/utils/Observer.h" -#include "td/utils/port/UdpSocketFd.h" - -#include "td/net/UdpServer.h" - -// PingPong -class PingPong : public td::actor::Actor { - public: - PingPong(int port, td::IPAddress dest, bool use_tcp) : port_(port), dest_(std::move(dest)), use_tcp_(use_tcp) { - } - - private: - int port_; - td::actor::ActorOwn udp_server_; - td::IPAddress dest_; - bool is_closing_{false}; - bool use_tcp_{false}; - - void start_up() override { - class Callback : public td::UdpServer::Callback { - public: - Callback(td::actor::ActorShared ping_pong) : ping_pong_(std::move(ping_pong)) { - } - - private: - td::actor::ActorShared ping_pong_; - void on_udp_message(td::UdpMessage udp_message) override { - send_closure(ping_pong_, &PingPong::on_udp_message, std::move(udp_message)); - } - }; - - if (use_tcp_) { - udp_server_ = td::UdpServer::create_via_tcp(PSLICE() << "UdpServer(via tcp) " << td::tag("port", port_), port_, - std::make_unique(actor_shared(this))) - .move_as_ok(); - } else { - udp_server_ = td::UdpServer::create(PSLICE() << "UdpServer " << td::tag("port", port_), port_, - std::make_unique(actor_shared(this))) - .move_as_ok(); - } - - alarm_timestamp() = td::Timestamp::now(); - } - - void on_udp_message(td::UdpMessage message) { - if (is_closing_) { - return; - } - if (message.error.is_error()) { - LOG(ERROR) << "Got error " << message.error << " from " << message.address; - return; - } - - auto data_slice = message.data.as_slice(); - LOG(INFO) << "Got query " << td::format::escaped(data_slice) << " from " << message.address; - if (data_slice[5] == 'i') { - send_closure(udp_server_, &td::UdpServer::send, - td::UdpMessage{message.address, td::BufferSlice("magkpongpong"), {}}); - } - } - - int cnt_{0}; - void alarm() override { - if (++cnt_ > 10) { - return close(); - } - alarm_timestamp() = td::Timestamp::in(1); - LOG(INFO) << "Send ping"; - send_closure(udp_server_, &td::UdpServer::send, td::UdpMessage{dest_, td::BufferSlice("magkpingping"), {}}); - } - - void close() { - is_closing_ = true; - udp_server_.reset(); - } - void hangup_shared() override { - // udp_server_ was_closed - stop(); - } - void tear_down() override { - td::actor::SchedulerContext::get()->stop(); - } -}; - -int main(int argc, char *argv[]) { - td::OptionsParser options_parser; - options_parser.set_description("Udp ping server/client (8083 <-> 8084) (based on td::actors2)"); - - int from_port = 8083; - int to_port = 8084; - bool is_client = false; - bool use_tcp = false; - options_parser.add_option('c', "client", "Work as client (server by default)", [&]() { - is_client = true; - return td::Status::OK(); - }); - options_parser.add_option('t', "tcp", "Use tcp (udp by default)", [&]() { - use_tcp = true; - return td::Status::OK(); - }); - auto status = options_parser.run(argc, argv); - if (status.is_error()) { - LOG(ERROR) << status.error(); - LOG(INFO) << options_parser; - return 1; - } - if (is_client) { - std::swap(from_port, to_port); - } - td::IPAddress to_ip; - to_ip.init_ipv4_port("127.0.0.1", to_port).ensure(); - - // NB: Interface will be changed - td::actor::Scheduler scheduler({2}); - LOG(INFO) << "Listen to " << from_port; - scheduler.run_in_context([&] { - td::actor::create_actor(td::actor::ActorOptions().with_name("TcpClient").with_poll(), from_port, to_ip, - use_tcp) - .release(); - }); - scheduler.run(); - return 0; -} diff --git a/submodules/ton/tonlib-src/tdnet/td/net/FdListener.cpp b/submodules/ton/tonlib-src/tdnet/td/net/FdListener.cpp deleted file mode 100644 index a807408c..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/FdListener.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/net/FdListener.h" - -namespace td { -void FdListener::start_up() { - fd_.add_flags(PollFlags::ReadWrite()); - td::actor::SchedulerContext::get()->get_poll().subscribe(std::move(fd_), PollFlags::ReadWrite()); -} - -void FdListener::tear_down() { - td::actor::SchedulerContext::get()->get_poll().unsubscribe(fd_ref_); -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/FdListener.h b/submodules/ton/tonlib-src/tdnet/td/net/FdListener.h deleted file mode 100644 index 261d7e37..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/FdListener.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" - -#include "td/utils/Observer.h" -#include "td/utils/port/detail/PollableFd.h" - -namespace td { -class FdListener : public td::actor::Actor { - public: - FdListener(td::PollableFd fd, std::unique_ptr guard) - : fd_(std::move(fd)), fd_ref_(fd_.ref()), guard_(std::move(guard)) { - } - - private: - PollableFd fd_; - PollableFdRef fd_ref_; - std::unique_ptr guard_; - - void start_up() override; - - void tear_down() override; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp deleted file mode 100644 index 7b7364ba..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/net/TcpListener.h" - -namespace td { -TcpListener::TcpListener(int port, std::unique_ptr callback) : port_(port), callback_(std::move(callback)) { -} -void TcpListener::notify() { - td::actor::send_closure_later(self_, &TcpListener::on_net); -} -void TcpListener::on_net() { - loop(); -} - -void TcpListener::start_up() { - self_ = actor_id(this); - - auto r_socket = td::ServerSocketFd::open(port_); - if (r_socket.is_error()) { - LOG(ERROR) << r_socket.error(); - return stop(); - } - - server_socket_fd_ = r_socket.move_as_ok(); - - // Subscribe for socket updates - // NB: Interface will be changed - td::actor::SchedulerContext::get()->get_poll().subscribe(server_socket_fd_.get_poll_info().extract_pollable_fd(this), - PollFlags::Read()); -} - -void TcpListener::tear_down() { - // unsubscribe from socket updates - // nb: interface will be changed - td::actor::SchedulerContext::get()->get_poll().unsubscribe(server_socket_fd_.get_poll_info().get_pollable_fd_ref()); -} - -void TcpListener::loop() { - auto status = [&] { - while (td::can_read(server_socket_fd_)) { - auto r_socket = server_socket_fd_.accept(); - if (r_socket.is_error() && r_socket.error().code() == -1) { - break; - } - TRY_RESULT(client_socket, std::move(r_socket)); - LOG(ERROR) << "Accept"; - callback_->accept(std::move(client_socket)); - } - if (td::can_close(server_socket_fd_)) { - stop(); - } - return td::Status::OK(); - }(); - - if (status.is_error()) { - LOG(ERROR) << "Server error " << status; - return stop(); - } -} -TcpInfiniteListener::TcpInfiniteListener(int32 port, std::unique_ptr callback) - : port_(port), callback_(std::move(callback)) { -} - -void TcpInfiniteListener::start_up() { - loop(); -} - -void TcpInfiniteListener::hangup() { - close_flag_ = true; - tcp_listener_.reset(); - if (refcnt_ == 0) { - stop(); - } -} - -void TcpInfiniteListener::loop() { - if (!tcp_listener_.empty()) { - return; - } - class Callback : public TcpListener::Callback { - public: - Callback(actor::ActorShared parent) : parent_(std::move(parent)) { - } - void accept(SocketFd fd) override { - actor::send_closure(parent_, &TcpInfiniteListener::accept, std::move(fd)); - } - - private: - actor::ActorShared parent_; - }; - refcnt_++; - tcp_listener_ = actor::create_actor( - actor::ActorOptions().with_name(PSLICE() << "TcpListener" << tag("port", port_)).with_poll(), port_, - std::make_unique(actor_shared(this))); -} - -void TcpInfiniteListener::accept(SocketFd fd) { - callback_->accept(std::move(fd)); -} - -void TcpInfiniteListener::hangup_shared() { - refcnt_--; - tcp_listener_.reset(); - if (close_flag_) { - if (refcnt_ == 0) { - stop(); - } - } else { - alarm_timestamp() = Timestamp::in(5 /*5 seconds*/); - } -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h deleted file mode 100644 index fc11f8bc..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" - -#include "td/utils/port/ServerSocketFd.h" -#include "td/utils/Observer.h" - -namespace td { -class TcpListener : public td::actor::Actor, private td::ObserverBase { - public: - class Callback { - public: - virtual ~Callback() = default; - virtual void accept(SocketFd fd) = 0; - }; - - TcpListener(int port, std::unique_ptr callback); - - private: - int port_; - std::unique_ptr callback_; - td::ServerSocketFd server_socket_fd_; - td::actor::ActorId self_; - - void notify() override; - void on_net(); - - void start_up() override; - - void tear_down() override; - - void loop() override; -}; - -class TcpInfiniteListener : public actor::Actor { - public: - TcpInfiniteListener(int32 port, std::unique_ptr callback); - - private: - int32 port_; - std::unique_ptr callback_; - actor::ActorOwn tcp_listener_; - int32 refcnt_{0}; - bool close_flag_{false}; - - void start_up() override; - - void hangup() override; - void loop() override; - void accept(SocketFd fd); - void hangup_shared() override; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp b/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp deleted file mode 100644 index a1c53aa6..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/net/UdpServer.h" -#include "td/net/FdListener.h" -#include "td/net/TcpListener.h" - -#include "td/utils/BufferedFd.h" - -#include - -namespace td { -namespace { -int VERBOSITY_NAME(udp_server) = VERBOSITY_NAME(DEBUG) + 10; -} -namespace detail { -class UdpServerImpl : public UdpServer { - public: - void send(td::UdpMessage &&message) override; - static td::actor::ActorOwn create(td::Slice name, td::UdpSocketFd fd, - std::unique_ptr callback); - - UdpServerImpl(td::UdpSocketFd fd, std::unique_ptr callback); - - private: - td::actor::ActorOwn<> fd_listener_; - std::unique_ptr callback_; - td::BufferedUdp fd_; - bool is_closing_{false}; - - void start_up() override; - void on_fd_updated(); - - void loop() override; - - void hangup() override; - void hangup_shared() override; -}; - -void UdpServerImpl::send(td::UdpMessage &&message) { - fd_.send(std::move(message)); - loop(); // TODO: some yield logic -} - -td::actor::ActorOwn UdpServerImpl::create(td::Slice name, td::UdpSocketFd fd, - std::unique_ptr callback) { - return td::actor::create_actor( - actor::ActorOptions().with_name(name).with_poll(!td::Poll::is_edge_triggered()), std::move(fd), - std::move(callback)); -} - -UdpServerImpl::UdpServerImpl(td::UdpSocketFd fd, std::unique_ptr callback) - : callback_(std::move(callback)), fd_(std::move(fd)) { -} - -void UdpServerImpl::start_up() { - //CHECK(td::actor::SchedulerContext::get()->has_poll() == false); - class Observer : public td::ObserverBase, public Destructor { - public: - Observer(td::actor::ActorShared udp_server) : udp_server_(std::move(udp_server)) { - } - void notify() override { - VLOG(udp_server) << "on_fd_updated"; - td::actor::send_signals_later(udp_server_, td::actor::ActorSignals::wakeup()); - } - - private: - td::actor::ActorShared udp_server_; - }; - - auto observer = std::make_unique(actor_shared(this)); - auto pollable_fd = fd_.get_poll_info().extract_pollable_fd(observer.get()); - fd_listener_ = td::actor::create_actor(actor::ActorOptions().with_name("FdListener").with_poll(), - std::move(pollable_fd), std::move(observer)); -} - -void UdpServerImpl::on_fd_updated() { - loop(); -} - -void UdpServerImpl::loop() { - if (is_closing_) { - return; - } - //CHECK(td::actor::SchedulerContext::get()->has_poll() == false); - fd_.get_poll_info().get_flags(); - VLOG(udp_server) << "loop " << td::tag("can read", can_read(fd_)) << " " << td::tag("can write", can_write(fd_)); - Status status; - status = [&] { - while (true) { - TRY_RESULT(o_message, fd_.receive()); - if (!o_message) { - return Status::OK(); - } - callback_->on_udp_message(std::move(*o_message)); - } - return Status::OK(); - }(); - if (status.is_ok()) { - status = fd_.flush_send(); - } - - if (status.is_error()) { - VLOG(udp_server) << "Got " << status << " sleep for 1 second"; - alarm_timestamp() = Timestamp::in(1); - } -} - -void UdpServerImpl::hangup() { - is_closing_ = true; - // wait till fd_listener_ is closed and fd is unsubscribed - fd_listener_.reset(); -} -void UdpServerImpl::hangup_shared() { - stop(); -} - -class TcpClient : public td::actor::Actor, td::ObserverBase { - public: - class Callback { - public: - virtual ~Callback() = default; - virtual void on_message(BufferSlice data) = 0; - virtual void on_closed(actor::ActorId<>) = 0; - }; - TcpClient(td::SocketFd fd, std::unique_ptr callback) - : buffered_fd_(std::move(fd)), callback_(std::move(callback)) { - } - - void send(BufferSlice data) { - uint32 data_size = narrow_cast(data.size()); - - buffered_fd_.output_buffer().append(Slice(reinterpret_cast(&data_size), sizeof(data_size))); - buffered_fd_.output_buffer().append(std::move(data)); - loop(); - } - - private: - td::BufferedFd buffered_fd_; - std::unique_ptr callback_; - td::actor::ActorId self_; - - void notify() override { - // NB: Interface will be changed - td::actor::send_closure_later(self_, &TcpClient::on_net); - } - void on_net() { - loop(); - } - - void start_up() override { - self_ = actor_id(this); - LOG(INFO) << "Start"; - // Subscribe for socket updates - // NB: Interface will be changed - td::actor::SchedulerContext::get()->get_poll().subscribe(buffered_fd_.get_poll_info().extract_pollable_fd(this), - PollFlags::ReadWrite()); - alarm_timestamp() = Timestamp::in(10); - notify(); - } - - void tear_down() override { - LOG(INFO) << "Close"; - // unsubscribe from socket updates - // nb: interface will be changed - td::actor::SchedulerContext::get()->get_poll().unsubscribe(buffered_fd_.get_poll_info().get_pollable_fd_ref()); - callback_->on_closed(actor_id(this)); - } - - void loop() override { - auto status = [&] { - TRY_STATUS(buffered_fd_.flush_read()); - auto &input = buffered_fd_.input_buffer(); - while (true) { - constexpr size_t header_size = 4; - if (input.size() < header_size) { - break; - } - auto it = input.clone(); - uint32 data_size; - it.advance(header_size, MutableSlice(reinterpret_cast(&data_size), sizeof(data_size))); - if (data_size > (1 << 26)) { - return Status::Error("Too big packet"); - } - if (it.size() < data_size) { - break; - } - auto data = it.cut_head(data_size).move_as_buffer_slice(); - alarm_timestamp() = Timestamp::in(10); - callback_->on_message(std::move(data)); - input = std::move(it); - } - - TRY_STATUS(buffered_fd_.flush_write()); - if (td::can_close(buffered_fd_)) { - stop(); - } - return td::Status::OK(); - }(); - if (status.is_error()) { - LOG(INFO) << "Client got error " << status; - stop(); - } - } - void alarm() override { - LOG(INFO) << "Close because of timeout"; - stop(); - } -}; - -struct Target { - IPAddress ip_address; - actor::ActorOwn inbound; - actor::ActorOwn outbound; -}; - -class TargetSet { - public: - using Id = size_t; - Id register_target(IPAddress address) { - auto it_ok = ip_to_id_.insert(std::make_pair(address, 0)); - if (it_ok.second) { - id_to_target_.push_back({}); - id_to_target_.back().ip_address = address; - it_ok.first->second = id_to_target_.size(); - } - return it_ok.first->second; - } - - Target &get_target(Id id) { - return id_to_target_.at(id - 1); - } - - private: - std::map ip_to_id_; - std::vector id_to_target_; -}; -class UdpServerViaTcp : public UdpServer { - public: - UdpServerViaTcp(int32 port, std::unique_ptr callback) : port_(port), callback_(std::move(callback)) { - } - - private: - int32 port_; - std::unique_ptr callback_; - actor::ActorOwn tcp_listener_; - TargetSet target_set_; - int refcnt_{0}; - bool close_flag_{false}; - - void start_up() override { - //TcpInfiniteListener - class TcpListenerCallback : public TcpListener::Callback { - public: - TcpListenerCallback(actor::ActorShared parent) : parent_(std::move(parent)) { - } - void accept(SocketFd fd) override { - actor::send_closure(parent_, &UdpServerViaTcp::accept, std::move(fd)); - } - - private: - actor::ActorShared parent_; - }; - refcnt_++; - tcp_listener_ = actor::create_actor(PSLICE() << "TcpInfiniteListener" << port_, port_, - std::make_unique(actor_shared(this))); - } - - void send(UdpMessage &&message) override { - if (close_flag_) { - return; - } - auto target_id = target_set_.register_target(message.address); - auto &target = target_set_.get_target(target_id); - if (target.inbound.empty() && target.outbound.empty()) { - auto r_fd = SocketFd::open(target.ip_address); - if (r_fd.is_error()) { - LOG(INFO) << r_fd.error(); - return; - } - auto fd = r_fd.move_as_ok(); - do_accept(std::move(fd), message.address, false); - } - if (!target.inbound.empty()) { - send_closure_later(target.inbound, &TcpClient::send, std::move(message.data)); - } else if (!target.outbound.empty()) { - send_closure_later(target.outbound, &TcpClient::send, std::move(message.data)); - } - } - - void on_message(BufferSlice data) { - if (close_flag_) { - return; - } - auto token = get_link_token(); - auto &target = target_set_.get_target(narrow_cast(token)); - UdpMessage message; - message.address = target.ip_address; - message.data = std::move(data); - callback_->on_udp_message(std::move(message)); - } - void on_closed(actor::ActorId<> id) { - if (close_flag_) { - return; - } - auto token = get_link_token(); - auto &target = target_set_.get_target(narrow_cast(token)); - if (target.inbound.get() == id) { - target.inbound.reset(); - } - if (target.outbound.get() == id) { - target.outbound.reset(); - } - } - - void accept(SocketFd fd) { - if (close_flag_) { - return; - } - IPAddress ip_address; - auto status = ip_address.init_peer_address(fd); - if (status.is_error()) { - LOG(INFO) << status; - return; - } - do_accept(std::move(fd), ip_address, true); - } - void do_accept(SocketFd fd, IPAddress ip_address, bool is_inbound) { - class TcpClientCallback : public TcpClient::Callback { - public: - TcpClientCallback(actor::ActorShared parent) : parent_(std::move(parent)) { - } - void on_message(BufferSlice data) override { - send_closure(parent_, &UdpServerViaTcp::on_message, std::move(data)); - } - void on_closed(actor::ActorId<> id) override { - send_closure(parent_, &UdpServerViaTcp::on_closed, std::move(id)); - } - - private: - actor::ActorShared parent_; - }; - - auto target_id = target_set_.register_target(ip_address); - auto &target = target_set_.get_target(target_id); - refcnt_++; - auto actor = actor::create_actor(actor::ActorOptions().with_name("TcpClient").with_poll(), std::move(fd), - std::make_unique(actor_shared(this, target_id))); - if (is_inbound) { - target.inbound = std::move(actor); - } else { - target.outbound = std::move(actor); - } - } - - void hangup() override { - close_flag_ = true; - target_set_ = {}; - tcp_listener_ = {}; - } - - void hangup_shared() override { - refcnt_--; - if (refcnt_ == 0) { - stop(); - } - } - - void loop() override { - } -}; - -} // namespace detail - -Result> UdpServer::create(td::Slice name, int32 port, std::unique_ptr callback) { - td::IPAddress from_ip; - TRY_STATUS(from_ip.init_ipv4_port("0.0.0.0", port)); - TRY_RESULT(fd, UdpSocketFd::open(from_ip)); - fd.maximize_rcv_buffer().ensure(); - return detail::UdpServerImpl::create(name, std::move(fd), std::move(callback)); -} -Result> UdpServer::create_via_tcp(td::Slice name, int32 port, - std::unique_ptr callback) { - return actor::create_actor(name, port, std::move(callback)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.h b/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.h deleted file mode 100644 index f6d0d268..00000000 --- a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/actor/actor.h" -#include "td/utils/BufferedUdp.h" - -#include "td/utils/port/UdpSocketFd.h" - -namespace td { - -class UdpServer : public td::actor::Actor { - public: - class Callback { - public: - virtual ~Callback() = default; - virtual void on_udp_message(td::UdpMessage udp_message) = 0; - }; - virtual void send(td::UdpMessage &&message) = 0; - - static Result> create(td::Slice name, int32 port, std::unique_ptr callback); - static Result> create_via_tcp(td::Slice name, int32 port, - std::unique_ptr callback); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/test/net-test.cpp b/submodules/ton/tonlib-src/tdnet/test/net-test.cpp deleted file mode 100644 index bb084a67..00000000 --- a/submodules/ton/tonlib-src/tdnet/test/net-test.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/actor/actor.h" -#include "td/net/UdpServer.h" -#include "td/utils/tests.h" - -class PingPong : public td::actor::Actor { - public: - PingPong(int port, td::IPAddress dest, bool use_tcp, bool is_first) - : port_(port), dest_(std::move(dest)), use_tcp_(use_tcp) { - if (is_first) { - state_ = Send; - to_send_cnt_ = 5; - to_send_cnt_ = 1; - } - } - - private: - int port_; - td::actor::ActorOwn udp_server_; - td::IPAddress dest_; - bool is_closing_{false}; - bool is_closing_delayed_{false}; - bool use_tcp_{false}; - enum State { Send, Receive } state_{State::Receive}; - int cnt_{0}; - int to_send_cnt_{0}; - - void start_up() override { - class Callback : public td::UdpServer::Callback { - public: - Callback(td::actor::ActorShared ping_pong) : ping_pong_(std::move(ping_pong)) { - } - - private: - td::actor::ActorShared ping_pong_; - void on_udp_message(td::UdpMessage udp_message) override { - send_closure(ping_pong_, &PingPong::on_udp_message, std::move(udp_message)); - } - }; - - if (use_tcp_) { - udp_server_ = td::UdpServer::create_via_tcp(PSLICE() << "UdpServer(via tcp) " << td::tag("port", port_), port_, - std::make_unique(actor_shared(this))) - .move_as_ok(); - } else { - udp_server_ = td::UdpServer::create(PSLICE() << "UdpServer " << td::tag("port", port_), port_, - std::make_unique(actor_shared(this))) - .move_as_ok(); - } - - alarm_timestamp() = td::Timestamp::in(0.1); - } - - void on_udp_message(td::UdpMessage message) { - if (is_closing_) { - return; - } - if (message.error.is_error()) { - LOG(ERROR) << "Got error " << message.error << " from " << message.address; - return; - } - - auto data_slice = message.data.as_slice(); - LOG(INFO) << "Got query " << td::format::escaped(data_slice) << " from " << message.address; - CHECK(state_ == State::Receive); - if (data_slice.size() < 5) { - CHECK(data_slice == "stop"); - close(); - } - if (data_slice[5] == 'i') { - state_ = State::Send; - to_send_cnt_ = td::Random::fast(1, 4); - to_send_cnt_ = 1; - send_closure_later(actor_id(this), &PingPong::loop); - } - } - void loop() override { - if (state_ != State::Send || is_closing_) { - return; - } - to_send_cnt_--; - td::Slice msg; - if (to_send_cnt_ <= 0) { - state_ = State::Receive; - cnt_++; - if (cnt_ >= 1000) { - msg = "stop"; - } else { - msg = "makgpingping"; - } - } else { - msg = "magkpongpong"; - } - LOG(INFO) << "Send query: " << msg; - send_closure_later(actor_id(this), &PingPong::loop); - send_closure(udp_server_, &td::UdpServer::send, td::UdpMessage{dest_, td::BufferSlice(msg), {}}); - - if (msg.size() == 4) { - close_delayed(); - } - } - - void alarm() override { - if (is_closing_delayed_) { - close(); - return; - } - send_closure_later(actor_id(this), &PingPong::loop); - } - void close_delayed() { - // Temporary hack to avoid ECONNRESET error - is_closing_ = true; - is_closing_delayed_ = true; - alarm_timestamp() = td::Timestamp::in(0.1); - } - void close() { - is_closing_ = true; - udp_server_.reset(); - } - void hangup_shared() override { - // udp_server_ was_closed - stop(); - } - void tear_down() override { - td::actor::SchedulerContext::get()->stop(); - } -}; - -void run_server(int from_port, int to_port, bool is_first, bool use_tcp) { - td::IPAddress to_ip; - to_ip.init_host_port("localhost", to_port).ensure(); - - td::actor::Scheduler scheduler({1}); - scheduler.run_in_context([&] { - td::actor::create_actor(td::actor::ActorOptions().with_name("PingPong"), from_port, to_ip, use_tcp, - is_first) - .release(); - }); - scheduler.run(); -} - -TEST(Net, PingPong) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - for (auto use_tcp : {false, true}) { - auto a = td::thread([use_tcp] { run_server(8091, 8092, true, use_tcp); }); - auto b = td::thread([use_tcp] { run_server(8092, 8091, false, use_tcp); }); - a.join(); - b.join(); - } -} diff --git a/submodules/ton/tonlib-src/tdtl/.gitrepo b/submodules/ton/tonlib-src/tdtl/.gitrepo deleted file mode 100644 index 7346b4bf..00000000 --- a/submodules/ton/tonlib-src/tdtl/.gitrepo +++ /dev/null @@ -1,11 +0,0 @@ -; DO NOT EDIT (unless you know what you are doing) -; -; This subdirectory is a git "subrepo", and this file is maintained by the -; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme -; -[subrepo] - remote = https://github.com/arseny30/tdtl - branch = master - commit = c6c23a5a9e3f13b576116a0e7bf5a032faa33ff2 - parent = 004e7575cf77d514c77bbab3b764568621f7d140 - cmdver = 0.3.1 diff --git a/submodules/ton/tonlib-src/tdtl/CMakeLists.txt b/submodules/ton/tonlib-src/tdtl/CMakeLists.txt deleted file mode 100644 index b0f83cd9..00000000 --- a/submodules/ton/tonlib-src/tdtl/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -#SOURCE SETS -set(TDTL_SOURCE - td/tl/tl_config.cpp - td/tl/tl_core.cpp - td/tl/tl_file_outputer.cpp - td/tl/tl_file_utils.cpp - td/tl/tl_generate.cpp - td/tl/tl_outputer.cpp - td/tl/tl_string_outputer.cpp - td/tl/tl_writer.cpp - - td/tl/tl_config.h - td/tl/tl_core.h - td/tl/tl_file_outputer.h - td/tl/tl_file_utils.h - td/tl/tl_generate.h - td/tl/tl_outputer.h - td/tl/tl_simple.h - td/tl/tl_simple_parser.h - td/tl/tl_string_outputer.h - td/tl/tl_writer.h -) - -add_library(tdtl STATIC ${TDTL_SOURCE}) -target_include_directories(tdtl PUBLIC $) -#TODO -#target_compile_options(tdtl PRIVATE "-std=c++03") diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.cpp deleted file mode 100644 index cc1b0f42..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_config.h" - -#include -#include -#include -#include - -namespace td { -namespace tl { - -const std::int32_t TLS_SCHEMA_V2 = 0x3a2f9be2; -const std::int32_t TLS_SCHEMA_V3 = 0xe4a8604b; -const std::int32_t TLS_SCHEMA_V4 = 0x90ac88d7; -const std::int32_t TLS_TYPE = 0x12eb4386; -const std::int32_t TLS_COMBINATOR = 0x5c0a1ed5; -const std::int32_t TLS_COMBINATOR_LEFT_BUILTIN = 0xcd211f63; -const std::int32_t TLS_COMBINATOR_LEFT = 0x4c12c6d9; -const std::int32_t TLS_COMBINATOR_RIGHT_V2 = 0x2c064372; -const std::int32_t TLS_ARG_V2 = 0x29dfe61b; - -const std::int32_t TLS_EXPR_NAT = 0xdcb49bd8; -const std::int32_t TLS_EXPR_TYPE = 0xecc9da78; - -const std::int32_t TLS_NAT_CONST_OLD = 0xdcb49bd8; -const std::int32_t TLS_NAT_CONST = 0x8ce940b1; -const std::int32_t TLS_NAT_VAR = 0x4e8a14f0; -const std::int32_t TLS_TYPE_VAR = 0x0142ceae; -const std::int32_t TLS_ARRAY = 0xd9fb20de; -const std::int32_t TLS_TYPE_EXPR = 0xc1863d08; - -void tl_config::add_type(tl_type *type) { - types.push_back(type); - id_to_type[type->id] = type; - name_to_type[type->name] = type; -} - -tl_type *tl_config::get_type(std::int32_t type_id) const { - auto it = id_to_type.find(type_id); - assert(it != id_to_type.end()); - return it->second; -} - -tl_type *tl_config::get_type(const std::string &type_name) { - return name_to_type[type_name]; -} - -void tl_config::add_function(tl_combinator *function) { - functions.push_back(function); - id_to_function[function->id] = function; - name_to_function[function->name] = function; -} - -tl_combinator *tl_config::get_function(std::int32_t function_id) { - return id_to_function[function_id]; -} - -tl_combinator *tl_config::get_function(const std::string &function_name) { - return name_to_function[function_name]; -} - -std::size_t tl_config::get_type_count() const { - return types.size(); -} - -tl_type *tl_config::get_type_by_num(std::size_t num) const { - return types[num]; -} - -std::size_t tl_config::get_function_count() const { - return functions.size(); -} - -tl_combinator *tl_config::get_function_by_num(std::size_t num) const { - return functions[num]; -} - -std::int32_t tl_config_parser::try_parse_int() { - return try_parse(p.fetch_int()); -} - -std::int64_t tl_config_parser::try_parse_long() { - return try_parse(p.fetch_long()); -} - -std::string tl_config_parser::try_parse_string() { - return try_parse(p.fetch_string()); -} - -template -T tl_config_parser::try_parse(const T &res) const { - if (p.get_error() != NULL) { - std::fprintf(stderr, "Wrong TL-scheme specified: %s at %d\n", p.get_error(), static_cast(p.get_error_pos())); - std::abort(); - } - - return res; -} - -int tl_config_parser::get_schema_version(std::int32_t version_id) { - if (version_id == TLS_SCHEMA_V4) { - return 4; - } - if (version_id == TLS_SCHEMA_V3) { - return 3; - } - if (version_id == TLS_SCHEMA_V2) { - return 2; - } - return -1; -} - -template -T *store(std::unique_ptr ptr) { - static std::vector> storage; - auto res = ptr.get(); - storage.push_back(std::move(ptr)); - return res; -} - -tl_tree *tl_config_parser::read_num_const() { - int num = static_cast(try_parse_int()); - - return store(std::make_unique(FLAG_NOVAR, num)); -} - -tl_tree *tl_config_parser::read_num_var(int *var_count) { - std::int32_t diff = try_parse_int(); - int var_num = static_cast(try_parse_int()); - - if (var_num >= *var_count) { - *var_count = var_num + 1; - } - - return store(std::make_unique(0, var_num, diff)); -} - -tl_tree *tl_config_parser::read_type_var(int *var_count) { - int var_num = static_cast(try_parse_int()); - std::int32_t flags = try_parse_int(); - - if (var_num >= *var_count) { - *var_count = var_num + 1; - } - assert(!(flags & (FLAG_NOVAR | FLAG_BARE))); - - return store(std::make_unique(flags, var_num)); -} - -tl_tree *tl_config_parser::read_array(int *var_count) { - std::int32_t flags = FLAG_NOVAR; - tl_tree *multiplicity = read_nat_expr(var_count); - - tl_tree_array *T = store(std::make_unique(flags, multiplicity, read_args_list(var_count))); - - for (std::size_t i = 0; i < T->args.size(); i++) { - if (!(T->args[i].flags & FLAG_NOVAR)) { - T->flags &= ~FLAG_NOVAR; - } - } - return T; -} - -tl_tree *tl_config_parser::read_type(int *var_count) { - tl_type *type = config.get_type(try_parse_int()); - assert(type != NULL); - std::int32_t flags = try_parse_int() | FLAG_NOVAR; - int arity = static_cast(try_parse_int()); - assert(type->arity == arity); - - tl_tree_type *T = store(std::make_unique(flags, type, arity)); - for (std::int32_t i = 0; i < arity; i++) { - tl_tree *child = read_expr(var_count); - - T->children[i] = child; - if (!(child->flags & FLAG_NOVAR)) { - T->flags &= ~FLAG_NOVAR; - } - } - return T; -} - -tl_tree *tl_config_parser::read_type_expr(int *var_count) { - std::int32_t tree_type = try_parse_int(); - switch (tree_type) { - case TLS_TYPE_VAR: - return read_type_var(var_count); - case TLS_TYPE_EXPR: - return read_type(var_count); - case TLS_ARRAY: - return read_array(var_count); - default: - std::fprintf(stderr, "tree_type = %d\n", static_cast(tree_type)); - std::abort(); - } -} - -tl_tree *tl_config_parser::read_nat_expr(int *var_count) { - std::int32_t tree_type = try_parse_int(); - switch (tree_type) { - case TLS_NAT_CONST_OLD: - case TLS_NAT_CONST: - return read_num_const(); - case TLS_NAT_VAR: - return read_num_var(var_count); - default: - std::fprintf(stderr, "tree_type = %d\n", static_cast(tree_type)); - std::abort(); - } -} - -tl_tree *tl_config_parser::read_expr(int *var_count) { - std::int32_t tree_type = try_parse_int(); - switch (tree_type) { - case TLS_EXPR_NAT: - return read_nat_expr(var_count); - case TLS_EXPR_TYPE: - return read_type_expr(var_count); - default: - std::fprintf(stderr, "tree_type = %d\n", static_cast(tree_type)); - std::abort(); - } -} - -std::vector tl_config_parser::read_args_list(int *var_count) { - const int schema_flag_opt_field = 2 << static_cast(schema_version >= 3); - const int schema_flag_has_vars = schema_flag_opt_field ^ 6; - - std::size_t args_num = static_cast(try_parse_int()); - std::vector args(args_num); - for (std::size_t i = 0; i < args_num; i++) { - arg cur_arg; - - std::int32_t arg_v = try_parse_int(); - if (arg_v != TLS_ARG_V2) { - std::fprintf(stderr, "Wrong tls_arg magic %d\n", static_cast(arg_v)); - std::abort(); - } - - cur_arg.name = try_parse_string(); - cur_arg.flags = try_parse_int(); - - bool is_optional = false; - if (cur_arg.flags & schema_flag_opt_field) { - cur_arg.flags &= ~schema_flag_opt_field; - is_optional = true; - } - if (cur_arg.flags & schema_flag_has_vars) { - cur_arg.flags &= ~schema_flag_has_vars; - cur_arg.var_num = static_cast(try_parse_int()); - } else { - cur_arg.var_num = -1; - } - - if (cur_arg.var_num >= *var_count) { - *var_count = cur_arg.var_num + 1; - } - if (is_optional) { - cur_arg.exist_var_num = static_cast(try_parse_int()); - cur_arg.exist_var_bit = static_cast(try_parse_int()); - } else { - cur_arg.exist_var_num = -1; - cur_arg.exist_var_bit = 0; - } - cur_arg.type = read_type_expr(var_count); - if (/*cur_arg.var_num < 0 && cur_arg.exist_var_num < 0 && */ (cur_arg.type->flags & FLAG_NOVAR)) { - cur_arg.flags |= FLAG_NOVAR; - } - - args[i] = cur_arg; - } - return args; -} - -tl_combinator *tl_config_parser::read_combinator() { - std::int32_t t = try_parse_int(); - if (t != TLS_COMBINATOR) { - std::fprintf(stderr, "Wrong tls_combinator magic %d\n", static_cast(t)); - std::abort(); - } - - tl_combinator *combinator = store(std::make_unique()); - combinator->id = try_parse_int(); - combinator->name = try_parse_string(); - combinator->type_id = try_parse_int(); - combinator->var_count = 0; - - std::int32_t left_type = try_parse_int(); - if (left_type == TLS_COMBINATOR_LEFT) { - combinator->args = read_args_list(&combinator->var_count); - } else { - if (left_type != TLS_COMBINATOR_LEFT_BUILTIN) { - std::fprintf(stderr, "Wrong tls_combinator_left magic %d\n", static_cast(left_type)); - std::abort(); - } - } - - std::int32_t right_ver = try_parse_int(); - if (right_ver != TLS_COMBINATOR_RIGHT_V2) { - std::fprintf(stderr, "Wrong tls_combinator_right magic %d\n", static_cast(right_ver)); - std::abort(); - } - combinator->result = read_type_expr(&combinator->var_count); - - return combinator; -} - -tl_type *tl_config_parser::read_type() { - std::int32_t t = try_parse_int(); - if (t != TLS_TYPE) { - std::fprintf(stderr, "Wrong tls_type magic %d\n", t); - std::abort(); - } - - tl_type *type = store(std::make_unique()); - type->id = try_parse_int(); - type->name = try_parse_string(); - type->constructors_num = static_cast(try_parse_int()); - type->constructors.reserve(type->constructors_num); - type->flags = try_parse_int(); - type->flags &= ~(1 | 8 | 16 | 1024); - if (type->flags != 0) { - std::fprintf(stderr, "Type %s has non-zero flags: %d\n", type->name.c_str(), static_cast(type->flags)); - } - type->arity = static_cast(try_parse_int()); - - try_parse_long(); // unused - return type; -} - -tl_config tl_config_parser::parse_config() { - schema_version = get_schema_version(try_parse_int()); - if (schema_version < 2) { - std::fprintf(stderr, "Unsupported tl-schema version %d\n", static_cast(schema_version)); - std::abort(); - } - - try_parse_int(); // date - try_parse_int(); // version - - std::int32_t types_n = try_parse_int(); - std::size_t constructors_total = 0; - for (std::int32_t i = 0; i < types_n; i++) { - tl_type *type = read_type(); - config.add_type(type); - constructors_total += type->constructors_num; - } - - std::int32_t constructors_n = try_parse_int(); - assert(static_cast(constructors_n) == constructors_total); - for (std::int32_t i = 0; i < constructors_n; i++) { - tl_combinator *constructor = read_combinator(); - config.get_type(constructor->type_id)->add_constructor(constructor); - } - - std::int32_t functions_n = try_parse_int(); - for (std::int32_t i = 0; i < functions_n; i++) { - config.add_function(read_combinator()); - } - p.fetch_end(); - try_parse(0); - - return config; -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.h deleted file mode 100644 index 2fe6469f..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_config.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "tl_core.h" -#include "tl_simple_parser.h" - -#include -#include -#include -#include -#include - -namespace td { -namespace tl { - -class tl_config { - std::vector types; - std::map id_to_type; - std::map name_to_type; - - std::vector functions; - std::map id_to_function; - std::map name_to_function; - - public: - void add_type(tl_type *type); - - tl_type *get_type(std::int32_t type_id) const; - - tl_type *get_type(const std::string &type_name); - - void add_function(tl_combinator *function); - - tl_combinator *get_function(std::int32_t function_id); - - tl_combinator *get_function(const std::string &function_name); - - std::size_t get_type_count() const; - - tl_type *get_type_by_num(std::size_t num) const; - - std::size_t get_function_count() const; - - tl_combinator *get_function_by_num(std::size_t num) const; -}; - -class tl_config_parser { - tl_simple_parser p; - int schema_version; - tl_config config; - - static int get_schema_version(std::int32_t version_id); - - tl_tree *read_num_const(); - tl_tree *read_num_var(int *var_count); - tl_tree *read_type_var(int *var_count); - tl_tree *read_array(int *var_count); - tl_tree *read_type(int *var_count); - tl_tree *read_type_expr(int *var_count); - tl_tree *read_nat_expr(int *var_count); - tl_tree *read_expr(int *var_count); - std::vector read_args_list(int *var_count); - - tl_combinator *read_combinator(); - tl_type *read_type(); - - template - T try_parse(const T &res) const; - - std::int32_t try_parse_int(); - std::int64_t try_parse_long(); - std::string try_parse_string(); - - public: - tl_config_parser(const char *s, std::size_t len) : p(s, len), schema_version(-1) { - } - - tl_config parse_config(); -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.cpp deleted file mode 100644 index 93aaf881..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_core.h" - -#include - -namespace td { -namespace tl { - -void tl_type::add_constructor(tl_combinator *new_constructor) { - constructors.push_back(new_constructor); - - assert(constructors.size() <= constructors_num); -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.h deleted file mode 100644 index f45db000..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_core.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include -#include - -namespace td { -namespace tl { - -const int NODE_TYPE_TYPE = 1; -const int NODE_TYPE_NAT_CONST = 2; -const int NODE_TYPE_VAR_TYPE = 3; -const int NODE_TYPE_VAR_NUM = 4; -const int NODE_TYPE_ARRAY = 5; - -const std::int32_t ID_VAR_NUM = 0x70659eff; -const std::int32_t ID_VAR_TYPE = 0x2cecf817; -const std::int32_t ID_INT = 0xa8509bda; -const std::int32_t ID_LONG = 0x22076cba; -const std::int32_t ID_DOUBLE = 0x2210c154; -const std::int32_t ID_STRING = 0xb5286e24; -const std::int32_t ID_VECTOR = 0x1cb5c415; -const std::int32_t ID_DICTIONARY = 0x1f4c618f; -const std::int32_t ID_MAYBE_TRUE = 0x3f9c8ef8; -const std::int32_t ID_MAYBE_FALSE = 0x27930a7b; -const std::int32_t ID_BOOL_FALSE = 0xbc799737; -const std::int32_t ID_BOOL_TRUE = 0x997275b5; - -const std::int32_t FLAG_OPT_VAR = (1 << 17); -const std::int32_t FLAG_EXCL = (1 << 18); -const std::int32_t FLAG_NOVAR = (1 << 21); -const std::int32_t FLAG_DEFAULT_CONSTRUCTOR = (1 << 25); -const std::int32_t FLAG_BARE = (1 << 0); -const std::int32_t FLAG_COMPLEX = (1 << 1); -const std::int32_t FLAGS_MASK = ((1 << 16) - 1); - -class tl_combinator; - -class tl_tree; - -class tl_type { - public: - std::int32_t id; - std::string name; - int arity; - std::int32_t flags; - int simple_constructors; - std::size_t constructors_num; - std::vector constructors; - - void add_constructor(tl_combinator *new_constructor); -}; - -class arg { - public: - std::string name; - std::int32_t flags; - int var_num; - int exist_var_num; - int exist_var_bit; - tl_tree *type; -}; - -class tl_combinator { - public: - std::int32_t id; - std::string name; - int var_count; - std::int32_t type_id; - std::vector args; - tl_tree *result; -}; - -class tl_tree { - public: - std::int32_t flags; - - explicit tl_tree(std::int32_t flags) : flags(flags) { - } - - virtual int get_type() const = 0; - - virtual ~tl_tree() { - } -}; - -class tl_tree_type : public tl_tree { - public: - tl_type *type; - std::vector children; - - tl_tree_type(std::int32_t flags, tl_type *type, int child_count) : tl_tree(flags), type(type), children(child_count) { - } - - virtual int get_type() const { - return NODE_TYPE_TYPE; - } -}; - -class tl_tree_nat_const : public tl_tree { - public: - int num; - - tl_tree_nat_const(std::int32_t flags, int num) : tl_tree(flags), num(num) { - } - - virtual int get_type() const { - return NODE_TYPE_NAT_CONST; - } -}; - -class tl_tree_var_type : public tl_tree { - public: - int var_num; - - tl_tree_var_type(std::int32_t flags, int var_num) : tl_tree(flags), var_num(var_num) { - } - - virtual int get_type() const { - return NODE_TYPE_VAR_TYPE; - } -}; - -class tl_tree_var_num : public tl_tree { - public: - int var_num; - int diff; - - tl_tree_var_num(std::int32_t flags, int var_num, int diff) : tl_tree(flags), var_num(var_num), diff(diff) { - } - - virtual int get_type() const { - return NODE_TYPE_VAR_NUM; - } -}; - -class tl_tree_array : public tl_tree { - public: - tl_tree *multiplicity; - std::vector args; - - tl_tree_array(std::int32_t flags, tl_tree *multiplicity, const std::vector &a) - : tl_tree(flags), multiplicity(multiplicity), args(a) { - } - - virtual int get_type() const { - return NODE_TYPE_ARRAY; - } -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.cpp deleted file mode 100644 index 1cda2222..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_file_outputer.h" - -#include - -namespace td { -namespace tl { - -void tl_file_outputer::append(const std::string &str) { - assert(f != NULL); - std::fprintf(f, "%s", str.c_str()); -} - -tl_file_outputer::tl_file_outputer() : f(NULL) { -} - -void tl_file_outputer::close() { - if (f) { - std::fclose(f); - } -} - -bool tl_file_outputer::open(const std::string &file_name) { - close(); - - f = std::fopen(file_name.c_str(), "w"); - - return (f != NULL); -} - -tl_file_outputer::~tl_file_outputer() { - close(); -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.h deleted file mode 100644 index 45694595..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_outputer.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "tl_outputer.h" - -#include -#include - -namespace td { -namespace tl { - -class tl_file_outputer : public tl_outputer { - FILE *f; - - void close(); - - public: - tl_file_outputer(); - - bool open(const std::string &file_name); - - virtual void append(const std::string &str); - - virtual ~tl_file_outputer(); -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.cpp deleted file mode 100644 index d604447e..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_file_utils.h" - -#include -#include - -namespace td { -namespace tl { - -std::string get_file_contents(const std::string &file_name, const std::string &mode) { - FILE *f = std::fopen(file_name.c_str(), mode.c_str()); - if (f == NULL) { - return std::string(); - } - - int fseek_res = std::fseek(f, 0, SEEK_END); - if (fseek_res != 0) { - std::fprintf(stderr, "Can't seek to the end of the file \"%s\"", file_name.c_str()); - std::abort(); - } - long size_long = std::ftell(f); - if (size_long < 0 || size_long >= (1 << 25)) { - std::fprintf(stderr, "Wrong file \"%s\" has wrong size = %ld", file_name.c_str(), size_long); - std::abort(); - } - std::size_t size = static_cast(size_long); - - std::string result(size, ' '); - if (size != 0) { - std::rewind(f); - std::size_t fread_res = std::fread(&result[0], size, 1, f); - if (fread_res != 1) { - std::fprintf(stderr, "Can't read file \"%s\"", file_name.c_str()); - std::abort(); - } - } - std::fclose(f); - - return result; -} - -bool put_file_contents(const std::string &file_name, const std::string &mode, const std::string &contents) { - FILE *f = std::fopen(file_name.c_str(), mode.c_str()); - if (f == NULL) { - std::fprintf(stderr, "Can't open file \"%s\"\n", file_name.c_str()); - return false; - } - - std::size_t fwrite_res = std::fwrite(contents.c_str(), contents.size(), 1, f); - if (fwrite_res != 1) { - std::fclose(f); - return false; - } - if (std::fclose(f) != 0) { - return false; - } - return true; -} - -std::string remove_documentation(const std::string &str) { - std::size_t line_begin = 0; - std::string result; - bool inside_documentation = false; - while (line_begin < str.size()) { - std::size_t line_end = str.find('\n', line_begin); - if (line_end == std::string::npos) { - line_end = str.size() - 1; - } - std::string line = str.substr(line_begin, line_end - line_begin + 1); - line_begin = line_end + 1; - - std::size_t pos = line.find_first_not_of(' '); - if (pos != std::string::npos && ((line[pos] == '/' && line[pos + 1] == '/' && line[pos + 2] == '/') || - (line[pos] == '/' && line[pos + 1] == '*' && line[pos + 2] == '*') || - (inside_documentation && line[pos] == '*'))) { - inside_documentation = !(line[pos] == '/' && line[pos + 1] == '/' && line[pos + 2] == '/') && - !(line[pos] == '*' && line[pos + 1] == '/'); - continue; - } - - inside_documentation = false; - result += line; - } - return result; -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.h deleted file mode 100644 index 44782ae8..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_file_utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include - -namespace td { -namespace tl { - -std::string get_file_contents(const std::string &file_name, const std::string &mode); - -bool put_file_contents(const std::string &file_name, const std::string &mode, const std::string &contents); - -std::string remove_documentation(const std::string &str); - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.cpp deleted file mode 100644 index 9e149aae..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.cpp +++ /dev/null @@ -1,856 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_generate.h" - -#include "tl_config.h" -#include "tl_core.h" -#include "tl_file_utils.h" -#include "tl_outputer.h" -#include "tl_string_outputer.h" -#include "tl_writer.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace td { -namespace tl { - -static bool is_reachable_for_parser(int parser_type, const std::string &name, - const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - TL_writer::Mode mode = w.get_parser_mode(parser_type); - if (mode == TL_writer::Client) { - return result_types.count(name) > 0; - } - if (mode == TL_writer::Server) { - return request_types.count(name) > 0; - } - return true; -} - -static bool is_reachable_for_storer(int storer_type, const std::string &name, - const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - TL_writer::Mode mode = w.get_storer_mode(storer_type); - if (mode == TL_writer::Client) { - return request_types.count(name) > 0; - } - if (mode == TL_writer::Server) { - return result_types.count(name) > 0; - } - return true; -} - -static void write_class_constructor(tl_outputer &out, const tl_combinator *t, const std::string &class_name, - bool is_default, const TL_writer &w) { - // std::fprintf(stderr, "Gen constructor %s\n", class_name.c_str()); - int fields_num = 0; - for (std::size_t i = 0; i < t->args.size(); i++) { - fields_num += !w.gen_constructor_parameter(0, class_name, t->args[i], is_default).empty(); - } - - out.append(w.gen_constructor_begin(fields_num, class_name, is_default)); - int field_num = 0; - for (std::size_t i = 0; i < t->args.size(); i++) { - std::string parameter_init = w.gen_constructor_parameter(field_num, class_name, t->args[i], is_default); - if (parameter_init.size()) { - out.append(parameter_init); - field_num++; - } - } - assert(field_num == fields_num); - - field_num = 0; - for (std::size_t i = 0; i < t->args.size(); i++) { - std::string field_init = w.gen_constructor_field_init(field_num, class_name, t->args[i], is_default); - if (field_init.size()) { - out.append(field_init); - field_num++; - } - } - - out.append(w.gen_constructor_end(t, field_num, is_default)); -} - -static void write_function_fetch(tl_outputer &out, const std::string &parser_name, const tl_combinator *t, - const std::string &class_name, const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - // std::fprintf(stderr, "Write function fetch %s\n", class_name.c_str()); - std::vector vars(t->var_count); - int parser_type = w.get_parser_type(t, parser_name); - - if (!is_reachable_for_parser(parser_type, t->name, request_types, result_types, w)) { - return; - } - - out.append(w.gen_fetch_function_begin(parser_name, class_name, class_name, 0, vars, parser_type)); - out.append(w.gen_vars(t, NULL, vars)); - int field_num = 0; - for (std::size_t i = 0; i < t->args.size(); i++) { - std::string field_fetch = w.gen_field_fetch(field_num, t->args[i], vars, false, parser_type); - if (field_fetch.size()) { - out.append(field_fetch); - field_num++; - } - } - - out.append(w.gen_fetch_function_end(false, field_num, vars, parser_type)); -} - -static void write_function_store(tl_outputer &out, const std::string &storer_name, const tl_combinator *t, - const std::string &class_name, std::vector &vars, - const std::set &request_types, const std::set &result_types, - const TL_writer &w) { - // std::fprintf(stderr, "Write function store %s\n", class_name.c_str()); - int storer_type = w.get_storer_type(t, storer_name); - - if (!is_reachable_for_storer(storer_type, t->name, request_types, result_types, w)) { - return; - } - - out.append(w.gen_store_function_begin(storer_name, class_name, 0, vars, storer_type)); - out.append(w.gen_constructor_id_store(t->id, storer_type)); - for (std::size_t i = 0; i < t->args.size(); i++) { - out.append(w.gen_field_store(t->args[i], vars, false, storer_type)); - } - - out.append(w.gen_store_function_end(vars, storer_type)); -} - -static void write_function_result_fetch(tl_outputer &out, const std::string &parser_name, const tl_combinator *t, - const std::string &class_name, const tl_tree *result, - const std::vector &vars, const TL_writer &w) { - // std::fprintf(stderr, "Write function result fetch %s\n", class_name.c_str()); - int parser_type = w.get_parser_type(t, parser_name); - - out.append(w.gen_fetch_function_result_begin(parser_name, class_name, result)); - - if (result->get_type() == NODE_TYPE_VAR_TYPE) { - const tl_tree_var_type *result_var_type = static_cast(result); - - for (std::size_t i = 0; i < t->args.size(); i++) { - const arg &a = t->args[i]; - - int arg_type = a.type->get_type(); - if (arg_type == NODE_TYPE_VAR_TYPE) { - const tl_tree_var_type *tree_var_type = static_cast(a.type); - assert(a.flags & FLAG_EXCL); - assert(tree_var_type->var_num >= 0); - if (tree_var_type->var_num == result_var_type->var_num) { - out.append(w.gen_var_type_fetch(a)); - } - } - } - } else { - assert(result->get_type() == NODE_TYPE_TYPE); - const tl_tree_type *result_type = static_cast(result); - out.append(w.gen_type_fetch("", result_type, vars, parser_type)); - } - - out.append(w.gen_fetch_function_result_end()); - - out.append(w.gen_fetch_function_result_any_begin(parser_name, class_name, false)); - out.append(w.gen_fetch_function_result_any_end(false)); -} - -static void write_constructor_fetch(tl_outputer &out, const std::string &parser_name, const tl_combinator *t, - const std::string &class_name, const std::string &parent_class_name, - const tl_tree_type *result_type, bool is_flat, - const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - std::vector vars(t->var_count); - - int parser_type = w.get_parser_type(t, parser_name); - - if (!is_reachable_for_parser(parser_type, t->name, request_types, result_types, w)) { - return; - } - - out.append(w.gen_fetch_function_begin(parser_name, class_name, parent_class_name, - static_cast(result_type->children.size()), vars, parser_type)); - out.append(w.gen_vars(t, result_type, vars)); - out.append(w.gen_uni(result_type, vars, true)); - int field_num = 0; - for (std::size_t i = 0; i < t->args.size(); i++) { - std::string field_fetch = w.gen_field_fetch(field_num, t->args[i], vars, is_flat, parser_type); - if (field_fetch.size()) { - out.append(field_fetch); - field_num++; - } - } - - out.append(w.gen_fetch_function_end(class_name != parent_class_name, field_num, vars, parser_type)); -} - -static void write_constructor_store(tl_outputer &out, const std::string &storer_name, const tl_combinator *t, - const std::string &class_name, const tl_tree_type *result_type, bool is_flat, - const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - std::vector vars(t->var_count); - int storer_type = w.get_storer_type(t, storer_name); - - if (!is_reachable_for_storer(storer_type, t->name, request_types, result_types, w)) { - return; - } - - out.append(w.gen_store_function_begin(storer_name, class_name, static_cast(result_type->children.size()), vars, - storer_type)); - out.append(w.gen_vars(t, result_type, vars)); - out.append(w.gen_uni(result_type, vars, false)); - for (std::size_t i = 0; i < t->args.size(); i++) { - // std::fprintf(stderr, "%s: %s\n", result_type->type->name.c_str(), t->name.c_str()); - out.append(w.gen_field_store(t->args[i], vars, is_flat, storer_type)); - } - - out.append(w.gen_store_function_end(vars, storer_type)); -} - -static int gen_field_definitions(tl_outputer &out, const tl_combinator *t, const std::string &class_name, - const TL_writer &w) { - int required_args = 0; - - for (std::size_t i = 0; i < t->args.size(); i++) { - const arg &a = t->args[i]; - - assert(-1 <= a.var_num && a.var_num < t->var_count); - - required_args += !(a.flags & FLAG_OPT_VAR); - - if (a.flags & FLAG_OPT_VAR) { - // continue; - } - - std::string type_name = w.gen_field_type(a); - if (type_name.size()) { - out.append(w.gen_field_definition(class_name, type_name, w.gen_field_name(a.name))); - } - } - - return required_args; -} - -static void write_function(tl_outputer &out, const tl_combinator *t, const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - assert(w.is_combinator_supported(t)); - - std::string class_name = w.gen_class_name(t->name); - - out.append(w.gen_class_begin(class_name, w.gen_base_function_class_name(), false)); - - int required_args = gen_field_definitions(out, t, class_name, w); - out.append(w.gen_flags_definitions(t)); - - std::vector vars(t->var_count); - out.append(w.gen_function_vars(t, vars)); - - write_class_constructor(out, t, class_name, true, w); - if (required_args) { - write_class_constructor(out, t, class_name, false, w); - } - - out.append(w.gen_get_id(class_name, t->id, false)); - - out.append(w.gen_function_result_type(t->result)); - - // PARSER - std::vector parsers = w.get_parsers(); - for (std::size_t i = 0; i < parsers.size(); i++) { - write_function_fetch(out, parsers[i], t, class_name, request_types, result_types, w); - } - - // STORER - std::vector storers = w.get_storers(); - for (std::size_t i = 0; i < storers.size(); i++) { - write_function_store(out, storers[i], t, class_name, vars, request_types, result_types, w); - } - - // PARSE RESULT - for (std::size_t i = 0; i < parsers.size(); i++) { - if (w.get_parser_mode(-1) == TL_writer::Server) { - continue; - } - - write_function_result_fetch(out, parsers[i], t, class_name, t->result, vars, w); - } - - // ADDITIONAL FUNCTIONS - std::vector additional_functions = w.get_additional_functions(); - for (std::size_t i = 0; i < additional_functions.size(); i++) { - out.append(w.gen_additional_function(additional_functions[i], t, true)); - } - - out.append(w.gen_class_end()); -} - -static void write_constructor(tl_outputer &out, const tl_combinator *t, const std::string &base_class, - const std::string &parent_class, bool is_proxy, - const std::set &request_types, const std::set &result_types, - const TL_writer &w) { - assert(w.is_combinator_supported(t)); - - std::string class_name = w.gen_class_name(t->name); - - out.append(w.gen_class_begin(class_name, base_class, is_proxy)); - int required_args = gen_field_definitions(out, t, class_name, w); - out.append(w.gen_flags_definitions(t)); - - write_class_constructor(out, t, class_name, true, w); - if (required_args) { - write_class_constructor(out, t, class_name, false, w); - } - - out.append(w.gen_get_id(class_name, t->id, false)); - - // PARSER - assert(t->result->get_type() == NODE_TYPE_TYPE); - const tl_tree_type *result_type = static_cast(t->result); - - std::vector parsers = w.get_parsers(); - for (std::size_t i = 0; i < parsers.size(); i++) { - write_constructor_fetch(out, parsers[i], t, class_name, parent_class, result_type, - required_args == 1 && result_type->type->simple_constructors == 1, request_types, - result_types, w); - } - - // STORER - std::vector storers = w.get_storers(); - for (std::size_t i = 0; i < storers.size(); i++) { - write_constructor_store(out, storers[i], t, class_name, result_type, - required_args == 1 && result_type->type->simple_constructors == 1, request_types, - result_types, w); - } - - // ADDITIONAL FUNCTIONS - std::vector additional_functions = w.get_additional_functions(); - for (std::size_t i = 0; i < additional_functions.size(); i++) { - out.append(w.gen_additional_function(additional_functions[i], t, false)); - } - - out.append(w.gen_class_end()); -} - -void write_class(tl_outputer &out, const tl_type *t, const std::set &request_types, - const std::set &result_types, const TL_writer &w) { - assert(t->constructors_num > 0); - assert(!w.is_built_in_simple_type(t->name)); - assert(!w.is_built_in_complex_type(t->name)); - assert(!(t->flags & FLAG_COMPLEX)); - - assert(t->arity >= 0); - assert(t->simple_constructors > 0); - assert(t->flags == 0); - - const std::string base_class = w.gen_base_type_class_name(t->arity); - const std::string class_name = w.gen_class_name(t->name); - - std::vector empty_vars; - bool optimize_one_constructor = (t->simple_constructors == 1); - if (!optimize_one_constructor) { - out.append(w.gen_class_begin(class_name, base_class, true)); - - out.append(w.gen_get_id(class_name, 0, true)); - - std::vector parsers = w.get_parsers(); - for (std::size_t i = 0; i < parsers.size(); i++) { - if (!is_reachable_for_parser(-1, t->name, request_types, result_types, w)) { - continue; - } - - out.append(w.gen_fetch_function_begin(parsers[i], class_name, class_name, t->arity, empty_vars, -1)); - out.append(w.gen_fetch_switch_begin()); - for (std::size_t j = 0; j < t->constructors_num; j++) { - if (w.is_combinator_supported(t->constructors[j])) { - out.append(w.gen_fetch_switch_case(t->constructors[j], t->arity)); - } - } - - out.append(w.gen_fetch_switch_end()); - out.append(w.gen_fetch_function_end(false, -1, empty_vars, -1)); - } - - std::vector storers = w.get_storers(); - for (std::size_t i = 0; i < storers.size(); i++) { - if (!is_reachable_for_storer(-1, t->name, request_types, result_types, w)) { - continue; - } - - out.append(w.gen_store_function_begin(storers[i], class_name, t->arity, empty_vars, -1)); - out.append(w.gen_store_function_end(empty_vars, -1)); - } - - std::vector additional_functions = w.get_additional_functions(); - for (std::size_t i = 0; i < additional_functions.size(); i++) { - out.append(w.gen_additional_proxy_function_begin(additional_functions[i], t, class_name, t->arity, false)); - for (std::size_t j = 0; j < t->constructors_num; j++) { - if (w.is_combinator_supported(t->constructors[j])) { - out.append( - w.gen_additional_proxy_function_case(additional_functions[i], t, t->constructors[j], t->arity, false)); - } - } - - out.append(w.gen_additional_proxy_function_end(additional_functions[i], t, false)); - } - - out.append(w.gen_class_end()); - } - - int written_constructors = 0; - for (std::size_t i = 0; i < t->constructors_num; i++) { - if (w.is_combinator_supported(t->constructors[i])) { - if (optimize_one_constructor) { - write_constructor(out, t->constructors[i], base_class, w.gen_class_name(t->constructors[i]->name), false, - request_types, result_types, w); - out.append(w.gen_class_alias(w.gen_class_name(t->constructors[i]->name), class_name)); - } else { - write_constructor(out, t->constructors[i], class_name, class_name, false, request_types, result_types, w); - } - written_constructors++; - } else { - std::fprintf(stderr, "Skip complex constructor %s of %s\n", t->constructors[i]->name.c_str(), t->name.c_str()); - } - } - assert(written_constructors == t->simple_constructors); -} - -static void dfs_type(const tl_type *t, std::set &found, const TL_writer &w); - -static void dfs_tree(const tl_tree *t, std::set &found, const TL_writer &w) { - int type = t->get_type(); - - if (type == NODE_TYPE_ARRAY) { - const tl_tree_array *arr = static_cast(t); - for (std::size_t i = 0; i < arr->args.size(); i++) { - dfs_tree(arr->args[i].type, found, w); - } - } else if (type == NODE_TYPE_TYPE) { - const tl_tree_type *tree_type = static_cast(t); - dfs_type(tree_type->type, found, w); - for (std::size_t i = 0; i < tree_type->children.size(); i++) { - dfs_tree(tree_type->children[i], found, w); - } - } else { - assert(type == NODE_TYPE_VAR_TYPE); - } -} - -static void dfs_combinator(const tl_combinator *constructor, std::set &found, const TL_writer &w) { - if (!w.is_combinator_supported(constructor)) { - return; - } - - if (!found.insert(constructor->name).second) { - return; - } - - for (std::size_t i = 0; i < constructor->args.size(); i++) { - dfs_tree(constructor->args[i].type, found, w); - } -} - -static void dfs_type(const tl_type *t, std::set &found, const TL_writer &w) { - if (!found.insert(t->name).second) { - return; - } - - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || w.is_built_in_complex_type(t->name)) { - return; - } - - assert(!(t->flags & FLAG_COMPLEX)); - - for (std::size_t i = 0; i < t->constructors_num; i++) { - dfs_combinator(t->constructors[i], found, w); - } -} - -void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) { - out.append(w.gen_output_begin()); - - std::size_t types_n = config.get_type_count(); - std::size_t functions_n = config.get_function_count(); - - bool found_complex = false; - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - assert(t->constructors_num == t->constructors.size()); - if (t->constructors_num == 0) { // built-in dummy types - if (t->name == "Type") { - assert(t->id == ID_VAR_TYPE); - t->flags |= FLAG_COMPLEX; - found_complex = true; - } - continue; - } - - for (std::size_t j = 0; j < t->constructors_num; j++) { - tl_combinator *constructor = t->constructors[j]; - assert(constructor->type_id == t->id); - assert(constructor->result->get_type() == NODE_TYPE_TYPE); - assert(static_cast(constructor->result)->type == t); - assert(static_cast(constructor->result)->children.size() == - static_cast(t->arity)); - assert(static_cast(constructor->result)->flags == (t->arity > 0 ? 0 : FLAG_NOVAR)); - - for (std::size_t k = 0; k < constructor->args.size(); k++) { - const arg &a = constructor->args[k]; - - assert(-1 <= a.var_num && a.var_num <= constructor->var_count); - - int arg_type = a.type->get_type(); - assert(arg_type == NODE_TYPE_TYPE || arg_type == NODE_TYPE_VAR_TYPE || arg_type == NODE_TYPE_ARRAY); - if (a.var_num >= 0) { - assert(arg_type == NODE_TYPE_TYPE); - assert(static_cast(a.type)->type->id == ID_VAR_NUM || - static_cast(a.type)->type->id == ID_VAR_TYPE); - } - - if (arg_type == NODE_TYPE_ARRAY) { - const tl_tree_array *arr = static_cast(a.type); - assert(arr->multiplicity->get_type() == NODE_TYPE_NAT_CONST || - arr->multiplicity->get_type() == NODE_TYPE_VAR_NUM); - for (std::size_t l = 0; l < arr->args.size(); l++) { - const arg &b = arr->args[l]; - int b_arg_type = b.type->get_type(); - if (b_arg_type == NODE_TYPE_VAR_TYPE || b_arg_type == NODE_TYPE_ARRAY || b.var_num != -1 || - b.exist_var_num != -1) { - if (!w.is_built_in_complex_type(t->name)) { - t->flags |= FLAG_COMPLEX; - found_complex = true; - } - } else { - assert(b_arg_type == NODE_TYPE_TYPE); - } - assert(b.flags == FLAG_NOVAR || b.flags == 0); - } - } - } - } - - for (int i = 0; i < t->arity; i++) { - int main_type = static_cast(t->constructors[0]->result)->children[i]->get_type(); - for (std::size_t j = 1; j < t->constructors_num; j++) { - assert(static_cast(t->constructors[j]->result)->children[i]->get_type() == main_type); - } - assert(main_type == NODE_TYPE_VAR_TYPE || main_type == NODE_TYPE_VAR_NUM); - if (main_type == NODE_TYPE_VAR_TYPE) { - if (!w.is_built_in_complex_type(t->name)) { - t->flags |= FLAG_COMPLEX; - found_complex = true; - } - } - } - } - - while (found_complex) { - found_complex = false; - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_complex_type(t->name)) { // built-in dummy or complex types - continue; - } - if (t->flags & FLAG_COMPLEX) { // already complex - continue; - } - - t->simple_constructors = 0; - for (std::size_t i = 0; i < t->constructors_num; i++) { - t->simple_constructors += w.is_combinator_supported(t->constructors[i]); - } - if (t->simple_constructors == 0) { - t->flags |= FLAG_COMPLEX; - found_complex = true; - // std::fprintf(stderr, "Found complex %s\n", t->name.c_str()); - } - } - } - - std::set request_types; - std::set result_types; - for (std::size_t function = 0; function < functions_n; function++) { - const tl_combinator *t = config.get_function_by_num(function); - dfs_combinator(t, request_types, w); - dfs_tree(t->result, result_types, w); - } - - // write forward declarations - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || w.is_built_in_complex_type(t->name) || - (t->flags & FLAG_COMPLEX)) { // built-in or complex types - continue; - } - - assert(t->flags == 0); - - if (t->simple_constructors != 1) { - out.append(w.gen_forward_class_declaration(w.gen_class_name(t->name), true)); - } else { - for (std::size_t i = 0; i < t->constructors_num; i++) { - if (w.is_combinator_supported(t->constructors[i])) { - out.append(w.gen_forward_class_declaration(w.gen_class_name(t->constructors[i]->name), false)); - } - } - } - } - for (int i = 0; i <= w.get_max_arity(); i++) { - out.append(w.gen_forward_class_declaration(w.gen_base_type_class_name(i), true)); - } - - for (std::size_t function = 0; function < functions_n; function++) { - tl_combinator *t = config.get_function_by_num(function); - if (!w.is_combinator_supported(t)) { - continue; - } - - // out.append(w.gen_forward_class_declaration(w.gen_class_name(t->name), false)); - } - // out.append(w.gen_forward_class_declaration(w.gen_base_function_class_name(), true)); - - // write base classes - std::vector empty_vars; - for (int i = 0; i <= w.get_max_arity(); i++) { - out.append(w.gen_class_begin(w.gen_base_type_class_name(i), w.gen_base_tl_class_name(), true)); - - out.append(w.gen_get_id(w.gen_base_type_class_name(i), 0, true)); - - std::vector parsers = w.get_parsers(); - for (std::size_t j = 0; j < parsers.size(); j++) { - int case_count = 0; - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || w.is_built_in_complex_type(t->name) || - (t->flags & FLAG_COMPLEX)) { // built-in or complex types - continue; - } - if (t->arity != i) { // additional condition - continue; - } - - for (std::size_t k = 0; k < t->constructors_num; k++) { - if (w.is_combinator_supported(t->constructors[k]) && - is_reachable_for_parser(-1, t->constructors[k]->name, request_types, result_types, w)) { - case_count++; - } - } - } - - if (case_count == 0) { - continue; - } - - out.append(w.gen_fetch_function_begin(parsers[j], w.gen_base_type_class_name(i), w.gen_base_type_class_name(i), i, - empty_vars, -1)); - out.append(w.gen_fetch_switch_begin()); - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || w.is_built_in_complex_type(t->name) || - (t->flags & FLAG_COMPLEX)) { // built-in or complex types - continue; - } - if (t->arity != i) { // additional condition - continue; - } - - for (std::size_t k = 0; k < t->constructors_num; k++) { - if (w.is_combinator_supported(t->constructors[k]) && - is_reachable_for_parser(-1, t->constructors[k]->name, request_types, result_types, w)) { - out.append(w.gen_fetch_switch_case(t->constructors[k], i)); - } - } - } - out.append(w.gen_fetch_switch_end()); - out.append(w.gen_fetch_function_end(false, -1, empty_vars, -1)); - } - - std::vector additional_functions = w.get_additional_functions(); - for (std::size_t j = 0; j < additional_functions.size(); j++) { - out.append(w.gen_additional_proxy_function_begin(additional_functions[j], NULL, w.gen_base_type_class_name(i), i, - false)); - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || w.is_built_in_complex_type(t->name) || - (t->flags & FLAG_COMPLEX)) { // built-in or complex types - continue; - } - if (t->arity != i) { // additional condition - continue; - } - - int function_type = w.get_additional_function_type(additional_functions[j]); - if ((function_type & 1) && t->simple_constructors != 1) { - out.append(w.gen_additional_proxy_function_case(additional_functions[j], NULL, w.gen_class_name(t->name), i)); - } - if ((function_type & 2) || ((function_type & 1) && t->simple_constructors == 1)) { - for (std::size_t k = 0; k < t->constructors_num; k++) { - if (w.is_combinator_supported(t->constructors[k])) { - out.append( - w.gen_additional_proxy_function_case(additional_functions[j], NULL, t->constructors[k], i, false)); - } - } - } - } - - out.append(w.gen_additional_proxy_function_end(additional_functions[j], NULL, false)); - } - - std::vector storers = w.get_storers(); - for (std::size_t j = 0; j < storers.size(); j++) { - out.append(w.gen_store_function_begin(storers[j], w.gen_base_type_class_name(i), i, empty_vars, -1)); - out.append(w.gen_store_function_end(empty_vars, -1)); - } - - out.append(w.gen_class_end()); - } - - { - out.append(w.gen_class_begin(w.gen_base_function_class_name(), w.gen_base_tl_class_name(), true)); - - out.append(w.gen_get_id(w.gen_base_function_class_name(), 0, true)); - - std::vector parsers = w.get_parsers(); - for (std::size_t j = 0; j < parsers.size(); j++) { - if (w.get_parser_mode(-1) == TL_writer::Client) { - continue; - } - - out.append(w.gen_fetch_function_begin(parsers[j], w.gen_base_function_class_name(), - w.gen_base_function_class_name(), 0, empty_vars, -1)); - out.append(w.gen_fetch_switch_begin()); - for (std::size_t function = 0; function < functions_n; function++) { - tl_combinator *t = config.get_function_by_num(function); - - if (w.is_combinator_supported(t)) { - out.append(w.gen_fetch_switch_case(t, 0)); - } - } - out.append(w.gen_fetch_switch_end()); - out.append(w.gen_fetch_function_end(false, -1, empty_vars, -1)); - } - - std::vector storers = w.get_storers(); - for (std::size_t j = 0; j < storers.size(); j++) { - if (w.get_storer_mode(-1) == TL_writer::Server) { - continue; - } - - out.append(w.gen_store_function_begin(storers[j], w.gen_base_function_class_name(), 0, empty_vars, -1)); - out.append(w.gen_store_function_end(empty_vars, -1)); - } - - for (std::size_t j = 0; j < parsers.size(); j++) { - if (w.get_parser_mode(-1) == TL_writer::Server) { - continue; - } - - out.append(w.gen_fetch_function_result_any_begin(parsers[j], w.gen_base_function_class_name(), true)); - out.append(w.gen_fetch_function_result_any_end(true)); - } - - std::vector additional_functions = w.get_additional_functions(); - for (std::size_t j = 0; j < additional_functions.size(); j++) { - out.append(w.gen_additional_proxy_function_begin(additional_functions[j], NULL, w.gen_base_function_class_name(), - 0, true)); - for (std::size_t function = 0; function < functions_n; function++) { - tl_combinator *t = config.get_function_by_num(function); - - if (w.is_combinator_supported(t)) { - out.append(w.gen_additional_proxy_function_case(additional_functions[j], NULL, t, 0, true)); - } - } - - out.append(w.gen_additional_proxy_function_end(additional_functions[j], NULL, true)); - } - - out.append(w.gen_class_end()); - } - - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || - w.is_built_in_complex_type(t->name)) { // built-in dummy or complex types - continue; - } - - if (t->flags & FLAG_COMPLEX) { - std::fprintf(stderr, "Can't generate class %s\n", t->name.c_str()); - continue; - } - - write_class(out, t, request_types, result_types, w); - } - - for (std::size_t function = 0; function < functions_n; function++) { - tl_combinator *t = config.get_function_by_num(function); - if (!w.is_combinator_supported(t)) { - // std::fprintf(stderr, "Function %s is too hard to store\n", t->name.c_str()); - continue; - } - - write_function(out, t, request_types, result_types, w); - } - out.append(w.gen_output_end()); - - for (std::size_t type = 0; type < types_n; type++) { - tl_type *t = config.get_type_by_num(type); - if (t->flags & FLAG_COMPLEX) { - t->flags &= ~FLAG_COMPLEX; // remove temporary flag - } - } -} - -tl_config read_tl_config_from_file(const std::string &file_name) { - std::string config = get_file_contents(file_name, "rb"); - if (config.empty()) { - std::fprintf(stderr, "Config file %s is empty\n", file_name.c_str()); - std::abort(); - } - if (config.size() % sizeof(std::int32_t) != 0) { - std::fprintf(stderr, "Config size = %d is not multiple of %d\n", static_cast(config.size()), - static_cast(sizeof(std::int32_t))); - std::abort(); - } - - tl_config_parser parser(config.c_str(), config.size()); - return parser.parse_config(); -} - -bool write_tl_to_file(const tl_config &config, const std::string &file_name, const TL_writer &w) { - tl_string_outputer out; - write_tl(config, out, w); - - auto old_file_contents = get_file_contents(file_name, "rb"); - if (!w.is_documentation_generated()) { - old_file_contents = remove_documentation(old_file_contents); - } - - if (old_file_contents != out.get_result()) { - std::fprintf(stderr, "Write tl to file %s\n", file_name.c_str()); - return put_file_contents(file_name, "wb", out.get_result()); - } - - return true; -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.h deleted file mode 100644 index 508c104f..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_generate.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "tl_config.h" -#include "tl_outputer.h" -#include "tl_writer.h" - -#include - -namespace td { -namespace tl { - -void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w); - -tl_config read_tl_config_from_file(const std::string &file_name); -bool write_tl_to_file(const tl_config &config, const std::string &file_name, const TL_writer &w); - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.cpp deleted file mode 100644 index 081fb311..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_outputer.h" - -namespace td { -namespace tl { - -tl_outputer::~tl_outputer() { -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.h deleted file mode 100644 index fc2fe6d4..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_outputer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include - -namespace td { -namespace tl { - -class tl_outputer { - public: - virtual void append(const std::string &str) = 0; - - virtual ~tl_outputer() = 0; -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple.h deleted file mode 100644 index 5a0af816..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/tl/tl_config.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace td { -namespace tl { -namespace simple { -// TL type is - -std::string gen_cpp_name(std::string name) { - for (std::size_t i = 0; i < name.size(); i++) { - if ((name[i] < '0' || '9' < name[i]) && (name[i] < 'a' || 'z' < name[i]) && (name[i] < 'A' || 'Z' < name[i])) { - name[i] = '_'; - } - } - assert(name.size() > 0); - assert(name[name.size() - 1] != '_'); - return name; -} - -std::string gen_cpp_field_name(std::string name) { - return gen_cpp_name(name) + "_"; -} - -struct CustomType; -struct Type { - enum { - Int32, - Int53, - Int64, - Double, - String, - Bytes, - SecureString, - SecureBytes, - Vector, - Bool, - Int128, - Int256, - True, - Object, - Function, - Custom - } type; - - // type == Custom - bool is_bare{false}; - const CustomType *custom{nullptr}; - - // type == Vector - const Type *vector_value_type{nullptr}; -}; - -struct Arg { - const Type *type; - std::string name; -}; - -struct Constructor { - std::string name; - std::int32_t id; - std::vector args; - const CustomType *type; -}; - -struct CustomType { - std::string name; - std::vector constructors; -}; - -struct Function { - std::string name; - std::int32_t id; - std::vector args; - const Type *type; -}; - -class Schema { - public: - explicit Schema(const tl_config &config) { - config_ = &config; - for (std::size_t type_num = 0, type_count = config.get_type_count(); type_num < type_count; type_num++) { - auto *from_type = config.get_type_by_num(type_num); - if (from_type->name == "Vector") { - continue; - } - auto *type = get_type(from_type); - if (type->type == Type::Custom) { - custom_types.push_back(type->custom); - } - } - for (std::size_t function_num = 0, function_count = config.get_function_count(); function_num < function_count; - function_num++) { - auto *from_function = config.get_function_by_num(function_num); - functions.push_back(get_function(from_function)); - } - } - - std::vector custom_types; - std::vector functions; - - private: - std::vector> functions_; - std::vector> constructors_; - std::vector> custom_types_; - std::vector> types_; - - const tl_config *config_{nullptr}; - std::map type_by_id; - std::map constructor_by_id; - std::map function_by_id; - - const Type *get_type(const tl_type *from_type) { - auto &type = type_by_id[from_type->id]; - if (!type) { - types_.push_back(std::make_unique()); - type = types_.back().get(); - - if (from_type->name == "Int32" || from_type->name == "Int") { - type->type = Type::Int32; - } else if (from_type->name == "Int53") { - type->type = Type::Int53; - } else if (from_type->name == "Int64" || from_type->name == "Long") { - type->type = Type::Int64; - } else if (from_type->name == "Double") { - type->type = Type::Double; - } else if (from_type->name == "String") { - type->type = Type::String; - } else if (from_type->name == "Bytes") { - type->type = Type::Bytes; - } else if (from_type->name == "SecureString") { - type->type = Type::SecureString; - } else if (from_type->name == "SecureBytes") { - type->type = Type::SecureBytes; - } else if (from_type->name == "Bool") { - type->type = Type::Bool; - } else if (from_type->name == "Int128") { - type->type = Type::Int128; - } else if (from_type->name == "Int256") { - type->type = Type::Int256; - } else if (from_type->name == "True") { - type->type = Type::True; - } else if (from_type->name == "Object") { - type->type = Type::Object; - } else if (from_type->name == "Function") { - type->type = Type::Function; - } else if (from_type->name == "Vector") { - assert(false); // unreachable - } else { - type->type = Type::Custom; - custom_types_.push_back(std::make_unique()); - auto *custom_type = custom_types_.back().get(); - type->custom = custom_type; - custom_type->name = from_type->name; - for (auto *constructor : from_type->constructors) { - custom_type->constructors.push_back(get_constructor(constructor)); - } - } - } - return type; - } - const CustomType *get_custom_type(const tl_type *from_type) { - auto *type = get_type(from_type); - assert(type->type == Type::Custom); - return type->custom; - } - - const Constructor *get_constructor(const tl_combinator *from) { - auto &constructor = constructor_by_id[from->id]; - if (!constructor) { - constructors_.push_back(std::make_unique()); - constructor = constructors_.back().get(); - constructor->id = from->id; - constructor->name = from->name; - constructor->type = get_custom_type(config_->get_type(from->type_id)); - for (auto &from_arg : from->args) { - Arg arg; - arg.name = from_arg.name; - arg.type = get_type(from_arg.type); - constructor->args.push_back(std::move(arg)); - } - } - return constructor; - } - const Function *get_function(const tl_combinator *from) { - auto &function = function_by_id[from->id]; - if (!function) { - functions_.push_back(std::make_unique()); - function = functions_.back().get(); - function->id = from->id; - function->name = from->name; - function->type = get_type(config_->get_type(from->type_id)); - for (auto &from_arg : from->args) { - Arg arg; - arg.name = from_arg.name; - arg.type = get_type(from_arg.type); - function->args.push_back(std::move(arg)); - } - } - return function; - } - const Type *get_type(const tl_tree *tree) { - assert(tree->get_type() == NODE_TYPE_TYPE); - auto *type_tree = static_cast(tree); - if (type_tree->type->name == "Vector") { - assert(type_tree->children.size() == 1); - types_.push_back(std::make_unique()); - auto *type = types_.back().get(); - type->type = Type::Vector; - type->vector_value_type = get_type(type_tree->children[0]); - return type; - } else { - assert(type_tree->children.empty()); - return get_type(type_tree->type); - } - } -}; - -} // namespace simple -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple_parser.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple_parser.h deleted file mode 100644 index 58518ba3..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_simple_parser.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include -#include - -namespace td { -namespace tl { - -class tl_simple_parser { - const char *data; - const char *data_begin; - std::size_t data_len; - const char *error; - std::size_t error_pos; - - void set_error(const char *error_message) { - if (error == NULL) { - assert(error_message != NULL); - error = error_message; - error_pos = static_cast(data - data_begin); - data = "\x00\x00\x00\x00\x00\x00\x00\x00"; - data_len = 0; - } else { - data = "\x00\x00\x00\x00\x00\x00\x00\x00"; - assert(data_len == 0); - } - } - - void check_len(const std::size_t len) { - if (data_len < len) { - set_error("Not enough data to read"); - } else { - data_len -= len; - } - } - - tl_simple_parser(const tl_simple_parser &other); - tl_simple_parser &operator=(const tl_simple_parser &other); - - public: - tl_simple_parser(const char *data, std::size_t data_len) - : data(data), data_begin(data), data_len(data_len), error(), error_pos() { - } - - const char *get_error() const { - return error; - } - - std::size_t get_error_pos() const { - return error_pos; - } - - std::int32_t fetch_int() { - check_len(sizeof(std::int32_t)); - std::int32_t result = *reinterpret_cast(data); - data += sizeof(std::int32_t); - return result; - } - - std::int64_t fetch_long() { - check_len(sizeof(std::int64_t)); - std::int64_t result; - std::memcpy(&result, data, sizeof(std::int64_t)); - data += sizeof(std::int64_t); - return result; - } - - std::string fetch_string() { - check_len(4); - int result_len = static_cast(data[0]); - if (result_len < 254) { - check_len((result_len >> 2) * 4); - std::string result(data + 1, result_len); - data += ((result_len >> 2) + 1) * 4; - return result; - } - - if (result_len == 254) { - result_len = static_cast(data[1]) + (static_cast(data[2]) << 8) + - (static_cast(data[3]) << 16); - check_len(((result_len + 3) >> 2) * 4); - std::string result(data + 4, result_len); - data += ((result_len + 7) >> 2) * 4; - return result; - } - - set_error("Can't fetch string, 255 found"); - return std::string(); - } - - void fetch_end() { - if (data_len) { - set_error("Too much data to fetch"); - } - } -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.cpp deleted file mode 100644 index 9faca7f7..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_string_outputer.h" - -namespace td { -namespace tl { - -void tl_string_outputer::append(const std::string &str) { - result += str; -} - -std::string tl_string_outputer::get_result() const { -#if defined(_WIN32) - std::string fixed_result; - for (std::size_t i = 0; i < result.size(); i++) { - if (result[i] == '\n') { - fixed_result += '\r'; - } - fixed_result += result[i]; - } - return fixed_result; -#else - return result; -#endif -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.h deleted file mode 100644 index 9c87c257..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_string_outputer.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "tl_outputer.h" - -#include - -namespace td { -namespace tl { - -class tl_string_outputer : public tl_outputer { - std::string result; - - public: - virtual void append(const std::string &str); - - std::string get_result() const; -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.cpp b/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.cpp deleted file mode 100644 index 5c672f26..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "tl_writer.h" - -#include "tl_core.h" - -#include -#include - -namespace td { -namespace tl { - -std::string TL_writer::int_to_string(int x) { - char buf[15]; - std::sprintf(buf, "%d", x); - return buf; -} - -bool TL_writer::is_alnum(char c) { - return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); -} - -char TL_writer::to_lower(char c) { - return 'A' <= c && c <= 'Z' ? static_cast(c - 'A' + 'a') : c; -} - -char TL_writer::to_upper(char c) { - return 'a' <= c && c <= 'z' ? static_cast(c - 'a' + 'A') : c; -} - -std::vector TL_writer::get_additional_functions() const { - return std::vector(); -} - -bool TL_writer::is_type_supported(const tl_tree_type *tree_type) const { - if (tree_type->type->flags & FLAG_COMPLEX) { - return false; - } - - for (std::size_t i = 0; i < tree_type->children.size(); i++) { - const tl_tree *child = tree_type->children[i]; - assert(child->get_type() == NODE_TYPE_TYPE || child->get_type() == NODE_TYPE_VAR_TYPE || - child->get_type() == NODE_TYPE_NAT_CONST || child->get_type() == NODE_TYPE_VAR_NUM); - - if (child->get_type() == NODE_TYPE_TYPE) { - if (!is_type_supported(static_cast(child))) { - return false; - } - } - if (child->get_type() == NODE_TYPE_VAR_TYPE) { - return false; // TODO - } - } - - return true; -} - -bool TL_writer::is_combinator_supported(const tl_combinator *constructor) const { - std::vector is_function_result(constructor->var_count); - for (std::size_t i = 0; i < constructor->args.size(); i++) { - const arg &a = constructor->args[i]; - - int arg_type = a.type->get_type(); - if (arg_type == NODE_TYPE_VAR_TYPE) { - const tl_tree_var_type *t = static_cast(a.type); - if (a.flags & FLAG_EXCL) { - assert(t->var_num >= 0); - if (is_function_result[t->var_num]) { - return false; // lazy to check that result of two function calls is the same - } - is_function_result[t->var_num] = true; - } else { - return false; // do not support generic types - } - } - } - - for (std::size_t i = 0; i < constructor->args.size(); i++) { - const arg &a = constructor->args[i]; - - int arg_type = a.type->get_type(); - if (a.var_num >= 0) { - assert(arg_type == NODE_TYPE_TYPE); - const tl_tree_type *a_type = static_cast(a.type); - if (a_type->type->id == ID_VAR_TYPE) { - assert(!(a_type->flags & FLAG_EXCL)); - if (!is_function_result[a.var_num]) { - assert(false); // not possible, otherwise type is an argument of a type, but all types with type arguments - // are already marked complex - return false; - } else { - continue; - } - } - } - - if (arg_type == NODE_TYPE_VAR_TYPE) { - continue; - } else if (arg_type == NODE_TYPE_TYPE) { - if (!is_type_supported(static_cast(a.type))) { - return false; - } - } else { - assert(arg_type == NODE_TYPE_ARRAY); - const tl_tree_array *arr = static_cast(a.type); - for (std::size_t j = 0; j < arr->args.size(); j++) { - const arg &b = arr->args[j]; - assert(b.type->get_type() == NODE_TYPE_TYPE && b.var_num == -1); - if (!is_type_supported(static_cast(b.type))) { - return false; - } - } - } - } - - tl_tree *result = constructor->result; - if (result->get_type() == NODE_TYPE_TYPE) { - if (!is_type_supported(static_cast(result))) { - return false; - } - } else { - assert(result->get_type() == NODE_TYPE_VAR_TYPE); - const tl_tree_var_type *t = static_cast(result); - return is_function_result[t->var_num]; - } - - return true; -} - -bool TL_writer::is_documentation_generated() const { - return false; -} - -std::string TL_writer::gen_main_class_name(const tl_type *t) const { - if (t->simple_constructors == 1) { - for (std::size_t i = 0; i < t->constructors_num; i++) { - if (is_combinator_supported(t->constructors[i])) { - return gen_class_name(t->constructors[i]->name); - } - } - } - - return gen_class_name(t->name); -} - -int TL_writer::get_parser_type(const tl_combinator *t, const std::string &parser_name) const { - return t->var_count > 0; -} - -int TL_writer::get_storer_type(const tl_combinator *t, const std::string &storer_name) const { - return 0; -} - -int TL_writer::get_additional_function_type(const std::string &additional_function_name) const { - return 0; -} - -TL_writer::Mode TL_writer::get_parser_mode(int type) const { - return All; -} - -TL_writer::Mode TL_writer::get_storer_mode(int type) const { - return All; -} - -std::string TL_writer::gen_field_type(const arg &a) const { - if (a.flags & FLAG_EXCL) { - assert(a.flags == FLAG_EXCL); - assert(a.type->get_type() == NODE_TYPE_VAR_TYPE); - - return gen_var_type_name(); - } - - assert(a.flags == FLAG_NOVAR || a.flags == 0 || a.flags == (FLAG_OPT_VAR | FLAG_NOVAR | FLAG_BARE)); - - if (a.type->get_type() == NODE_TYPE_TYPE) { - const tl_tree_type *arg_type = static_cast(a.type); - assert(arg_type->children.size() == static_cast(arg_type->type->arity)); - - if (arg_type->type->id == ID_VAR_TYPE) { - return std::string(); - } - - return gen_type_name(arg_type); - } else { - assert(a.flags == FLAG_NOVAR || a.flags == 0); - - assert(a.type->get_type() == NODE_TYPE_ARRAY); - const tl_tree_array *arg_array = static_cast(a.type); - assert((arg_array->flags & ~FLAG_NOVAR) == 0); - return gen_array_type_name(arg_array, a.name); - } -} - -std::string TL_writer::gen_additional_function(const std::string &function_name, const tl_combinator *t, - bool is_function) const { - assert(false); - return ""; -} - -std::string TL_writer::gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type, - const std::string &class_name, int arity, - bool is_function) const { - assert(false); - return ""; -} - -std::string TL_writer::gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type, - const std::string &class_name, int arity) const { - assert(false); - return ""; -} - -std::string TL_writer::gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type, - const tl_combinator *t, int arity, bool is_function) const { - assert(false); - return ""; -} - -std::string TL_writer::gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type, - bool is_function) const { - assert(false); - return ""; -} - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.h b/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.h deleted file mode 100644 index acdd77ae..00000000 --- a/submodules/ton/tonlib-src/tdtl/td/tl/tl_writer.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "tl_core.h" - -#include -#include -#include - -namespace td { -namespace tl { - -class var_description { - public: - int index; - bool is_stored; - bool is_type; - int parameter_num; - int function_arg_num; - - var_description() : index(-1), is_stored(false), is_type(false), parameter_num(-1), function_arg_num(-1) { - } -}; - -class TL_writer { - TL_writer(const TL_writer &other); - TL_writer &operator=(const TL_writer &other); - - protected: - const std::string tl_name; - - public: - enum Mode { All, Client, Server }; - - explicit TL_writer(const std::string &tl_name) : tl_name(tl_name) { - } - - virtual ~TL_writer() { - } - - virtual int get_max_arity() const = 0; - - static std::string int_to_string(int x); - static bool is_alnum(char c); - static char to_lower(char c); - static char to_upper(char c); - - virtual bool is_built_in_simple_type(const std::string &name) const = 0; - virtual bool is_built_in_complex_type(const std::string &name) const = 0; - virtual bool is_type_supported(const tl_tree_type *tree_type) const; - virtual bool is_type_bare(const tl_type *t) const = 0; - virtual bool is_combinator_supported(const tl_combinator *constructor) const; - virtual bool is_documentation_generated() const; - - virtual int get_parser_type(const tl_combinator *t, const std::string &parser_name) const; - virtual int get_storer_type(const tl_combinator *t, const std::string &storer_name) const; - virtual int get_additional_function_type(const std::string &additional_function_name) const; - virtual Mode get_parser_mode(int type) const; - virtual Mode get_storer_mode(int type) const; - virtual std::vector get_parsers() const = 0; - virtual std::vector get_storers() const = 0; - virtual std::vector get_additional_functions() const; - - virtual std::string gen_base_tl_class_name() const = 0; - virtual std::string gen_base_type_class_name(int arity) const = 0; - virtual std::string gen_base_function_class_name() const = 0; - virtual std::string gen_class_name(std::string name) const = 0; - virtual std::string gen_field_name(std::string name) const = 0; - virtual std::string gen_var_name(const var_description &desc) const = 0; - virtual std::string gen_parameter_name(int index) const = 0; - virtual std::string gen_main_class_name(const tl_type *t) const; - virtual std::string gen_field_type(const arg &a) const; - virtual std::string gen_type_name(const tl_tree_type *tree_type) const = 0; - virtual std::string gen_array_type_name(const tl_tree_array *arr, const std::string &field_name) const = 0; - virtual std::string gen_var_type_name() const = 0; - - virtual std::string gen_int_const(const tl_tree *tree_c, const std::vector &vars) const = 0; - - virtual std::string gen_output_begin() const = 0; - virtual std::string gen_output_end() const = 0; - - virtual std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const = 0; - - virtual std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, - bool is_proxy) const = 0; - virtual std::string gen_class_end() const = 0; - - virtual std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const = 0; - - virtual std::string gen_field_definition(const std::string &class_name, const std::string &type_name, - const std::string &field_name) const = 0; - virtual std::string gen_flags_definitions(const tl_combinator *t) const { - return ""; - } - - virtual std::string gen_vars(const tl_combinator *t, const tl_tree_type *result_type, - std::vector &vars) const = 0; - virtual std::string gen_function_vars(const tl_combinator *t, std::vector &vars) const = 0; - virtual std::string gen_uni(const tl_tree_type *result_type, std::vector &vars, - bool check_negative) const = 0; - virtual std::string gen_constructor_id_store(std::int32_t id, int storer_type) const = 0; - virtual std::string gen_field_fetch(int field_num, const arg &a, std::vector &vars, bool flat, - int parser_type) const = 0; - virtual std::string gen_field_store(const arg &a, std::vector &vars, bool flat, - int storer_type) const = 0; - virtual std::string gen_type_fetch(const std::string &field_name, const tl_tree_type *tree_type, - const std::vector &vars, int parser_type) const = 0; - virtual std::string gen_type_store(const std::string &field_name, const tl_tree_type *tree_type, - const std::vector &vars, int storer_type) const = 0; - virtual std::string gen_var_type_fetch(const arg &a) const = 0; - - virtual std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const = 0; - - virtual std::string gen_function_result_type(const tl_tree *result) const = 0; - - virtual std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name, - const std::string &parent_class_name, int arity, - std::vector &vars, int parser_type) const = 0; - virtual std::string gen_fetch_function_end(bool has_parent, int field_num, const std::vector &vars, - int parser_type) const = 0; - - virtual std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name, - const tl_tree *result) const = 0; - virtual std::string gen_fetch_function_result_end() const = 0; - virtual std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name, - bool is_proxy) const = 0; - virtual std::string gen_fetch_function_result_any_end(bool is_proxy) const = 0; - - virtual std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity, - std::vector &vars, int storer_type) const = 0; - virtual std::string gen_store_function_end(const std::vector &vars, int storer_type) const = 0; - - virtual std::string gen_fetch_switch_begin() const = 0; - virtual std::string gen_fetch_switch_case(const tl_combinator *t, int arity) const = 0; - virtual std::string gen_fetch_switch_end() const = 0; - - virtual std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const = 0; - virtual std::string gen_constructor_parameter(int field_num, const std::string &class_name, const arg &a, - bool is_default) const = 0; - virtual std::string gen_constructor_field_init(int field_num, const std::string &class_name, const arg &a, - bool is_default) const = 0; - virtual std::string gen_constructor_end(const tl_combinator *t, int fields_num, bool is_default) const = 0; - - virtual std::string gen_additional_function(const std::string &function_name, const tl_combinator *t, - bool is_function) const; - virtual std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type, - const std::string &class_name, int arity, - bool is_function) const; - virtual std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type, - const std::string &class_name, int arity) const; - virtual std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type, - const tl_combinator *t, int arity, bool is_function) const; - virtual std::string gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type, - bool is_function) const; -}; - -} // namespace tl -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/.gitrepo b/submodules/ton/tonlib-src/tdutils/.gitrepo deleted file mode 100644 index dd9b347e..00000000 --- a/submodules/ton/tonlib-src/tdutils/.gitrepo +++ /dev/null @@ -1,12 +0,0 @@ -; DO NOT EDIT (unless you know what you are doing) -; -; This subdirectory is a git "subrepo", and this file is maintained by the -; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme -; -[subrepo] - remote = git@github.com:arseny30/tdutils.git - branch = master - commit = cebe6b0ee08089006ff9ed7d3c4ec38be23b22fa - parent = ce4bbf3c37dcc2fdce25ba07d3d8432ce2d77d85 - cmdver = 0.4.0 - method = merge diff --git a/submodules/ton/tonlib-src/tdutils/CMakeLists.txt b/submodules/ton/tonlib-src/tdutils/CMakeLists.txt deleted file mode 100644 index 721a32b7..00000000 --- a/submodules/ton/tonlib-src/tdutils/CMakeLists.txt +++ /dev/null @@ -1,342 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -option(TDUTILS_MIME_TYPE "Generate mime types conversion (gperf is required)" ON) - -if (WIN32) - if (WINGETOPT_FOUND) - set(TD_HAVE_GETOPT 1) - endif() -else() - set(TD_HAVE_GETOPT 1) -endif() - -if (NOT ZLIB_FOUND) - find_package(ZLIB) -endif() -if (ZLIB_FOUND) - set(TD_HAVE_ZLIB 1) - message(STATUS "Found ZLIB: ${ZLIB_INCLUDE_DIR} ${ZLIB_LIBRARIES}") - - # OpenSSL internally depends on zlib - if (NOT OPENSSL_FOUND) - find_package(OpenSSL) - endif() - if (OPENSSL_FOUND) - set(TD_HAVE_OPENSSL 1) - endif() -endif() - -if (CRC32C_FOUND) - set(TD_HAVE_CRC32C 1) -endif() - -if (ABSL_FOUND) - set(TD_HAVE_ABSL 1) -endif() - -configure_file(td/utils/config.h.in td/utils/config.h @ONLY) - -add_subdirectory(generate) - -# TDUTILS -set_source_files_properties(${TDMIME_AUTO} PROPERTIES GENERATED TRUE) -if (CLANG OR GCC) - set_property(SOURCE ${TDMIME_AUTO} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-conversion") -elseif (MSVC) - set_property(SOURCE ${TDMIME_AUTO} APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4267") -endif() -if (CLANG) - set_property(SOURCE ${TDMIME_AUTO} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-deprecated-register") -endif() - -set(TDUTILS_SOURCE - td/utils/port/Clocks.cpp - td/utils/port/FileFd.cpp - td/utils/port/IPAddress.cpp - td/utils/port/MemoryMapping.cpp - td/utils/port/path.cpp - td/utils/port/PollFlags.cpp - td/utils/port/rlimit.cpp - td/utils/port/ServerSocketFd.cpp - td/utils/port/signals.cpp - td/utils/port/sleep.cpp - td/utils/port/SocketFd.cpp - td/utils/port/stacktrace.cpp - td/utils/port/Stat.cpp - td/utils/port/StdStreams.cpp - td/utils/port/thread_local.cpp - td/utils/port/user.cpp - td/utils/port/UdpSocketFd.cpp - td/utils/port/wstring_convert.cpp - - td/utils/port/detail/Epoll.cpp - td/utils/port/detail/EventFdBsd.cpp - td/utils/port/detail/EventFdLinux.cpp - td/utils/port/detail/EventFdWindows.cpp - td/utils/port/detail/Iocp.cpp - td/utils/port/detail/KQueue.cpp - td/utils/port/detail/NativeFd.cpp - td/utils/port/detail/Poll.cpp - td/utils/port/detail/Select.cpp - td/utils/port/detail/ThreadIdGuard.cpp - td/utils/port/detail/WineventPoll.cpp - - ${TDMIME_AUTO} - - td/utils/base64.cpp - td/utils/BigNum.cpp - td/utils/buffer.cpp - td/utils/BufferedUdp.cpp - td/utils/check.cpp - td/utils/crypto.cpp - td/utils/FileLog.cpp - td/utils/filesystem.cpp - td/utils/find_boundary.cpp - td/utils/Gzip.cpp - td/utils/GzipByteFlow.cpp - td/utils/Hints.cpp - td/utils/HttpUrl.cpp - td/utils/JsonBuilder.cpp - td/utils/logging.cpp - td/utils/misc.cpp - td/utils/MpmcQueue.cpp - td/utils/OptionsParser.cpp - td/utils/Random.cpp - td/utils/Slice.cpp - td/utils/SharedSlice.cpp - td/utils/StackAllocator.cpp - td/utils/Status.cpp - td/utils/StringBuilder.cpp - td/utils/Time.cpp - td/utils/Timer.cpp - td/utils/TsFileLog.cpp - td/utils/tests.cpp - td/utils/tl_parsers.cpp - td/utils/translit.cpp - td/utils/unicode.cpp - td/utils/utf8.cpp - - td/utils/port/Clocks.h - td/utils/port/config.h - td/utils/port/CxCli.h - td/utils/port/EventFd.h - td/utils/port/EventFdBase.h - td/utils/port/FileFd.h - td/utils/port/IPAddress.h - td/utils/port/IoSlice.h - td/utils/port/MemoryMapping.h - td/utils/port/path.h - td/utils/port/platform.h - td/utils/port/Poll.h - td/utils/port/PollBase.h - td/utils/port/PollFlags.h - td/utils/port/rlimit.h - td/utils/port/RwMutex.h - td/utils/port/ServerSocketFd.h - td/utils/port/signals.h - td/utils/port/sleep.h - td/utils/port/SocketFd.h - td/utils/port/stacktrace.h - td/utils/port/Stat.h - td/utils/port/StdStreams.h - td/utils/port/thread.h - td/utils/port/thread_local.h - td/utils/port/user.h - td/utils/port/UdpSocketFd.h - td/utils/port/wstring_convert.h - - td/utils/port/detail/Epoll.h - td/utils/port/detail/EventFdBsd.h - td/utils/port/detail/EventFdLinux.h - td/utils/port/detail/EventFdWindows.h - td/utils/port/detail/Iocp.h - td/utils/port/detail/KQueue.h - td/utils/port/detail/NativeFd.h - td/utils/port/detail/Poll.h - td/utils/port/detail/PollableFd.h - td/utils/port/detail/Select.h - td/utils/port/detail/ThreadIdGuard.h - td/utils/port/detail/ThreadPthread.h - td/utils/port/detail/ThreadStl.h - td/utils/port/detail/WineventPoll.h - - td/utils/AesCtrByteFlow.h - td/utils/as.h - td/utils/base64.h - td/utils/benchmark.h - td/utils/BigNum.h - td/utils/bits.h - td/utils/buffer.h - td/utils/BufferedFd.h - td/utils/BufferedReader.h - td/utils/BufferedUdp.h - td/utils/ByteFlow.h - td/utils/CancellationToken.h - td/utils/ChangesProcessor.h - td/utils/check.h - td/utils/Closure.h - td/utils/common.h - td/utils/ConcurrentHashTable.h - td/utils/Container.h - td/utils/Context.h - td/utils/crypto.h - td/utils/DecTree.h - td/utils/Destructor.h - td/utils/Enumerator.h - td/utils/EpochBasedMemoryReclamation.h - td/utils/FileLog.h - td/utils/filesystem.h - td/utils/find_boundary.h - td/utils/FloodControlFast.h - td/utils/FloodControlStrict.h - td/utils/format.h - td/utils/Gzip.h - td/utils/GzipByteFlow.h - td/utils/Hash.h - td/utils/HashMap.h - td/utils/HashSet.h - td/utils/HazardPointers.h - td/utils/Heap.h - td/utils/Hints.h - td/utils/HttpUrl.h - td/utils/int_types.h - td/utils/invoke.h - td/utils/JsonBuilder.h - td/utils/List.h - td/utils/logging.h - td/utils/MemoryLog.h - td/utils/misc.h - td/utils/MovableValue.h - td/utils/MpmcQueue.h - td/utils/MpmcWaiter.h - td/utils/MpscPollableQueue.h - td/utils/MpscLinkQueue.h - td/utils/Named.h - td/utils/ObjectPool.h - td/utils/Observer.h - td/utils/optional.h - td/utils/OptionsParser.h - td/utils/OrderedEventsProcessor.h - td/utils/overloaded.h - td/utils/Parser.h - td/utils/PathView.h - td/utils/queue.h - td/utils/Random.h - td/utils/ScopeGuard.h - td/utils/SharedObjectPool.h - td/utils/Slice-decl.h - td/utils/Slice.h - td/utils/Span.h - td/utils/SpinLock.h - td/utils/StackAllocator.h - td/utils/Status.h - td/utils/StealingQueue.h - td/utils/Storer.h - td/utils/StorerBase.h - td/utils/StringBuilder.h - td/utils/tests.h - td/utils/ThreadSafeCounter.h - td/utils/Time.h - td/utils/TimedStat.h - td/utils/Timer.h - td/utils/TsFileLog.h - td/utils/tl_helpers.h - td/utils/tl_parsers.h - td/utils/tl_storers.h - td/utils/translit.h - td/utils/type_traits.h - td/utils/UInt.h - td/utils/uint128.h - td/utils/unicode.h - td/utils/unique_ptr.h - td/utils/utf8.h - td/utils/Variant.h - td/utils/VectorQueue.h -) - -if (TDUTILS_MIME_TYPE) - set(TDUTILS_SOURCE - ${TDUTILS_SOURCE} - td/utils/MimeType.cpp - td/utils/MimeType.h - ) -endif() - -set(TDUTILS_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/test/buffer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/Enumerator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/gzip.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/HazardPointers.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/heap.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/json.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/log.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/misc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/MpmcQueue.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/MpmcWaiter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/MpscLinkQueue.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/OrderedEventsProcessor.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/port.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/pq.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/SharedObjectPool.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/SharedSlice.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/StealingQueue.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test/variant.cpp - PARENT_SCOPE -) - -#RULES -#LIBRARIES -add_library(tdutils STATIC ${TDUTILS_SOURCE}) -if (WIN32) - # find_library(WS2_32_LIBRARY ws2_32) - # find_library(MSWSOCK_LIBRARY Mswsock) - # target_link_libraries(tdutils PRIVATE ${WS2_32_LIBRARY} ${MSWSOCK_LIBRARY}) - target_link_libraries(tdutils PRIVATE ws2_32 Mswsock Normaliz) -endif() -if (NOT CMAKE_CROSSCOMPILING AND TDUTILS_MIME_TYPE) - add_dependencies(tdutils tdmime_auto) -endif() - -if (DEFINED CMAKE_THREAD_LIBS_INIT) - target_link_libraries(tdutils PUBLIC ${CMAKE_THREAD_LIBS_INIT}) -endif() -target_include_directories(tdutils PUBLIC $ $) - -if (OPENSSL_FOUND) - target_link_libraries(tdutils PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES}) - target_include_directories(tdutils SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR}) -endif() - -if (ZLIB_FOUND) - target_link_libraries(tdutils PRIVATE ${ZLIB_LIBRARIES}) - target_include_directories(tdutils SYSTEM PRIVATE ${ZLIB_INCLUDE_DIR}) -endif() - -if (CRC32C_FOUND) - target_link_libraries(tdutils PRIVATE crc32c) -endif() -if (ABSL_FOUND) - target_link_libraries_system(tdutils absl::flat_hash_map absl::flat_hash_set absl::hash) -endif() - -if (WIN32 AND WINGETOPT_FOUND) - target_link_libraries(tdutils PRIVATE wingetopt) -endif() - -if (ANDROID) - target_link_libraries(tdutils PRIVATE log) -endif() - -if (CMAKE_HOST_SYSTEM_NAME MATCHES "NetBSD") - target_link_libraries(tdutils PUBLIC /usr/pkg/gcc5/i486--netbsdelf/lib/libatomic.so) -endif() - -install(TARGETS tdutils EXPORT TdTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include -) diff --git a/submodules/ton/tonlib-src/tdutils/generate/CMakeLists.txt b/submodules/ton/tonlib-src/tdutils/generate/CMakeLists.txt deleted file mode 100644 index 07353e51..00000000 --- a/submodules/ton/tonlib-src/tdutils/generate/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -# Generates files for MIME type <-> extension conversions -# DEPENDS ON: gperf grep bash/powershell - -if (NOT TDUTILS_MIME_TYPE) - return() -endif() - -file(MAKE_DIRECTORY auto) - -set(TDMIME_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/auto/mime_type_to_extension.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/auto/extension_to_mime_type.cpp -) -set(TDMIME_AUTO - ${TDMIME_SOURCE} - PARENT_SCOPE -) - -add_custom_target(tdmime_auto DEPENDS ${TDMIME_SOURCE}) - -if (NOT CMAKE_CROSSCOMPILING) - find_program(GPERF_EXECUTABLE gperf) - if (NOT GPERF_EXECUTABLE) - message(FATAL_ERROR "Could NOT find gperf. Add path to gperf executable to PATH environment variable or specify it manually using GPERF_EXECUTABLE option, i. e. 'cmake -DGPERF_EXECUTABLE:FILEPATH=\"\"'.") - endif() - - set(GPERF_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/auto/mime_type_to_extension.gperf - ${CMAKE_CURRENT_SOURCE_DIR}/auto/extension_to_mime_type.gperf - ) - - set(GPERF_GEN_SOURCE generate_mime_types_gperf.cpp) - - add_executable(generate_mime_types_gperf ${GPERF_GEN_SOURCE}) - - add_custom_command( - OUTPUT ${GPERF_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND generate_mime_types_gperf mime_types.txt ${GPERF_FILES} - DEPENDS generate_mime_types_gperf mime_types.txt - ) - - if (WIN32) - set(MIME_TYPE_TO_EXTENSION_CMD ${GPERF_EXECUTABLE} -m100 --output-file=auto/mime_type_to_extension.cpp auto/mime_type_to_extension.gperf) - else() - set(MIME_TYPE_TO_EXTENSION_CMD ${GPERF_EXECUTABLE} -m100 auto/mime_type_to_extension.gperf | grep -v __gnu_inline__ > auto/mime_type_to_extension.cpp) - endif() - add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/auto/mime_type_to_extension.cpp - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${MIME_TYPE_TO_EXTENSION_CMD} - DEPENDS auto/mime_type_to_extension.gperf - ) - - if (WIN32) - set(EXTENSION_TO_MIME_TYPE_CMD ${GPERF_EXECUTABLE} -m100 --output-file=auto/extension_to_mime_type.cpp auto/extension_to_mime_type.gperf) - else() - set(EXTENSION_TO_MIME_TYPE_CMD ${GPERF_EXECUTABLE} -m100 auto/extension_to_mime_type.gperf | grep -v __gnu_inline__ > auto/extension_to_mime_type.cpp) - endif() - add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/auto/extension_to_mime_type.cpp - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${EXTENSION_TO_MIME_TYPE_CMD} - DEPENDS auto/extension_to_mime_type.gperf - ) -endif() diff --git a/submodules/ton/tonlib-src/tdutils/generate/generate_mime_types_gperf.cpp b/submodules/ton/tonlib-src/tdutils/generate/generate_mime_types_gperf.cpp deleted file mode 100644 index 03edb535..00000000 --- a/submodules/ton/tonlib-src/tdutils/generate/generate_mime_types_gperf.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static std::pair split(std::string s, char delimiter = ' ') { - auto delimiter_pos = s.find(delimiter); - if (delimiter_pos == std::string::npos) { - return {std::move(s), ""}; - } else { - auto head = s.substr(0, delimiter_pos); - auto tail = s.substr(delimiter_pos + 1); - return {head, tail}; - } -} - -static bool generate(const char *file_name, const char *from_name, const char *to_name, - const std::map &map) { - // binary mode is needed for MSYS2 gperf - std::ofstream out(file_name, std::ios_base::trunc | std::ios_base::binary); - if (!out) { - std::cerr << "Can't open output file \"" << file_name << std::endl; - return false; - } - - out << "%struct-type\n"; - out << "%ignore-case\n"; - out << "%language=ANSI-C\n"; - out << "%readonly-tables\n"; - out << "%includes\n"; - out << "%enum\n"; - out << "%define slot-name " << from_name << "\n"; - out << "%define initializer-suffix ,nullptr\n"; - out << "%define slot-name " << from_name << "\n"; - out << "%define hash-function-name " << from_name << "_hash\n"; - out << "%define lookup-function-name search_" << from_name << "\n"; - // out << "%define class-name " << from_name << "_to_" << to_name << "\n"; - out << "struct " << from_name << "_and_" << to_name << " {\n"; - out << " const char *" << from_name << ";\n"; - out << " const char *" << to_name << ";\n"; - out << "}\n"; - out << "%%\n"; - - for (auto &value : map) { - out << '"' << value.first << "\", \"" << value.second << '"' << "\n"; - } - - out << "%%\n"; - out << "const char *" << from_name << "_to_" << to_name << "(const char *" << from_name << ", size_t " << from_name - << "_len) {\n"; - out << " const auto &result = search_" << from_name << "(" << from_name << ", " << from_name << "_len);\n"; - out << " if (result == nullptr) {\n"; - out << " return nullptr;\n"; - out << " }\n"; - out << "\n"; - out << " return result->" << to_name << ";\n"; - out << "}\n"; - - return true; -} - -static bool is_private_mime_type(const std::string &mime_type) { - return mime_type.find("/x-") != std::string::npos; -} - -int main(int argc, char *argv[]) { - if (argc != 4) { - std::cerr << "Wrong number of arguments supplied. Expected 'generate_mime_types_gperf " - " '" - << std::endl; - return EXIT_FAILURE; - } - - std::ifstream mime_types_file(argv[1]); - if (!mime_types_file) { - std::cerr << "Can't open input file \"" << argv[1] << std::endl; - return EXIT_FAILURE; - } - - std::map mime_type_to_extension; - std::map extension_to_mime_type; - - std::string line; - while (std::getline(mime_types_file, line)) { - while (!line.empty() && (line.back() == '\r' || line.back() == '\n')) { - line.pop_back(); - } - - std::string mime_type; - std::string extensions_string; - std::tie(mime_type, extensions_string) = split(line, '\t'); - - if (mime_type.empty()) { - std::cerr << "Wrong MIME type description \"" << line << "\"" << std::endl; - continue; - } - - auto extensions_start_position = extensions_string.find_first_not_of(" \t"); - if (extensions_start_position == std::string::npos) { - std::cerr << "Wrong MIME type description \"" << line << "\"" << std::endl; - continue; - } - extensions_string = extensions_string.substr(extensions_start_position); - - std::vector extensions; - while (!extensions_string.empty()) { - extensions.push_back(""); - std::tie(extensions.back(), extensions_string) = split(extensions_string); - } - assert(!extensions.empty()); - - std::map preffered_extensions{{"image/jpeg", "jpg"}, {"audio/mpeg", "mp3"}, - {"audio/midi", "midi"}, {"text/x-pascal", "pas"}, - {"text/x-asm", "asm"}, {"video/quicktime", "mov"}}; - std::size_t index = 0; - if (preffered_extensions.count(mime_type) != 0) { - index = std::find(extensions.begin(), extensions.end(), preffered_extensions[mime_type]) - extensions.begin(); - assert(index < extensions.size()); - } - if (mime_type_to_extension.emplace_hint(mime_type_to_extension.end(), mime_type, extensions[index])->second != - extensions[index]) { - std::cerr << "MIME type \"" << mime_type << "\" has more than one extensions list" << std::endl; - } - - for (auto &extension : extensions) { - if (!extension_to_mime_type.emplace(extension, mime_type).second) { - if (is_private_mime_type(extension_to_mime_type[extension]) == is_private_mime_type(mime_type)) { - std::cerr << "Extension \"" << extension << "\" matches more than one type" << std::endl; - } else { - if (!is_private_mime_type(mime_type)) { - extension_to_mime_type[extension] = mime_type; - } - } - } - } - } - - if (!generate(argv[2], "mime_type", "extension", mime_type_to_extension)) { - return EXIT_FAILURE; - } - if (!generate(argv[3], "extension", "mime_type", extension_to_mime_type)) { - return EXIT_FAILURE; - } -} diff --git a/submodules/ton/tonlib-src/tdutils/generate/mime_types.txt b/submodules/ton/tonlib-src/tdutils/generate/mime_types.txt deleted file mode 100644 index cc1fb5e3..00000000 --- a/submodules/ton/tonlib-src/tdutils/generate/mime_types.txt +++ /dev/null @@ -1,777 +0,0 @@ -application/andrew-inset ez -application/applixware aw -application/atom+xml atom -application/atomcat+xml atomcat -application/atomsvc+xml atomsvc -application/ccxml+xml ccxml -application/cdmi-capability cdmia -application/cdmi-container cdmic -application/cdmi-domain cdmid -application/cdmi-object cdmio -application/cdmi-queue cdmiq -application/cu-seeme cu -application/davmount+xml davmount -application/docbook+xml dbk -application/dssc+der dssc -application/dssc+xml xdssc -application/ecmascript es -application/emma+xml emma -application/epub+zip epub -application/exi exi -application/font-tdpfr pfr -application/gml+xml gml -application/gpx+xml gpx -application/gxf gxf -application/hyperstudio stk -application/inkml+xml ink inkml -application/ipfix ipfix -application/java-archive jar -application/java-serialized-object ser -application/java-vm class -application/javascript js -application/json json -application/jsonml+json jsonml -application/lost+xml lostxml -application/mac-binhex40 hqx -application/mac-compactpro cpt -application/mads+xml mads -application/marc mrc -application/marcxml+xml mrcx -application/mathematica ma nb mb -application/mathml+xml mathml -application/mbox mbox -application/mediaservercontrol+xml mscml -application/metalink+xml metalink -application/metalink4+xml meta4 -application/mets+xml mets -application/mods+xml mods -application/mp21 m21 mp21 -application/mp4 mp4s -application/msword doc dot -application/mxf mxf -application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy -application/oda oda -application/oebps-package+xml opf -application/ogg ogx -application/omdoc+xml omdoc -application/onenote onetoc onetoc2 onetmp onepkg -application/oxps oxps -application/patch-ops-error+xml xer -application/pdf pdf -application/pgp-encrypted pgp -application/pgp-signature asc sig -application/pics-rules prf -application/pkcs10 p10 -application/pkcs7-mime p7m p7c -application/pkcs7-signature p7s -application/pkcs8 p8 -application/pkix-attr-cert ac -application/pkix-cert cer -application/pkix-crl crl -application/pkix-pkipath pkipath -application/pkixcmp pki -application/pls+xml pls -application/postscript ai eps ps -application/prs.cww cww -application/pskc+xml pskcxml -application/rdf+xml rdf -application/reginfo+xml rif -application/relax-ng-compact-syntax rnc -application/resource-lists+xml rl -application/resource-lists-diff+xml rld -application/rls-services+xml rs -application/rpki-ghostbusters gbr -application/rpki-manifest mft -application/rpki-roa roa -application/rsd+xml rsd -application/rss+xml rss -application/rtf rtf -application/sbml+xml sbml -application/scvp-cv-request scq -application/scvp-cv-response scs -application/scvp-vp-request spq -application/scvp-vp-response spp -application/sdp sdp -application/set-payment-initiation setpay -application/set-registration-initiation setreg -application/shf+xml shf -application/smil+xml smi smil -application/sparql-query rq -application/sparql-results+xml srx -application/srgs gram -application/srgs+xml grxml -application/sru+xml sru -application/ssdl+xml ssdl -application/ssml+xml ssml -application/tei+xml tei teicorpus -application/thraud+xml tfi -application/timestamped-data tsd -application/vnd.3gpp.pic-bw-large plb -application/vnd.3gpp.pic-bw-small psb -application/vnd.3gpp.pic-bw-var pvb -application/vnd.3gpp2.tcap tcap -application/vnd.3m.post-it-notes pwn -application/vnd.accpac.simply.aso aso -application/vnd.accpac.simply.imp imp -application/vnd.acucobol acu -application/vnd.acucorp atc acutc -application/vnd.adobe.air-application-installer-package+zip air -application/vnd.adobe.formscentral.fcdt fcdt -application/vnd.adobe.fxp fxp fxpl -application/vnd.adobe.xdp+xml xdp -application/vnd.adobe.xfdf xfdf -application/vnd.ahead.space ahead -application/vnd.airzip.filesecure.azf azf -application/vnd.airzip.filesecure.azs azs -application/vnd.amazon.ebook azw -application/vnd.americandynamics.acc acc -application/vnd.amiga.ami ami -application/vnd.android.package-archive apk -application/vnd.anser-web-certificate-issue-initiation cii -application/vnd.anser-web-funds-transfer-initiation fti -application/vnd.antix.game-component atx -application/vnd.apple.installer+xml mpkg -application/vnd.apple.mpegurl m3u8 -application/vnd.aristanetworks.swi swi -application/vnd.astraea-software.iota iota -application/vnd.audiograph aep -application/vnd.blueice.multipass mpm -application/vnd.bmi bmi -application/vnd.businessobjects rep -application/vnd.chemdraw+xml cdxml -application/vnd.chipnuts.karaoke-mmd mmd -application/vnd.cinderella cdy -application/vnd.claymore cla -application/vnd.cloanto.rp9 rp9 -application/vnd.clonk.c4group c4g c4d c4f c4p c4u -application/vnd.cluetrust.cartomobile-config c11amc -application/vnd.cluetrust.cartomobile-config-pkg c11amz -application/vnd.commonspace csp -application/vnd.contact.cmsg cdbcmsg -application/vnd.cosmocaller cmc -application/vnd.crick.clicker clkx -application/vnd.crick.clicker.keyboard clkk -application/vnd.crick.clicker.palette clkp -application/vnd.crick.clicker.template clkt -application/vnd.crick.clicker.wordbank clkw -application/vnd.criticaltools.wbs+xml wbs -application/vnd.ctc-posml pml -application/vnd.cups-ppd ppd -application/vnd.curl.car car -application/vnd.curl.pcurl pcurl -application/vnd.dart dart -application/vnd.data-vision.rdz rdz -application/vnd.dece.data uvf uvvf uvd uvvd -application/vnd.dece.ttml+xml uvt uvvt -application/vnd.dece.unspecified uvx uvvx -application/vnd.dece.zip uvz uvvz -application/vnd.denovo.fcselayout-link fe_launch -application/vnd.dna dna -application/vnd.dolby.mlp mlp -application/vnd.dpgraph dpg -application/vnd.dreamfactory dfac -application/vnd.ds-keypoint kpxx -application/vnd.dvb.ait ait -application/vnd.dvb.service svc -application/vnd.dynageo geo -application/vnd.ecowin.chart mag -application/vnd.enliven nml -application/vnd.epson.esf esf -application/vnd.epson.msf msf -application/vnd.epson.quickanime qam -application/vnd.epson.salt slt -application/vnd.epson.ssf ssf -application/vnd.eszigno3+xml es3 et3 -application/vnd.ezpix-album ez2 -application/vnd.ezpix-package ez3 -application/vnd.fdf fdf -application/vnd.fdsn.mseed mseed -application/vnd.fdsn.seed seed dataless -application/vnd.flographit gph -application/vnd.fluxtime.clip ftc -application/vnd.framemaker fm frame maker book -application/vnd.frogans.fnc fnc -application/vnd.frogans.ltf ltf -application/vnd.fsc.weblaunch fsc -application/vnd.fujitsu.oasys oas -application/vnd.fujitsu.oasys2 oa2 -application/vnd.fujitsu.oasys3 oa3 -application/vnd.fujitsu.oasysgp fg5 -application/vnd.fujitsu.oasysprs bh2 -application/vnd.fujixerox.ddd ddd -application/vnd.fujixerox.docuworks xdw -application/vnd.fujixerox.docuworks.binder xbd -application/vnd.fuzzysheet fzs -application/vnd.genomatix.tuxedo txd -application/vnd.geogebra.file ggb -application/vnd.geogebra.tool ggt -application/vnd.geometry-explorer gex gre -application/vnd.geonext gxt -application/vnd.geoplan g2w -application/vnd.geospace g3w -application/vnd.gmx gmx -application/vnd.google-earth.kml+xml kml -application/vnd.google-earth.kmz kmz -application/vnd.grafeq gqf gqs -application/vnd.groove-account gac -application/vnd.groove-help ghf -application/vnd.groove-identity-message gim -application/vnd.groove-injector grv -application/vnd.groove-tool-message gtm -application/vnd.groove-tool-template tpl -application/vnd.groove-vcard vcg -application/vnd.hal+xml hal -application/vnd.handheld-entertainment+xml zmm -application/vnd.hbci hbci -application/vnd.hhe.lesson-player les -application/vnd.hp-hpgl hpgl -application/vnd.hp-hpid hpid -application/vnd.hp-hps hps -application/vnd.hp-jlyt jlt -application/vnd.hp-pcl pcl -application/vnd.hp-pclxl pclxl -application/vnd.hydrostatix.sof-data sfd-hdstx -application/vnd.ibm.minipay mpy -application/vnd.ibm.modcap afp listafp list3820 -application/vnd.ibm.rights-management irm -application/vnd.ibm.secure-container sc -application/vnd.iccprofile icc icm -application/vnd.igloader igl -application/vnd.immervision-ivp ivp -application/vnd.immervision-ivu ivu -application/vnd.insors.igm igm -application/vnd.intercon.formnet xpw xpx -application/vnd.intergeo i2g -application/vnd.intu.qbo qbo -application/vnd.intu.qfx qfx -application/vnd.ipunplugged.rcprofile rcprofile -application/vnd.irepository.package+xml irp -application/vnd.is-xpr xpr -application/vnd.isac.fcs fcs -application/vnd.jam jam -application/vnd.jcp.javame.midlet-rms rms -application/vnd.jisp jisp -application/vnd.joost.joda-archive joda -application/vnd.kahootz ktz ktr -application/vnd.kde.karbon karbon -application/vnd.kde.kchart chrt -application/vnd.kde.kformula kfo -application/vnd.kde.kivio flw -application/vnd.kde.kontour kon -application/vnd.kde.kpresenter kpr kpt -application/vnd.kde.kspread ksp -application/vnd.kde.kword kwd kwt -application/vnd.kenameaapp htke -application/vnd.kidspiration kia -application/vnd.kinar kne knp -application/vnd.koan skp skd skt skm -application/vnd.kodak-descriptor sse -application/vnd.las.las+xml lasxml -application/vnd.llamagraphics.life-balance.desktop lbd -application/vnd.llamagraphics.life-balance.exchange+xml lbe -application/vnd.lotus-1-2-3 123 -application/vnd.lotus-approach apr -application/vnd.lotus-freelance pre -application/vnd.lotus-notes nsf -application/vnd.lotus-organizer org -application/vnd.lotus-screencam scm -application/vnd.lotus-wordpro lwp -application/vnd.macports.portpkg portpkg -application/vnd.mcd mcd -application/vnd.medcalcdata mc1 -application/vnd.mediastation.cdkey cdkey -application/vnd.mfer mwf -application/vnd.mfmp mfm -application/vnd.micrografx.flo flo -application/vnd.micrografx.igx igx -application/vnd.mif mif -application/vnd.mobius.daf daf -application/vnd.mobius.dis dis -application/vnd.mobius.mbk mbk -application/vnd.mobius.mqy mqy -application/vnd.mobius.msl msl -application/vnd.mobius.plc plc -application/vnd.mobius.txf txf -application/vnd.mophun.application mpn -application/vnd.mophun.certificate mpc -application/vnd.mozilla.xul+xml xul -application/vnd.ms-artgalry cil -application/vnd.ms-cab-compressed cab -application/vnd.ms-excel xls xlm xla xlc xlt xlw -application/vnd.ms-excel.addin.macroenabled.12 xlam -application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb -application/vnd.ms-excel.sheet.macroenabled.12 xlsm -application/vnd.ms-excel.template.macroenabled.12 xltm -application/vnd.ms-fontobject eot -application/vnd.ms-htmlhelp chm -application/vnd.ms-ims ims -application/vnd.ms-lrm lrm -application/vnd.ms-officetheme thmx -application/vnd.ms-pki.seccat cat -application/vnd.ms-pki.stl stl -application/vnd.ms-powerpoint ppt pps pot -application/vnd.ms-powerpoint.addin.macroenabled.12 ppam -application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm -application/vnd.ms-powerpoint.slide.macroenabled.12 sldm -application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm -application/vnd.ms-powerpoint.template.macroenabled.12 potm -application/vnd.ms-project mpp mpt -application/vnd.ms-word.document.macroenabled.12 docm -application/vnd.ms-word.template.macroenabled.12 dotm -application/vnd.ms-works wps wks wcm wdb -application/vnd.ms-wpl wpl -application/vnd.ms-xpsdocument xps -application/vnd.mseq mseq -application/vnd.musician mus -application/vnd.muvee.style msty -application/vnd.mynfc taglet -application/vnd.neurolanguage.nlu nlu -application/vnd.nitf ntf nitf -application/vnd.noblenet-directory nnd -application/vnd.noblenet-sealer nns -application/vnd.noblenet-web nnw -application/vnd.nokia.n-gage.data ngdat -application/vnd.nokia.n-gage.symbian.install n-gage -application/vnd.nokia.radio-preset rpst -application/vnd.nokia.radio-presets rpss -application/vnd.novadigm.edm edm -application/vnd.novadigm.edx edx -application/vnd.novadigm.ext ext -application/vnd.oasis.opendocument.chart odc -application/vnd.oasis.opendocument.chart-template otc -application/vnd.oasis.opendocument.database odb -application/vnd.oasis.opendocument.formula odf -application/vnd.oasis.opendocument.formula-template odft -application/vnd.oasis.opendocument.graphics odg -application/vnd.oasis.opendocument.graphics-template otg -application/vnd.oasis.opendocument.image odi -application/vnd.oasis.opendocument.image-template oti -application/vnd.oasis.opendocument.presentation odp -application/vnd.oasis.opendocument.presentation-template otp -application/vnd.oasis.opendocument.spreadsheet ods -application/vnd.oasis.opendocument.spreadsheet-template ots -application/vnd.oasis.opendocument.text odt -application/vnd.oasis.opendocument.text-master odm -application/vnd.oasis.opendocument.text-template ott -application/vnd.oasis.opendocument.text-web oth -application/vnd.olpc-sugar xo -application/vnd.oma.dd2+xml dd2 -application/vnd.openofficeorg.extension oxt -application/vnd.openxmlformats-officedocument.presentationml.presentation pptx -application/vnd.openxmlformats-officedocument.presentationml.slide sldx -application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx -application/vnd.openxmlformats-officedocument.presentationml.template potx -application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx -application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx -application/vnd.openxmlformats-officedocument.wordprocessingml.document docx -application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx -application/vnd.osgeo.mapguide.package mgp -application/vnd.osgi.dp dp -application/vnd.osgi.subsystem esa -application/vnd.palm pdb pqa oprc -application/vnd.pawaafile paw -application/vnd.pg.format str -application/vnd.pg.osasli ei6 -application/vnd.picsel efif -application/vnd.pmi.widget wg -application/vnd.pocketlearn plf -application/vnd.powerbuilder6 pbd -application/vnd.previewsystems.box box -application/vnd.proteus.magazine mgz -application/vnd.publishare-delta-tree qps -application/vnd.pvi.ptid1 ptid -application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb -application/vnd.realvnc.bed bed -application/vnd.recordare.musicxml mxl -application/vnd.recordare.musicxml+xml musicxml -application/vnd.rig.cryptonote cryptonote -application/vnd.rim.cod cod -application/vnd.rn-realmedia rm -application/vnd.rn-realmedia-vbr rmvb -application/vnd.route66.link66+xml link66 -application/vnd.sailingtracker.track st -application/vnd.seemail see -application/vnd.sema sema -application/vnd.semd semd -application/vnd.semf semf -application/vnd.shana.informed.formdata ifm -application/vnd.shana.informed.formtemplate itp -application/vnd.shana.informed.interchange iif -application/vnd.shana.informed.package ipk -application/vnd.simtech-mindmapper twd twds -application/vnd.smaf mmf -application/vnd.smart.teacher teacher -application/vnd.solent.sdkm+xml sdkm sdkd -application/vnd.spotfire.dxp dxp -application/vnd.spotfire.sfs sfs -application/vnd.stardivision.calc sdc -application/vnd.stardivision.draw sda -application/vnd.stardivision.impress sdd -application/vnd.stardivision.math smf -application/vnd.stardivision.writer sdw vor -application/vnd.stardivision.writer-global sgl -application/vnd.stepmania.package smzip -application/vnd.stepmania.stepchart sm -application/vnd.sun.xml.calc sxc -application/vnd.sun.xml.calc.template stc -application/vnd.sun.xml.draw sxd -application/vnd.sun.xml.draw.template std -application/vnd.sun.xml.impress sxi -application/vnd.sun.xml.impress.template sti -application/vnd.sun.xml.math sxm -application/vnd.sun.xml.writer sxw -application/vnd.sun.xml.writer.global sxg -application/vnd.sun.xml.writer.template stw -application/vnd.sus-calendar sus susp -application/vnd.svd svd -application/vnd.symbian.install sis sisx -application/vnd.syncml+xml xsm -application/vnd.syncml.dm+wbxml bdm -application/vnd.syncml.dm+xml xdm -application/vnd.tao.intent-module-archive tao -application/vnd.tcpdump.pcap pcap cap dmp -application/vnd.tmobile-livetv tmo -application/vnd.trid.tpt tpt -application/vnd.triscape.mxs mxs -application/vnd.trueapp tra -application/vnd.ufdl ufd ufdl -application/vnd.uiq.theme utz -application/vnd.umajin umj -application/vnd.unity unityweb -application/vnd.uoml+xml uoml -application/vnd.vcx vcx -application/vnd.visio vsd vst vss vsw -application/vnd.visionary vis -application/vnd.vsf vsf -application/vnd.wap.wbxml wbxml -application/vnd.wap.wmlc wmlc -application/vnd.wap.wmlscriptc wmlsc -application/vnd.webturbo wtb -application/vnd.wolfram.player nbp -application/vnd.wordperfect wpd -application/vnd.wqd wqd -application/vnd.wt.stf stf -application/vnd.xara xar -application/vnd.xfdl xfdl -application/vnd.yamaha.hv-dic hvd -application/vnd.yamaha.hv-script hvs -application/vnd.yamaha.hv-voice hvp -application/vnd.yamaha.openscoreformat osf -application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg -application/vnd.yamaha.smaf-audio saf -application/vnd.yamaha.smaf-phrase spf -application/vnd.yellowriver-custom-menu cmp -application/vnd.zul zir zirz -application/vnd.zzazz.deck+xml zaz -application/voicexml+xml vxml -application/widget wgt -application/winhlp hlp -application/wsdl+xml wsdl -application/wspolicy+xml wspolicy -application/x-7z-compressed 7z -application/x-abiword abw -application/x-ace-compressed ace -application/x-apple-diskimage dmg -application/x-authorware-bin aab x32 u32 vox -application/x-authorware-map aam -application/x-authorware-seg aas -application/x-bcpio bcpio -application/x-bittorrent torrent -application/x-blorb blb blorb -application/x-bzip bz -application/x-bzip2 bz2 boz -application/x-cbr cbr cba cbt cbz cb7 -application/x-cdlink vcd -application/x-cfs-compressed cfs -application/x-chat chat -application/x-chess-pgn pgn -application/x-conference nsc -application/x-cpio cpio -application/x-csh csh -application/x-debian-package deb udeb -application/x-dgc-compressed dgc -application/x-director dir dcr dxr cst cct cxt w3d fgd swa -application/x-doom wad -application/x-dtbncx+xml ncx -application/x-dtbook+xml dtb -application/x-dtbresource+xml res -application/x-dvi dvi -application/x-envoy evy -application/x-eva eva -application/x-font-bdf bdf -application/x-font-ghostscript gsf -application/x-font-linux-psf psf -application/x-font-otf otf -application/x-font-pcf pcf -application/x-font-snf snf -application/x-font-ttf ttf ttc -application/x-font-type1 pfa pfb pfm afm -application/x-font-woff woff -application/x-freearc arc -application/x-futuresplash spl -application/x-gca-compressed gca -application/x-glulx ulx -application/x-gnumeric gnumeric -application/x-gramps-xml gramps -application/x-gtar gtar -application/x-hdf hdf -application/x-install-instructions install -application/x-iso9660-image iso -application/x-java-jnlp-file jnlp -application/x-latex latex -application/x-lzh-compressed lzh lha -application/x-mie mie -application/x-mobipocket-ebook prc mobi -application/x-ms-application application -application/x-ms-shortcut lnk -application/x-ms-wmd wmd -application/x-ms-wmz wmz -application/x-ms-xbap xbap -application/x-msaccess mdb -application/x-msbinder obd -application/x-mscardfile crd -application/x-msclip clp -application/x-msdownload exe dll com bat msi -application/x-msmediaview mvb m13 m14 -application/x-msmetafile wmf wmz emf emz -application/x-msmoney mny -application/x-mspublisher pub -application/x-msschedule scd -application/x-msterminal trm -application/x-mswrite wri -application/x-netcdf nc cdf -application/x-nzb nzb -application/x-pkcs12 p12 pfx -application/x-pkcs7-certificates p7b spc -application/x-pkcs7-certreqresp p7r -application/x-rar-compressed rar -application/x-research-info-systems ris -application/x-sh sh -application/x-shar shar -application/x-shockwave-flash swf -application/x-silverlight-app xap -application/x-sql sql -application/x-stuffit sit -application/x-stuffitx sitx -application/x-subrip srt -application/x-sv4cpio sv4cpio -application/x-sv4crc sv4crc -application/x-t3vm-image t3 -application/x-tads gam -application/x-tar tar -application/x-tcl tcl -application/x-tex tex -application/x-tex-tfm tfm -application/x-texinfo texinfo texi -application/x-tgif obj -application/x-tgsticker tgs -application/x-ustar ustar -application/x-wais-source src -application/x-x509-ca-cert der crt -application/x-xfig fig -application/x-xliff+xml xlf -application/x-xpinstall xpi -application/x-xz xz -application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 -application/xaml+xml xaml -application/xcap-diff+xml xdf -application/xenc+xml xenc -application/xhtml+xml xhtml xht -application/xml xml xsl -application/xml-dtd dtd -application/xop+xml xop -application/xproc+xml xpl -application/xslt+xml xslt -application/xspf+xml xspf -application/xv+xml mxml xhvml xvml xvm -application/yang yang -application/yin+xml yin -application/zip zip -audio/adpcm adp -audio/basic au snd -audio/midi mid midi kar rmi -audio/mp4 m4a mp4a -audio/mpeg mpga mp2 mp2a mp3 m2a m3a -audio/ogg oga ogg spx -audio/s3m s3m -audio/silk sil -audio/vnd.dece.audio uva uvva -audio/vnd.digital-winds eol -audio/vnd.dra dra -audio/vnd.dts dts -audio/vnd.dts.hd dtshd -audio/vnd.lucent.voice lvp -audio/vnd.ms-playready.media.pya pya -audio/vnd.nuera.ecelp4800 ecelp4800 -audio/vnd.nuera.ecelp7470 ecelp7470 -audio/vnd.nuera.ecelp9600 ecelp9600 -audio/vnd.rip rip -audio/webm weba -audio/x-aac aac -audio/x-aiff aif aiff aifc -audio/x-caf caf -audio/x-flac flac -audio/x-matroska mka -audio/x-mpegurl m3u -audio/x-ms-wax wax -audio/x-ms-wma wma -audio/x-pn-realaudio ram ra -audio/x-pn-realaudio-plugin rmp -audio/x-wav wav -audio/xm xm -chemical/x-cdx cdx -chemical/x-cif cif -chemical/x-cmdf cmdf -chemical/x-cml cml -chemical/x-csml csml -chemical/x-xyz xyz -font/collection ttc -font/otf otf -font/ttf ttf -font/woff woff -font/woff2 woff2 -image/bmp bmp -image/cgm cgm -image/g3fax g3 -image/gif gif -image/heic heic -image/heic-sequence heics -image/heif heif -image/heif-sequence heifs -image/ief ief -image/jpeg jpeg jpg jpe -image/ktx ktx -image/png png -image/prs.btif btif -image/sgi sgi -image/svg+xml svg svgz -image/tiff tiff tif -image/vnd.adobe.photoshop psd -image/vnd.dece.graphic uvi uvvi uvg uvvg -image/vnd.djvu djvu djv -image/vnd.dvb.subtitle sub -image/vnd.dwg dwg -image/vnd.dxf dxf -image/vnd.fastbidsheet fbs -image/vnd.fpx fpx -image/vnd.fst fst -image/vnd.fujixerox.edmics-mmr mmr -image/vnd.fujixerox.edmics-rlc rlc -image/vnd.ms-modi mdi -image/vnd.ms-photo wdp -image/vnd.net-fpx npx -image/vnd.wap.wbmp wbmp -image/vnd.xiff xif -image/webp webp -image/x-3ds 3ds -image/x-cmu-raster ras -image/x-cmx cmx -image/x-freehand fh fhc fh4 fh5 fh7 -image/x-icon ico -image/x-mrsid-image sid -image/x-pcx pcx -image/x-pict pic pct -image/x-portable-anymap pnm -image/x-portable-bitmap pbm -image/x-portable-graymap pgm -image/x-portable-pixmap ppm -image/x-rgb rgb -image/x-tga tga -image/x-xbitmap xbm -image/x-xpixmap xpm -image/x-xwindowdump xwd -message/rfc822 eml mime -model/iges igs iges -model/mesh msh mesh silo -model/vnd.collada+xml dae -model/vnd.dwf dwf -model/vnd.gdl gdl -model/vnd.gtw gtw -model/vnd.mts mts -model/vnd.vtu vtu -model/vrml wrl vrml -model/x3d+binary x3db x3dbz -model/x3d+vrml x3dv x3dvz -model/x3d+xml x3d x3dz -text/cache-manifest appcache -text/calendar ics ifb -text/css css -text/csv csv -text/html html htm -text/n3 n3 -text/plain txt text conf def list log in -text/prs.lines.tag dsc -text/richtext rtx -text/sgml sgml sgm -text/tab-separated-values tsv -text/troff t tr roff man me ms -text/turtle ttl -text/uri-list uri uris urls -text/vcard vcard -text/vnd.curl curl -text/vnd.curl.dcurl dcurl -text/vnd.curl.mcurl mcurl -text/vnd.curl.scurl scurl -text/vnd.dvb.subtitle sub -text/vnd.fly fly -text/vnd.fmi.flexstor flx -text/vnd.graphviz gv -text/vnd.in3d.3dml 3dml -text/vnd.in3d.spot spot -text/vnd.sun.j2me.app-descriptor jad -text/vnd.wap.wml wml -text/vnd.wap.wmlscript wmls -text/x-asm s asm -text/x-c c cc cxx cpp h hh dic -text/x-fortran f for f77 f90 -text/x-java-source java -text/x-nfo nfo -text/x-opml opml -text/x-pascal p pas -text/x-php php -text/x-setext etx -text/x-sfv sfv -text/x-uuencode uu -text/x-vcalendar vcs -text/x-vcard vcf -video/3gpp 3gp -video/3gpp2 3g2 -video/h261 h261 -video/h263 h263 -video/h264 h264 -video/h265 h265 -video/jpeg jpgv -video/jpm jpm jpgm -video/mj2 mj2 mjp2 -video/mp4 mp4 mp4v mpg4 -video/mpeg mpeg mpg mpe m1v m2v -video/ogg ogv -video/quicktime qt mov -video/vnd.dece.hd uvh uvvh -video/vnd.dece.mobile uvm uvvm -video/vnd.dece.pd uvp uvvp -video/vnd.dece.sd uvs uvvs -video/vnd.dece.video uvv uvvv -video/vnd.dvb.file dvb -video/vnd.fvt fvt -video/vnd.mpegurl mxu m4u -video/vnd.ms-playready.media.pyv pyv -video/vnd.uvvu.mp4 uvu uvvu -video/vnd.vivo viv -video/webm webm -video/x-f4v f4v -video/x-fli fli -video/x-flv flv -video/x-m4v m4v -video/x-matroska mkv mk3d mks -video/x-mng mng -video/x-ms-asf asf asx -video/x-ms-vob vob -video/x-ms-wm wm -video/x-ms-wmv wmv -video/x-ms-wmx wmx -video/x-ms-wvx wvx -video/x-msvideo avi -video/x-sgi-movie movie -video/x-smv smv -x-conference/x-cooltalk ice diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/AesCtrByteFlow.h b/submodules/ton/tonlib-src/tdutils/td/utils/AesCtrByteFlow.h deleted file mode 100644 index 8ce35b49..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/AesCtrByteFlow.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/ByteFlow.h" -#include "td/utils/common.h" -#include "td/utils/crypto.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/UInt.h" - -namespace td { - -#if TD_HAVE_OPENSSL -class AesCtrByteFlow : public ByteFlowInplaceBase { - public: - void init(const UInt256 &key, const UInt128 &iv) { - state_.init(key, iv); - } - void init(AesCtrState &&state) { - state_ = std::move(state); - } - AesCtrState move_aes_ctr_state() { - return std::move(state_); - } - void loop() override { - bool was_updated = false; - while (true) { - auto ready = input_->prepare_read(); - if (ready.empty()) { - break; - } - state_.encrypt(ready, MutableSlice(const_cast(ready.data()), ready.size())); - input_->confirm_read(ready.size()); - output_.advance_end(ready.size()); - was_updated = true; - } - if (was_updated) { - on_output_updated(); - } - if (!is_input_active_) { - finish(Status::OK()); // End of input stream. - } - set_need_size(1); - } - - private: - AesCtrState state_; -}; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/AtomicRead.h b/submodules/ton/tonlib-src/tdutils/td/utils/AtomicRead.h deleted file mode 100644 index 0eb85c6d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/AtomicRead.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include - -#include "td/utils/common.h" -#include "td/utils/port/thread.h" -namespace td { -template - -class AtomicRead { - public: - void read(T &dest) const { - while (true) { - static_assert(std::is_trivially_copyable::value, "T must be trivially copyable"); - auto version_before = version.load(); - memcpy(&dest, &value, sizeof(dest)); - auto version_after = version.load(); - if (version_before == version_after && version_before % 2 == 0) { - break; - } - td::this_thread::yield(); - } - } - - friend struct Write; - struct Write { - explicit Write(AtomicRead *read) { - read->do_lock(); - ptr.reset(read); - } - struct Destructor { - void operator()(AtomicRead *read) const { - read->do_unlock(); - } - }; - T &operator*() { - return value(); - } - T *operator->() { - return &value(); - } - T &value() { - CHECK(ptr); - return ptr->value; - } - - private: - std::unique_ptr ptr; - }; - Write lock() { - return Write(this); - } - - private: - std::atomic version{0}; - T value; - - void do_lock() { - CHECK(++version % 2 == 1); - } - void do_unlock() { - CHECK(++version % 2 == 0); - } -}; -}; // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.cpp deleted file mode 100644 index 91341352..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/BigNum.h" - -char disable_linker_warning_about_empty_file_bignum_cpp TD_UNUSED; - -#if TD_HAVE_OPENSSL - -#include "td/utils/logging.h" -#include "td/utils/misc.h" - -#include -#include - -namespace td { - -class BigNumContext::Impl { - public: - BN_CTX *big_num_context; - - Impl() : big_num_context(BN_CTX_new()) { - LOG_IF(FATAL, big_num_context == nullptr); - } - Impl(const Impl &other) = delete; - Impl &operator=(const Impl &other) = delete; - Impl(Impl &&other) = delete; - Impl &operator=(Impl &&other) = delete; - ~Impl() { - BN_CTX_free(big_num_context); - } -}; - -BigNumContext::BigNumContext() : impl_(make_unique()) { -} - -BigNumContext::BigNumContext(BigNumContext &&other) = default; -BigNumContext &BigNumContext::operator=(BigNumContext &&other) = default; - -BigNumContext::~BigNumContext() = default; - -class BigNum::Impl { - public: - BIGNUM *big_num; - - Impl() : Impl(BN_new()) { - } - explicit Impl(BIGNUM *big_num) : big_num(big_num) { - LOG_IF(FATAL, big_num == nullptr); - } - Impl(const Impl &other) = delete; - Impl &operator=(const Impl &other) = delete; - Impl(Impl &&other) = delete; - Impl &operator=(Impl &&other) = delete; - ~Impl() { - BN_clear_free(big_num); - } -}; - -BigNum::BigNum() : impl_(make_unique()) { -} - -BigNum::BigNum(const BigNum &other) : BigNum() { - *this = other; -} - -BigNum &BigNum::operator=(const BigNum &other) { - CHECK(impl_ != nullptr); - CHECK(other.impl_ != nullptr); - BIGNUM *result = BN_copy(impl_->big_num, other.impl_->big_num); - LOG_IF(FATAL, result == nullptr); - return *this; -} - -BigNum::BigNum(BigNum &&other) = default; - -BigNum &BigNum::operator=(BigNum &&other) = default; - -BigNum::~BigNum() = default; - -BigNum BigNum::from_binary(Slice str) { - return BigNum(make_unique(BN_bin2bn(str.ubegin(), narrow_cast(str.size()), nullptr))); -} - -BigNum BigNum::from_le_binary(Slice str) { -#if defined(OPENSSL_IS_BORINGSSL) - return BigNum(make_unique(BN_le2bn(str.ubegin(), narrow_cast(str.size()), nullptr))); -#elif OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) - return BigNum(make_unique(BN_lebin2bn(str.ubegin(), narrow_cast(str.size()), nullptr))); -#else - LOG(FATAL) << "Unsupported from_le_binary"; - return BigNum(); -#endif -} - -Result BigNum::from_decimal(CSlice str) { - BigNum result; - int res = BN_dec2bn(&result.impl_->big_num, str.c_str()); - if (res == 0 || static_cast(res) != str.size()) { - return Status::Error(PSLICE() << "Failed to parse \"" << str << "\" as BigNum"); - } - return result; -} - -Result BigNum::from_hex(CSlice str) { - BigNum result; - int res = BN_hex2bn(&result.impl_->big_num, str.c_str()); - if (res == 0 || static_cast(res) != str.size()) { - return Status::Error(PSLICE() << "Failed to parse \"" << str << "\" as hexadecimal BigNum"); - } - return result; -} - -BigNum BigNum::from_raw(void *openssl_big_num) { - return BigNum(make_unique(static_cast(openssl_big_num))); -} - -BigNum::BigNum(unique_ptr &&impl) : impl_(std::move(impl)) { -} - -void BigNum::ensure_const_time() { -#if !defined(OPENSSL_IS_BORINGSSL) - BN_set_flags(impl_->big_num, BN_FLG_CONSTTIME); -#else - LOG(FATAL) << "Unsupported BN_FLG_CONSTTIME"; -#endif -} - -int BigNum::get_num_bits() const { - return BN_num_bits(impl_->big_num); -} - -int BigNum::get_num_bytes() const { - return BN_num_bytes(impl_->big_num); -} - -void BigNum::set_bit(int num) { - int result = BN_set_bit(impl_->big_num, num); - LOG_IF(FATAL, result != 1); -} - -void BigNum::clear_bit(int num) { - int result = BN_clear_bit(impl_->big_num, num); - LOG_IF(FATAL, result != 1); -} - -bool BigNum::is_bit_set(int num) const { - return BN_is_bit_set(impl_->big_num, num) != 0; -} - -bool BigNum::is_prime(BigNumContext &context) const { - int result = BN_is_prime_ex(impl_->big_num, BN_prime_checks, context.impl_->big_num_context, nullptr); - LOG_IF(FATAL, result == -1); - return result == 1; -} - -void BigNum::operator+=(uint32 value) { - int result = BN_add_word(impl_->big_num, value); - LOG_IF(FATAL, result != 1); -} - -void BigNum::operator-=(uint32 value) { - int result = BN_sub_word(impl_->big_num, value); - LOG_IF(FATAL, result != 1); -} - -void BigNum::operator*=(uint32 value) { - int result = BN_mul_word(impl_->big_num, value); - LOG_IF(FATAL, result != 1); -} - -void BigNum::operator/=(uint32 value) { - BN_ULONG result = BN_div_word(impl_->big_num, value); - LOG_IF(FATAL, result == static_cast(-1)); -} - -uint32 BigNum::operator%(uint32 value) const { - BN_ULONG result = BN_mod_word(impl_->big_num, value); - LOG_IF(FATAL, result == static_cast(-1)); - return narrow_cast(result); -} - -void BigNum::set_value(uint32 new_value) { - if (new_value == 0) { - BN_zero(impl_->big_num); - } else { - int result = BN_set_word(impl_->big_num, new_value); - LOG_IF(FATAL, result != 1); - } -} - -BigNum BigNum::clone() const { - BIGNUM *result = BN_dup(impl_->big_num); - LOG_IF(FATAL, result == nullptr); - return BigNum(make_unique(result)); -} - -string BigNum::to_binary(int exact_size) const { - int num_size = get_num_bytes(); - if (exact_size == -1) { - exact_size = num_size; - } else { - CHECK(exact_size >= num_size); - } - string res(exact_size, '\0'); - BN_bn2bin(impl_->big_num, MutableSlice(res).ubegin() + (exact_size - num_size)); - return res; -} - -string BigNum::to_le_binary(int exact_size) const { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) || defined(OPENSSL_IS_BORINGSSL) - int num_size = get_num_bytes(); - if (exact_size == -1) { - exact_size = num_size; - } else { - CHECK(exact_size >= num_size); - } - string res(exact_size, '\0'); -#if defined(OPENSSL_IS_BORINGSSL) - BN_bn2le_padded(MutableSlice(res).ubegin(), exact_size, impl_->big_num); -#else - BN_bn2lebinpad(impl_->big_num, MutableSlice(res).ubegin(), exact_size); -#endif - return res; -#else - LOG(FATAL) << "Unsupported to_le_binary"; - return ""; -#endif -} - -string BigNum::to_decimal() const { - char *result = BN_bn2dec(impl_->big_num); - CHECK(result != nullptr); - string res(result); - OPENSSL_free(result); - return res; -} - -void BigNum::random(BigNum &r, int bits, int top, int bottom) { - int result = BN_rand(r.impl_->big_num, bits, top, bottom); - LOG_IF(FATAL, result != 1); -} - -void BigNum::add(BigNum &r, const BigNum &a, const BigNum &b) { - int result = BN_add(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num); - LOG_IF(FATAL, result != 1); -} - -void BigNum::sub(BigNum &r, const BigNum &a, const BigNum &b) { - CHECK(r.impl_->big_num != a.impl_->big_num); - CHECK(r.impl_->big_num != b.impl_->big_num); - int result = BN_sub(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mul(BigNum &r, BigNum &a, BigNum &b, BigNumContext &context) { - int result = BN_mul(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mod_add(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) { - int result = BN_mod_add(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num, - context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mod_sub(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) { - int result = BN_mod_sub(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num, - context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mod_mul(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) { - int result = BN_mod_mul(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num, - context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mod_inverse(BigNum &r, BigNum &a, const BigNum &m, BigNumContext &context) { - auto result = BN_mod_inverse(r.impl_->big_num, a.impl_->big_num, m.impl_->big_num, context.impl_->big_num_context); - LOG_IF(FATAL, result != r.impl_->big_num); -} - -void BigNum::div(BigNum *quotient, BigNum *remainder, const BigNum ÷nd, const BigNum &divisor, - BigNumContext &context) { - auto q = quotient == nullptr ? nullptr : quotient->impl_->big_num; - auto r = remainder == nullptr ? nullptr : remainder->impl_->big_num; - if (q == nullptr && r == nullptr) { - return; - } - - auto result = BN_div(q, r, dividend.impl_->big_num, divisor.impl_->big_num, context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::mod_exp(BigNum &r, const BigNum &a, const BigNum &p, const BigNum &m, BigNumContext &context) { - int result = BN_mod_exp(r.impl_->big_num, a.impl_->big_num, p.impl_->big_num, m.impl_->big_num, - context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -void BigNum::gcd(BigNum &r, BigNum &a, BigNum &b, BigNumContext &context) { - int result = BN_gcd(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, context.impl_->big_num_context); - LOG_IF(FATAL, result != 1); -} - -int BigNum::compare(const BigNum &a, const BigNum &b) { - return BN_cmp(a.impl_->big_num, b.impl_->big_num); -} - -StringBuilder &operator<<(StringBuilder &sb, const BigNum &bn) { - return sb << bn.to_decimal(); -} - -} // namespace td -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.h b/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.h deleted file mode 100644 index 73e3e21e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BigNum.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#if TD_HAVE_OPENSSL - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" - -namespace td { - -class BigNumContext { - public: - BigNumContext(); - BigNumContext(const BigNumContext &other) = delete; - BigNumContext &operator=(const BigNumContext &other) = delete; - BigNumContext(BigNumContext &&other); - BigNumContext &operator=(BigNumContext &&other); - ~BigNumContext(); - - private: - class Impl; - unique_ptr impl_; - - friend class BigNum; -}; - -class BigNum { - public: - BigNum(); - BigNum(const BigNum &other); - BigNum &operator=(const BigNum &other); - BigNum(BigNum &&other); - BigNum &operator=(BigNum &&other); - ~BigNum(); - - static BigNum from_binary(Slice str); - - // Available only if OpenSSL >= 1.1.0 - static BigNum from_le_binary(Slice str); - - static Result from_decimal(CSlice str); - - static Result from_hex(CSlice str); - - static BigNum from_raw(void *openssl_big_num); - - void set_value(uint32 new_value); - - void ensure_const_time(); - - int get_num_bits() const; - - int get_num_bytes() const; - - void set_bit(int num); - - void clear_bit(int num); - - bool is_bit_set(int num) const; - - bool is_prime(BigNumContext &context) const; - - BigNum clone() const; - - string to_binary(int exact_size = -1) const; - - // Available only if OpenSSL >= 1.1.0 - string to_le_binary(int exact_size = -1) const; - - string to_decimal() const; - - void operator+=(uint32 value); - - void operator-=(uint32 value); - - void operator*=(uint32 value); - - void operator/=(uint32 value); - - uint32 operator%(uint32 value) const; - - static void random(BigNum &r, int bits, int top, int bottom); - - static void add(BigNum &r, const BigNum &a, const BigNum &b); - - static void sub(BigNum &r, const BigNum &a, const BigNum &b); - - static void mul(BigNum &r, BigNum &a, BigNum &b, BigNumContext &context); - - static void mod_add(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context); - - static void mod_sub(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context); - - static void mod_mul(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context); - - static void mod_inverse(BigNum &r, BigNum &a, const BigNum &m, BigNumContext &context); - - static void div(BigNum *quotient, BigNum *remainder, const BigNum ÷nd, const BigNum &divisor, - BigNumContext &context); - - static void mod_exp(BigNum &r, const BigNum &a, const BigNum &p, const BigNum &m, BigNumContext &context); - - static void gcd(BigNum &r, BigNum &a, BigNum &b, BigNumContext &context); - - static int compare(const BigNum &a, const BigNum &b); - - private: - class Impl; - unique_ptr impl_; - - explicit BigNum(unique_ptr &&impl); -}; - -StringBuilder &operator<<(StringBuilder &sb, const BigNum &bn); - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/BufferedFd.h deleted file mode 100644 index 9940eb1e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedFd.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/IoSlice.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/Status.h" - -#include - -namespace td { -// just reads from given reader and writes to given writer -template -class BufferedFdBase : public FdT { - public: - BufferedFdBase() = default; - explicit BufferedFdBase(FdT &&fd_); - // TODO: make move constructor and move assignment safer - - Result flush_read(size_t max_read = std::numeric_limits::max()) TD_WARN_UNUSED_RESULT; - Result flush_write() TD_WARN_UNUSED_RESULT; - - bool need_flush_write(size_t at_least = 0) { - CHECK(write_); - write_->sync_with_writer(); - return write_->size() > at_least; - } - size_t ready_for_flush_write() { - CHECK(write_); - write_->sync_with_writer(); - return write_->size(); - } - void set_input_writer(ChainBufferWriter *read) { - read_ = read; - } - void set_output_reader(ChainBufferReader *write) { - write_ = write; - } - - private: - ChainBufferWriter *read_ = nullptr; - ChainBufferReader *write_ = nullptr; -}; - -template -class BufferedFd : public BufferedFdBase { - using Parent = BufferedFdBase; - ChainBufferWriter input_writer_; - ChainBufferReader input_reader_; - ChainBufferWriter output_writer_; - ChainBufferReader output_reader_; - void init(); - void init_ptr(); - - public: - BufferedFd(); - explicit BufferedFd(FdT &&fd_); - BufferedFd(BufferedFd &&); - BufferedFd &operator=(BufferedFd &&); - BufferedFd(const BufferedFd &) = delete; - BufferedFd &operator=(const BufferedFd &) = delete; - ~BufferedFd(); - - void close(); - size_t left_unread() { - return input_reader_.size(); - } - size_t left_unwritten() { - return output_reader_.size(); - } - - Result flush_read(size_t max_read = std::numeric_limits::max()) TD_WARN_UNUSED_RESULT; - Result flush_write() TD_WARN_UNUSED_RESULT; - - // Yep, direct access to buffers. It is IO interface too. - ChainBufferReader &input_buffer(); - ChainBufferWriter &output_buffer(); -}; - -// IMPLEMENTATION - -/*** BufferedFd ***/ -template -BufferedFdBase::BufferedFdBase(FdT &&fd_) : FdT(std::move(fd_)) { -} - -template -Result BufferedFdBase::flush_read(size_t max_read) { - CHECK(read_); - size_t result = 0; - while (::td::can_read(*this) && max_read) { - MutableSlice slice = read_->prepare_append().truncate(max_read); - TRY_RESULT(x, FdT::read(slice)); - slice.truncate(x); - read_->confirm_append(x); - result += x; - max_read -= x; - } - return result; -} - -template -Result BufferedFdBase::flush_write() { - // TODO: sync on demand - write_->sync_with_writer(); - size_t result = 0; - while (!write_->empty() && ::td::can_write(*this)) { - constexpr size_t buf_size = 20; - IoSlice buf[buf_size]; - - auto it = write_->clone(); - size_t buf_i; - for (buf_i = 0; buf_i < buf_size; buf_i++) { - Slice slice = it.prepare_read(); - if (slice.empty()) { - break; - } - buf[buf_i] = as_io_slice(slice); - it.confirm_read(slice.size()); - } - TRY_RESULT(x, FdT::writev(Span(buf, buf_i))); - write_->advance(x); - result += x; - } - return result; -} - -/*** BufferedFd ***/ -template -void BufferedFd::init() { - input_reader_ = input_writer_.extract_reader(); - output_reader_ = output_writer_.extract_reader(); - init_ptr(); -} - -template -void BufferedFd::init_ptr() { - this->set_input_writer(&input_writer_); - this->set_output_reader(&output_reader_); -} - -template -BufferedFd::BufferedFd() { - init(); -} - -template -BufferedFd::BufferedFd(FdT &&fd_) : Parent(std::move(fd_)) { - init(); -} - -template -BufferedFd::BufferedFd(BufferedFd &&from) { - *this = std::move(from); -} - -template -BufferedFd &BufferedFd::operator=(BufferedFd &&from) { - FdT::operator=(std::move(static_cast(from))); - input_reader_ = std::move(from.input_reader_); - input_writer_ = std::move(from.input_writer_); - output_reader_ = std::move(from.output_reader_); - output_writer_ = std::move(from.output_writer_); - init_ptr(); - return *this; -} - -template -BufferedFd::~BufferedFd() { - close(); -} - -template -void BufferedFd::close() { - FdT::close(); - // TODO: clear buffers -} - -template -Result BufferedFd::flush_read(size_t max_read) { - TRY_RESULT(result, Parent::flush_read(max_read)); - if (result) { - // TODO: faster sync is possible if you owns writer. - input_reader_.sync_with_writer(); - LOG(DEBUG) << "Flush read: +" << format::as_size(result) << tag("total", format::as_size(input_reader_.size())); - } - return result; -} - -template -Result BufferedFd::flush_write() { - TRY_RESULT(result, Parent::flush_write()); - if (result) { - LOG(DEBUG) << "Flush write: +" << format::as_size(result) << tag("left", format::as_size(output_reader_.size())); - } - return result; -} - -// Yep, direct access to buffers. It is IO interface too. -template -ChainBufferReader &BufferedFd::input_buffer() { - return input_reader_; -} - -template -ChainBufferWriter &BufferedFd::output_buffer() { - return output_writer_; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedReader.h b/submodules/ton/tonlib-src/tdutils/td/utils/BufferedReader.h deleted file mode 100644 index da639b3d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedReader.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -class BufferedReader { - public: - explicit BufferedReader(FileFd &file, size_t buff_size = 8152) - : file_(file), buff_(buff_size), begin_pos_(0), end_pos_(0) { - } - - Result read(MutableSlice slice) TD_WARN_UNUSED_RESULT; - - private: - FileFd &file_; - vector buff_; - size_t begin_pos_; - size_t end_pos_; -}; - -inline Result BufferedReader::read(MutableSlice slice) { - size_t available = end_pos_ - begin_pos_; - if (available >= slice.size()) { - // have enough data in buffer - slice.copy_from({&buff_[begin_pos_], slice.size()}); - begin_pos_ += slice.size(); - return slice.size(); - } - - if (available) { - slice.copy_from({&buff_[begin_pos_], available}); - begin_pos_ += available; - slice.remove_prefix(available); - } - - if (slice.size() > buff_.size() / 2) { - TRY_RESULT(result, file_.read(slice)); - return result + available; - } - - TRY_RESULT(result, file_.read({&buff_[0], buff_.size()})); - begin_pos_ = 0; - end_pos_ = result; - - size_t left = min(end_pos_, slice.size()); - slice.copy_from({&buff_[0], left}); - begin_pos_ = left; - return left + available; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.cpp deleted file mode 100644 index 2f9add2e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/BufferedUdp.h" - -char disable_linker_warning_about_empty_file_buffered_udp_cpp TD_UNUSED; - -namespace td { - -#if TD_PORT_POSIX -TD_THREAD_LOCAL detail::UdpReader *BufferedUdp::udp_reader_; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.h b/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.h deleted file mode 100644 index 8a966c0b..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/BufferedUdp.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/optional.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/port/UdpSocketFd.h" -#include "td/utils/Span.h" -#include "td/utils/Status.h" -#include "td/utils/VectorQueue.h" - -#include - -namespace td { - -#if TD_PORT_POSIX -namespace detail { -class UdpWriter { - public: - static Status write_once(UdpSocketFd &fd, VectorQueue &queue) TD_WARN_UNUSED_RESULT { - std::array messages; - auto to_send = queue.as_span(); - size_t to_send_n = td::min(messages.size(), to_send.size()); - to_send.truncate(to_send_n); - for (size_t i = 0; i < to_send_n; i++) { - messages[i].to = &to_send[i].address; - messages[i].data = to_send[i].data.as_slice(); - } - - size_t cnt; - auto status = fd.send_messages(::td::Span(messages).truncate(to_send_n), cnt); - queue.pop_n(cnt); - return status; - } -}; - -class UdpReaderHelper { - public: - void init_inbound_message(UdpSocketFd::InboundMessage &message) { - message.from = &message_.address; - message.error = &message_.error; - if (buffer_.size() < MAX_PACKET_SIZE) { - buffer_ = BufferSlice(RESERVED_SIZE); - } - CHECK(buffer_.size() >= MAX_PACKET_SIZE); - message.data = buffer_.as_slice().truncate(MAX_PACKET_SIZE); - } - - UdpMessage extract_udp_message(UdpSocketFd::InboundMessage &message) { - message_.data = buffer_.from_slice(message.data); - auto size = message_.data.size(); - size = (size + 7) & ~7; - CHECK(size <= MAX_PACKET_SIZE); - buffer_.confirm_read(size); - return std::move(message_); - } - - private: - enum : size_t { MAX_PACKET_SIZE = 2048, RESERVED_SIZE = MAX_PACKET_SIZE * 8 }; - UdpMessage message_; - BufferSlice buffer_; -}; - -// One for thread is enough -class UdpReader { - public: - UdpReader() { - for (size_t i = 0; i < messages_.size(); i++) { - helpers_[i].init_inbound_message(messages_[i]); - } - } - Status read_once(UdpSocketFd &fd, VectorQueue &queue) TD_WARN_UNUSED_RESULT { - for (size_t i = 0; i < messages_.size(); i++) { - CHECK(messages_[i].data.size() == 2048); - } - size_t cnt = 0; - auto status = fd.receive_messages(messages_, cnt); - for (size_t i = 0; i < cnt; i++) { - queue.push(helpers_[i].extract_udp_message(messages_[i])); - helpers_[i].init_inbound_message(messages_[i]); - } - for (size_t i = cnt; i < messages_.size(); i++) { - LOG_CHECK(messages_[i].data.size() == 2048) - << " cnt = " << cnt << " i = " << i << " size = " << messages_[i].data.size() << " status = " << status; - } - if (status.is_error() && !UdpSocketFd::is_critical_read_error(status)) { - queue.push(UdpMessage{{}, {}, std::move(status)}); - } - return status; - } - - private: - enum : size_t { BUFFER_SIZE = 16 }; - std::array messages_; - std::array helpers_; -}; - -} // namespace detail - -#endif - -class BufferedUdp : public UdpSocketFd { - public: - explicit BufferedUdp(UdpSocketFd fd) : UdpSocketFd(std::move(fd)) { - } - -#if TD_PORT_POSIX - Result> receive() { - if (input_.empty() && can_read(*this)) { - TRY_STATUS(flush_read_once()); - } - if (input_.empty()) { - return optional(); - } - return input_.pop(); - } - - void send(UdpMessage message) { - output_.push(std::move(message)); - } - - Status flush_send() { - Status status; - while (status.is_ok() && can_write(*this) && !output_.empty()) { - status = flush_send_once(); - } - return status; - } -#endif - - UdpSocketFd move_as_udp_socket_fd() { - return std::move(as_fd()); - } - - UdpSocketFd &as_fd() { - return *static_cast(this); - } - - private: -#if TD_PORT_POSIX - VectorQueue input_; - VectorQueue output_; - - VectorQueue &input() { - return input_; - } - VectorQueue &output() { - return output_; - } - - Status flush_send_once() TD_WARN_UNUSED_RESULT { - return detail::UdpWriter::write_once(as_fd(), output_); - } - - Status flush_read_once() TD_WARN_UNUSED_RESULT { - init_thread_local(udp_reader_); - return udp_reader_->read_once(as_fd(), input_); - } - - static TD_THREAD_LOCAL detail::UdpReader *udp_reader_; -#endif -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/ByteFlow.h b/submodules/ton/tonlib-src/tdutils/td/utils/ByteFlow.h deleted file mode 100644 index db30ce4d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/ByteFlow.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/common.h" -#include "td/utils/Status.h" - -namespace td { - -class ByteFlowInterface { - public: - virtual void close_input(Status status) = 0; - virtual void wakeup() = 0; - virtual void set_parent(ByteFlowInterface &other) = 0; - virtual void set_input(ChainBufferReader *input) = 0; - virtual size_t get_need_size() = 0; - ByteFlowInterface() = default; - ByteFlowInterface(const ByteFlowInterface &) = delete; - ByteFlowInterface &operator=(const ByteFlowInterface &) = delete; - ByteFlowInterface(ByteFlowInterface &&) = default; - ByteFlowInterface &operator=(ByteFlowInterface &&) = default; - virtual ~ByteFlowInterface() = default; -}; - -class ByteFlowBaseCommon : public ByteFlowInterface { - public: - ByteFlowBaseCommon() = default; - - void close_input(Status status) final { - if (status.is_error()) { - finish(std::move(status)); - } else { - is_input_active_ = false; - wakeup(); - } - } - - void wakeup() final { - if (stop_flag_) { - return; - } - input_->sync_with_writer(); - if (waiting_flag_) { - if (!is_input_active_) { - finish(Status::OK()); - } - return; - } - if (is_input_active_) { - if (need_size_ != 0 && input_->size() < need_size_) { - return; - } - } - need_size_ = 0; - loop(); - } - - size_t get_need_size() final { - return need_size_; - } - - virtual void loop() = 0; - - protected: - bool waiting_flag_ = false; - ChainBufferReader *input_ = nullptr; - bool is_input_active_ = true; - size_t need_size_ = 0; - void finish(Status status) { - stop_flag_ = true; - need_size_ = 0; - if (parent_) { - parent_->close_input(std::move(status)); - parent_ = nullptr; - } - } - - void set_need_size(size_t need_size) { - need_size_ = need_size; - } - - void on_output_updated() { - if (parent_) { - parent_->wakeup(); - } - } - void consume_input() { - waiting_flag_ = true; - if (!is_input_active_) { - finish(Status::OK()); - } - } - - private: - ByteFlowInterface *parent_ = nullptr; - bool stop_flag_ = false; - friend class ByteFlowBase; - friend class ByteFlowInplaceBase; -}; - -class ByteFlowBase : public ByteFlowBaseCommon { - public: - ByteFlowBase() = default; - - void set_input(ChainBufferReader *input) final { - input_ = input; - } - void set_parent(ByteFlowInterface &other) final { - parent_ = &other; - parent_->set_input(&output_reader_); - } - void loop() override = 0; - - // ChainBufferWriter &get_output() { - // return output_; - //} - - protected: - ChainBufferWriter output_; - ChainBufferReader output_reader_ = output_.extract_reader(); -}; - -class ByteFlowInplaceBase : public ByteFlowBaseCommon { - public: - ByteFlowInplaceBase() = default; - - void set_input(ChainBufferReader *input) final { - input_ = input; - output_ = ChainBufferReader(input_->begin().clone(), input_->begin().clone(), false); - } - void set_parent(ByteFlowInterface &other) final { - parent_ = &other; - parent_->set_input(&output_); - } - void loop() override = 0; - - ChainBufferReader &get_output() { - return output_; - } - - protected: - ChainBufferReader output_; -}; - -inline ByteFlowInterface &operator>>(ByteFlowInterface &from, ByteFlowInterface &to) { - from.set_parent(to); - return to; -} - -class ByteFlowSource : public ByteFlowInterface { - public: - ByteFlowSource() = default; - explicit ByteFlowSource(ChainBufferReader *buffer) : buffer_(buffer) { - } - ByteFlowSource(ByteFlowSource &&other) : buffer_(other.buffer_), parent_(other.parent_) { - other.buffer_ = nullptr; - other.parent_ = nullptr; - } - ByteFlowSource &operator=(ByteFlowSource &&other) { - buffer_ = other.buffer_; - parent_ = other.parent_; - other.buffer_ = nullptr; - other.parent_ = nullptr; - return *this; - } - ByteFlowSource(const ByteFlowSource &) = delete; - ByteFlowSource &operator=(const ByteFlowSource &) = delete; - ~ByteFlowSource() override = default; - - void set_input(ChainBufferReader *) final { - UNREACHABLE(); - } - void set_parent(ByteFlowInterface &parent) final { - CHECK(parent_ == nullptr); - parent_ = &parent; - parent_->set_input(buffer_); - } - void close_input(Status status) final { - CHECK(parent_); - parent_->close_input(std::move(status)); - parent_ = nullptr; - } - void wakeup() final { - CHECK(parent_); - parent_->wakeup(); - } - size_t get_need_size() final { - if (parent_ == nullptr) { - return 0; - } - return parent_->get_need_size(); - } - - private: - ChainBufferReader *buffer_ = nullptr; - ByteFlowInterface *parent_ = nullptr; -}; - -class ByteFlowSink : public ByteFlowInterface { - public: - void set_input(ChainBufferReader *input) final { - CHECK(buffer_ == nullptr); - buffer_ = input; - } - void set_parent(ByteFlowInterface & /*parent*/) final { - UNREACHABLE(); - } - void close_input(Status status) final { - CHECK(active_); - active_ = false; - status_ = std::move(status); - buffer_->sync_with_writer(); - } - void wakeup() final { - buffer_->sync_with_writer(); - } - size_t get_need_size() final { - UNREACHABLE(); - return 0; - } - bool is_ready() { - return !active_; - } - Status &status() { - return status_; - } - ChainBufferReader *result() { - CHECK(is_ready() && status().is_ok()); - return buffer_; - } - ChainBufferReader *get_output() { - return buffer_; - } - - private: - bool active_ = true; - Status status_; - ChainBufferReader *buffer_ = nullptr; -}; - -class ByteFlowMoveSink : public ByteFlowInterface { - public: - ByteFlowMoveSink() = default; - explicit ByteFlowMoveSink(ChainBufferWriter *output) { - set_output(output); - } - void set_input(ChainBufferReader *input) final { - CHECK(!input_); - input_ = input; - } - void set_parent(ByteFlowInterface & /*parent*/) final { - UNREACHABLE(); - } - void close_input(Status status) final { - CHECK(active_); - active_ = false; - status_ = std::move(status); - wakeup(); - } - void wakeup() final { - input_->sync_with_writer(); - output_->append(*input_); - } - size_t get_need_size() final { - UNREACHABLE(); - return 0; - } - void set_output(ChainBufferWriter *output) { - CHECK(!output_); - output_ = output; - } - - bool is_ready() { - return !active_; - } - Status &status() { - return status_; - } - - private: - bool active_ = true; - Status status_; - ChainBufferReader *input_ = nullptr; - ChainBufferWriter *output_ = nullptr; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h b/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h deleted file mode 100644 index 9f30d204..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include - -namespace td { - -namespace detail { -struct RawCancellationToken { - std::atomic is_cancelled_{false}; -}; -} // namespace detail - -class CancellationToken { - public: - explicit operator bool() const { - // Empty CancellationToken is never cancelled - if (!token_) { - return false; - } - return token_->is_cancelled_.load(std::memory_order_acquire); - } - CancellationToken() = default; - explicit CancellationToken(std::shared_ptr token) : token_(std::move(token)) { - } - - private: - std::shared_ptr token_; -}; - -class CancellationTokenSource { - public: - CancellationTokenSource() = default; - CancellationTokenSource(CancellationTokenSource &&other) : token_(std::move(other.token_)) { - } - CancellationTokenSource &operator=(CancellationTokenSource &&other) { - cancel(); - token_ = std::move(other.token_); - return *this; - } - CancellationTokenSource(const CancellationTokenSource &other) = delete; - CancellationTokenSource &operator=(const CancellationTokenSource &other) = delete; - ~CancellationTokenSource() { - cancel(); - } - - CancellationToken get_cancellation_token() { - if (!token_) { - token_ = std::make_shared(); - } - return CancellationToken(token_); - } - void cancel() { - if (!token_) { - return; - } - token_->is_cancelled_.store(true, std::memory_order_release); - token_.reset(); - } - - private: - std::shared_ptr token_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/ChangesProcessor.h b/submodules/ton/tonlib-src/tdutils/td/utils/ChangesProcessor.h deleted file mode 100644 index 16c37dd3..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/ChangesProcessor.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include - -namespace td { - -// Process changes after they are finished in order of addition -template -class ChangesProcessor { - public: - using Id = uint64; - - void clear() { - offset_ += data_array_.size(); - ready_i_ = 0; - data_array_.clear(); - } - - template - Id add(FromDataT &&data) { - auto res = offset_ + data_array_.size(); - data_array_.emplace_back(std::forward(data), false); - return static_cast(res); - } - - template - void finish(Id token, F &&func) { - size_t pos = static_cast(token) - offset_; - if (pos >= data_array_.size()) { - return; - } - data_array_[pos].second = true; - while (ready_i_ < data_array_.size() && data_array_[ready_i_].second == true) { - func(std::move(data_array_[ready_i_].first)); - ready_i_++; - } - try_compactify(); - } - - private: - size_t offset_ = 1; - size_t ready_i_ = 0; - std::vector> data_array_; - void try_compactify() { - if (ready_i_ > 5 && ready_i_ * 2 > data_array_.size()) { - data_array_.erase(data_array_.begin(), data_array_.begin() + ready_i_); - offset_ += ready_i_; - ready_i_ = 0; - } - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Closure.h b/submodules/ton/tonlib-src/tdutils/td/utils/Closure.h deleted file mode 100644 index 3b2fc9de..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Closure.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/invoke.h" -#include "td/utils/logging.h" - -#include -#include -#include -#include - -// -// Essentially we have: -// (ActorT::func, arg1, arg2, ..., argn) -// We want to call: -// actor->func(arg1, arg2, ..., argn) -// And in some cases we would like to delay this call. -// -// First attempt would be -// [a1=arg1, a2=arg2, ..., an=argn](ActorT *actor) { -// actor->func(a1, a2, ..., an) -// } -// -// But there are some difficulties with elimitation on unnecessary copies. -// We want to use move constructor when it is possible -// -// We may pass -// Tmp. Temporary / rvalue reference -// Var. Variable / reference -// CnstRef. const reference -// -// -// Function may expect -// Val. Value -// CnstRef. const reference -// Ref. rvalue reverence / reference -// -// TODO: -// Immediate call / Delayed call -// Tmp->Val move / move->move -// Tmp->CnstRef + / move->+ -// Tmp->Ref + / move->+ -// Var->Val copy / copy->move -// Var->CnstRef + / copy-> -// Var->Ref + / copy->+ // khm. It will complile, but won't work -// -// So I will use common idiom: forward references -// If delay is needed, just std::forward data to temporary storage, and std::move them when call is executed. -// -// -// create_immediate_closure(&ActorT::func, arg1, arg2, ..., argn).run(actor) -// to_delayed_closure(std::move(immediate)).run(actor) - -namespace td { -template -class DelayedClosure; - -template -class ImmediateClosure { - public: - using Delayed = DelayedClosure; - friend Delayed; - using ActorType = ActorT; - - // no &&. just save references as references. - explicit ImmediateClosure(FunctionT func, ArgsT... args) : args(func, std::forward(args)...) { - } - - private: - std::tuple args; - - public: - auto run(ActorT *actor) -> decltype(mem_call_tuple(actor, std::move(args))) { - return mem_call_tuple(actor, std::move(args)); - } -}; - -template -ImmediateClosure create_immediate_closure( - ResultT (ActorT::*func)(DestArgsT...), SrcArgsT &&... args) { - return ImmediateClosure(func, - std::forward(args)...); -} - -template -class DelayedClosure { - public: - using ActorType = ActorT; - using Delayed = DelayedClosure; - - DelayedClosure clone() const { - return do_clone(*this); - } - - explicit DelayedClosure(ImmediateClosure &&other) : args(std::move(other.args)) { - } - - explicit DelayedClosure(FunctionT func, ArgsT... args) : args(func, std::forward(args)...) { - } - - template - void for_each(const F &f) { - tuple_for_each(args, f); - } - - private: - using ArgsStorageT = std::tuple::type...>; - - ArgsStorageT args; - - template - explicit DelayedClosure(const DelayedClosure &other, - std::enable_if_t::value...>::value, int> = 0) - : args(other.args) { - } - - template - explicit DelayedClosure( - const DelayedClosure &other, - std::enable_if_t::value...>::value, int> = 0) { - LOG(FATAL) << "Deleted constructor"; - std::abort(); - } - - template - std::enable_if_t::value...>::value, - DelayedClosure> - do_clone(const DelayedClosure &value) const { - LOG(FATAL) << "Trying to clone DelayedClosure that contains noncopyable elements"; - std::abort(); - } - - template - std::enable_if_t::value...>::value, - DelayedClosure> - do_clone(const DelayedClosure &value) const { - return DelayedClosure(value); - } - - public: - auto run(ActorT *actor) -> decltype(mem_call_tuple(actor, std::move(args))) { - return mem_call_tuple(actor, std::move(args)); - } -}; - -template -typename ImmediateClosure::Delayed to_delayed_closure(ImmediateClosure &&other) { - return typename ImmediateClosure::Delayed(std::move(other)); -} - -template -DelayedClosure to_delayed_closure(DelayedClosure &&other) { - return std::move(other); -} - -template -auto create_delayed_closure(ResultT (ActorT::*func)(DestArgsT...), SrcArgsT &&... args) { - return DelayedClosure(func, - std::forward(args)...); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/ConcurrentHashTable.h b/submodules/ton/tonlib-src/tdutils/td/utils/ConcurrentHashTable.h deleted file mode 100644 index 95661e94..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/ConcurrentHashTable.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/HazardPointers.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread_local.h" - -#include -#include -#include - -namespace td { - -// AtomicHashArray -// Building block for other concurrent hash maps -// -// Support one operation: -// template -// bool with_value(KeyT key, bool should_create, F &&func); -// -// Finds slot for key, and call func(value) -// Creates slot if should_create is true. -// Returns true if func was called. -// -// Concurrent calls with the same key may result in concurrent calls to func(value) -// It is responsibility of the caller to handle such races. -// -// Key should already be random -// It is responsibility of the caller to provide unique random key. -// One may use injective hash function, or handle collisions in some other way. - -template -class AtomicHashArray { - public: - explicit AtomicHashArray(size_t n) : nodes_(n) { - } - struct Node { - std::atomic key{KeyT{}}; - ValueT value{}; - }; - size_t size() const { - return nodes_.size(); - } - Node &node_at(size_t i) { - return nodes_[i]; - } - static KeyT empty_key() { - return KeyT{}; - } - - template - bool with_value(KeyT key, bool should_create, F &&f) { - DCHECK(key != empty_key()); - size_t pos = static_cast(key) % nodes_.size(); - size_t n = td::min(td::max(static_cast(300), nodes_.size() / 16 + 2), nodes_.size()); - - for (size_t i = 0; i < n; i++) { - pos++; - if (pos >= nodes_.size()) { - pos = 0; - } - auto &node = nodes_[pos]; - while (true) { - auto node_key = node.key.load(std::memory_order_acquire); - if (node_key == empty_key()) { - if (!should_create) { - return false; - } - KeyT expected_key = empty_key(); - if (node.key.compare_exchange_strong(expected_key, key, std::memory_order_relaxed, - std::memory_order_relaxed)) { - f(node.value); - return true; - } - } else if (node_key == key) { - f(node.value); - return true; - } else { - break; - } - } - } - return false; - } - - private: - std::vector nodes_; -}; - -// Simple concurrent hash map with multiple limitations -template -class ConcurrentHashMap { - using HashMap = AtomicHashArray>; - static HazardPointers hp_; - - public: - explicit ConcurrentHashMap(size_t n = 32) { - n = 1; - hash_map_.store(make_unique(n).release()); - } - ConcurrentHashMap(const ConcurrentHashMap &) = delete; - ConcurrentHashMap &operator=(const ConcurrentHashMap &) = delete; - ConcurrentHashMap(ConcurrentHashMap &&) = delete; - ConcurrentHashMap &operator=(ConcurrentHashMap &&) = delete; - ~ConcurrentHashMap() { - unique_ptr(hash_map_.load()); - } - - static std::string get_name() { - return "ConcurrrentHashMap"; - } - - static KeyT empty_key() { - return KeyT{}; - } - static ValueT empty_value() { - return ValueT{}; - } - static ValueT migrate_value() { - return (ValueT)(1); // c-style conversion because reinterpret_cast(1) is CE in MSVC - } - - ValueT insert(KeyT key, ValueT value) { - CHECK(key != empty_key()); - CHECK(value != migrate_value()); - typename HazardPointers::Holder holder(hp_, get_thread_id(), 0); - while (true) { - auto hash_map = holder.protect(hash_map_); - if (!hash_map) { - do_migrate(nullptr); - continue; - } - - bool ok = false; - ValueT inserted_value; - hash_map->with_value(key, true, [&](auto &node_value) { - ValueT expected_value = this->empty_value(); - if (node_value.compare_exchange_strong(expected_value, value, std::memory_order_release, - std::memory_order_acquire)) { - ok = true; - inserted_value = value; - } else { - if (expected_value == this->migrate_value()) { - ok = false; - } else { - ok = true; - inserted_value = expected_value; - } - } - }); - if (ok) { - return inserted_value; - } - do_migrate(hash_map); - } - } - - ValueT find(KeyT key, ValueT value) { - typename HazardPointers::Holder holder(hp_, get_thread_id(), 0); - while (true) { - auto hash_map = holder.protect(hash_map_); - if (!hash_map) { - do_migrate(nullptr); - continue; - } - - bool has_value = hash_map->with_value( - key, false, [&](auto &node_value) { value = node_value.load(std::memory_order_acquire); }); - if (!has_value || value != migrate_value()) { - return value; - } - do_migrate(hash_map); - } - } - - template - void for_each(F &&f) { - auto hash_map = hash_map_.load(); - CHECK(hash_map); - auto size = hash_map->size(); - for (size_t i = 0; i < size; i++) { - auto &node = hash_map->node_at(i); - auto key = node.key.load(std::memory_order_relaxed); - auto value = node.value.load(std::memory_order_relaxed); - - if (key != empty_key()) { - CHECK(value != migrate_value()); - if (value != empty_value()) { - f(key, value); - } - } - } - } - - private: - // use no padding intentionally - std::atomic hash_map_{nullptr}; - - std::mutex migrate_mutex_; - std::condition_variable migrate_cv_; - - int migrate_cnt_{0}; - int migrate_generation_{0}; - HashMap *migrate_from_hash_map_{nullptr}; - HashMap *migrate_to_hash_map_{nullptr}; - struct Task { - size_t begin; - size_t end; - bool empty() const { - return begin >= end; - } - size_t size() const { - if (empty()) { - return 0; - } - return end - begin; - } - }; - - struct TaskCreator { - size_t chunk_size; - size_t size; - std::atomic pos{0}; - Task create() { - auto i = pos++; - auto begin = i * chunk_size; - auto end = begin + chunk_size; - if (end > size) { - end = size; - } - return {begin, end}; - } - }; - TaskCreator task_creator; - - void do_migrate(HashMap *ptr) { - //LOG(ERROR) << "In do_migrate: " << ptr; - std::unique_lock lock(migrate_mutex_); - if (hash_map_.load() != ptr) { - return; - } - init_migrate(); - CHECK(!ptr || migrate_from_hash_map_ == ptr); - migrate_cnt_++; - auto migrate_generation = migrate_generation_; - lock.unlock(); - - run_migrate(); - - lock.lock(); - migrate_cnt_--; - if (migrate_cnt_ == 0) { - finish_migrate(); - } - migrate_cv_.wait(lock, [&] { return migrate_generation_ != migrate_generation; }); - } - - void finish_migrate() { - //LOG(ERROR) << "In finish_migrate"; - hash_map_.store(migrate_to_hash_map_); - hp_.retire(get_thread_id(), migrate_from_hash_map_); - migrate_from_hash_map_ = nullptr; - migrate_to_hash_map_ = nullptr; - migrate_generation_++; - migrate_cv_.notify_all(); - } - - void init_migrate() { - if (migrate_from_hash_map_ != nullptr) { - return; - } - //LOG(ERROR) << "In init_migrate"; - CHECK(migrate_cnt_ == 0); - migrate_generation_++; - migrate_from_hash_map_ = hash_map_.exchange(nullptr); - auto new_size = migrate_from_hash_map_->size() * 2; - migrate_to_hash_map_ = make_unique(new_size).release(); - task_creator.chunk_size = 100; - task_creator.size = migrate_from_hash_map_->size(); - task_creator.pos = 0; - } - - void run_migrate() { - //LOG(ERROR) << "In run_migrate"; - size_t cnt = 0; - while (true) { - auto task = task_creator.create(); - cnt += task.size(); - if (task.empty()) { - break; - } - run_task(task); - } - //LOG(ERROR) << "In run_migrate " << cnt; - } - - void run_task(Task task) { - for (auto i = task.begin; i < task.end; i++) { - auto &node = migrate_from_hash_map_->node_at(i); - auto old_value = node.value.exchange(migrate_value(), std::memory_order_acq_rel); - if (old_value == 0) { - continue; - } - auto node_key = node.key.load(std::memory_order_relaxed); - //LOG(ERROR) << node_key << " " << node_key; - auto ok = migrate_to_hash_map_->with_value( - node_key, true, [&](auto &node_value) { node_value.store(old_value, std::memory_order_relaxed); }); - LOG_CHECK(ok) << "Migration overflow"; - } - } -}; - -template -td::HazardPointers::HashMap> ConcurrentHashMap::hp_(64); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Container.h b/submodules/ton/tonlib-src/tdutils/td/utils/Container.h deleted file mode 100644 index e235f21f..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Container.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include - -namespace td { - -// 1. Allocates all objects in vector. (but vector never shrinks) -// 2. Id is safe way to reach this object. -// 3. All ids are unique. -// 4. All ids are non-zero. -template -class Container { - public: - using Id = uint64; - DataT *get(Id id) { - int32 slot_id = decode_id(id); - if (slot_id == -1) { - return nullptr; - } - return &slots_[slot_id].data; - } - - void erase(Id id) { - int32 slot_id = decode_id(id); - if (slot_id == -1) { - return; - } - release(slot_id); - } - - DataT extract(Id id) { - int32 slot_id = decode_id(id); - CHECK(slot_id != -1); - auto res = std::move(slots_[slot_id].data); - release(slot_id); - return res; - } - - Id create(DataT &&data = DataT(), uint8 type = 0) { - int32 id = store(std::move(data), type); - return encode_id(id); - } - - Id reset_id(Id id) { - int32 slot_id = decode_id(id); - CHECK(slot_id != -1); - inc_generation(slot_id); - return encode_id(slot_id); - } - - static uint8 type_from_id(Id id) { - return static_cast(id); - } - - vector ids() { - vector is_bad(slots_.size(), false); - for (auto id : empty_slots_) { - is_bad[id] = true; - } - vector res; - for (size_t i = 0, n = slots_.size(); i < n; i++) { - if (!is_bad[i]) { - res.push_back(encode_id(static_cast(i))); - } - } - return res; - } - template - void for_each(const F &f) { - auto ids = this->ids(); - for (auto id : ids) { - f(id, *get(id)); - } - } - size_t size() const { - CHECK(empty_slots_.size() <= slots_.size()); - return slots_.size() - empty_slots_.size(); - } - bool empty() const { - return size() == 0; - } - void clear() { - *this = Container(); - } - - private: - static constexpr uint32 GENERATION_STEP = 1 << 8; - static constexpr uint32 TYPE_MASK = (1 << 8) - 1; - struct Slot { - uint32 generation; - DataT data; - }; - vector slots_; - vector empty_slots_; - - Id encode_id(int32 id) const { - return (static_cast(id) << 32) | slots_[id].generation; - } - - int32 decode_id(Id id) const { - int32 slot_id = static_cast(id >> 32); - uint32 generation = static_cast(id); - if (slot_id < 0 || slot_id >= static_cast(slots_.size())) { - return -1; - } - if (generation != slots_[slot_id].generation) { - return -1; - } - return slot_id; - } - - int32 store(DataT &&data, uint8 type) { - int32 pos; - if (!empty_slots_.empty()) { - pos = empty_slots_.back(); - empty_slots_.pop_back(); - slots_[pos].data = std::move(data); - slots_[pos].generation ^= (slots_[pos].generation & TYPE_MASK) ^ type; - } else { - CHECK(slots_.size() <= static_cast(std::numeric_limits::max())); - pos = static_cast(slots_.size()); - slots_.push_back(Slot{GENERATION_STEP + type, std::move(data)}); - } - return pos; - } - - void release(int32 id) { - inc_generation(id); - slots_[id].data = DataT(); - if (slots_[id].generation & ~TYPE_MASK) { // generation overflow. Can't use this id anymore - empty_slots_.push_back(id); - } - } - - void inc_generation(int32 id) { - slots_[id].generation += GENERATION_STEP; - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Context.h b/submodules/ton/tonlib-src/tdutils/td/utils/Context.h deleted file mode 100644 index c15a568c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Context.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/thread_local.h" - -namespace td { - -template -class Context { - public: - static Impl *get() { - return context_; - } - class Guard { - public: - explicit Guard(Impl *new_context) { - old_context_ = context_; - context_ = new_context; - } - ~Guard() { - context_ = old_context_; - } - Guard(const Guard &) = delete; - Guard &operator=(const Guard &) = delete; - Guard(Guard &&) = delete; - Guard &operator=(Guard &&) = delete; - - private: - Impl *old_context_; - }; - - private: - static TD_THREAD_LOCAL Impl *context_; -}; - -template -TD_THREAD_LOCAL Impl *Context::context_; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/DecTree.h b/submodules/ton/tonlib-src/tdutils/td/utils/DecTree.h deleted file mode 100644 index 786dc0b0..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/DecTree.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Random.h" - -#include -#include - -namespace td { - -template > -class DecTree { - struct Node { - unique_ptr left_; - unique_ptr right_; - size_t size_; - KeyType key_; - ValueType value_; - uint32 y_; - - void relax() { - size_ = 1; - if (left_ != nullptr) { - size_ += left_->size_; - } - if (right_ != nullptr) { - size_ += right_->size_; - } - } - - Node(KeyType key, ValueType value, uint32 y) : size_(1), key_(std::move(key)), value_(std::move(value)), y_(y) { - } - }; - unique_ptr root_; - - static unique_ptr create_node(KeyType key, ValueType value, uint32 y) { - return make_unique(std::move(key), std::move(value), y); - } - - static unique_ptr insert_node(unique_ptr Tree, KeyType key, ValueType value, uint32 y) { - if (Tree == nullptr) { - return create_node(std::move(key), std::move(value), y); - } - if (Tree->y_ < y) { - auto P = split_node(std::move(Tree), key); - auto T = create_node(std::move(key), std::move(value), y); - T->left_ = std::move(P.first); - T->right_ = std::move(P.second); - T->relax(); - return T; - } - if (Compare()(key, Tree->key_)) { - Tree->left_ = insert_node(std::move(Tree->left_), std::move(key), std::move(value), y); - } else if (Compare()(Tree->key_, key)) { - Tree->right_ = insert_node(std::move(Tree->right_), std::move(key), std::move(value), y); - } else { - // ?? assert - } - Tree->relax(); - return Tree; - } - - static unique_ptr remove_node(unique_ptr Tree, const KeyType &key) { - if (Tree == nullptr) { - // ?? assert - return nullptr; - } - if (Compare()(key, Tree->key_)) { - Tree->left_ = remove_node(std::move(Tree->left_), key); - } else if (Compare()(Tree->key_, key)) { - Tree->right_ = remove_node(std::move(Tree->right_), key); - } else { - Tree = merge_node(std::move(Tree->left_), std::move(Tree->right_)); - } - if (Tree != nullptr) { - Tree->relax(); - } - return Tree; - } - - static ValueType *get_node(unique_ptr &Tree, const KeyType &key) { - if (Tree == nullptr) { - return nullptr; - } - if (Compare()(key, Tree->key_)) { - return get_node(Tree->left_, key); - } else if (Compare()(Tree->key_, key)) { - return get_node(Tree->right_, key); - } else { - return &Tree->value_; - } - } - - static ValueType *get_node_by_idx(unique_ptr &Tree, size_t idx) { - CHECK(Tree != nullptr); - auto s = (Tree->left_ != nullptr) ? Tree->left_->size_ : 0; - if (idx < s) { - return get_node_by_idx(Tree->left_, idx); - } else if (idx == s) { - return &Tree->value_; - } else { - return get_node_by_idx(Tree->right_, idx - s - 1); - } - } - - static const ValueType *get_node(const unique_ptr &Tree, const KeyType &key) { - if (Tree == nullptr) { - return nullptr; - } - if (Compare()(key, Tree->key_)) { - return get_node(Tree->left_, key); - } else if (Compare()(Tree->key_, key)) { - return get_node(Tree->right_, key); - } else { - return &Tree->value_; - } - } - - static const ValueType *get_node_by_idx(const unique_ptr &Tree, size_t idx) { - CHECK(Tree != nullptr); - auto s = (Tree->left_ != nullptr) ? Tree->left_->size_ : 0; - if (idx < s) { - return get_node_by_idx(Tree->left_, idx); - } else if (idx == s) { - return &Tree->value_; - } else { - return get_node_by_idx(Tree->right_, idx - s - 1); - } - } - - static std::pair, unique_ptr> split_node(unique_ptr Tree, const KeyType &key) { - if (Tree == nullptr) { - return {nullptr, nullptr}; - } - if (Compare()(key, Tree->key_)) { - auto P = split_node(std::move(Tree->left_), key); - Tree->left_ = std::move(P.second); - Tree->relax(); - P.second = std::move(Tree); - return P; - } else { - auto P = split_node(std::move(Tree->right_), key); - Tree->right_ = std::move(P.first); - Tree->relax(); - P.first = std::move(Tree); - return P; - } - } - - static unique_ptr merge_node(unique_ptr left, unique_ptr right) { - if (left == nullptr) { - return right; - } - if (right == nullptr) { - return left; - } - if (left->y_ < right->y_) { - right->left_ = merge_node(std::move(left), std::move(right->left_)); - right->relax(); - return right; - } else { - left->right_ = merge_node(std::move(left->right_), std::move(right)); - left->relax(); - return left; - } - } - - public: - size_t size() const { - if (root_ == nullptr) { - return 0; - } else { - return root_->size_; - } - } - void insert(KeyType key, ValueType value) { - root_ = insert_node(std::move(root_), std::move(key), std::move(value), td::Random::fast_uint32()); - } - void remove(const KeyType &key) { - root_ = remove_node(std::move(root_), key); - } - void reset() { - root_ = nullptr; - } - ValueType *get(const KeyType &key) { - return get_node(root_, key); - } - ValueType *get_random() { - if (size() == 0) { - return nullptr; - } else { - return get_node_by_idx(root_, td::Random::fast_uint32() % size()); - } - } - const ValueType *get(const KeyType &key) const { - return get_node(root_, key); - } - const ValueType *get_random() const { - if (size() == 0) { - return nullptr; - } else { - return get_node_by_idx(root_, td::Random::fast_uint32() % size()); - } - } - bool exists(const KeyType &key) const { - return get_node(root_, key) != nullptr; - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Destructor.h b/submodules/ton/tonlib-src/tdutils/td/utils/Destructor.h deleted file mode 100644 index fadeb89b..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Destructor.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include -#include - -namespace td { - -class Destructor { - public: - Destructor() = default; - Destructor(const Destructor &other) = delete; - Destructor &operator=(const Destructor &other) = delete; - Destructor(Destructor &&other) = default; - Destructor &operator=(Destructor &&other) = default; - virtual ~Destructor() = default; -}; - -template -class LambdaDestructor : public Destructor { - public: - explicit LambdaDestructor(F &&f) : f_(std::move(f)) { - } - LambdaDestructor(const LambdaDestructor &other) = delete; - LambdaDestructor &operator=(const LambdaDestructor &other) = delete; - LambdaDestructor(LambdaDestructor &&other) = default; - LambdaDestructor &operator=(LambdaDestructor &&other) = default; - ~LambdaDestructor() override { - f_(); - } - - private: - F f_; -}; - -template -auto create_destructor(F &&f) { - return make_unique>(std::forward(f)); -} -template -auto create_shared_destructor(F &&f) { - return std::make_shared>(std::forward(f)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Enumerator.h b/submodules/ton/tonlib-src/tdutils/td/utils/Enumerator.h deleted file mode 100644 index d7bfe512..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Enumerator.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/misc.h" - -#include -#include - -namespace td { - -template -class Enumerator { - public: - using Key = int32; - - Key add(ValueT v) { - int32 next_id = narrow_cast(arr_.size() + 1); - bool was_inserted; - decltype(map_.begin()) it; - std::tie(it, was_inserted) = map_.emplace(std::move(v), next_id); - if (was_inserted) { - arr_.push_back(&it->first); - } - return it->second; - } - - const ValueT &get(Key key) const { - auto pos = static_cast(key - 1); - CHECK(pos < arr_.size()); - return *arr_[pos]; - } - - private: - std::map map_; - std::vector arr_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/EpochBasedMemoryReclamation.h b/submodules/ton/tonlib-src/tdutils/td/utils/EpochBasedMemoryReclamation.h deleted file mode 100644 index e1122ea2..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/EpochBasedMemoryReclamation.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/sleep.h" - -#include -#include - -namespace td { - -template -class EpochBasedMemoryReclamation { - public: - EpochBasedMemoryReclamation(const EpochBasedMemoryReclamation &other) = delete; - EpochBasedMemoryReclamation &operator=(const EpochBasedMemoryReclamation &other) = delete; - EpochBasedMemoryReclamation(EpochBasedMemoryReclamation &&other) = delete; - EpochBasedMemoryReclamation &operator=(EpochBasedMemoryReclamation &&other) = delete; - ~EpochBasedMemoryReclamation() = default; - - class Locker { - public: - Locker(size_t thread_id, EpochBasedMemoryReclamation *ebmr) : thread_id_(thread_id), ebmr_(ebmr) { - } - Locker(const Locker &other) = delete; - Locker &operator=(const Locker &other) = delete; - Locker(Locker &&other) = default; - Locker &operator=(Locker &&other) = delete; - - ~Locker() { - if (ebmr_) { - retire_sync(); - unlock(); - ebmr_.release(); - } - } - void lock() { - DCHECK(ebmr_); - ebmr_->lock(thread_id_); - } - void unlock() { - DCHECK(ebmr_); - ebmr_->unlock(thread_id_); - } - - void retire_sync() { - ebmr_->retire_sync(thread_id_); - } - - void retire() { - ebmr_->retire(thread_id_); - } - - void retire(T *ptr) { - ebmr_->retire(thread_id_, ptr); - } - - private: - size_t thread_id_; - struct Never { - template - void operator()(S *) const { - UNREACHABLE(); - } - }; - std::unique_ptr ebmr_; - }; - - explicit EpochBasedMemoryReclamation(size_t threads_n) : threads_(threads_n) { - } - - Locker get_locker(size_t thread_id) { - return Locker{thread_id, this}; - } - - size_t to_delete_size_unsafe() const { - size_t res = 0; - for (auto &thread_data : threads_) { - // LOG(ERROR) << "---" << thread_data.epoch.load() / 2; - for (size_t i = 0; i < MAX_BAGS; i++) { - res += thread_data.to_delete[i].size(); - // LOG(ERROR) << thread_data.to_delete[i].size(); - } - } - return res; - } - - private: - static constexpr size_t MAX_BAGS = 3; - struct ThreadData { - std::atomic epoch{1}; - char pad[TD_CONCURRENCY_PAD - sizeof(epoch)]; - - size_t to_skip{0}; - size_t checked_thread_i{0}; - size_t bag_i{0}; - std::vector> to_delete[MAX_BAGS]; - char pad2[TD_CONCURRENCY_PAD - sizeof(to_delete)]; - - void rotate_bags() { - bag_i = (bag_i + 1) % MAX_BAGS; - to_delete[bag_i].clear(); - } - - void set_epoch(int64 new_epoch) { - //LOG(ERROR) << new_epoch; - if (epoch.load(std::memory_order_relaxed) / 2 != new_epoch) { - checked_thread_i = 0; - to_skip = 0; - rotate_bags(); - } - epoch = new_epoch * 2; - } - - void idle() { - epoch.store(epoch.load(std::memory_order_relaxed) | 1); - } - - size_t undeleted() const { - size_t res = 0; - for (size_t i = 0; i < MAX_BAGS; i++) { - res += to_delete[i].size(); - } - return res; - } - }; - std::vector threads_; - char pad[TD_CONCURRENCY_PAD - sizeof(threads_)]; - - std::atomic epoch_{1}; - char pad2[TD_CONCURRENCY_PAD - sizeof(epoch_)]; - - void lock(size_t thread_id) { - auto &data = threads_[thread_id]; - auto epoch = epoch_.load(); - data.set_epoch(epoch); - - if (data.to_skip == 0) { - data.to_skip = 30; - step_check(data); - } else { - data.to_skip--; - } - } - - void unlock(size_t thread_id) { - //LOG(ERROR) << "UNLOCK"; - auto &data = threads_[thread_id]; - data.idle(); - } - - bool step_check(ThreadData &data) { - auto epoch = data.epoch.load(std::memory_order_relaxed) / 2; - auto checked_thread_epoch = threads_[data.checked_thread_i].epoch.load(); - if (checked_thread_epoch % 2 == 1 || checked_thread_epoch / 2 == epoch) { - data.checked_thread_i++; - if (data.checked_thread_i == threads_.size()) { - if (epoch_.compare_exchange_strong(epoch, epoch + 1)) { - data.set_epoch(epoch + 1); - } else { - data.set_epoch(epoch); - } - } - return true; - } - return false; - } - - void retire_sync(size_t thread_id) { - auto &data = threads_[thread_id]; - - while (true) { - retire(thread_id); - data.idle(); - if (data.undeleted() == 0) { - break; - } - usleep_for(1000); - } - } - - void retire(size_t thread_id) { - auto &data = threads_[thread_id]; - data.set_epoch(epoch_.load()); - while (step_check(data) && data.undeleted() != 0) { - } - } - - void retire(size_t thread_id, T *ptr) { - auto &data = threads_[thread_id]; - data.to_delete[data.bag_i].push_back(unique_ptr{ptr}); - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.cpp deleted file mode 100644 index 9dbedab7..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/FileLog.h" - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/path.h" -#include "td/utils/port/StdStreams.h" -#include "td/utils/Slice.h" - -#include - -namespace td { - -Status FileLog::init(string path, int64 rotate_threshold, bool redirect_stderr) { - if (path == path_) { - set_rotate_threshold(rotate_threshold); - return Status::OK(); - } - if (path.empty()) { - return Status::Error("Log file path can't be empty"); - } - - TRY_RESULT(fd, FileFd::open(path, FileFd::Create | FileFd::Write | FileFd::Append)); - - fd_.close(); - fd_ = std::move(fd); - if (!Stderr().empty() && redirect_stderr) { - fd_.get_native_fd().duplicate(Stderr().get_native_fd()).ignore(); - } - - auto r_path = realpath(path, true); - if (r_path.is_error()) { - path_ = std::move(path); - } else { - path_ = r_path.move_as_ok(); - } - TRY_RESULT(size, fd_.get_size()); - size_ = size; - rotate_threshold_ = rotate_threshold; - redirect_stderr_ = redirect_stderr; - return Status::OK(); -} - -Slice FileLog::get_path() const { - return path_; -} - -vector FileLog::get_file_paths() { - vector result; - if (!path_.empty()) { - result.push_back(path_); - result.push_back(PSTRING() << path_ << ".old"); - } - return result; -} - -void FileLog::set_rotate_threshold(int64 rotate_threshold) { - rotate_threshold_ = rotate_threshold; -} - -int64 FileLog::get_rotate_threshold() const { - return rotate_threshold_; -} - -void FileLog::append(CSlice cslice, int log_level) { - Slice slice = cslice; - while (!slice.empty()) { - auto r_size = fd_.write(slice); - if (r_size.is_error()) { - process_fatal_error(PSLICE() << r_size.error() << " in " << __FILE__ << " at " << __LINE__); - } - auto written = r_size.ok(); - size_ += static_cast(written); - slice.remove_prefix(written); - } - if (log_level == VERBOSITY_NAME(FATAL)) { - process_fatal_error(cslice); - } - - if (size_ > rotate_threshold_ || want_rotate_.load(std::memory_order_relaxed)) { - auto status = rename(path_, PSLICE() << path_ << ".old"); - if (status.is_error()) { - process_fatal_error(PSLICE() << status.error() << " in " << __FILE__ << " at " << __LINE__); - } - do_rotate(); - } -} - -void FileLog::rotate() { - if (path_.empty()) { - return; - } - do_rotate(); -} - -void FileLog::lazy_rotate() { - want_rotate_ = true; -} - -void FileLog::do_rotate() { - want_rotate_ = false; - td::ScopedDisableLog disable_log; // to ensure that nothing will be printed to the closed log - CHECK(!path_.empty()); - fd_.close(); - auto r_fd = FileFd::open(path_, FileFd::Create | FileFd::Truncate | FileFd::Write); - if (r_fd.is_error()) { - process_fatal_error(PSLICE() << r_fd.error() << " in " << __FILE__ << " at " << __LINE__); - } - fd_ = r_fd.move_as_ok(); - if (!Stderr().empty() && redirect_stderr_) { - fd_.get_native_fd().duplicate(Stderr().get_native_fd()).ignore(); - } - size_ = 0; -} - -Result> FileLog::create(string path, int64 rotate_threshold, bool redirect_stderr) { - auto l = make_unique(); - TRY_STATUS(l->init(std::move(path), rotate_threshold, redirect_stderr)); - return std::move(l); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.h b/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.h deleted file mode 100644 index 68bb7e7e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/FileLog.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -class FileLog : public LogInterface { - static constexpr int64 DEFAULT_ROTATE_THRESHOLD = 10 * (1 << 20); - - public: - static Result> create(string path, int64 rotate_threshold = DEFAULT_ROTATE_THRESHOLD, - bool redirect_stderr = true); - Status init(string path, int64 rotate_threshold = DEFAULT_ROTATE_THRESHOLD, bool redirect_stderr = true); - - Slice get_path() const; - - vector get_file_paths() override; - - void set_rotate_threshold(int64 rotate_threshold); - - int64 get_rotate_threshold() const; - - void append(CSlice cslice, int log_level) override; - - void rotate() override; - - void lazy_rotate(); - - private: - FileFd fd_; - string path_; - int64 size_ = 0; - int64 rotate_threshold_ = 0; - bool redirect_stderr_; - std::atomic want_rotate_{}; - - void do_rotate(); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlFast.h b/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlFast.h deleted file mode 100644 index 36bae44f..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlFast.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/TimedStat.h" - -namespace td { - -class FloodControlFast { - public: - uint32 add_event(int32 now) { - for (auto &limit : limits_) { - limit.stat_.add_event(CounterStat::Event(), now); - if (limit.stat_.get_stat(now).count_ > limit.count_) { - wakeup_at_ = max(wakeup_at_, now + limit.duration_ * 2); - } - } - return wakeup_at_; - } - uint32 get_wakeup_at() { - return wakeup_at_; - } - - void add_limit(uint32 duration, int32 count) { - limits_.push_back({TimedStat(duration, 0), duration, count}); - } - - void clear_events() { - for (auto &limit : limits_) { - limit.stat_.clear_events(); - } - wakeup_at_ = 0; - } - - private: - class CounterStat { - public: - struct Event {}; - int32 count_ = 0; - void on_event(Event e) { - count_++; - } - void clear() { - count_ = 0; - } - }; - - uint32 wakeup_at_ = 0; - struct Limit { - TimedStat stat_; - uint32 duration_; - int32 count_; - }; - std::vector limits_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlStrict.h b/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlStrict.h deleted file mode 100644 index 2aa2d020..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/FloodControlStrict.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include - -namespace td { - -// More strict implementaions of flood control than FloodControlFast. -// Should be just fine for small counters. -class FloodControlStrict { - public: - int32 add_event(int32 now) { - events_.push_back(Event{now}); - if (without_update_ > 0) { - without_update_--; - } else { - update(now); - } - return wakeup_at_; - } - - // no more than count in each duration. - void add_limit(int32 duration, int32 count) { - limits_.push_back(Limit{duration, count, 0}); - } - - int32 get_wakeup_at() { - return wakeup_at_; - } - - void clear_events() { - events_.clear(); - for (auto &limit : limits_) { - limit.pos_ = 0; - } - without_update_ = 0; - wakeup_at_ = 0; - } - - int32 update(int32 now) { - size_t min_pos = events_.size(); - - without_update_ = std::numeric_limits::max(); - for (auto &limit : limits_) { - if (limit.pos_ + limit.count_ < events_.size()) { - limit.pos_ = events_.size() - limit.count_; - } - - // binary-search? :D - while (limit.pos_ < events_.size() && events_[limit.pos_].timestamp_ + limit.duration_ < now) { - limit.pos_++; - } - - if (limit.count_ + limit.pos_ <= events_.size()) { - CHECK(limit.count_ + limit.pos_ == events_.size()); - wakeup_at_ = max(wakeup_at_, events_[limit.pos_].timestamp_ + limit.duration_); - without_update_ = 0; - } else { - without_update_ = min(without_update_, limit.count_ + limit.pos_ - events_.size()); - } - - min_pos = min(min_pos, limit.pos_); - } - - if (min_pos * 2 > events_.size()) { - for (auto &limit : limits_) { - limit.pos_ -= min_pos; - } - events_.erase(events_.begin(), events_.begin() + min_pos); - } - return wakeup_at_; - } - - private: - int32 wakeup_at_ = 0; - struct Event { - int32 timestamp_; - }; - struct Limit { - int32 duration_; - int32 count_; - size_t pos_; - }; - size_t without_update_ = 0; - std::vector events_; - std::vector limits_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.cpp deleted file mode 100644 index 0811e640..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/GitInfo.h" - -#include "auto/git_info.h" - -namespace td { - -CSlice GitInfo::commit() { - return GIT_COMMIT; -} -bool GitInfo::is_dirty() { - return GIT_DIRTY; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.h b/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.h deleted file mode 100644 index 868e054e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/GitInfo.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Slice.h" - -namespace td { - -class GitInfo { - public: - static CSlice commit(); - static bool is_dirty(); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.cpp deleted file mode 100644 index 00af4451..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/Gzip.h" - -char disable_linker_warning_about_empty_file_gzip_cpp TD_UNUSED; - -#if TD_HAVE_ZLIB -#include "td/utils/logging.h" - -#include -#include -#include - -#include - -namespace td { - -class Gzip::Impl { - public: - z_stream stream_; - - // z_stream is not copyable nor movable - Impl() = default; - Impl(const Impl &other) = delete; - Impl &operator=(const Impl &other) = delete; - Impl(Impl &&other) = delete; - Impl &operator=(Impl &&other) = delete; - ~Impl() = default; -}; - -Status Gzip::init_encode() { - CHECK(mode_ == Empty); - init_common(); - mode_ = Encode; - int ret = deflateInit2(&impl_->stream_, 6, Z_DEFLATED, 15, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) { - return Status::Error(PSLICE() << "zlib deflate init failed: " << ret); - } - return Status::OK(); -} - -Status Gzip::init_decode() { - CHECK(mode_ == Empty); - init_common(); - mode_ = Decode; - int ret = inflateInit2(&impl_->stream_, MAX_WBITS + 32); - if (ret != Z_OK) { - return Status::Error(PSLICE() << "zlib inflate init failed: " << ret); - } - return Status::OK(); -} - -void Gzip::set_input(Slice input) { - CHECK(input_size_ == 0); - CHECK(!close_input_flag_); - CHECK(input.size() <= std::numeric_limits::max()); - CHECK(impl_->stream_.avail_in == 0); - input_size_ = input.size(); - impl_->stream_.avail_in = static_cast(input.size()); - impl_->stream_.next_in = reinterpret_cast(const_cast(input.data())); -} - -void Gzip::set_output(MutableSlice output) { - CHECK(output_size_ == 0); - CHECK(output.size() <= std::numeric_limits::max()); - CHECK(impl_->stream_.avail_out == 0); - output_size_ = output.size(); - impl_->stream_.avail_out = static_cast(output.size()); - impl_->stream_.next_out = reinterpret_cast(output.data()); -} - -Result Gzip::run() { - while (true) { - int ret; - if (mode_ == Decode) { - ret = inflate(&impl_->stream_, Z_NO_FLUSH); - } else { - ret = deflate(&impl_->stream_, close_input_flag_ ? Z_FINISH : Z_NO_FLUSH); - } - - if (ret == Z_OK) { - return Running; - } - if (ret == Z_STREAM_END) { - // TODO(now): fail if input is not empty; - clear(); - return Done; - } - clear(); - return Status::Error(PSLICE() << "zlib error " << ret); - } -} - -size_t Gzip::left_input() const { - return impl_->stream_.avail_in; -} -size_t Gzip::left_output() const { - return impl_->stream_.avail_out; -} - -void Gzip::init_common() { - std::memset(&impl_->stream_, 0, sizeof(impl_->stream_)); - impl_->stream_.zalloc = Z_NULL; - impl_->stream_.zfree = Z_NULL; - impl_->stream_.opaque = Z_NULL; - impl_->stream_.avail_in = 0; - impl_->stream_.next_in = nullptr; - impl_->stream_.avail_out = 0; - impl_->stream_.next_out = nullptr; - - input_size_ = 0; - output_size_ = 0; - - close_input_flag_ = false; -} - -void Gzip::clear() { - if (mode_ == Decode) { - inflateEnd(&impl_->stream_); - } else if (mode_ == Encode) { - deflateEnd(&impl_->stream_); - } - mode_ = Empty; -} - -Gzip::Gzip() : impl_(make_unique()) { -} - -Gzip::Gzip(Gzip &&other) : Gzip() { - swap(other); -} - -Gzip &Gzip::operator=(Gzip &&other) { - CHECK(this != &other); - clear(); - swap(other); - return *this; -} - -void Gzip::swap(Gzip &other) { - using std::swap; - swap(impl_, other.impl_); - swap(input_size_, other.input_size_); - swap(output_size_, other.output_size_); - swap(close_input_flag_, other.close_input_flag_); - swap(mode_, other.mode_); -} - -Gzip::~Gzip() { - clear(); -} - -BufferSlice gzdecode(Slice s) { - Gzip gzip; - gzip.init_decode().ensure(); - ChainBufferWriter message; - gzip.set_input(s); - gzip.close_input(); - double k = 2; - gzip.set_output(message.prepare_append(static_cast(static_cast(s.size()) * k))); - while (true) { - auto r_state = gzip.run(); - if (r_state.is_error()) { - return BufferSlice(); - } - auto state = r_state.ok(); - if (state == Gzip::Done) { - message.confirm_append(gzip.flush_output()); - break; - } - if (gzip.need_input()) { - return BufferSlice(); - } - if (gzip.need_output()) { - message.confirm_append(gzip.flush_output()); - k *= 1.5; - gzip.set_output(message.prepare_append(static_cast(static_cast(gzip.left_input()) * k))); - } - } - return message.extract_reader().move_as_buffer_slice(); -} - -BufferSlice gzencode(Slice s, double k) { - Gzip gzip; - gzip.init_encode().ensure(); - gzip.set_input(s); - gzip.close_input(); - size_t max_size = static_cast(static_cast(s.size()) * k); - BufferWriter message{max_size}; - gzip.set_output(message.prepare_append()); - auto r_state = gzip.run(); - if (r_state.is_error()) { - return BufferSlice(); - } - auto state = r_state.ok(); - if (state != Gzip::Done) { - return BufferSlice(); - } - message.confirm_append(gzip.flush_output()); - return message.as_buffer_slice(); -} - -} // namespace td -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.h b/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.h deleted file mode 100644 index 0b890c75..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Gzip.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#if TD_HAVE_ZLIB -#include "td/utils/buffer.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -class Gzip { - public: - Gzip(); - Gzip(const Gzip &) = delete; - Gzip &operator=(const Gzip &) = delete; - Gzip(Gzip &&other); - Gzip &operator=(Gzip &&other); - ~Gzip(); - - enum Mode { Empty, Encode, Decode }; - Status init(Mode mode) TD_WARN_UNUSED_RESULT { - if (mode == Encode) { - return init_encode(); - } else if (mode == Decode) { - return init_decode(); - } - clear(); - return Status::OK(); - } - - Status init_encode() TD_WARN_UNUSED_RESULT; - - Status init_decode() TD_WARN_UNUSED_RESULT; - - void set_input(Slice input); - - void set_output(MutableSlice output); - - void close_input() { - close_input_flag_ = true; - } - - bool need_input() const { - return left_input() == 0; - } - - bool need_output() const { - return left_output() == 0; - } - - size_t left_input() const; - - size_t left_output() const; - - size_t used_input() const { - return input_size_ - left_input(); - } - - size_t used_output() const { - return output_size_ - left_output(); - } - - size_t flush_input() { - auto res = used_input(); - input_size_ = left_input(); - return res; - } - - size_t flush_output() { - auto res = used_output(); - output_size_ = left_output(); - return res; - } - - enum State { Running, Done }; - Result run() TD_WARN_UNUSED_RESULT; - - private: - class Impl; - unique_ptr impl_; - - size_t input_size_ = 0; - size_t output_size_ = 0; - bool close_input_flag_ = false; - Mode mode_ = Empty; - - void init_common(); - void clear(); - - void swap(Gzip &other); -}; - -BufferSlice gzdecode(Slice s); - -BufferSlice gzencode(Slice s, double k = 0.9); - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.cpp deleted file mode 100644 index 4d61a222..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/GzipByteFlow.h" - -char disable_linker_warning_about_empty_file_gzipbyteflow_cpp TD_UNUSED; - -#if TD_HAVE_ZLIB -#include "td/utils/common.h" -#include "td/utils/Status.h" - -namespace td { - -void GzipByteFlow::loop() { - while (true) { - if (gzip_.need_input()) { - auto slice = input_->prepare_read(); - if (slice.empty()) { - if (!is_input_active_) { - gzip_.close_input(); - } else { - break; - } - } else { - gzip_.set_input(input_->prepare_read()); - } - } - if (gzip_.need_output()) { - auto slice = output_.prepare_append(); - CHECK(!slice.empty()); - gzip_.set_output(slice); - } - auto r_state = gzip_.run(); - auto output_size = gzip_.flush_output(); - if (output_size) { - uncommited_size_ += output_size; - total_output_size_ += output_size; - if (total_output_size_ > max_output_size_) { - return finish(Status::Error("Max output size limit exceeded")); - } - output_.confirm_append(output_size); - } - - auto input_size = gzip_.flush_input(); - if (input_size) { - input_->confirm_read(input_size); - } - if (r_state.is_error()) { - return finish(r_state.move_as_error()); - } - auto state = r_state.ok(); - if (state == Gzip::Done) { - on_output_updated(); - return consume_input(); - } - } - if (uncommited_size_ >= MIN_UPDATE_SIZE) { - uncommited_size_ = 0; - on_output_updated(); - } -} - -constexpr size_t GzipByteFlow::MIN_UPDATE_SIZE; - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.h b/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.h deleted file mode 100644 index ba78fef4..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/GzipByteFlow.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/ByteFlow.h" -#include "td/utils/Gzip.h" - -#include - -namespace td { - -#if TD_HAVE_ZLIB -class GzipByteFlow final : public ByteFlowBase { - public: - GzipByteFlow() = default; - - explicit GzipByteFlow(Gzip::Mode mode) { - gzip_.init(mode).ensure(); - } - - void init_decode() { - gzip_.init_decode().ensure(); - } - - void init_encode() { - gzip_.init_encode().ensure(); - } - - void set_max_output_size(size_t max_output_size) { - max_output_size_ = max_output_size; - } - - void loop() override; - - private: - Gzip gzip_; - size_t uncommited_size_ = 0; - size_t total_output_size_ = 0; - size_t max_output_size_ = std::numeric_limits::max(); - static constexpr size_t MIN_UPDATE_SIZE = 1 << 14; -}; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Hash.h b/submodules/ton/tonlib-src/tdutils/td/utils/Hash.h deleted file mode 100644 index 4a56fee6..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Hash.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#if TD_HAVE_ABSL -#include -#endif - -#include - -namespace td { -// A simple wrapper for absl::flat_hash_map, std::unordered_map and probably some our implementaion of hash map in -// the future - -// We will introduce out own Hashing utility like an absl one. -class Hasher { - public: - Hasher() = default; - explicit Hasher(size_t init_value) : hash_(init_value) { - } - std::size_t finalize() const { - return hash_; - } - - static Hasher combine(Hasher hasher, size_t value) { - hasher.hash_ ^= value; - return hasher; - } - - template - static Hasher combine(Hasher hasher, const std::pair &value) { - hasher = AbslHashValue(std::move(hasher), value.first); - hasher = AbslHashValue(std::move(hasher), value.second); - return hasher; - } - - private: - std::size_t hash_{0}; -}; - -template -class TdHash { - public: - template - std::size_t operator()(const T &value) const noexcept { - return AbslHashValue(Hasher(), value).finalize(); - } -}; - -#if TD_HAVE_ABSL -template -using AbslHash = absl::Hash; -#endif - -// default hash implementations -template -decltype(H::combine(std::declval(), std::declval())) AbslHashValue(H hasher, const T &value) { - return H::combine(std::move(hasher), value); -} - -#if TD_HAVE_ABSL -template -using Hash = AbslHash; -#else -template -using Hash = TdHash; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/HashMap.h b/submodules/ton/tonlib-src/tdutils/td/utils/HashMap.h deleted file mode 100644 index 9646bef9..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/HashMap.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Hash.h" - -#if TD_HAVE_ABSL -#include -#else -#include -#endif - -namespace td { - -#if TD_HAVE_ABSL -template > -using HashMap = absl::flat_hash_map; -#else -template > -using HashMap = std::unordered_map; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/HashSet.h b/submodules/ton/tonlib-src/tdutils/td/utils/HashSet.h deleted file mode 100644 index b00d5a92..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/HashSet.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Hash.h" - -#if TD_HAVE_ABSL -#include -#else -#include -#endif - -namespace td { - -#if TD_HAVE_ABSL -template > -using HashSet = absl::flat_hash_set; -#else -template > -using HashSet = std::unordered_set; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/HazardPointers.h b/submodules/ton/tonlib-src/tdutils/td/utils/HazardPointers.h deleted file mode 100644 index 41849221..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/HazardPointers.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include -#include -#include - -namespace td { - -template > -class HazardPointers { - public: - explicit HazardPointers(size_t threads_n) : threads_(threads_n) { - for (auto &data : threads_) { - for (auto &ptr : data.hazard_) { -// workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658 -#if TD_GCC && GCC_VERSION <= 40902 - ptr = nullptr; -#else - std::atomic_init(&ptr, static_cast(nullptr)); -#endif - } - } - } - HazardPointers(const HazardPointers &other) = delete; - HazardPointers &operator=(const HazardPointers &other) = delete; - HazardPointers(HazardPointers &&other) = delete; - HazardPointers &operator=(HazardPointers &&other) = delete; - - class Holder { - public: - template - S *protect(std::atomic &to_protect) { - return do_protect(hazard_ptr_, to_protect); - } - Holder(HazardPointers &hp, size_t thread_id, size_t pos) : Holder(hp.get_hazard_ptr(thread_id, pos)) { - CHECK(hazard_ptr_.load() == 0); - hazard_ptr_.store(reinterpret_cast(1)); - } - Holder(const Holder &other) = delete; - Holder &operator=(const Holder &other) = delete; - Holder(Holder &&other) = delete; - Holder &operator=(Holder &&other) = delete; - ~Holder() { - clear(); - } - void clear() { - hazard_ptr_.store(nullptr, std::memory_order_release); - } - - private: - friend class HazardPointers; - explicit Holder(std::atomic &ptr) : hazard_ptr_(ptr) { - } - std::atomic &hazard_ptr_; - }; - - void retire(size_t thread_id, T *ptr = nullptr) { - CHECK(thread_id < threads_.size()); - auto &data = threads_[thread_id]; - if (ptr) { - data.to_delete_.push_back(std::unique_ptr(ptr)); - } - for (auto it = data.to_delete_.begin(); it != data.to_delete_.end();) { - if (!is_protected(it->get())) { - it->reset(); - it = data.to_delete_.erase(it); - } else { - ++it; - } - } - } - - // old inteface - T *protect(size_t thread_id, size_t pos, std::atomic &ptr) { - return do_protect(get_hazard_ptr(thread_id, pos), ptr); - } - void clear(size_t thread_id, size_t pos) { - do_clear(get_hazard_ptr(thread_id, pos)); - } - - size_t to_delete_size_unsafe() const { - size_t res = 0; - for (auto &thread : threads_) { - res += thread.to_delete_.size(); - } - return res; - } - - private: - struct ThreadData { - std::array, MaxPointersN> hazard_; - char pad[TD_CONCURRENCY_PAD - sizeof(hazard_)]; - - // stupid gc - std::vector> to_delete_; - char pad2[TD_CONCURRENCY_PAD - sizeof(to_delete_)]; - }; - std::vector threads_; - char pad2[TD_CONCURRENCY_PAD - sizeof(threads_)]; - - template - static S *do_protect(std::atomic &hazard_ptr, std::atomic &to_protect) { - T *saved = nullptr; - T *to_save; - while ((to_save = to_protect.load()) != saved) { - hazard_ptr.store(to_save); - saved = to_save; - } - return static_cast(saved); - } - - static void do_clear(std::atomic &hazard_ptr) { - hazard_ptr.store(nullptr, std::memory_order_release); - } - - bool is_protected(T *ptr) { - for (auto &thread : threads_) { - for (auto &hazard_ptr : thread.hazard_) { - if (hazard_ptr.load() == ptr) { - return true; - } - } - } - return false; - } - - std::atomic &get_hazard_ptr(size_t thread_id, size_t pos) { - CHECK(thread_id < threads_.size()); - return threads_[thread_id].hazard_[pos]; - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Heap.h b/submodules/ton/tonlib-src/tdutils/td/utils/Heap.h deleted file mode 100644 index 37be5e07..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Heap.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { - -struct HeapNode { - bool in_heap() const { - return pos_ != -1; - } - bool is_top() const { - return pos_ == 0; - } - void remove() { - pos_ = -1; - } - int pos_ = -1; -}; - -template -class KHeap { - public: - bool empty() const { - return array_.empty(); - } - size_t size() const { - return array_.size(); - } - - KeyT top_key() const { - return array_[0].key_; - } - - HeapNode *pop() { - CHECK(!empty()); - HeapNode *result = array_[0].node_; - result->remove(); - erase(0); - return result; - } - - void insert(KeyT key, HeapNode *node) { - CHECK(!node->in_heap()); - array_.push_back({key, node}); - fix_up(static_cast(array_.size()) - 1); - } - - void fix(KeyT key, HeapNode *node) { - CHECK(node->in_heap()); - int pos = node->pos_; - KeyT old_key = array_[pos].key_; - array_[pos].key_ = key; - if (key < old_key) { - fix_up(pos); - } else { - fix_down(pos); - } - } - - void erase(HeapNode *node) { - CHECK(node->in_heap()); - int pos = node->pos_; - node->remove(); - erase(pos); - } - - template - void for_each(F &&f) const { - for (auto &it : array_) { - f(it.key_, it.node_); - } - } - - template - void for_each(F &&f) { - for (auto &it : array_) { - f(it.key_, it.node_); - } - } - - void check() const { - for (size_t i = 0; i < array_.size(); i++) { - for (size_t j = i * K + 1; j < i * K + 1 + K && j < array_.size(); j++) { - CHECK(array_[i].key_ <= array_[j].key_); - } - } - } - - private: - struct Item { - KeyT key_; - HeapNode *node_; - }; - vector array_; - - void fix_up(int pos) { - auto item = array_[pos]; - - while (pos) { - int parent_pos = (pos - 1) / K; - auto parent_item = array_[parent_pos]; - - if (parent_item.key_ < item.key_) { - break; - } - - parent_item.node_->pos_ = pos; - array_[pos] = parent_item; - pos = parent_pos; - } - - item.node_->pos_ = pos; - array_[pos] = item; - } - - void fix_down(int pos) { - auto item = array_[pos]; - while (true) { - int left_pos = pos * K + 1; - int right_pos = min(left_pos + K, static_cast(array_.size())); - int next_pos = pos; - KeyT next_key = item.key_; - for (int i = left_pos; i < right_pos; i++) { - KeyT i_key = array_[i].key_; - if (i_key < next_key) { - next_key = i_key; - next_pos = i; - } - } - if (next_pos == pos) { - break; - } - array_[pos] = array_[next_pos]; - array_[pos].node_->pos_ = pos; - pos = next_pos; - } - - item.node_->pos_ = pos; - array_[pos] = item; - } - - void erase(int pos) { - array_[pos] = array_.back(); - array_.pop_back(); - if (pos < static_cast(array_.size())) { - fix_down(pos); - fix_up(pos); - } - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Hints.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/Hints.cpp deleted file mode 100644 index b21a93dd..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Hints.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/Hints.h" - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Slice.h" -#include "td/utils/translit.h" -#include "td/utils/unicode.h" -#include "td/utils/utf8.h" - -#include - -namespace td { - -vector Hints::fix_words(vector words) { - std::sort(words.begin(), words.end()); - - size_t new_words_size = 0; - for (size_t i = 0; i != words.size(); i++) { - if (i == words.size() - 1 || !begins_with(words[i + 1], words[i])) { - if (i != new_words_size) { - words[new_words_size] = std::move(words[i]); - } - new_words_size++; - } - } - words.resize(new_words_size); - return words; -} - -vector Hints::get_words(Slice name, bool is_search) { - bool in_word = false; - string word; - vector words; - auto pos = name.ubegin(); - auto end = name.uend(); - while (pos != end) { - uint32 code; - pos = next_utf8_unsafe(pos, &code, is_search ? "get_words_search" : "get_words_add"); - - code = prepare_search_character(code); - if (code == 0) { - continue; - } - if (code == ' ') { - if (in_word) { - words.push_back(std::move(word)); - word.clear(); - in_word = false; - } - } else { - in_word = true; - code = remove_diacritics(code); - append_utf8_character(word, code); - } - } - if (in_word) { - words.push_back(std::move(word)); - } - - return fix_words(std::move(words)); -} - -void Hints::add_word(const string &word, KeyT key, std::map> &word_to_keys) { - vector &keys = word_to_keys[word]; - CHECK(std::find(keys.begin(), keys.end(), key) == keys.end()); - keys.push_back(key); -} - -void Hints::delete_word(const string &word, KeyT key, std::map> &word_to_keys) { - vector &keys = word_to_keys[word]; - auto key_it = std::find(keys.begin(), keys.end(), key); - CHECK(key_it != keys.end()); - if (keys.size() == 1) { - word_to_keys.erase(word); - } else { - CHECK(keys.size() > 1); - *key_it = keys.back(); - keys.pop_back(); - } -} - -void Hints::add(KeyT key, Slice name) { - // LOG(ERROR) << "Add " << key << ": " << name; - auto it = key_to_name_.find(key); - if (it != key_to_name_.end()) { - if (it->second == name) { - return; - } - vector old_transliterations; - for (auto &old_word : get_words(it->second, false)) { - delete_word(old_word, key, word_to_keys_); - - for (auto &w : get_word_transliterations(old_word, false)) { - if (w != old_word) { - old_transliterations.push_back(std::move(w)); - } - } - } - for (auto &word : fix_words(old_transliterations)) { - delete_word(word, key, translit_word_to_keys_); - } - } - if (name.empty()) { - if (it != key_to_name_.end()) { - key_to_name_.erase(it); - } - key_to_rating_.erase(key); - return; - } - - vector transliterations; - for (auto &word : get_words(name, false)) { - add_word(word, key, word_to_keys_); - - for (auto &w : get_word_transliterations(word, false)) { - if (w != word) { - transliterations.push_back(std::move(w)); - } - } - } - for (auto &word : fix_words(transliterations)) { - add_word(word, key, translit_word_to_keys_); - } - - key_to_name_[key] = name.str(); -} - -void Hints::set_rating(KeyT key, RatingT rating) { - // LOG(ERROR) << "Set rating " << key << ": " << rating; - key_to_rating_[key] = rating; -} - -void Hints::add_search_results(vector &results, const string &word, - const std::map> &word_to_keys) { - LOG(DEBUG) << "Search for word " << word; - auto it = word_to_keys.lower_bound(word); - while (it != word_to_keys.end() && begins_with(it->first, word)) { - results.insert(results.end(), it->second.begin(), it->second.end()); - ++it; - } -} - -vector Hints::search_word(const string &word) const { - vector results; - add_search_results(results, word, translit_word_to_keys_); - for (auto w : get_word_transliterations(word, true)) { - add_search_results(results, w, word_to_keys_); - } - - std::sort(results.begin(), results.end()); - results.erase(std::unique(results.begin(), results.end()), results.end()); - return results; -} - -std::pair> Hints::search(Slice query, int32 limit, bool return_all_for_empty_query) const { - // LOG(ERROR) << "Search " << query; - vector results; - - if (limit < 0) { - return {key_to_name_.size(), std::move(results)}; - } - - auto words = get_words(query, true); - if (return_all_for_empty_query && words.empty()) { - results.reserve(key_to_name_.size()); - for (auto &it : key_to_name_) { - results.push_back(it.first); - } - } - - for (size_t i = 0; i < words.size(); i++) { - vector keys = search_word(words[i]); - if (i == 0) { - results = std::move(keys); - continue; - } - - // now need to intersect two lists - size_t results_pos = 0; - size_t keys_pos = 0; - size_t new_results_size = 0; - while (results_pos != results.size() && keys_pos != keys.size()) { - if (results[results_pos] < keys[keys_pos]) { - results_pos++; - } else if (results[results_pos] > keys[keys_pos]) { - keys_pos++; - } else { - results[new_results_size++] = results[results_pos]; - results_pos++; - keys_pos++; - } - } - results.resize(new_results_size); - } - - auto total_size = results.size(); - if (total_size < static_cast(limit)) { - std::sort(results.begin(), results.end(), CompareByRating(key_to_rating_)); - } else { - std::partial_sort(results.begin(), results.begin() + limit, results.end(), CompareByRating(key_to_rating_)); - results.resize(limit); - } - - return {total_size, std::move(results)}; -} - -bool Hints::has_key(KeyT key) const { - return key_to_name_.find(key) != key_to_name_.end(); -} - -string Hints::key_to_string(KeyT key) const { - auto it = key_to_name_.find(key); - if (it == key_to_name_.end()) { - return string(); - } - return it->second; -} - -std::pair> Hints::search_empty(int32 limit) const { - return search(Slice(), limit, true); -} - -size_t Hints::size() const { - return key_to_name_.size(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Hints.h b/submodules/ton/tonlib-src/tdutils/td/utils/Hints.h deleted file mode 100644 index 8081d778..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Hints.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" - -#include -#include -#include - -namespace td { - -// TODO template KeyT -class Hints { - using KeyT = int64; - using RatingT = int64; - - public: - void add(KeyT key, Slice name); - - void remove(KeyT key) { - add(key, ""); - } - - void set_rating(KeyT key, RatingT rating); - - std::pair> search( - Slice query, int32 limit, - bool return_all_for_empty_query = false) const; // TODO sort by name instead of sort by rating - - bool has_key(KeyT key) const; - - string key_to_string(KeyT key) const; - - std::pair> search_empty(int32 limit) const; // == search("", limit, true) - - size_t size() const; - - private: - std::map> word_to_keys_; - std::map> translit_word_to_keys_; - std::unordered_map key_to_name_; - std::unordered_map key_to_rating_; - - static void add_word(const string &word, KeyT key, std::map> &word_to_keys); - static void delete_word(const string &word, KeyT key, std::map> &word_to_keys); - - static vector fix_words(vector words); - - static vector get_words(Slice name, bool is_search); - - static void add_search_results(vector &results, const string &word, - const std::map> &word_to_keys); - - vector search_word(const string &word) const; - - class CompareByRating { - const std::unordered_map &key_to_rating_; - - RatingT get_rating(const KeyT &key) const { - auto it = key_to_rating_.find(key); - if (it == key_to_rating_.end()) { - return RatingT(); - } - return it->second; - } - - public: - explicit CompareByRating(const std::unordered_map &key_to_rating) : key_to_rating_(key_to_rating) { - } - - bool operator()(const KeyT &lhs, const KeyT &rhs) const { - auto lhs_rating = get_rating(lhs); - auto rhs_rating = get_rating(rhs); - return lhs_rating < rhs_rating || (lhs_rating == rhs_rating && lhs < rhs); - } - }; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.cpp deleted file mode 100644 index 2a73f228..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/HttpUrl.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Parser.h" - -namespace td { - -string HttpUrl::get_url() const { - string result; - switch (protocol_) { - case Protocol::HTTP: - result += "http://"; - break; - case Protocol::HTTPS: - result += "https://"; - break; - default: - UNREACHABLE(); - } - if (!userinfo_.empty()) { - result += userinfo_; - result += '@'; - } - if (is_ipv6_) { - result += '['; - } - result += host_; - if (is_ipv6_) { - result += ']'; - } - if (specified_port_ > 0) { - result += ':'; - result += to_string(specified_port_); - } - LOG_CHECK(!query_.empty() && query_[0] == '/') << query_; - result += query_; - return result; -} - -Result parse_url(Slice url, HttpUrl::Protocol default_protocol) { - // url == [https?://][userinfo@]host[:port] - ConstParser parser(url); - string protocol_str = to_lower(parser.read_till_nofail(':')); - - HttpUrl::Protocol protocol; - if (parser.start_with("://")) { - parser.advance(3); - if (protocol_str == "http") { - protocol = HttpUrl::Protocol::HTTP; - } else if (protocol_str == "https") { - protocol = HttpUrl::Protocol::HTTPS; - } else { - return Status::Error("Unsupported URL protocol"); - } - } else { - parser = ConstParser(url); - protocol = default_protocol; - } - Slice userinfo_host_port = parser.read_till_nofail("/?#"); - - int port = 0; - const char *colon = userinfo_host_port.end() - 1; - while (colon > userinfo_host_port.begin() && *colon != ':' && *colon != ']' && *colon != '@') { - colon--; - } - Slice userinfo_host; - if (colon > userinfo_host_port.begin() && *colon == ':') { - port = to_integer(Slice(colon + 1, userinfo_host_port.end())); - userinfo_host = Slice(userinfo_host_port.begin(), colon); - } else { - userinfo_host = userinfo_host_port; - } - if (port < 0 || port > 65535) { - return Status::Error("Wrong port number specified in the URL"); - } - - auto at_pos = userinfo_host.rfind('@'); - Slice userinfo = at_pos == static_cast(-1) ? "" : userinfo_host.substr(0, at_pos); - Slice host = userinfo_host.substr(at_pos + 1); - - bool is_ipv6 = false; - if (!host.empty() && host[0] == '[' && host.back() == ']') { - host.remove_prefix(1); - host.remove_suffix(1); - is_ipv6 = true; - } - if (host.empty()) { - return Status::Error("URL host is empty"); - } - if (host == ".") { - return Status::Error("Host is invalid"); - } - - int specified_port = port; - if (port == 0) { - if (protocol == HttpUrl::Protocol::HTTP) { - port = 80; - } else { - CHECK(protocol == HttpUrl::Protocol::HTTPS); - port = 443; - } - } - - Slice query = parser.read_all(); - while (!query.empty() && is_space(query.back())) { - query.remove_suffix(1); - } - if (query.empty()) { - query = Slice("/"); - } - string query_str; - if (query[0] != '/') { - query_str = '/'; - } - for (auto c : query) { - if (static_cast(c) <= 0x20) { - query_str += '%'; - query_str += "0123456789ABCDEF"[c / 16]; - query_str += "0123456789ABCDEF"[c % 16]; - } else { - query_str += c; - } - } - - string host_str = to_lower(host); - for (size_t i = 0; i < host_str.size(); i++) { - char c = host_str[i]; - if (is_ipv6) { - if (c == ':' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || c == '.') { - continue; - } - return Status::Error("Wrong IPv6 URL host"); - } - - if (('a' <= c && c <= 'z') || c == '.' || ('0' <= c && c <= '9') || c == '-' || c == '_' || c == '!' || c == '$' || - c == ',' || c == '~' || c == '*' || c == '\'' || c == '(' || c == ')' || c == ';' || c == '&' || c == '+' || - c == '=') { - // symbols allowed by RFC 7230 and RFC 3986 - continue; - } - if (c == '%') { - c = host_str[++i]; - if (('a' <= c && c <= 'f') || ('0' <= c && c <= '9')) { - c = host_str[++i]; - if (('a' <= c && c <= 'f') || ('0' <= c && c <= '9')) { - // percent encoded symbol as allowed by RFC 7230 and RFC 3986 - continue; - } - } - return Status::Error("Wrong percent-encoded symbol in URL host"); - } - - // all other symbols aren't allowed - unsigned char uc = static_cast(c); - if (uc >= 128) { - // but we allow plain UTF-8 symbols - continue; - } - return Status::Error("Wrong URL host"); - } - - return HttpUrl{protocol, userinfo.str(), std::move(host_str), is_ipv6, specified_port, port, std::move(query_str)}; -} - -StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url) { - sb << tag("protocol", url.protocol_ == HttpUrl::Protocol::HTTP ? "HTTP" : "HTTPS") << tag("userinfo", url.userinfo_) - << tag("host", url.host_) << tag("port", url.port_) << tag("query", url.query_); - return sb; -} - -string get_url_query_file_name(const string &query) { - Slice query_slice = query; - query_slice.truncate(query.find_first_of("?#")); - - auto slash_pos = query_slice.rfind('/'); - if (slash_pos < query_slice.size()) { - return query_slice.substr(slash_pos + 1).str(); - } - return query_slice.str(); -} - -string get_url_file_name(Slice url) { - auto r_http_url = parse_url(url); - if (r_http_url.is_error()) { - LOG(WARNING) << "Receive wrong URL \"" << url << '"'; - return string(); - } - return get_url_query_file_name(r_http_url.ok().query_); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.h b/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.h deleted file mode 100644 index a4e0ab6f..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/HttpUrl.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" - -namespace td { - -class HttpUrl { - public: - enum class Protocol { HTTP, HTTPS } protocol_ = Protocol::HTTP; - string userinfo_; - string host_; - bool is_ipv6_ = false; - int specified_port_ = 0; - int port_ = 0; - string query_; - - string get_url() const; - - HttpUrl(Protocol protocol, string userinfo, string host, bool is_ipv6, int specified_port, int port, string query) - : protocol_(protocol) - , userinfo_(std::move(userinfo)) - , host_(std::move(host)) - , is_ipv6_(is_ipv6) - , specified_port_(specified_port) - , port_(port) - , query_(std::move(query)) { - } -}; - -Result parse_url(Slice url, - HttpUrl::Protocol default_protocol = HttpUrl::Protocol::HTTP) TD_WARN_UNUSED_RESULT; - -StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url); - -string get_url_query_file_name(const string &query); - -string get_url_file_name(Slice url); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.cpp deleted file mode 100644 index 7a844740..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/JsonBuilder.h" - -#include "td/utils/misc.h" -#include "td/utils/ScopeGuard.h" - -#include - -namespace td { - -StringBuilder &operator<<(StringBuilder &sb, const JsonRawString &val) { - sb << '"'; - SCOPE_EXIT { - sb << '"'; - }; - auto *s = val.value_.begin(); - auto len = val.value_.size(); - - for (size_t pos = 0; pos < len; pos++) { - auto ch = static_cast(s[pos]); - switch (ch) { - case '"': - sb << '\\' << '"'; - break; - case '\\': - sb << '\\' << '\\'; - break; - case '\b': - sb << '\\' << 'b'; - break; - case '\f': - sb << '\\' << 'f'; - break; - case '\n': - sb << '\\' << 'n'; - break; - case '\r': - sb << '\\' << 'r'; - break; - case '\t': - sb << '\\' << 't'; - break; - default: - if (ch <= 31) { - sb << JsonOneChar(s[pos]); - break; - } - sb << s[pos]; - break; - } - } - return sb; -} - -StringBuilder &operator<<(StringBuilder &sb, const JsonString &val) { - sb << '"'; - SCOPE_EXIT { - sb << '"'; - }; - auto *s = val.str_.begin(); - auto len = val.str_.size(); - - for (size_t pos = 0; pos < len; pos++) { - auto ch = static_cast(s[pos]); - switch (ch) { - case '"': - sb << '\\' << '"'; - break; - case '\\': - sb << '\\' << '\\'; - break; - case '\b': - sb << '\\' << 'b'; - break; - case '\f': - sb << '\\' << 'f'; - break; - case '\n': - sb << '\\' << 'n'; - break; - case '\r': - sb << '\\' << 'r'; - break; - case '\t': - sb << '\\' << 't'; - break; - default: - if (ch <= 31) { - sb << JsonOneChar(s[pos]); - break; - } - if (128 <= ch) { - int a = s[pos]; - CHECK((a & 0x40) != 0); - - CHECK(pos + 1 < len); - int b = s[++pos]; - CHECK((b & 0xc0) == 0x80); - if ((a & 0x20) == 0) { - CHECK((a & 0x1e) > 0); - sb << JsonChar(((a & 0x1f) << 6) | (b & 0x3f)); - break; - } - - CHECK(pos + 1 < len); - int c = s[++pos]; - CHECK((c & 0xc0) == 0x80); - if ((a & 0x10) == 0) { - CHECK(((a & 0x0f) | (b & 0x20)) > 0); - sb << JsonChar(((a & 0x0f) << 12) | ((b & 0x3f) << 6) | (c & 0x3f)); - break; - } - - CHECK(pos + 1 < len); - int d = s[++pos]; - CHECK((d & 0xc0) == 0x80); - if ((a & 0x08) == 0) { - CHECK(((a & 0x07) | (b & 0x30)) > 0); - sb << JsonChar(((a & 0x07) << 18) | ((b & 0x3f) << 12) | ((c & 0x3f) << 6) | (d & 0x3f)); - break; - } - - UNREACHABLE(); - break; - } - sb << s[pos]; - break; - } - } - return sb; -} - -Result json_string_decode(Parser &parser) { - if (!parser.try_skip('"')) { - return Status::Error("Opening '\"' expected"); - } - auto *cur_src = parser.data().data(); - auto *end_src = parser.data().end(); - auto *end = cur_src; - while (end < end_src && end[0] != '"') { - if (end[0] == '\\') { - end++; - } - end++; - } - if (end >= end_src) { - return Status::Error("Closing '\"' not found"); - } - parser.advance(end + 1 - cur_src); - end_src = end; - - auto *cur_dest = cur_src; - auto *begin_dest = cur_src; - - while (cur_src != end_src) { - auto *slash = static_cast(std::memchr(cur_src, '\\', end_src - cur_src)); - if (slash == nullptr) { - slash = end_src; - } - std::memmove(cur_dest, cur_src, slash - cur_src); - cur_dest += slash - cur_src; - cur_src = slash; - if (cur_src != end_src) { - cur_src++; - if (cur_src == end_src) { - // TODO UNREACHABLE(); - return Status::Error("Unexpected end of string"); - } - switch (*cur_src) { - case '"': - case '\\': - case '/': - *cur_dest++ = *cur_src++; - break; - case 'b': - *cur_dest++ = '\b'; - cur_src++; - break; - case 'f': - *cur_dest++ = '\f'; - cur_src++; - break; - case 'n': - *cur_dest++ = '\n'; - cur_src++; - break; - case 'r': - *cur_dest++ = '\r'; - cur_src++; - break; - case 't': - *cur_dest++ = '\t'; - cur_src++; - break; - case 'u': { - cur_src++; - if (cur_src + 4 > end_src) { - return Status::Error("\\u has less than 4 symbols"); - } - int num = 0; - for (int i = 0; i < 4; i++, cur_src++) { - int d = hex_to_int(*cur_src); - if (d == 16) { - return Status::Error("Invalid \\u -- not hex digit"); - } - num = num * 16 + d; - } - if (0xD7FF < num && num < 0xE000) { - if (cur_src + 6 <= end_src && cur_src[0] == '\\' && cur_src[1] == 'u') { - cur_src += 2; - int new_num = 0; - for (int i = 0; i < 4; i++, cur_src++) { - int d = hex_to_int(*cur_src); - if (d == 16) { - return Status::Error("Invalid \\u -- not hex digit"); - } - new_num = new_num * 16 + d; - } - if (0xD7FF < new_num && new_num < 0xE000) { - num = (((num & 0x3FF) << 10) | (new_num & 0x3FF)) + 0x10000; - } else { - cur_src -= 6; - } - } - } - - if (num < 128) { - *cur_dest++ = static_cast(num); - } else if (num < 0x800) { - *cur_dest++ = static_cast(0xc0 + (num >> 6)); - *cur_dest++ = static_cast(0x80 + (num & 63)); - } else if (num <= 0xffff) { - *cur_dest++ = static_cast(0xe0 + (num >> 12)); - *cur_dest++ = static_cast(0x80 + ((num >> 6) & 63)); - *cur_dest++ = static_cast(0x80 + (num & 63)); - } else { - *cur_dest++ = static_cast(0xf0 + (num >> 18)); - *cur_dest++ = static_cast(0x80 + ((num >> 12) & 63)); - *cur_dest++ = static_cast(0x80 + ((num >> 6) & 63)); - *cur_dest++ = static_cast(0x80 + (num & 63)); - } - break; - } - } - } - } - CHECK(cur_dest <= end_src); - return MutableSlice(begin_dest, cur_dest); -} - -Status json_string_skip(Parser &parser) { - if (!parser.try_skip('"')) { - return Status::Error("Opening '\"' expected"); - } - auto *begin_src = parser.data().data(); - auto *cur_src = begin_src; - auto *end_src = parser.data().end(); - auto *end = cur_src; - while (end < end_src && *end != '"') { - if (*end == '\\') { - end++; - } - end++; - } - if (end >= end_src) { - return Status::Error("Closing '\"' not found"); - } - parser.advance(end + 1 - cur_src); - end_src = end; - - while (cur_src != end_src) { - auto *slash = static_cast(std::memchr(cur_src, '\\', end_src - cur_src)); - if (slash == nullptr) { - slash = end_src; - } - cur_src = slash; - if (cur_src != end_src) { - cur_src++; - if (cur_src == end_src) { - // TODO UNREACHABLE(); - return Status::Error("Unexpected end of string"); - } - switch (*cur_src) { - case '"': - case '\\': - case '/': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - cur_src++; - break; - case 'u': { - cur_src++; - if (cur_src + 4 > end_src) { - return Status::Error("\\u has less than 4 symbols"); - } - int num = 0; - for (int i = 0; i < 4; i++, cur_src++) { - int d = hex_to_int(*cur_src); - if (d == 16) { - return Status::Error("Invalid \\u -- not hex digit"); - } - num = num * 16 + d; - } - if (0xD7FF < num && num < 0xE000) { - if (cur_src + 6 <= end_src && cur_src[0] == '\\' && cur_src[1] == 'u') { - cur_src += 2; - int new_num = 0; - for (int i = 0; i < 4; i++, cur_src++) { - int d = hex_to_int(*cur_src); - if (d == 16) { - return Status::Error("Invalid \\u -- not hex digit"); - } - new_num = new_num * 16 + d; - } - if (0xD7FF < new_num && new_num < 0xE000) { - // num = (((num & 0x3FF) << 10) | (new_num & 0x3FF)) + 0x10000; - } else { - cur_src -= 6; - } - } - } - break; - } - } - } - } - return Status::OK(); -} - -Result do_json_decode(Parser &parser, int32 max_depth) { - if (max_depth < 0) { - return Status::Error("Too big object depth"); - } - - parser.skip_whitespaces(); - switch (parser.peek_char()) { - case 'f': - if (parser.skip_start_with("false")) { - return JsonValue::create_boolean(false); - } - return Status::Error("Token starts with 'f' -- false expected"); - case 't': - if (parser.skip_start_with("true")) { - return JsonValue::create_boolean(true); - } - return Status::Error("Token starts with 't' -- true expected"); - case 'n': - if (parser.skip_start_with("null")) { - return JsonValue(); - } - return Status::Error("Token starts with 'n' -- null expected"); - case '"': { - TRY_RESULT(slice, json_string_decode(parser)); - return JsonValue::create_string(slice); - } - case '[': { - parser.skip('['); - parser.skip_whitespaces(); - std::vector res; - if (parser.try_skip(']')) { - return JsonValue::create_array(std::move(res)); - } - while (true) { - if (parser.empty()) { - return Status::Error("Unexpected string end"); - } - TRY_RESULT(value, do_json_decode(parser, max_depth - 1)); - res.emplace_back(std::move(value)); - - parser.skip_whitespaces(); - if (parser.try_skip(']')) { - break; - } - if (parser.try_skip(',')) { - parser.skip_whitespaces(); - continue; - } - if (parser.empty()) { - return Status::Error("Unexpected string end"); - } - return Status::Error("Unexpected symbol while parsing JSON Array"); - } - return JsonValue::create_array(std::move(res)); - } - case '{': { - parser.skip('{'); - parser.skip_whitespaces(); - std::vector > res; - if (parser.try_skip('}')) { - return JsonValue::make_object(std::move(res)); - } - while (true) { - if (parser.empty()) { - return Status::Error("Unexpected string end"); - } - TRY_RESULT(key, json_string_decode(parser)); - parser.skip_whitespaces(); - if (!parser.try_skip(':')) { - return Status::Error("':' expected"); - } - TRY_RESULT(value, do_json_decode(parser, max_depth - 1)); - res.emplace_back(std::move(key), std::move(value)); - - parser.skip_whitespaces(); - if (parser.try_skip('}')) { - break; - } - if (parser.try_skip(',')) { - parser.skip_whitespaces(); - continue; - } - if (parser.empty()) { - return Status::Error("Unexpected string end"); - } - return Status::Error("Unexpected symbol while parsing JSON Object"); - } - return JsonValue::make_object(std::move(res)); - } - case '-': - case '+': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - auto num = parser.read_while( - [](char c) { return c == '-' || ('0' <= c && c <= '9') || c == 'e' || c == 'E' || c == '+' || c == '.'; }); - return JsonValue::create_number(num); - } - case 0: - return Status::Error("Unexpected string end"); - default: { - char next = parser.peek_char(); - if (0 < next && next < 127) { - return Status::Error(PSLICE() << "Unexpected symbol '" << parser.peek_char() << "'"); - } else { - return Status::Error("Unexpected symbol"); - } - } - } - UNREACHABLE(); -} - -Status do_json_skip(Parser &parser, int32 max_depth) { - if (max_depth < 0) { - return Status::Error("Too big object depth"); - } - - parser.skip_whitespaces(); - switch (parser.peek_char()) { - case 'f': - if (parser.skip_start_with("false")) { - return Status::OK(); - } - return Status::Error("Starts with 'f' -- false expected"); - case 't': - if (parser.skip_start_with("true")) { - return Status::OK(); - } - return Status::Error("Starts with 't' -- true expected"); - case 'n': - if (parser.skip_start_with("null")) { - return Status::OK(); - } - return Status::Error("Starts with 'n' -- null expected"); - case '"': { - return json_string_skip(parser); - } - case '[': { - parser.skip('['); - parser.skip_whitespaces(); - if (parser.try_skip(']')) { - return Status::OK(); - } - while (true) { - if (parser.empty()) { - return Status::Error("Unexpected end"); - } - TRY_STATUS(do_json_skip(parser, max_depth - 1)); - - parser.skip_whitespaces(); - if (parser.try_skip(']')) { - break; - } - if (parser.try_skip(',')) { - parser.skip_whitespaces(); - continue; - } - return Status::Error("Unexpected symbol"); - } - return Status::OK(); - } - case '{': { - parser.skip('{'); - parser.skip_whitespaces(); - if (parser.try_skip('}')) { - return Status::OK(); - } - while (true) { - if (parser.empty()) { - return Status::Error("Unexpected end"); - } - TRY_STATUS(json_string_skip(parser)); - parser.skip_whitespaces(); - if (!parser.try_skip(':')) { - return Status::Error("':' expected"); - } - TRY_STATUS(do_json_skip(parser, max_depth - 1)); - - parser.skip_whitespaces(); - if (parser.try_skip('}')) { - break; - } - if (parser.try_skip(',')) { - parser.skip_whitespaces(); - continue; - } - return Status::Error("Unexpected symbol"); - } - return Status::OK(); - } - case '-': - case '+': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - parser.read_while( - [](char c) { return c == '-' || ('0' <= c && c <= '9') || c == 'e' || c == 'E' || c == '+' || c == '.'; }); - return Status::OK(); - } - case 0: - return Status::Error("Unexpected end"); - default: { - char next = parser.peek_char(); - if (0 < next && next < 127) { - return Status::Error(PSLICE() << "Unexpected symbol '" << parser.peek_char() << "'"); - } else { - return Status::Error("Unexpected symbol"); - } - } - } - return Status::Error("Can't parse"); -} - -Slice JsonValue::get_type_name(Type type) { - switch (type) { - case Type::Null: - return Slice("Null"); - case Type::Number: - return Slice("Number"); - case Type::Boolean: - return Slice("Boolean"); - case Type::String: - return Slice("String"); - case Type::Array: - return Slice("Array"); - case Type::Object: - return Slice("Object"); - default: - UNREACHABLE(); - return Slice("Unknown"); - } -} - -bool has_json_object_field(const JsonObject &object, Slice name) { - for (auto &field_value : object) { - if (field_value.first == name) { - return true; - } - } - return false; -} - -Result get_json_object_field(JsonObject &object, Slice name, JsonValue::Type type, bool is_optional) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (type != JsonValue::Type::Null && field_value.second.type() != type) { - return Status::Error(400, PSLICE() - << "Field \"" << name << "\" must be of type " << JsonValue::get_type_name(type)); - } - - return std::move(field_value.second); - } - } - if (!is_optional) { - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); - } - return JsonValue(); -} - -Result get_json_object_bool_field(JsonObject &object, Slice name, bool is_optional, bool default_value) { - TRY_RESULT(value, get_json_object_field(object, name, JsonValue::Type::Boolean, is_optional)); - if (value.type() == JsonValue::Type::Null) { - return default_value; - } - return value.get_boolean(); -} - -Result get_json_object_int_field(JsonObject &object, Slice name, bool is_optional, int32 default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return to_integer_safe(field_value.second.get_string()); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return to_integer_safe(field_value.second.get_number()); - } - - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Number"); - } - } - if (is_optional) { - return default_value; - } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); -} - -Result get_json_object_long_field(JsonObject &object, Slice name, bool is_optional, int64 default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return to_integer_safe(field_value.second.get_string()); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return to_integer_safe(field_value.second.get_number()); - } - - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); - } - } - if (is_optional) { - return default_value; - } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); -} - -Result get_json_object_double_field(JsonObject &object, Slice name, bool is_optional, double default_value) { - TRY_RESULT(value, get_json_object_field(object, name, JsonValue::Type::Number, is_optional)); - if (value.type() == JsonValue::Type::Null) { - return default_value; - } - return to_double(value.get_number()); -} - -Result get_json_object_string_field(JsonObject &object, Slice name, bool is_optional, string default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return field_value.second.get_string().str(); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return field_value.second.get_number().str(); - } - - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type String"); - } - } - if (is_optional) { - return default_value; - } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.h b/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.h deleted file mode 100644 index d67af283..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/JsonBuilder.h +++ /dev/null @@ -1,902 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/Parser.h" -#include "td/utils/Slice.h" -#include "td/utils/StackAllocator.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" - -#include -#include -#include -#include - -namespace td { - -template -std::tuple ctie(const Args &... args) TD_WARN_UNUSED_RESULT; - -template -std::tuple ctie(const Args &... args) { - return std::tie(args...); -} - -class JsonTrue { - public: - friend StringBuilder &operator<<(StringBuilder &sb, const JsonTrue &val) { - return sb << "true"; - } -}; - -class JsonFalse { - public: - friend StringBuilder &operator<<(StringBuilder &sb, const JsonFalse &val) { - return sb << "false"; - } -}; - -class JsonNull { - public: - friend StringBuilder &operator<<(StringBuilder &sb, JsonNull val) { - return sb << "null"; - } -}; - -class JsonBool { - public: - explicit JsonBool(bool value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonBool &val) { - if (val.value_) { - return sb << JsonTrue(); - } else { - return sb << JsonFalse(); - } - } - - private: - bool value_; -}; - -class JsonInt { - public: - explicit JsonInt(int32 value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonInt &val) { - return sb << val.value_; - } - - private: - int32 value_; -}; - -class JsonLong { - public: - explicit JsonLong(int64 value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonLong &val) { - return sb << val.value_; - } - - private: - int64 value_; -}; - -class JsonFloat { - public: - explicit JsonFloat(double value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonFloat &val) { - return sb << val.value_; - } - - private: - double value_; -}; - -class JsonOneChar { - public: - explicit JsonOneChar(unsigned int c) : c_(c) { - } - - friend StringBuilder &operator<<(StringBuilder &sb, const JsonOneChar &val) { - auto c = val.c_; - return sb << '\\' << 'u' << "0123456789abcdef"[c >> 12] << "0123456789abcdef"[(c >> 8) & 15] - << "0123456789abcdef"[(c >> 4) & 15] << "0123456789abcdef"[c & 15]; - } - - private: - unsigned int c_; -}; - -class JsonChar { - public: - explicit JsonChar(unsigned int c) : c_(c) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonChar &val) { - auto c = val.c_; - if (c < 0x10000) { - if (0xD7FF < c && c < 0xE000) { - // UTF-8 correctness has already been checked - UNREACHABLE(); - } - return sb << JsonOneChar(c); - } else if (c <= 0x10ffff) { - return sb << JsonOneChar(0xD7C0 + (c >> 10)) << JsonOneChar(0xDC00 + (c & 0x3FF)); - } else { - // UTF-8 correctness has already been checked - UNREACHABLE(); - } - } - - private: - unsigned int c_; -}; - -class JsonRaw { - public: - explicit JsonRaw(Slice value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonRaw &val) { - return sb << val.value_; - } - - private: - Slice value_; -}; - -class JsonRawString { - public: - explicit JsonRawString(Slice value) : value_(value) { - } - friend StringBuilder &operator<<(StringBuilder &sb, const JsonRawString &val); - - private: - Slice value_; -}; - -class JsonString { - public: - explicit JsonString(Slice str) : str_(str) { - } - - friend StringBuilder &operator<<(StringBuilder &sb, const JsonString &val); - - private: - Slice str_; -}; - -class JsonScope; -class JsonValueScope; -class JsonArrayScope; -class JsonObjectScope; - -class JsonBuilder { - public: - explicit JsonBuilder(StringBuilder &&sb = {}, int32 offset = -1) : sb_(std::move(sb)), offset_(offset) { - } - StringBuilder &string_builder() { - return sb_; - } - friend class JsonScope; - JsonValueScope enter_value() TD_WARN_UNUSED_RESULT; - JsonArrayScope enter_array() TD_WARN_UNUSED_RESULT; - JsonObjectScope enter_object() TD_WARN_UNUSED_RESULT; - - int32 offset() const { - return offset_; - } - bool is_pretty() const { - return offset_ >= 0; - } - void print_offset() { - for (int x = 0; x < offset_; x++) { - sb_ << " "; - } - } - void dec_offset() { - if (offset_ >= 0) { - CHECK(offset_ > 0); - offset_--; - } - } - void inc_offset() { - if (offset_ >= 0) { - offset_++; - } - } - - private: - StringBuilder sb_; - JsonScope *scope_ = nullptr; - int32 offset_; -}; - -class Jsonable {}; - -class JsonScope { - public: - explicit JsonScope(JsonBuilder *jb) : sb_(&jb->sb_), jb_(jb), save_scope_(jb->scope_) { - jb_->scope_ = this; - CHECK(is_active()); - } - JsonScope(const JsonScope &other) = delete; - JsonScope(JsonScope &&other) : sb_(other.sb_), jb_(other.jb_), save_scope_(other.save_scope_) { - other.jb_ = nullptr; - } - JsonScope &operator=(const JsonScope &) = delete; - JsonScope &operator=(JsonScope &&) = delete; - ~JsonScope() { - if (jb_) { - leave(); - } - } - void leave() { - CHECK(is_active()); - jb_->scope_ = save_scope_; - } - - protected: - StringBuilder *sb_; - - // For CHECK - JsonBuilder *jb_; - JsonScope *save_scope_; - - bool is_active() const { - return jb_ && jb_->scope_ == this; - } - - JsonScope &operator<<(JsonTrue x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(JsonFalse x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(JsonNull x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonBool &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonInt &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonLong &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonFloat &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonString &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonRawString &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(const JsonRaw &x) { - *sb_ << x; - return *this; - } - JsonScope &operator<<(bool x) { - return *this << JsonBool(x); - } - JsonScope &operator<<(int32 x) { - return *this << JsonInt(x); - } - JsonScope &operator<<(int64 x) { - return *this << JsonLong(x); - } - JsonScope &operator<<(double x) { - return *this << JsonFloat(x); - } - template - JsonScope &operator<<(const T *x); // not implemented - template - JsonScope &operator<<(const char (&x)[N]) { - return *this << JsonString(Slice(x)); - } - JsonScope &operator<<(const char *x) { - return *this << JsonString(Slice(x)); - } - JsonScope &operator<<(const string &x) { - return *this << JsonString(Slice(x)); - } - JsonScope &operator<<(Slice x) { - return *this << JsonString(x); - } -}; - -class JsonValueScope : public JsonScope { - public: - using JsonScope::JsonScope; - template - std::enable_if_t::type>::value, JsonValueScope &> operator<<( - const T &x) { - x.store(this); - return *this; - } - template - std::enable_if_t::type>::value, JsonValueScope &> operator<<( - const T &x) { - CHECK(!was_); - was_ = true; - JsonScope::operator<<(x); - return *this; - } - - JsonArrayScope enter_array() TD_WARN_UNUSED_RESULT; - JsonObjectScope enter_object() TD_WARN_UNUSED_RESULT; - - private: - bool was_ = false; -}; - -class JsonArrayScope : public JsonScope { - public: - explicit JsonArrayScope(JsonBuilder *jb) : JsonScope(jb) { - jb->inc_offset(); - *sb_ << "["; - } - JsonArrayScope(JsonArrayScope &&other) = default; - ~JsonArrayScope() { - if (jb_) { - leave(); - } - } - void leave() { - jb_->dec_offset(); - if (jb_->is_pretty()) { - *sb_ << "\n"; - jb_->print_offset(); - } - *sb_ << "]"; - } - template - JsonArrayScope &operator<<(const T &x) { - return (*this)(x); - } - template - JsonArrayScope &operator()(const T &x) { - enter_value() << x; - return *this; - } - JsonValueScope enter_value() { - CHECK(is_active()); - if (is_first_) { - *sb_ << ","; - } else { - is_first_ = true; - } - if (jb_->is_pretty()) { - *sb_ << "\n"; - jb_->print_offset(); - } - return jb_->enter_value(); - } - - private: - bool is_first_ = false; -}; - -class JsonObjectScope : public JsonScope { - public: - explicit JsonObjectScope(JsonBuilder *jb) : JsonScope(jb) { - jb->inc_offset(); - *sb_ << "{"; - } - JsonObjectScope(JsonObjectScope &&other) = default; - ~JsonObjectScope() { - if (jb_) { - leave(); - } - } - void leave() { - jb_->dec_offset(); - if (jb_->is_pretty()) { - *sb_ << "\n"; - jb_->print_offset(); - } - *sb_ << "}"; - } - template - JsonObjectScope &operator<<(std::tuple key_value) { - return (*this)(std::get<0>(key_value), std::get<1>(key_value)); - } - template - JsonObjectScope &operator<<(std::pair key_value) { - return (*this)(key_value.first, key_value.second); - } - template - JsonObjectScope &operator()(S &&key, T &&value) { - CHECK(is_active()); - if (is_first_) { - *sb_ << ","; - } else { - is_first_ = true; - } - if (jb_->is_pretty()) { - *sb_ << "\n"; - jb_->print_offset(); - } - jb_->enter_value() << key; - if (jb_->is_pretty()) { - *sb_ << " : "; - } else { - *sb_ << ":"; - } - jb_->enter_value() << value; - return *this; - } - JsonObjectScope &operator<<(const JsonRaw &key_value) { - CHECK(is_active()); - is_first_ = true; - jb_->enter_value() << key_value; - return *this; - } - - private: - bool is_first_ = false; -}; - -inline JsonArrayScope JsonValueScope::enter_array() { - CHECK(!was_); - was_ = true; - return JsonArrayScope(jb_); -} -inline JsonObjectScope JsonValueScope::enter_object() { - CHECK(!was_); - was_ = true; - return JsonObjectScope(jb_); -} -inline JsonValueScope JsonBuilder::enter_value() { - return JsonValueScope(this); -} -inline JsonObjectScope JsonBuilder::enter_object() { - return JsonObjectScope(this); -} -inline JsonArrayScope JsonBuilder::enter_array() { - return JsonArrayScope(this); -} - -class JsonValue; - -using JsonObject = vector>; -using JsonArray = vector; - -class JsonValue : public Jsonable { - public: - enum class Type { Null, Number, Boolean, String, Array, Object }; - - static Slice get_type_name(Type type); - - JsonValue() { - } - ~JsonValue() { - destroy(); - } - JsonValue(JsonValue &&other) : JsonValue() { - init(std::move(other)); - } - JsonValue &operator=(JsonValue &&other) { - if (&other == this) { - return *this; - } - destroy(); - init(std::move(other)); - return *this; - } - JsonValue(const JsonValue &other) = delete; - JsonValue &operator=(const JsonValue &other) = delete; - - Type type() const { - return type_; - } - - MutableSlice &get_string() { - CHECK(type_ == Type::String); - return string_; - } - const MutableSlice &get_string() const { - CHECK(type_ == Type::String); - return string_; - } - bool &get_boolean() { - CHECK(type_ == Type::Boolean); - return boolean_; - } - const bool &get_boolean() const { - CHECK(type_ == Type::Boolean); - return boolean_; - } - - MutableSlice &get_number() { - CHECK(type_ == Type::Number); - return number_; - } - const MutableSlice &get_number() const { - CHECK(type_ == Type::Number); - return number_; - } - - JsonArray &get_array() { - CHECK(type_ == Type::Array); - return array_; - } - const JsonArray &get_array() const { - CHECK(type_ == Type::Array); - return array_; - } - - JsonObject &get_object() { - CHECK(type_ == Type::Object); - return object_; - } - const JsonObject &get_object() const { - CHECK(type_ == Type::Object); - return object_; - } - - static JsonValue create_boolean(bool val) { - JsonValue res; - res.init_boolean(val); - return res; - } - - static JsonValue create_number(MutableSlice number) { - JsonValue res; - res.init_number(number); - return res; - } - - static JsonValue create_string(MutableSlice str) { - JsonValue res; - res.init_string(str); - return res; - } - - static JsonValue create_array(JsonArray v) { - JsonValue res; - res.init_array(std::move(v)); - return res; - } - - static JsonValue make_object(JsonObject c) { - JsonValue res; - res.init_object(std::move(c)); - return res; - } - - void store(JsonValueScope *scope) const { - switch (type_) { - case Type::Null: - *scope << JsonRaw("null"); - break; - case Type::Boolean: - if (get_boolean()) { - *scope << JsonRaw("true"); - } else { - *scope << JsonRaw("false"); - } - break; - case Type::Number: - *scope << JsonRaw(get_number()); - break; - case Type::String: - *scope << JsonString(get_string()); - break; - case Type::Array: { - auto arr = scope->enter_array(); - for (auto &val : get_array()) { - arr << val; - } - break; - } - case Type::Object: { - auto object = scope->enter_object(); - for (auto &key_value : get_object()) { - object << ctie(JsonString(key_value.first), key_value.second); - } - break; - } - } - }; - - private: - Type type_{Type::Null}; - union { - MutableSlice number_; - bool boolean_; - MutableSlice string_; - JsonArray array_; - JsonObject object_; - }; - - void init_null() { - type_ = Type::Null; - } - void init_number(MutableSlice number) { - type_ = Type::Number; - new (&number_) MutableSlice(number); - } - void init_boolean(bool boolean) { - type_ = Type::Boolean; - boolean_ = boolean; - } - void init_string(MutableSlice slice) { - type_ = Type::String; - new (&string_) MutableSlice(slice); - } - void init_array(JsonArray array) { - type_ = Type::Array; - new (&array_) JsonArray(std::move(array)); - } - void init_object(JsonObject object) { - type_ = Type::Object; - new (&object_) JsonObject(std::move(object)); - } - - void init(JsonValue &&other) { - switch (other.type_) { - case Type::Null: - break; - case Type::Number: - init_number(other.number_); - break; - case Type::Boolean: - init_boolean(other.boolean_); - break; - case Type::String: - init_string(other.string_); - break; - case Type::Array: - init_array(std::move(other.array_)); - break; - case Type::Object: - init_object(std::move(other.object_)); - break; - } - other.destroy(); - } - - void destroy() { - switch (type_) { - case Type::Null: - case Type::Boolean: - break; - case Type::Number: - number_.~MutableSlice(); - break; - case Type::String: - string_.~MutableSlice(); - break; - case Type::Array: - array_.~vector(); - break; - case Type::Object: - object_.~vector>(); - break; - } - type_ = Type::Null; - } -}; - -inline StringBuilder &operator<<(StringBuilder &sb, JsonValue::Type type) { - switch (type) { - case JsonValue::Type::Null: - return sb << "Null"; - case JsonValue::Type::Number: - return sb << "Number"; - case JsonValue::Type::Boolean: - return sb << "Boolean"; - case JsonValue::Type::String: - return sb << "String"; - case JsonValue::Type::Array: - return sb << "Array"; - case JsonValue::Type::Object: - return sb << "Object"; - default: - UNREACHABLE(); - return sb; - } -} - -class VirtuallyJsonable : public Jsonable { - public: - virtual void store(JsonValueScope *scope) const = 0; - VirtuallyJsonable() = default; - VirtuallyJsonable(const VirtuallyJsonable &) = delete; - VirtuallyJsonable &operator=(const VirtuallyJsonable &) = delete; - VirtuallyJsonable(VirtuallyJsonable &&) = default; - VirtuallyJsonable &operator=(VirtuallyJsonable &&) = default; - virtual ~VirtuallyJsonable() = default; -}; - -class VirtuallyJsonableInt : public VirtuallyJsonable { - public: - explicit VirtuallyJsonableInt(int32 value) : value_(value) { - } - void store(JsonValueScope *scope) const override { - *scope << JsonInt(value_); - } - - private: - int32 value_; -}; - -class VirtuallyJsonableLong : public VirtuallyJsonable { - public: - explicit VirtuallyJsonableLong(int64 value) : value_(value) { - } - void store(JsonValueScope *scope) const override { - *scope << JsonLong(value_); - } - - private: - int64 value_; -}; - -class VirtuallyJsonableString : public VirtuallyJsonable { - public: - explicit VirtuallyJsonableString(Slice value) : value_(value) { - } - void store(JsonValueScope *scope) const override { - *scope << JsonString(value_); - } - - private: - Slice value_; -}; - -Result json_string_decode(Parser &parser) TD_WARN_UNUSED_RESULT; -Status json_string_skip(Parser &parser) TD_WARN_UNUSED_RESULT; - -Result do_json_decode(Parser &parser, int32 max_depth) TD_WARN_UNUSED_RESULT; -Status do_json_skip(Parser &parser, int32 max_depth) TD_WARN_UNUSED_RESULT; - -inline Result json_decode(MutableSlice json) { - Parser parser(json); - const int32 DEFAULT_MAX_DEPTH = 100; - auto result = do_json_decode(parser, DEFAULT_MAX_DEPTH); - if (result.is_ok()) { - parser.skip_whitespaces(); - if (!parser.empty()) { - return Status::Error("Expected string end"); - } - } - return result; -} - -template -StrT json_encode(const ValT &val, bool pretty = false) { - auto buf_len = 1 << 18; - auto buf = StackAllocator::alloc(buf_len); - JsonBuilder jb(StringBuilder(buf.as_slice(), true), pretty ? 0 : -1); - jb.enter_value() << val; - if (pretty) { - jb.string_builder() << "\n"; - } - LOG_IF(ERROR, jb.string_builder().is_error()) << "JSON buffer overflow"; - auto slice = jb.string_builder().as_cslice(); - return StrT(slice.begin(), slice.size()); -} - -template -class ToJsonImpl : public Jsonable { - public: - explicit ToJsonImpl(const T &value) : value_(value) { - } - void store(JsonValueScope *scope) const { - to_json(*scope, value_); - } - - private: - const T &value_; -}; - -template -auto ToJson(const T &value) { - return ToJsonImpl(value); -} - -template -void to_json(JsonValueScope &jv, const T &value) { - jv << value; -} - -template -class JsonObjectImpl : Jsonable { - public: - explicit JsonObjectImpl(F &&f) : f_(std::forward(f)) { - } - void store(JsonValueScope *scope) const { - auto object = scope->enter_object(); - f_(object); - } - - private: - F f_; -}; -template -auto json_object(F &&f) { - return JsonObjectImpl(std::forward(f)); -} - -template -class JsonArrayImpl : Jsonable { - public: - explicit JsonArrayImpl(F &&f) : f_(std::forward(f)) { - } - void store(JsonValueScope *scope) const { - auto array = scope->enter_array(); - f_(array); - } - - private: - F f_; -}; - -template -auto json_array(F &&f) { - return JsonArrayImpl(std::forward(f)); -} - -template -auto json_array(const A &a, F &&f) { - return json_array([&a, &f](auto &arr) { - for (auto &x : a) { - arr(f(x)); - } - }); -} - -bool has_json_object_field(const JsonObject &object, Slice name); - -Result get_json_object_field(JsonObject &object, Slice name, JsonValue::Type type, - bool is_optional = true) TD_WARN_UNUSED_RESULT; - -Result get_json_object_bool_field(JsonObject &object, Slice name, bool is_optional = true, - bool default_value = false) TD_WARN_UNUSED_RESULT; - -Result get_json_object_int_field(JsonObject &object, Slice name, bool is_optional = true, - int32 default_value = 0) TD_WARN_UNUSED_RESULT; - -Result get_json_object_long_field(JsonObject &object, Slice name, bool is_optional = true, - int64 default_value = 0) TD_WARN_UNUSED_RESULT; - -Result get_json_object_double_field(JsonObject &object, Slice name, bool is_optional = true, - double default_value = 0.0) TD_WARN_UNUSED_RESULT; - -Result get_json_object_string_field(JsonObject &object, Slice name, bool is_optional = true, - string default_value = "") TD_WARN_UNUSED_RESULT; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/List.h b/submodules/ton/tonlib-src/tdutils/td/utils/List.h deleted file mode 100644 index 4f3c3889..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/List.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { - -struct ListNode { - ListNode *next; - ListNode *prev; - ListNode() { - clear(); - } - - ~ListNode() { - remove(); - } - - ListNode(const ListNode &) = delete; - ListNode &operator=(const ListNode &) = delete; - - ListNode(ListNode &&other) { - if (other.empty()) { - clear(); - } else { - ListNode *head = other.prev; - other.remove(); - head->put(this); - } - } - - ListNode &operator=(ListNode &&other) { - this->remove(); - - if (!other.empty()) { - ListNode *head = other.prev; - other.remove(); - head->put(this); - } - - return *this; - } - - void connect(ListNode *to) { - CHECK(to != nullptr); - next = to; - to->prev = this; - } - - void remove() { - prev->connect(next); - clear(); - } - - void put(ListNode *other) { - other->connect(next); - this->connect(other); - } - - void put_back(ListNode *other) { - prev->connect(other); - other->connect(this); - } - - ListNode *get() { - ListNode *result = prev; - if (result == this) { - return nullptr; - } - result->prev->connect(this); - result->clear(); - // this->connect(result->next); - return result; - } - - bool empty() const { - return next == this; - } - - private: - void clear() { - next = this; - prev = this; - } -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MemoryLog.h b/submodules/ton/tonlib-src/tdutils/td/utils/MemoryLog.h deleted file mode 100644 index 92bb0d76..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MemoryLog.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/Slice.h" - -#include -#include -#include - -namespace td { - -template -class MemoryLog : public LogInterface { - static constexpr size_t MAX_OUTPUT_SIZE = buffer_size / 16 < (8 << 10) ? buffer_size / 16 : (8 << 10); - - public: - MemoryLog() { - std::memset(buffer_, ' ', sizeof(buffer_)); - } - - void append(CSlice new_slice, int log_level) override { - Slice slice = new_slice; - slice.truncate(MAX_OUTPUT_SIZE); - while (!slice.empty() && slice.back() == '\n') { - slice.remove_suffix(1); - } - size_t slice_size = slice.size(); - CHECK(slice_size * 3 < buffer_size); - size_t pad_size = ((slice_size + 15) & ~15) - slice_size; - constexpr size_t magic_size = 16; - uint32 total_size = static_cast(slice_size + pad_size + magic_size); - uint32 real_pos = pos_.fetch_add(total_size, std::memory_order_relaxed); - CHECK((total_size & 15) == 0); - - uint32 start_pos = real_pos & (buffer_size - 1); - uint32 end_pos = start_pos + total_size; - if (likely(end_pos <= buffer_size)) { - std::memcpy(&buffer_[start_pos + magic_size], slice.data(), slice_size); - std::memcpy(&buffer_[start_pos + magic_size + slice_size], " ", pad_size); - } else { - size_t first = buffer_size - start_pos - magic_size; - size_t second = slice_size - first; - std::memcpy(&buffer_[start_pos + magic_size], slice.data(), first); - std::memcpy(&buffer_[0], slice.data() + first, second); - std::memcpy(&buffer_[second], " ", pad_size); - } - - CHECK((start_pos & 15) == 0); - CHECK(start_pos <= buffer_size - magic_size); - buffer_[start_pos] = '\n'; - size_t printed = std::snprintf(&buffer_[start_pos + 1], magic_size - 1, "LOG:%08x: ", real_pos); - CHECK(printed == magic_size - 2); - buffer_[start_pos + magic_size - 1] = ' '; - - if (log_level == VERBOSITY_NAME(FATAL)) { - process_fatal_error(new_slice); - } - } - - void rotate() override { - } - - Slice get_buffer() const { - return Slice(buffer_, sizeof(buffer_)); - } - - size_t get_pos() const { - return pos_ & (buffer_size - 1); - } - - private: - char buffer_[buffer_size]; - std::atomic pos_{0}; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.cpp deleted file mode 100644 index ad873d1c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/MimeType.h" - -#include "td/utils/logging.h" - -const char *extension_to_mime_type(const char *extension, size_t extension_len); // auto-generated -const char *mime_type_to_extension(const char *mime_type, size_t mime_type_len); // auto-generated - -namespace td { - -string MimeType::to_extension(Slice mime_type, Slice default_value) { - if (mime_type.empty()) { - return default_value.str(); - } - - const char *result = ::mime_type_to_extension(mime_type.data(), mime_type.size()); - if (result != nullptr) { - return result; - } - - LOG(INFO) << "Unknown file MIME type " << mime_type; - return default_value.str(); -} - -string MimeType::from_extension(Slice extension, Slice default_value) { - if (extension.empty()) { - return default_value.str(); - } - - const char *result = ::extension_to_mime_type(extension.data(), extension.size()); - if (result != nullptr) { - return result; - } - - LOG(INFO) << "Unknown file extension " << extension; - return default_value.str(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.h b/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.h deleted file mode 100644 index 583bd659..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MimeType.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" - -namespace td { - -class MimeType { - public: - static string to_extension(Slice mime_type, Slice default_value = Slice()); - static string from_extension(Slice extension, Slice default_value = Slice()); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MovableValue.h b/submodules/ton/tonlib-src/tdutils/td/utils/MovableValue.h deleted file mode 100644 index 64001a5d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MovableValue.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace td { - -template -class MovableValue { - public: - MovableValue() = default; - MovableValue(T val) : val_(val) { - } - MovableValue(MovableValue &&other) : val_(other.val_) { - other.clear(); - } - MovableValue &operator=(MovableValue &&other) { - val_ = other.val_; - other.clear(); - return *this; - } - MovableValue(const MovableValue &) = delete; - MovableValue &operator=(const MovableValue &) = delete; - ~MovableValue() = default; - - void clear() { - val_ = empty_val; - } - const T &get() const { - return val_; - } - - private: - T val_ = empty_val; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.cpp deleted file mode 100644 index 9fe7f550..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/MpmcQueue.h" - -namespace td { -namespace detail { - -MpmcStat stat_; - -} // namespace detail -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.h b/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.h deleted file mode 100644 index e6504e35..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcQueue.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -// MPMC queue -// Simple semaphore protected implementation -// To close queue, one should send as much sentinel elements as there are readers. -// Once there are no readers and writers, one may easily destroy queue - -#include "td/utils/format.h" -#include "td/utils/HazardPointers.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" -#include "td/utils/ScopeGuard.h" - -#include -#include - -namespace td { - -namespace detail { - -struct MpmcStat { - void alloc_ok(size_t thread_id) { - s(thread_id).alloc_ok_cnt++; - } - void alloc_error(size_t thread_id) { - s(thread_id).alloc_error_cnt++; - } - void push_loop_error(size_t thread_id) { - s(thread_id).push_loop_error_cnt++; - } - void push_loop_ok(size_t thread_id) { - s(thread_id).push_loop_ok_cnt++; - } - void dump() { - int alloc_ok_cnt = 0; - int alloc_error_cnt = 0; - int push_loop_error_cnt = 0; - int push_loop_ok_cnt = 0; - for (auto &d : arr) { - alloc_ok_cnt += d.alloc_ok_cnt; - alloc_error_cnt += d.alloc_error_cnt; - push_loop_error_cnt += d.push_loop_error_cnt; - push_loop_ok_cnt += d.push_loop_ok_cnt; - } - LOG(ERROR) << tag("alloc_ok_cnt", alloc_ok_cnt) << tag("alloc_error_cnt", alloc_error_cnt) - << tag("push_loop_error_cnt", push_loop_error_cnt) << tag("push_loop_ok_cnt", push_loop_ok_cnt); - } - - private: - struct ThreadStat { - int alloc_ok_cnt{0}; - int alloc_error_cnt{0}; - int push_loop_ok_cnt{0}; - int push_loop_error_cnt{0}; - char pad[TD_CONCURRENCY_PAD - sizeof(int) * 4]; - }; - std::array arr; - ThreadStat &s(size_t thread_id) { - return arr[thread_id]; - } -}; - -extern MpmcStat stat_; - -} // namespace detail - -template -class OneValue { - public: - bool set_value(T &value) { - value_ = std::move(value); - int state = Empty; - if (state_.compare_exchange_strong(state, Value, std::memory_order_acq_rel)) { - return true; - } - value = std::move(value_); - return false; - } - bool get_value(T &value) { - auto old_state = state_.exchange(Taken, std::memory_order_acq_rel); - if (old_state == Value) { - value = std::move(value_); - return true; - } - return false; - } - void reset() { - state_ = Empty; - value_ = T(); - } - - private: - enum Type : int { Empty = 0, Taken, Value }; - std::atomic state_{Empty}; - T value_{}; -}; - -template -class OneValue { - public: - bool set_value(T *value) { - T *was = Empty(); - return state_.compare_exchange_strong(was, value, std::memory_order_acq_rel); - } - bool get_value(T *&value) { - value = state_.exchange(Taken(), std::memory_order_acq_rel); - return value != Empty(); - } - void reset() { - state_ = Empty(); - } - OneValue() { - } - - private: - std::atomic state_{Empty()}; - static T *Empty() { - static int64 xxx; - return reinterpret_cast(&xxx); - } - static T *Taken() { - static int64 xxx; - return reinterpret_cast(&xxx); - } -}; - -template -class MpmcQueueBlock { - public: - explicit MpmcQueueBlock(size_t size) : nodes_(size) { - } - enum class PopStatus { Ok, Empty, Closed }; - - //blocking pop - //returns Ok or Closed - PopStatus pop(T &value) { - while (true) { - auto read_pos = read_pos_.fetch_add(1, std::memory_order_relaxed); - if (read_pos >= nodes_.size()) { - return PopStatus::Closed; - } - //TODO blocking get_value - if (nodes_[static_cast(read_pos)].one_value.get_value(value)) { - return PopStatus::Ok; - } - } - } - - //nonblocking pop - //returns Ok, Empty or Closed - PopStatus try_pop(T &value) { - while (true) { - // this check slows 1:1 case but prevents writer starvation in 1:N case - if (write_pos_.load(std::memory_order_relaxed) <= read_pos_.load(std::memory_order_relaxed) && - read_pos_.load(std::memory_order_relaxed) < nodes_.size()) { - return PopStatus::Empty; - } - auto read_pos = read_pos_.fetch_add(1, std::memory_order_relaxed); - if (read_pos >= nodes_.size()) { - return PopStatus::Closed; - } - if (nodes_[static_cast(read_pos)].one_value.get_value(value)) { - return PopStatus::Ok; - } - auto write_pos = write_pos_.load(std::memory_order_relaxed); - if (write_pos <= read_pos + 1) { - return PopStatus::Empty; - } - } - } - - enum class PushStatus { Ok, Closed }; - PushStatus push(T &value) { - while (true) { - auto write_pos = write_pos_.fetch_add(1, std::memory_order_relaxed); - if (write_pos >= nodes_.size()) { - return PushStatus::Closed; - } - if (nodes_[static_cast(write_pos)].one_value.set_value(value)) { - //stat_.push_loop_ok(0); - return PushStatus::Ok; - } - //stat_.push_loop_error(0); - } - } - - private: - struct Node { - OneValue one_value; - }; - std::atomic write_pos_{0}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::atomic read_pos_{0}; - char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::vector nodes_; - char pad3[TD_CONCURRENCY_PAD - sizeof(std::vector)]; -}; - -template -class MpmcQueueOld { - public: - explicit MpmcQueueOld(size_t threads_n) : MpmcQueueOld(1024, threads_n) { - } - static std::string get_description() { - return "Mpmc queue (fetch and add array queue)"; - } - MpmcQueueOld(size_t block_size, size_t threads_n) : block_size_{block_size}, hazard_pointers_{threads_n} { - auto node = make_unique(block_size_); - write_pos_ = node.get(); - read_pos_ = node.get(); - node.release(); - } - - MpmcQueueOld(const MpmcQueueOld &other) = delete; - MpmcQueueOld &operator=(const MpmcQueueOld &other) = delete; - MpmcQueueOld(MpmcQueueOld &&other) = delete; - MpmcQueueOld &operator=(MpmcQueueOld &&other) = delete; - ~MpmcQueueOld() { - auto *ptr = read_pos_.load(std::memory_order_relaxed); - while (ptr) { - auto *to_delete = ptr; - ptr = ptr->next_.load(std::memory_order_relaxed); - delete to_delete; - } - //stat_.dump(); - //stat_ = detail::MpmcStat(); - } - - size_t hazard_pointers_to_delele_size_unsafe() const { - return hazard_pointers_.to_delete_size_unsafe(); - } - void gc(size_t thread_id) { - hazard_pointers_.retire(thread_id); - } - - using PushStatus = typename MpmcQueueBlock::PushStatus; - using PopStatus = typename MpmcQueueBlock::PopStatus; - - void push(T value, size_t thread_id) { - typename decltype(hazard_pointers_)::Holder hazard_ptr_holder(hazard_pointers_, thread_id, 0); - while (true) { - auto node = hazard_ptr_holder.protect(write_pos_); - auto status = node->block.push(value); - switch (status) { - case PushStatus::Ok: - return; - case PushStatus::Closed: { - auto next = node->next_.load(std::memory_order_acquire); - if (next == nullptr) { - auto new_node = new Node(block_size_); - new_node->block.push(value); - if (node->next_.compare_exchange_strong(next, new_node, std::memory_order_acq_rel)) { - //stat_.alloc_ok(thread_id); - write_pos_.compare_exchange_strong(node, new_node, std::memory_order_acq_rel); - return; - } else { - //stat_.alloc_error(thread_id); - new_node->block.pop(value); - //CHECK(status == PopStatus::Ok); - delete new_node; - } - } - //CHECK(next != nullptr); - write_pos_.compare_exchange_strong(node, next, std::memory_order_acq_rel); - break; - } - } - } - } - - bool try_pop(T &value, size_t thread_id) { - typename decltype(hazard_pointers_)::Holder hazard_ptr_holder(hazard_pointers_, thread_id, 0); - while (true) { - auto node = hazard_ptr_holder.protect(read_pos_); - auto status = node->block.try_pop(value); - switch (status) { - case PopStatus::Ok: - return true; - case PopStatus::Empty: - return false; - case PopStatus::Closed: { - auto next = node->next_.load(std::memory_order_acquire); - if (!next) { - return false; - } - if (read_pos_.compare_exchange_strong(node, next, std::memory_order_acq_rel)) { - hazard_ptr_holder.clear(); - hazard_pointers_.retire(thread_id, node); - } - break; - } - } - } - } - - T pop(size_t thread_id) { - T value; - while (true) { - if (try_pop(value, thread_id)) { - return value; - } - td::this_thread::yield(); - } - } - - private: - struct Node { - explicit Node(size_t block_size) : block{block_size} { - } - std::atomic next_{nullptr}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - MpmcQueueBlock block; - //Got pad in MpmcQueueBlock - }; - std::atomic write_pos_{nullptr}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::atomic read_pos_{nullptr}; - char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - size_t block_size_; - HazardPointers hazard_pointers_; - //Got pad in HazardPointers -}; - -template -class MpmcQueue { - public: - explicit MpmcQueue(size_t threads_n) : MpmcQueue(1024, threads_n) { - } - static std::string get_description() { - return "NEW Mpmc queue (fetch and add array queue)"; - } - MpmcQueue(size_t block_size, size_t threads_n) : hazard_pointers_{threads_n} { - auto node = make_unique(); - write_pos_ = node.get(); - read_pos_ = node.get(); - node.release(); - } - - MpmcQueue(const MpmcQueue &other) = delete; - MpmcQueue &operator=(const MpmcQueue &other) = delete; - MpmcQueue(MpmcQueue &&other) = delete; - MpmcQueue &operator=(MpmcQueue &&other) = delete; - ~MpmcQueue() { - auto *ptr = read_pos_.load(std::memory_order_relaxed); - while (ptr) { - auto *to_delete = ptr; - ptr = ptr->next.load(std::memory_order_relaxed); - delete to_delete; - } - } - - size_t hazard_pointers_to_delele_size_unsafe() const { - return hazard_pointers_.to_delete_size_unsafe(); - } - void gc(size_t thread_id) { - hazard_pointers_.retire(thread_id); - } - - void push(T value, size_t thread_id) { - SCOPE_EXIT { - hazard_pointers_.clear(thread_id, 0); - }; - while (true) { - auto node = hazard_pointers_.protect(thread_id, 0, write_pos_); - auto &block = node->block; - auto pos = block.write_pos++; - if (pos >= block.data.size()) { - auto next = node->next.load(); - if (next == nullptr) { - auto new_node = new Node{}; - new_node->block.write_pos++; - new_node->block.data[0].set_value(value); - Node *null = nullptr; - if (node->next.compare_exchange_strong(null, new_node)) { - write_pos_.compare_exchange_strong(node, new_node); - return; - } else { - new_node->block.data[0].get_value(value); - delete new_node; - } - } else { - write_pos_.compare_exchange_strong(node, next); - } - } else { - if (block.data[static_cast(pos)].set_value(value)) { - return; - } - } - } - } - - bool try_pop(T &value, size_t thread_id) { - SCOPE_EXIT { - hazard_pointers_.clear(thread_id, 0); - }; - while (true) { - auto node = hazard_pointers_.protect(thread_id, 0, read_pos_); - auto &block = node->block; - if (block.write_pos <= block.read_pos && node->next.load(std::memory_order_relaxed) == nullptr) { - return false; - } - auto pos = block.read_pos++; - if (pos >= block.data.size()) { - auto next = node->next.load(); - if (!next) { - return false; - } - if (read_pos_.compare_exchange_strong(node, next)) { - hazard_pointers_.clear(thread_id, 0); - hazard_pointers_.retire(thread_id, node); - } - } else { - if (block.data[static_cast(pos)].get_value(value)) { - return true; - } - } - } - } - - T pop(size_t thread_id) { - T value; - while (true) { - if (try_pop(value, thread_id)) { - return value; - } - td::this_thread::yield(); - } - } - - private: - struct Block { - std::atomic write_pos{0}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::atomic read_pos{0}; - char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::array, 1024> data; - char pad3[TD_CONCURRENCY_PAD]; - }; - struct Node { - Node() = default; - - Block block; - std::atomic next{nullptr}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - //Got pad in MpmcQueueBlock - }; - std::atomic write_pos_{nullptr}; - char pad[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - std::atomic read_pos_{nullptr}; - char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic)]; - HazardPointers hazard_pointers_; - //Got pad in HazardPointers -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcWaiter.h b/submodules/ton/tonlib-src/tdutils/td/utils/MpmcWaiter.h deleted file mode 100644 index 8fb1a511..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MpmcWaiter.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" - -#include -#include -#include -#include - -namespace td { - -class MpmcEagerWaiter { - public: - struct Slot { - private: - friend class MpmcEagerWaiter; - int yields; - uint32 worker_id; - }; - void init_slot(Slot &slot, uint32 worker_id) { - slot.yields = 0; - slot.worker_id = worker_id; - } - void wait(Slot &slot) { - if (slot.yields < RoundsTillSleepy) { - td::this_thread::yield(); - slot.yields++; - return; - } else if (slot.yields == RoundsTillSleepy) { - auto state = state_.load(std::memory_order_relaxed); - if (!State::has_worker(state)) { - auto new_state = State::with_worker(state, slot.worker_id); - if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) { - td::this_thread::yield(); - slot.yields++; - return; - } - if (state == State::awake()) { - slot.yields = 0; - return; - } - } - td::this_thread::yield(); - slot.yields = 0; - return; - } else if (slot.yields < RoundsTillAsleep) { - auto state = state_.load(std::memory_order_acquire); - if (State::still_sleepy(state, slot.worker_id)) { - td::this_thread::yield(); - slot.yields++; - return; - } - slot.yields = 0; - return; - } else { - auto state = state_.load(std::memory_order_acquire); - if (State::still_sleepy(state, slot.worker_id)) { - std::unique_lock lock(mutex_); - if (state_.compare_exchange_strong(state, State::asleep(), std::memory_order_acq_rel)) { - condition_variable_.wait(lock); - } - } - slot.yields = 0; - return; - } - } - - void stop_wait(Slot &slot) { - if (slot.yields > RoundsTillSleepy) { - notify_cold(); - } - slot.yields = 0; - return; - } - - void close() { - } - - void notify() { - std::atomic_thread_fence(std::memory_order_seq_cst); - if (state_.load(std::memory_order_acquire) == State::awake()) { - return; - } - notify_cold(); - } - - private: - struct State { - static constexpr uint32 awake() { - return 0; - } - static constexpr uint32 asleep() { - return 1; - } - static bool is_asleep(uint32 state) { - return (state & 1) != 0; - } - static bool has_worker(uint32 state) { - return (state >> 1) != 0; - } - static int32 with_worker(uint32 state, uint32 worker) { - return state | ((worker + 1) << 1); - } - static bool still_sleepy(uint32 state, uint32 worker) { - return (state >> 1) == (worker + 1); - } - }; - enum { RoundsTillSleepy = 32, RoundsTillAsleep = 64 }; - // enum { RoundsTillSleepy = 1, RoundsTillAsleep = 2 }; - std::atomic state_{State::awake()}; - std::mutex mutex_; - std::condition_variable condition_variable_; - - void notify_cold() { - auto old_state = state_.exchange(State::awake(), std::memory_order_release); - if (State::is_asleep(old_state)) { - std::lock_guard guard(mutex_); - condition_variable_.notify_all(); - } - } -}; - -class MpmcSleepyWaiter { - public: - struct Slot { - private: - friend class MpmcSleepyWaiter; - - enum State { Search, Work, Sleep } state_{Work}; - - void park() { - std::unique_lock guard(mutex_); - condition_variable_.wait(guard, [&] { return unpark_flag_; }); - unpark_flag_ = false; - } - - bool cancel_park() { - auto res = unpark_flag_; - unpark_flag_ = false; - return res; - } - - void unpark() { - //TODO: try unlock guard before notify_all - std::unique_lock guard(mutex_); - unpark_flag_ = true; - condition_variable_.notify_all(); - } - - std::mutex mutex_; - std::condition_variable condition_variable_; - bool unpark_flag_{false}; // TODO: move out of lock - int yield_cnt{0}; - int32 worker_id{0}; - char padding[128]; - }; - - // There are a lot of workers - // Each has a slot - // - // States of a worker: - // - searching for work | Search - // - processing work | Work - // - sleeping | Sleep - // - // When somebody adds a work it calls notify - // - // notify - // if there are workers in search phase do nothing. - // if all workers are awake do nothing - // otherwise wake some random worker - // - // Initially all workers are in Search mode. - // - // When worker found nothing it may try to call wait. - // This may put it in a Sleep for some time. - // After wait return worker will be in Search state again. - // - // Suppose worker found a work and ready to process it. - // Than it may call stop_wait. This will cause transition from - // Search to Work state. - // - // Main invariant: - // After notify is called there should be at least on worker in Search or Work state. - // If possible - in Search state - // - - void init_slot(Slot &slot, int32 worker_id) { - slot.state_ = Slot::State::Work; - slot.unpark_flag_ = false; - slot.worker_id = worker_id; - VLOG(waiter) << "Init slot " << worker_id; - } - - int VERBOSITY_NAME(waiter) = VERBOSITY_NAME(DEBUG) + 10; - void wait(Slot &slot) { - if (slot.state_ == Slot::State::Work) { - VLOG(waiter) << "Work -> Search"; - state_++; - slot.state_ = Slot::State::Search; - slot.yield_cnt = 0; - return; - } - if (slot.state_ == Slot::Search) { - if (slot.yield_cnt++ < 10 && false) { - td::this_thread::yield(); - return; - } - - slot.state_ = Slot::State::Sleep; - std::unique_lock guard(sleepers_mutex_); - auto state_view = StateView(state_.fetch_add((1 << PARKING_SHIFT) - 1)); - CHECK(state_view.searching_count != 0); - bool should_search = state_view.searching_count == 1; - if (closed_) { - return; - } - sleepers_.push_back(&slot); - LOG_CHECK(slot.unpark_flag_ == false) << slot.worker_id; - VLOG(waiter) << "add to sleepers " << slot.worker_id; - //guard.unlock(); - if (should_search) { - VLOG(waiter) << "Search -> Search once then Sleep "; - return; - } - VLOG(waiter) << "Search -> Sleep " << state_view.searching_count << " " << state_view.parked_count; - } - - CHECK(slot.state_ == Slot::State::Sleep); - VLOG(waiter) << "Park " << slot.worker_id; - slot.park(); - VLOG(waiter) << "Resume " << slot.worker_id; - slot.state_ = Slot::State::Search; - slot.yield_cnt = 0; - } - - void stop_wait(Slot &slot) { - if (slot.state_ == Slot::State::Work) { - return; - } - if (slot.state_ == Slot::State::Sleep) { - VLOG(waiter) << "Search once then Sleep -> Work/Search " << slot.worker_id; - slot.state_ = Slot::State::Work; - std::unique_lock guard(sleepers_mutex_); - auto it = std::find(sleepers_.begin(), sleepers_.end(), &slot); - if (it != sleepers_.end()) { - sleepers_.erase(it); - VLOG(waiter) << "remove from sleepers " << slot.worker_id; - state_.fetch_sub((1 << PARKING_SHIFT) - 1); - guard.unlock(); - } else { - guard.unlock(); - VLOG(waiter) << "not in sleepers" << slot.worker_id; - CHECK(slot.cancel_park()); - } - } - VLOG(waiter) << "Search once then Sleep -> Work " << slot.worker_id; - slot.state_ = Slot::State::Search; - auto state_view = StateView(state_.fetch_sub(1)); - CHECK(state_view.searching_count != 0); - CHECK(state_view.searching_count < 1000); - bool should_notify = state_view.searching_count == 1; - if (should_notify) { - VLOG(waiter) << "Notify others"; - notify(); - } - VLOG(waiter) << "Search -> Work "; - slot.state_ = Slot::State::Work; - } - - void notify() { - auto view = StateView(state_.load()); - //LOG(ERROR) << view.parked_count; - if (view.searching_count > 0 || view.parked_count == 0) { - VLOG(waiter) << "Ingore notify: " << view.searching_count << " " << view.parked_count; - return; - } - - VLOG(waiter) << "Notify: " << view.searching_count << " " << view.parked_count; - std::unique_lock guard(sleepers_mutex_); - - view = StateView(state_.load()); - if (view.searching_count > 0) { - VLOG(waiter) << "Skip notify: got searching"; - return; - } - - CHECK(view.parked_count == static_cast(sleepers_.size())); - if (sleepers_.empty()) { - VLOG(waiter) << "Skip notify: no sleepers"; - return; - } - - auto sleeper = sleepers_.back(); - sleepers_.pop_back(); - state_.fetch_sub((1 << PARKING_SHIFT) - 1); - VLOG(waiter) << "Unpark " << sleeper->worker_id; - sleeper->unpark(); - } - - void close() { - StateView state(state_.load()); - LOG_CHECK(state.parked_count == 0) << state.parked_count; - LOG_CHECK(state.searching_count == 0) << state.searching_count; - } - - private: - static constexpr td::int32 PARKING_SHIFT = 16; - struct StateView { - td::int32 parked_count; - td::int32 searching_count; - explicit StateView(int32 x) { - parked_count = x >> PARKING_SHIFT; - searching_count = x & ((1 << PARKING_SHIFT) - 1); - } - }; - std::atomic state_{0}; - - std::mutex sleepers_mutex_; - std::vector sleepers_; - - bool closed_ = false; -}; - -using MpmcWaiter = MpmcSleepyWaiter; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MpscLinkQueue.h b/submodules/ton/tonlib-src/tdutils/td/utils/MpscLinkQueue.h deleted file mode 100644 index 831616de..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MpscLinkQueue.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -#include - -namespace td { -//NB: holder of the queue holds all responsibility of freeing its nodes -class MpscLinkQueueImpl { - public: - class Node; - class Reader; - - void push(Node *node) { - node->next_ = head_.load(std::memory_order_relaxed); - while (!head_.compare_exchange_strong(node->next_, node, std::memory_order_release, std::memory_order_relaxed)) { - } - } - - void push_unsafe(Node *node) { - node->next_ = head_.load(std::memory_order_relaxed); - head_.store(node, std::memory_order_relaxed); - } - - void pop_all(Reader &reader) { - return reader.add(head_.exchange(nullptr, std::memory_order_acquire)); - } - - void pop_all_unsafe(Reader &reader) { - return reader.add(head_.exchange(nullptr, std::memory_order_relaxed)); - } - - class Node { - friend class MpscLinkQueueImpl; - Node *next_{nullptr}; - }; - - class Reader { - public: - Node *read() { - auto old_head = head_; - if (head_) { - head_ = head_->next_; - } - return old_head; - } - void delay(Node *node) { - node->next_ = head_; - if (!head_) { - tail_ = node; - } - head_ = node; - } - size_t calc_size() const { - size_t res = 0; - for (auto it = head_; it != nullptr; it = it->next_, res++) { - } - return res; - } - - private: - friend class MpscLinkQueueImpl; - void add(Node *node) { - if (node == nullptr) { - return; - } - // Reverse list - Node *tail = node; - Node *head = nullptr; - while (node) { - auto next = node->next_; - node->next_ = head; - head = node; - node = next; - } - if (head_ == nullptr) { - head_ = head; - } else { - tail_->next_ = head; - } - tail_ = tail; - } - Node *head_{nullptr}; - Node *tail_{nullptr}; - }; - - private: - std::atomic head_{nullptr}; -}; - -// Uses MpscLinkQueueImpl. -// Node should have to_mpsc_link_queue_node and from_mpsc_link_queue_node functions -template -class MpscLinkQueue { - public: - void push(Node node) { - impl_.push(node.to_mpsc_link_queue_node()); - } - void push_unsafe(Node node) { - impl_.push_unsafe(node.to_mpsc_link_queue_node()); - } - class Reader { - public: - ~Reader() { - CHECK(!read()); - } - Node read() { - auto node = impl_.read(); - if (!node) { - return {}; - } - return Node::from_mpsc_link_queue_node(node); - } - void delay(Node node) { - impl_.delay(node.to_mpsc_link_queue_node()); - } - size_t calc_size() const { - return impl_.calc_size(); - } - - private: - friend class MpscLinkQueue; - - MpscLinkQueueImpl::Reader impl_; - MpscLinkQueueImpl::Reader &impl() { - return impl_; - } - }; - - void pop_all(Reader &reader) { - return impl_.pop_all(reader.impl()); - } - void pop_all_unsafe(Reader &reader) { - return impl_.pop_all_unsafe(reader.impl()); - } - - private: - MpscLinkQueueImpl impl_; -}; - -template -class MpscLinkQueueUniquePtrNode { - public: - MpscLinkQueueUniquePtrNode() = default; - explicit MpscLinkQueueUniquePtrNode(unique_ptr ptr) : ptr_(std::move(ptr)) { - } - - MpscLinkQueueImpl::Node *to_mpsc_link_queue_node() { - return ptr_.release()->to_mpsc_link_queue_node(); - } - static MpscLinkQueueUniquePtrNode from_mpsc_link_queue_node(td::MpscLinkQueueImpl::Node *node) { - return MpscLinkQueueUniquePtrNode(unique_ptr(Value::from_mpsc_link_queue_node(node))); - } - - explicit operator bool() { - return ptr_ != nullptr; - } - - Value &value() { - return *ptr_; - } - - private: - unique_ptr ptr_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/MpscPollableQueue.h b/submodules/ton/tonlib-src/tdutils/td/utils/MpscPollableQueue.h deleted file mode 100644 index cdace8d1..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/MpscPollableQueue.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/misc.h" -#include "td/utils/port/EventFd.h" - -#if !TD_EVENTFD_UNSUPPORTED - -#include "td/utils/SpinLock.h" - -#include - -namespace td { -// interface like in PollableQueue -template -class MpscPollableQueue { - public: - using ValueType = T; - - int reader_wait_nonblock() { - auto ready = reader_vector_.size() - reader_pos_; - if (ready != 0) { - return narrow_cast(ready); - } - - for (int i = 0; i < 2; i++) { - auto guard = lock_.lock(); - if (writer_vector_.empty()) { - if (i == 1) { - wait_event_fd_ = true; - return 0; - } - } else { - reader_vector_.clear(); - reader_pos_ = 0; - std::swap(writer_vector_, reader_vector_); - return narrow_cast(reader_vector_.size()); - } - event_fd_.acquire(); - } - UNREACHABLE(); - } - ValueType reader_get_unsafe() { - return std::move(reader_vector_[reader_pos_++]); - } - void reader_flush() { - //nop - } - void writer_put(ValueType value) { - auto guard = lock_.lock(); - writer_vector_.push_back(std::move(value)); - if (wait_event_fd_) { - wait_event_fd_ = false; - guard.reset(); - event_fd_.release(); - } - } - EventFd &reader_get_event_fd() { - return event_fd_; - } - void writer_flush() { - //nop - } - - void init() { - event_fd_.init(); - } - void destroy() { - if (!event_fd_.empty()) { - event_fd_.close(); - wait_event_fd_ = false; - writer_vector_.clear(); - reader_vector_.clear(); - reader_pos_ = 0; - } - } - - // Just an example of usage - int reader_wait() { - int res; - while ((res = reader_wait_nonblock()) == 0) { - reader_get_event_fd().wait(1000); - } - return res; - } - - private: - SpinLock lock_; - bool wait_event_fd_{false}; - EventFd event_fd_; - std::vector writer_vector_; - std::vector reader_vector_; - size_t reader_pos_{0}; -}; - -} // namespace td - -#else - -namespace td { - -// dummy implementation which shouldn't be used - -template -class MpscPollableQueue { - public: - using ValueType = T; - - void init() { - UNREACHABLE(); - } - - template - void writer_put(PutValueType &&value) { - UNREACHABLE(); - } - - void writer_flush() { - UNREACHABLE(); - } - - int reader_wait_nonblock() { - UNREACHABLE(); - return 0; - } - - ValueType reader_get_unsafe() { - UNREACHABLE(); - return ValueType(); - } - - void reader_flush() { - UNREACHABLE(); - } - - MpscPollableQueue() = default; - MpscPollableQueue(const MpscPollableQueue &) = delete; - MpscPollableQueue &operator=(const MpscPollableQueue &) = delete; - MpscPollableQueue(MpscPollableQueue &&) = delete; - MpscPollableQueue &operator=(MpscPollableQueue &&) = delete; - ~MpscPollableQueue() = default; -}; - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Named.h b/submodules/ton/tonlib-src/tdutils/td/utils/Named.h deleted file mode 100644 index 70fadc07..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Named.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" - -namespace td { - -class Named { - public: - Slice get_name() const { - return name_; - } - void set_name(Slice name) { - name_ = name.str(); - } - - private: - string name_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/ObjectPool.h b/submodules/ton/tonlib-src/tdutils/td/utils/ObjectPool.h deleted file mode 100644 index 12fb5f6b..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/ObjectPool.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" - -#include -#include -#include - -namespace td { -// It is draft object pool implementaion -// -// Compared with std::shared_ptr: -// + WeakPtr are much faster. Just pointer copy. No barriers, no atomics. -// - We can't destroy object, because we don't know if it is pointed to by some weak pointer -// -template -class ObjectPool { - struct Storage; - - public: - class WeakPtr { - public: - WeakPtr() : generation_(-1), storage_(nullptr) { - } - WeakPtr(int32 generation, Storage *storage) : generation_(generation), storage_(storage) { - } - - DataT &operator*() const { - return storage_->data; - } - - DataT *operator->() const { - return &**this; - } - - // Pattern of usage: 1. Read an object 2. Check if read was valid via is_alive - // - // It is not very usual case of acquire/release use. - // Instead of publishing an object via some flag we do the opposite. - // We publish new generation via destruction of the data. - // In usual case if we see a flag then we are able to use an object. - // In our case if we have used an object and it is already invalid, then generation will mismatch - bool is_alive() const { - if (!storage_) { - return false; - } - std::atomic_thread_fence(std::memory_order_acquire); - return generation_ == storage_->generation.load(std::memory_order_relaxed); - } - - // Used for ActorId - bool is_alive_unsafe() const { - if (!storage_) { - return false; - } - return generation_ == storage_->generation.load(std::memory_order_relaxed); - } - - bool empty() const { - return storage_ == nullptr; - } - void clear() { - generation_ = -1; - storage_ = nullptr; - } - int32 generation() { - return generation_; - } - - private: - int32 generation_; - Storage *storage_; - }; - - class OwnerPtr { - public: - OwnerPtr() = default; - OwnerPtr(const OwnerPtr &) = delete; - OwnerPtr &operator=(const OwnerPtr &) = delete; - OwnerPtr(OwnerPtr &&other) : storage_(other.storage_), parent_(other.parent_) { - other.storage_ = nullptr; - other.parent_ = nullptr; - } - OwnerPtr &operator=(OwnerPtr &&other) { - if (this != &other) { - storage_ = other.storage_; - parent_ = other.parent_; - other.storage_ = nullptr; - other.parent_ = nullptr; - } - return *this; - } - ~OwnerPtr() { - reset(); - } - - DataT *get() { - return &storage_->data; - } - DataT &operator*() { - return *get(); - } - DataT *operator->() { - return get(); - } - - const DataT *get() const { - return &storage_->data; - } - const DataT &operator*() const { - return *get(); - } - const DataT *operator->() const { - return get(); - } - - WeakPtr get_weak() { - return WeakPtr(storage_->generation.load(std::memory_order_relaxed), storage_); - } - int32 generation() { - return storage_->generation.load(std::memory_order_relaxed); - } - - Storage *release() { - auto result = storage_; - storage_ = nullptr; - return result; - } - - bool empty() const { - return storage_ == nullptr; - } - - void reset() { - if (storage_ != nullptr) { - // for crazy cases when data owns owner pointer to itself. - auto tmp = storage_; - storage_ = nullptr; - parent_->release(OwnerPtr(tmp, parent_)); - } - } - - private: - friend class ObjectPool; - OwnerPtr(Storage *storage, ObjectPool *parent) : storage_(storage), parent_(parent) { - } - Storage *storage_ = nullptr; - ObjectPool *parent_ = nullptr; - }; - - template - OwnerPtr create(ArgsT &&... args) { - Storage *storage = get_storage(); - storage->init_data(std::forward(args)...); - return OwnerPtr(storage, this); - } - - OwnerPtr create_empty() { - Storage *storage = get_storage(); - return OwnerPtr(storage, this); - } - - void set_check_empty(bool flag) { - check_empty_flag_ = flag; - } - - void release(OwnerPtr &&owner_ptr) { - Storage *storage = owner_ptr.release(); - storage->destroy_data(); - release_storage(storage); - } - - ObjectPool() = default; - ObjectPool(const ObjectPool &) = delete; - ObjectPool &operator=(const ObjectPool &) = delete; - ObjectPool(ObjectPool &&other) = delete; - ObjectPool &operator=(ObjectPool &&other) = delete; - ~ObjectPool() { - while (head_.load()) { - auto to_delete = head_.load(); - head_ = to_delete->next; - delete to_delete; - storage_count_--; - } - LOG_CHECK(storage_count_.load() == 0) << storage_count_.load(); - } - - private: - struct Storage { - // union { - DataT data; - //}; - Storage *next = nullptr; - std::atomic generation{1}; - - template - void init_data(ArgsT &&... args) { - // new (&data) DataT(std::forward(args)...); - data = DataT(std::forward(args)...); - } - void destroy_data() { - generation.fetch_add(1, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); - data.clear(); - } - }; - - std::atomic storage_count_{0}; - std::atomic head_{static_cast(nullptr)}; - bool check_empty_flag_ = false; - - // TODO(perf): allocation Storages in chunks? Anyway we won't be able to release them. - // TODO(perf): memory order - // TODO(perf): use another non lockfree list for release on the same thread - // only one thread, so no aba problem - Storage *get_storage() { - if (head_.load() == nullptr) { - storage_count_++; - return new Storage(); - } - Storage *res; - while (true) { - res = head_.load(); - auto *next = res->next; - if (head_.compare_exchange_weak(res, next)) { - break; - } - } - return res; - } - // release can be called from other thread - void release_storage(Storage *storage) { - while (true) { - auto *save_head = head_.load(); - storage->next = save_head; - if (head_.compare_exchange_weak(save_head, storage)) { - break; - } - } - } -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Observer.h b/submodules/ton/tonlib-src/tdutils/td/utils/Observer.h deleted file mode 100644 index 32097f3b..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Observer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { - -class ObserverBase { - public: - ObserverBase() = default; - ObserverBase(const ObserverBase &) = delete; - ObserverBase &operator=(const ObserverBase &) = delete; - ObserverBase(ObserverBase &&) = delete; - ObserverBase &operator=(ObserverBase &&) = delete; - virtual ~ObserverBase() = default; - - virtual void notify() = 0; -}; - -class Observer : ObserverBase { - public: - Observer() = default; - explicit Observer(unique_ptr &&ptr) : observer_ptr_(std::move(ptr)) { - } - - void notify() override { - if (observer_ptr_) { - observer_ptr_->notify(); - } - } - - private: - unique_ptr observer_ptr_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/OptionsParser.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/OptionsParser.cpp deleted file mode 100644 index 4712b5ed..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/OptionsParser.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/OptionsParser.h" - -#if TD_HAVE_GETOPT -#include "getopt.h" -#endif - -#if !TD_WINDOWS -#include -#include -#endif - -namespace td { - -void OptionsParser::set_description(std::string description) { - description_ = std::move(description); -} - -void OptionsParser::add_option(Option::Type type, char short_key, Slice long_key, Slice description, - std::function callback) { - for (auto &option : options_) { - if (option.short_key == short_key || (!long_key.empty() && long_key == option.long_key)) { - LOG(ERROR) << "Ignore duplicated option '" << short_key << "' '" << long_key << "'"; - } - } - options_.push_back(Option{type, short_key, long_key.str(), description.str(), std::move(callback)}); -} - -void OptionsParser::add_option(char short_key, Slice long_key, Slice description, - std::function callback) { - add_option(Option::Type::Arg, short_key, long_key, description, std::move(callback)); -} - -void OptionsParser::add_option(char short_key, Slice long_key, Slice description, - std::function callback) { - // Ouch. There must be some better way - add_option(Option::Type::NoArg, short_key, long_key, description, - std::bind([](std::function &func, Slice) { return func(); }, std::move(callback), - std::placeholders::_1)); -} - -Result OptionsParser::run(int argc, char *argv[]) { -#if TD_HAVE_GETOPT - char buff[1024]; - StringBuilder sb(MutableSlice{buff, sizeof(buff)}); - for (auto &opt : options_) { - CHECK(opt.type != Option::OptionalArg); - sb << opt.short_key; - if (opt.type == Option::Arg) { - sb << ":"; - } - } - if (sb.is_error()) { - return Status::Error("Can't parse options"); - } - CSlice short_options = sb.as_cslice(); - - vector::type; - - static_assert(std::is_integral::value, "expected integral type to cast to"); - static_assert(std::is_integral::value, "expected integral type to cast from"); - - auto r = R(a); - LOG_CHECK(A(r) == a) << static_cast(a) << " " << static_cast(r) << " " << file_ << " " << line_; - LOG_CHECK((is_same_signedness::value) || ((static_cast(r) < RT{}) == (static_cast(a) < AT{}))) - << static_cast(a) << " " << static_cast(r) << " " << file_ << " " << line_; - - return r; - } -}; -} // namespace detail - -#define narrow_cast detail::NarrowCast(__FILE__, __LINE__).cast - -template -Result narrow_cast_safe(const A &a) { - using RT = typename detail::safe_undeflying_type::type; - using AT = typename detail::safe_undeflying_type::type; - - static_assert(std::is_integral::value, "expected integral type to cast to"); - static_assert(std::is_integral::value, "expected integral type to cast from"); - - auto r = R(a); - if (!(A(r) == a)) { - return Status::Error("Narrow cast failed"); - } - if (!((detail::is_same_signedness::value) || ((static_cast(r) < RT{}) == (static_cast(a) < AT{})))) { - return Status::Error("Narrow cast failed"); - } - - return r; -} - -template -bool is_aligned_pointer(const T *pointer) { - static_assert(Alignment > 0 && (Alignment & (Alignment - 1)) == 0, "Wrong alignment"); - return (reinterpret_cast(static_cast(pointer)) & (Alignment - 1)) == 0; -} - -namespace detail { -template -struct reversion_wrapper { - T &iterable; -}; - -template -auto begin(reversion_wrapper w) { - return w.iterable.rbegin(); -} - -template -auto end(reversion_wrapper w) { - return w.iterable.rend(); -} -} // namespace detail - -template -detail::reversion_wrapper reversed(T &iterable) { - return {iterable}; -} - -string buffer_to_hex(Slice buffer); - -string zero_encode(Slice data); - -string zero_decode(Slice data); - -string zero_one_encode(Slice data); - -string zero_one_decode(Slice data); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/optional.h b/submodules/ton/tonlib-src/tdutils/td/utils/optional.h deleted file mode 100644 index 3eb2d518..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/optional.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Status.h" - -#include -#include - -namespace td { - -template ::value> -class optional { - public: - optional() = default; - template , optional>::value && std::is_constructible::value, - int> = 0> - optional(T1 &&t) : impl_(std::forward(t)) { - } - - optional(const optional &other) { - if (other) { - impl_ = Result(other.value()); - } - } - - optional &operator=(const optional &other) { - if (other) { - impl_ = Result(other.value()); - } else { - impl_ = Result(); - } - return *this; - } - - optional(optional &&other) = default; - optional &operator=(optional &&other) = default; - ~optional() = default; - - explicit operator bool() const { - return impl_.is_ok(); - } - T &value() { - return impl_.ok_ref(); - } - const T &value() const { - return impl_.ok_ref(); - } - T &operator*() { - return value(); - } - T unwrap() { - CHECK(*this); - auto res = std::move(value()); - impl_ = {}; - return res; - } - - td::optional copy() const { - if (*this) { - return value(); - } - return {}; - } - - template - void emplace(ArgsT &&... args) { - impl_.emplace(std::forward(args)...); - } - - private: - Result impl_; -}; - -template -struct optional : optional { - optional() = default; - - using optional::optional; - - optional(const optional &other) = delete; - optional &operator=(const optional &other) = delete; - optional(optional &&) = default; - optional &operator=(optional &&) = default; - ~optional() = default; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/overloaded.h b/submodules/ton/tonlib-src/tdutils/td/utils/overloaded.h deleted file mode 100644 index 492dbc3e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/overloaded.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace td { - -namespace detail { - -template -struct overload; - -template -struct overload : public F { - explicit overload(F f) : F(f) { - } -}; - -template -struct overload - : public overload - , overload { - overload(F f, Fs... fs) : overload(f), overload(fs...) { - } - using overload::operator(); - using overload::operator(); -}; - -} // namespace detail - -template -auto overloaded(F... f) { - return detail::overload(f...); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.cpp deleted file mode 100644 index bd856a8d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/Clocks.h" - -#include - -namespace td { - -ClocksDefault::Duration ClocksDefault::monotonic() { - auto duration = std::chrono::steady_clock::now().time_since_epoch(); - return static_cast(std::chrono::duration_cast(duration).count()) * 1e-9; -} - -ClocksDefault::Duration ClocksDefault::system() { - auto duration = std::chrono::system_clock::now().time_since_epoch(); - return static_cast(std::chrono::duration_cast(duration).count()) * 1e-9; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.h deleted file mode 100644 index d1e12aa3..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/Clocks.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace td { - -class ClocksBase { - public: - using Duration = double; -}; - -// TODO: (maybe) write system specific functions. -class ClocksDefault { - public: - using Duration = ClocksBase::Duration; - - static Duration monotonic(); - - static Duration system(); -}; - -using Clocks = ClocksDefault; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/CxCli.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/CxCli.h deleted file mode 100644 index 1a38977c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/CxCli.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#undef small - -#if TD_WINRT - -#include "td/utils/port/wstring_convert.h" - -#include "collection.h" - -#include -#include -#include - -#define REF_NEW ref new -#define CLRCALL -#define DEPRECATED_ATTRIBUTE(message) ::Windows::Foundation::Metadata::Deprecated(message,\ - ::Windows::Foundation::Metadata::DeprecationType::Deprecate, 0x0) - -namespace CxCli { - -using Windows::Foundation::Collections::IVector; -#define Array IVector -using Platform::Collections::Vector; -#define ArraySize(arr) ((arr)->Size) -#define ArrayGet(arr, index) ((arr)->GetAt(index)) -#define ArraySet(arr, index, value) ((arr)->SetAt((index), (value))) -#define ArrayIndexType unsigned - -using Platform::String; - -using Platform::NullReferenceException; - -template class ConcurrentDictionary { -public: - bool TryGetValue(Key key, Value &value) { - std::lock_guard guard(mutex_); - auto it = impl_.find(key); - if (it == impl_.end()) { - return false; - } - value = it->second; - return true; - } - bool TryRemove(Key key, Value &value) { - std::lock_guard guard(mutex_); - auto it = impl_.find(key); - if (it == impl_.end()) { - return false; - } - value = std::move(it->second); - impl_.erase(it); - return true; - } - Value &operator [] (Key key) { - std::lock_guard guard(mutex_); - return impl_[key]; - } -private: - std::mutex mutex_; - std::map impl_; -}; - -inline std::int64_t Increment(volatile std::int64_t &value) { - return InterlockedIncrement64(&value); -} - -inline std::string string_to_unmanaged(String^ str) { - if (!str) { - return std::string(); - } - return td::from_wstring(str->Data(), str->Length()).ok(); -} - -inline String^ string_from_unmanaged(const std::string &from) { - auto tmp = td::to_wstring(from).ok(); - return REF_NEW String(tmp.c_str(), static_cast(tmp.size())); -} - -} // namespace CxCli - -#elif TD_CLI - -#define REF_NEW gcnew -#define CLRCALL __clrcall -#define DEPRECATED_ATTRIBUTE(message) System::ObsoleteAttribute(message) - -namespace CxCli { - -using uint8 = td::uint8; -using int32 = td::int32; -using int64 = td::int64; -using float64 = double; - -#define Array array -#define Vector array -#define ArraySize(arr) ((arr)->Length) -#define ArrayGet(arr, index) ((arr)[index]) -#define ArraySet(arr, index, value) ((arr)[index] = (value)) -#define ArrayIndexType int - -using System::String; - -using System::NullReferenceException; - -using System::Collections::Concurrent::ConcurrentDictionary; - -inline std::int64_t Increment(std::int64_t %value) { - return System::Threading::Interlocked::Increment(value); -} - -inline std::string string_to_unmanaged(String^ str) { - if (!str || str->Length == 0) { - return std::string(); - } - - Array^ bytes = System::Text::Encoding::UTF8->GetBytes(str); - cli::pin_ptr pinned_ptr = &bytes[0]; - std::string result(reinterpret_cast(&pinned_ptr[0]), bytes->Length); - return result; -} - -inline String^ string_from_unmanaged(const std::string &from) { - if (from.empty()) { - return String::Empty; - } - - Array^ bytes = REF_NEW Vector(static_cast(from.size())); - cli::pin_ptr pinned_ptr = &bytes[0]; - for (size_t i = 0; i < from.size(); ++i) { - pinned_ptr[i] = from[i]; - } - return System::Text::Encoding::UTF8->GetString(bytes); -} - -} // namespace CxCli - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFd.h deleted file mode 100644 index 99e70cdf..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFd.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -// include all and let config.h decide -#include "td/utils/port/detail/EventFdBsd.h" -#include "td/utils/port/detail/EventFdLinux.h" -#include "td/utils/port/detail/EventFdWindows.h" - -namespace td { - -// clang-format off - -#if TD_EVENTFD_LINUX - using EventFd = detail::EventFdLinux; -#elif TD_EVENTFD_BSD - using EventFd = detail::EventFdBsd; -#elif TD_EVENTFD_WINDOWS - using EventFd = detail::EventFdWindows; -#elif TD_EVENTFD_UNSUPPORTED -#else - #error "EventFd's implementation is not defined" -#endif - -// clang-format on - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFdBase.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFdBase.h deleted file mode 100644 index 86bdfe6e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/EventFdBase.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/Status.h" - -namespace td { -class EventFdBase { - public: - EventFdBase() = default; - EventFdBase(const EventFdBase &) = delete; - EventFdBase &operator=(const EventFdBase &) = delete; - EventFdBase(EventFdBase &&) = default; - EventFdBase &operator=(EventFdBase &&) = default; - virtual ~EventFdBase() = default; - - virtual void init() = 0; - virtual bool empty() = 0; - virtual void close() = 0; - virtual PollableFdInfo &get_poll_info() = 0; - virtual Status get_pending_error() TD_WARN_UNUSED_RESULT = 0; - virtual void release() = 0; - virtual void acquire() = 0; - virtual void wait(int timeout_ms) = 0; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.cpp deleted file mode 100644 index 057da729..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/FileFd.h" - -#if TD_PORT_WINDOWS -#include "td/utils/port/Stat.h" -#include "td/utils/port/wstring_convert.h" -#endif - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/port/sleep.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/StringBuilder.h" - -#include -#include -#include - -#if TD_PORT_POSIX -#include -#include -#include -#include -#include -#endif - -namespace td { - -namespace { - -struct PrintFlags { - int32 flags; -}; - -StringBuilder &operator<<(StringBuilder &sb, const PrintFlags &print_flags) { - auto flags = print_flags.flags; - if (flags & ~(FileFd::Write | FileFd::Read | FileFd::Truncate | FileFd::Create | FileFd::Append | FileFd::CreateNew | - FileFd::Direct | FileFd::WinStat)) { - return sb << "opened with invalid flags " << flags; - } - - if (flags & FileFd::Create) { - sb << "opened/created "; - } else if (flags & FileFd::CreateNew) { - sb << "created "; - } else { - sb << "opened "; - } - - if ((flags & FileFd::Write) && (flags & FileFd::Read)) { - if (flags & FileFd::Append) { - sb << "for reading and appending"; - } else { - sb << "for reading and writing"; - } - } else if (flags & FileFd::Write) { - if (flags & FileFd::Append) { - sb << "for appending"; - } else { - sb << "for writing"; - } - } else if (flags & FileFd::Read) { - sb << "for reading"; - } else { - sb << "for nothing"; - } - - if (flags & FileFd::Truncate) { - sb << " with truncation"; - } - if (flags & FileFd::Direct) { - sb << " for direct io"; - } - if (flags & FileFd::WinStat) { - sb << " for stat"; - } - return sb; -} - -} // namespace - -namespace detail { -class FileFdImpl { - public: - PollableFdInfo info; -}; -} // namespace detail - -FileFd::FileFd() = default; -FileFd::FileFd(FileFd &&) = default; -FileFd &FileFd::operator=(FileFd &&) = default; -FileFd::~FileFd() = default; - -FileFd::FileFd(unique_ptr impl) : impl_(std::move(impl)) { -} - -Result FileFd::open(CSlice filepath, int32 flags, int32 mode) { - if (flags & ~(Write | Read | Truncate | Create | Append | CreateNew | Direct | WinStat)) { - return Status::Error(PSLICE() << "File \"" << filepath << "\" has failed to be " << PrintFlags{flags}); - } - - if ((flags & (Write | Read)) == 0) { - return Status::Error(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); - } - -#if TD_PORT_POSIX - int native_flags = 0; - - if ((flags & Write) && (flags & Read)) { - native_flags |= O_RDWR; - } else if (flags & Write) { - native_flags |= O_WRONLY; - } else { - CHECK(flags & Read); - native_flags |= O_RDONLY; - } - - if (flags & Truncate) { - native_flags |= O_TRUNC; - } - - if (flags & Create) { - native_flags |= O_CREAT; - } else if (flags & CreateNew) { - native_flags |= O_CREAT; - native_flags |= O_EXCL; - } - - if (flags & Append) { - native_flags |= O_APPEND; - } - -#if TD_LINUX - if (flags & Direct) { - native_flags |= O_DIRECT; - } -#endif - - int native_fd = detail::skip_eintr([&] { return ::open(filepath.c_str(), native_flags, static_cast(mode)); }); - if (native_fd < 0) { - return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); - } - return from_native_fd(NativeFd(native_fd)); -#elif TD_PORT_WINDOWS - // TODO: support modes - auto r_filepath = to_wstring(filepath); - if (r_filepath.is_error()) { - return Status::Error(PSLICE() << "Failed to convert file path \" << filepath << \" to UTF-16"); - } - auto w_filepath = r_filepath.move_as_ok(); - DWORD desired_access = 0; - if ((flags & Write) && (flags & Read)) { - desired_access |= GENERIC_READ | GENERIC_WRITE; - } else if (flags & Write) { - desired_access |= GENERIC_WRITE; - } else { - CHECK(flags & Read); - desired_access |= GENERIC_READ; - } - - // TODO: share mode - DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE; - - DWORD creation_disposition = 0; - if (flags & Create) { - if (flags & Truncate) { - creation_disposition = CREATE_ALWAYS; - } else { - creation_disposition = OPEN_ALWAYS; - } - } else if (flags & CreateNew) { - creation_disposition = CREATE_NEW; - } else { - if (flags & Truncate) { - creation_disposition = TRUNCATE_EXISTING; - } else { - creation_disposition = OPEN_EXISTING; - } - } - - DWORD native_flags = 0; - if (flags & Direct) { - native_flags |= FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING; - } - if (flags & WinStat) { - native_flags |= FILE_FLAG_BACKUP_SEMANTICS; - } -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - auto handle = - CreateFile(w_filepath.c_str(), desired_access, share_mode, nullptr, creation_disposition, native_flags, nullptr); -#else - CREATEFILE2_EXTENDED_PARAMETERS extended_parameters; - std::memset(&extended_parameters, 0, sizeof(extended_parameters)); - extended_parameters.dwSize = sizeof(extended_parameters); - extended_parameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; - extended_parameters.dwFileFlags = native_flags; - auto handle = CreateFile2(w_filepath.c_str(), desired_access, share_mode, creation_disposition, &extended_parameters); -#endif - if (handle == INVALID_HANDLE_VALUE) { - return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); - } - auto native_fd = NativeFd(handle); - if (flags & Append) { - LARGE_INTEGER offset; - offset.QuadPart = 0; - auto set_pointer_res = SetFilePointerEx(handle, offset, nullptr, FILE_END); - if (!set_pointer_res) { - return OS_ERROR(PSLICE() << "Failed to seek to the end of file \"" << filepath << "\""); - } - } - return from_native_fd(std::move(native_fd)); -#endif -} - -FileFd FileFd::from_native_fd(NativeFd native_fd) { - auto impl = make_unique(); - impl->info.set_native_fd(std::move(native_fd)); - impl->info.add_flags(PollFlags::Write()); - return FileFd(std::move(impl)); -} - -Result FileFd::write(Slice slice) { - auto native_fd = get_native_fd().fd(); -#if TD_PORT_POSIX - auto bytes_written = detail::skip_eintr([&] { return ::write(native_fd, slice.begin(), slice.size()); }); - bool success = bytes_written >= 0; -#elif TD_PORT_WINDOWS - DWORD bytes_written = 0; - BOOL success = WriteFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_written, nullptr); -#endif - if (success) { - return narrow_cast(bytes_written); - } - return OS_ERROR(PSLICE() << "Write to " << get_native_fd() << " has failed"); -} - -Result FileFd::writev(Span slices) { -#if TD_PORT_POSIX - auto native_fd = get_native_fd().fd(); - TRY_RESULT(slices_size, narrow_cast_safe(slices.size())); - auto bytes_written = detail::skip_eintr([&] { return ::writev(native_fd, slices.begin(), slices_size); }); - bool success = bytes_written >= 0; - if (success) { - return narrow_cast(bytes_written); - } - return OS_ERROR(PSLICE() << "Writev to " << get_native_fd() << " has failed"); -#else - size_t res = 0; - for (auto slice : slices) { - TRY_RESULT(size, write(slice)); - res += size; - } - return res; -#endif -} - -Result FileFd::read(MutableSlice slice) { - auto native_fd = get_native_fd().fd(); -#if TD_PORT_POSIX - auto bytes_read = detail::skip_eintr([&] { return ::read(native_fd, slice.begin(), slice.size()); }); - bool success = bytes_read >= 0; - if (!success) { - auto read_errno = errno; - if (read_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || read_errno == EWOULDBLOCK -#endif - ) { - success = true; - bytes_read = 0; - } - } - bool is_eof = success && narrow_cast(bytes_read) < slice.size(); -#elif TD_PORT_WINDOWS - DWORD bytes_read = 0; - BOOL success = ReadFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_read, nullptr); - bool is_eof = bytes_read == 0; -#endif - if (success) { - if (is_eof) { - get_poll_info().clear_flags(PollFlags::Read()); - } - return static_cast(bytes_read); - } - return OS_ERROR(PSLICE() << "Read from " << get_native_fd() << " has failed"); -} - -Result FileFd::pwrite(Slice slice, int64 offset) { - if (offset < 0) { - return Status::Error("Offset must be non-negative"); - } - auto native_fd = get_native_fd().fd(); -#if TD_PORT_POSIX - TRY_RESULT(offset_off_t, narrow_cast_safe(offset)); - auto bytes_written = - detail::skip_eintr([&] { return ::pwrite(native_fd, slice.begin(), slice.size(), offset_off_t); }); - bool success = bytes_written >= 0; -#elif TD_PORT_WINDOWS - DWORD bytes_written = 0; - OVERLAPPED overlapped; - std::memset(&overlapped, 0, sizeof(overlapped)); - overlapped.Offset = static_cast(offset); - overlapped.OffsetHigh = static_cast(offset >> 32); - BOOL success = WriteFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_written, &overlapped); -#endif - if (success) { - return narrow_cast(bytes_written); - } - return OS_ERROR(PSLICE() << "Pwrite to " << get_native_fd() << " at offset " << offset << " has failed"); -} - -Result FileFd::pread(MutableSlice slice, int64 offset) const { - if (offset < 0) { - return Status::Error("Offset must be non-negative"); - } - auto native_fd = get_native_fd().fd(); -#if TD_PORT_POSIX - TRY_RESULT(offset_off_t, narrow_cast_safe(offset)); - auto bytes_read = detail::skip_eintr([&] { return ::pread(native_fd, slice.begin(), slice.size(), offset_off_t); }); - bool success = bytes_read >= 0; -#elif TD_PORT_WINDOWS - DWORD bytes_read = 0; - OVERLAPPED overlapped; - std::memset(&overlapped, 0, sizeof(overlapped)); - overlapped.Offset = static_cast(offset); - overlapped.OffsetHigh = static_cast(offset >> 32); - BOOL success = ReadFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_read, &overlapped); -#endif - if (success) { - return narrow_cast(bytes_read); - } - return OS_ERROR(PSLICE() << "Pread from " << get_native_fd() << " at offset " << offset << " has failed"); -} - -static std::mutex in_process_lock_mutex; -static std::unordered_set locked_files; - -static Status create_local_lock(const string &path, int32 &max_tries) { - while (true) { - { // mutex lock scope - std::lock_guard lock(in_process_lock_mutex); - if (locked_files.find(path) == locked_files.end()) { - VLOG(fd) << "Lock file \"" << path << '"'; - locked_files.insert(path); - return Status::OK(); - } - } - - if (--max_tries <= 0) { - return Status::Error( - 0, PSLICE() << "Can't lock file \"" << path << "\", because it is already in use by current program"); - } - - usleep_for(100000); - } -} - -Status FileFd::lock(const LockFlags flags, const string &path, int32 max_tries) { - if (max_tries <= 0) { - return Status::Error(0, "Can't lock file: wrong max_tries"); - } - - bool need_local_unlock = false; - if (!path.empty()) { - if (flags == LockFlags::Unlock) { - need_local_unlock = true; - } else if (flags == LockFlags::Read) { - LOG(FATAL) << "Local locking in Read mode is unsupported"; - } else { - CHECK(flags == LockFlags::Write); - VLOG(fd) << "Trying to lock file \"" << path << '"'; - TRY_STATUS(create_local_lock(path, max_tries)); - need_local_unlock = true; - } - } - SCOPE_EXIT { - if (need_local_unlock) { - remove_local_lock(path); - } - }; - -#if TD_PORT_POSIX - auto native_fd = get_native_fd().fd(); -#elif TD_PORT_WINDOWS - auto native_fd = get_native_fd().fd(); -#endif - while (true) { -#if TD_PORT_POSIX - struct flock lock; - std::memset(&lock, 0, sizeof(lock)); - - lock.l_type = static_cast([&] { - switch (flags) { - case LockFlags::Read: - return F_RDLCK; - case LockFlags::Write: - return F_WRLCK; - case LockFlags::Unlock: - return F_UNLCK; - default: - UNREACHABLE(); - return F_UNLCK; - } - }()); - - lock.l_whence = SEEK_SET; - if (fcntl(native_fd, F_SETLK, &lock) == -1) { - if (errno == EAGAIN) { -#elif TD_PORT_WINDOWS - OVERLAPPED overlapped; - std::memset(&overlapped, 0, sizeof(overlapped)); - - BOOL result; - if (flags == LockFlags::Unlock) { - result = UnlockFileEx(native_fd, 0, MAXDWORD, MAXDWORD, &overlapped); - } else { - DWORD dw_flags = LOCKFILE_FAIL_IMMEDIATELY; - if (flags == LockFlags::Write) { - dw_flags |= LOCKFILE_EXCLUSIVE_LOCK; - } - - result = LockFileEx(native_fd, dw_flags, 0, MAXDWORD, MAXDWORD, &overlapped); - } - - if (!result) { - if (GetLastError() == ERROR_LOCK_VIOLATION) { -#endif - if (--max_tries > 0) { - usleep_for(100000); - continue; - } - - return OS_ERROR(PSLICE() << "Can't lock file \"" << path - << "\", because it is already in use; check for another program instance running"); - } - - return OS_ERROR("Can't lock file"); - } - - break; - } - - if (flags == LockFlags::Write) { - need_local_unlock = false; - } - return Status::OK(); -} - -void FileFd::remove_local_lock(const string &path) { - if (!path.empty()) { - VLOG(fd) << "Unlock file \"" << path << '"'; - std::unique_lock lock(in_process_lock_mutex); - auto erased = locked_files.erase(path); - CHECK(erased > 0); - } -} - -void FileFd::close() { - impl_.reset(); -} - -bool FileFd::empty() const { - return !impl_; -} - -const NativeFd &FileFd::get_native_fd() const { - return get_poll_info().native_fd(); -} - -NativeFd FileFd::move_as_native_fd() { - auto res = get_poll_info().move_as_native_fd(); - impl_.reset(); - return res; -} - -Result FileFd::get_size() const { - TRY_RESULT(s, stat()); - return s.size_; -} - -#if TD_PORT_WINDOWS -static uint64 filetime_to_unix_time_nsec(LONGLONG filetime) { - const auto FILETIME_UNIX_TIME_DIFF = 116444736000000000ll; - return static_cast((filetime - FILETIME_UNIX_TIME_DIFF) * 100); -} -#endif - -Result FileFd::stat() const { - CHECK(!empty()); -#if TD_PORT_POSIX - return detail::fstat(get_native_fd().fd()); -#elif TD_PORT_WINDOWS - Stat res; - - FILE_BASIC_INFO basic_info; - auto status = GetFileInformationByHandleEx(get_native_fd().fd(), FileBasicInfo, &basic_info, sizeof(basic_info)); - if (!status) { - return OS_ERROR("Get FileBasicInfo failed"); - } - res.atime_nsec_ = filetime_to_unix_time_nsec(basic_info.LastAccessTime.QuadPart); - res.mtime_nsec_ = filetime_to_unix_time_nsec(basic_info.LastWriteTime.QuadPart); - res.is_dir_ = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - res.is_reg_ = !res.is_dir_; // TODO this is still wrong - - FILE_STANDARD_INFO standard_info; - status = GetFileInformationByHandleEx(get_native_fd().fd(), FileStandardInfo, &standard_info, sizeof(standard_info)); - if (!status) { - return OS_ERROR("Get FileStandardInfo failed"); - } - res.size_ = standard_info.EndOfFile.QuadPart; - - return res; -#endif -} - -Status FileFd::sync() { - CHECK(!empty()); -#if TD_PORT_POSIX -#if TD_DARWIN - if (detail::skip_eintr([&] { return fcntl(get_native_fd().fd(), F_FULLFSYNC); }) == -1) { -#else - if (detail::skip_eintr([&] { return fsync(get_native_fd().fd()); }) != 0) { -#endif -#elif TD_PORT_WINDOWS - if (FlushFileBuffers(get_native_fd().fd()) == 0) { -#endif - return OS_ERROR("Sync failed"); - } - return Status::OK(); -} - -Status FileFd::seek(int64 position) { - CHECK(!empty()); -#if TD_PORT_POSIX - TRY_RESULT(position_off_t, narrow_cast_safe(position)); - if (detail::skip_eintr([&] { return ::lseek(get_native_fd().fd(), position_off_t, SEEK_SET); }) < 0) { -#elif TD_PORT_WINDOWS - LARGE_INTEGER offset; - offset.QuadPart = position; - if (SetFilePointerEx(get_native_fd().fd(), offset, nullptr, FILE_BEGIN) == 0) { -#endif - return OS_ERROR("Seek failed"); - } - return Status::OK(); -} - -Status FileFd::truncate_to_current_position(int64 current_position) { - CHECK(!empty()); -#if TD_PORT_POSIX - TRY_RESULT(current_position_off_t, narrow_cast_safe(current_position)); - if (detail::skip_eintr([&] { return ::ftruncate(get_native_fd().fd(), current_position_off_t); }) < 0) { -#elif TD_PORT_WINDOWS - if (SetEndOfFile(get_native_fd().fd()) == 0) { -#endif - return OS_ERROR("Truncate failed"); - } - return Status::OK(); -} -PollableFdInfo &FileFd::get_poll_info() { - CHECK(!empty()); - return impl_->info; -} -const PollableFdInfo &FileFd::get_poll_info() const { - CHECK(!empty()); - return impl_->info; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.h deleted file mode 100644 index cec3d018..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/FileFd.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/IoSlice.h" -#include "td/utils/port/Stat.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/Status.h" - -namespace td { -namespace detail { -class FileFdImpl; -} - -class FileFd { - public: - FileFd(); - FileFd(FileFd &&); - FileFd &operator=(FileFd &&); - ~FileFd(); - FileFd(const FileFd &) = delete; - FileFd &operator=(const FileFd &) = delete; - - enum Flags : int32 { Write = 1, Read = 2, Truncate = 4, Create = 8, Append = 16, CreateNew = 32, Direct = 64 }; - enum PrivateFlags : int32 { WinStat = 128 }; - - static Result open(CSlice filepath, int32 flags, int32 mode = 0600) TD_WARN_UNUSED_RESULT; - static FileFd from_native_fd(NativeFd fd) TD_WARN_UNUSED_RESULT; - - Result write(Slice slice) TD_WARN_UNUSED_RESULT; - Result writev(Span slices) TD_WARN_UNUSED_RESULT; - Result read(MutableSlice slice) TD_WARN_UNUSED_RESULT; - - Result pwrite(Slice slice, int64 offset) TD_WARN_UNUSED_RESULT; - Result pread(MutableSlice slice, int64 offset) const TD_WARN_UNUSED_RESULT; - - enum class LockFlags { Write, Read, Unlock }; - Status lock(const LockFlags flags, const string &path, int32 max_tries) TD_WARN_UNUSED_RESULT; - static void remove_local_lock(const string &path); - - PollableFdInfo &get_poll_info(); - const PollableFdInfo &get_poll_info() const; - void close(); - bool empty() const; - - Result get_size() const; - - Result stat() const; - - Status sync() TD_WARN_UNUSED_RESULT; - - Status seek(int64 position) TD_WARN_UNUSED_RESULT; - - Status truncate_to_current_position(int64 current_position) TD_WARN_UNUSED_RESULT; - - const NativeFd &get_native_fd() const; - NativeFd move_as_native_fd(); - - private: - unique_ptr impl_; - - explicit FileFd(unique_ptr impl); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.cpp deleted file mode 100644 index d6aea705..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#define _WINSOCK_DEPRECATED_NO_WARNINGS // we need to use inet_addr instead of inet_pton - -#include "td/utils/port/IPAddress.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Slice.h" -#include "td/utils/utf8.h" - -#if TD_WINDOWS -#include "td/utils/port/wstring_convert.h" -#else -#include -#include -#include -#endif - -#include -#include - -namespace td { - -static bool is_ascii_host_char(char c) { - return static_cast(c) <= 127; -} - -static bool is_ascii_host(Slice host) { - for (auto c : host) { - if (!is_ascii_host_char(c)) { - return false; - } - } - return true; -} - -#if !TD_WINDOWS -static void punycode(string &result, Slice part) { - vector codes; - codes.reserve(utf8_length(part)); - uint32 processed = 0; - auto begin = part.ubegin(); - auto end = part.uend(); - while (begin != end) { - uint32 code; - begin = next_utf8_unsafe(begin, &code, "punycode"); - if (code <= 127u) { - result += to_lower(static_cast(code)); - processed++; - } - codes.push_back(code); - } - - if (processed > 0) { - result += '-'; - } - - uint32 n = 127; - uint32 delta = 0; - int bias = -72; - bool is_first = true; - while (processed < codes.size()) { - // choose lowest not processed code - uint32 next_n = 0x110000; - for (auto code : codes) { - if (code > n && code < next_n) { - next_n = code; - } - } - delta += (next_n - n - 1) * (processed + 1); - - for (auto code : codes) { - if (code < next_n) { - delta++; - } - - if (code == next_n) { - // found next symbol, encode delta - int left = static_cast(delta); - while (true) { - bias += 36; - auto t = clamp(bias, 1, 26); - if (left < t) { - result += static_cast(left + 'a'); - break; - } - - left -= t; - auto digit = t + left % (36 - t); - result += static_cast(digit < 26 ? digit + 'a' : digit - 26 + '0'); - left /= 36 - t; - } - processed++; - - // update bias - if (is_first) { - delta /= 700; - is_first = false; - } else { - delta /= 2; - } - delta += delta / processed; - - bias = 0; - while (delta > 35 * 13) { - delta /= 35; - bias -= 36; - } - bias -= static_cast(36 * delta / (delta + 38)); - delta = 0; - } - } - - delta++; - n = next_n; - } -} -#endif - -Result idn_to_ascii(CSlice host) { - if (is_ascii_host(host)) { - return to_lower(host); - } - if (!check_utf8(host)) { - return Status::Error("Host name must be encoded in UTF-8"); - } - - const int MAX_DNS_NAME_LENGTH = 255; - if (host.size() >= MAX_DNS_NAME_LENGTH * 4) { // upper bound, 4 characters per symbol - return Status::Error("Host name is too long"); - } - -#if TD_WINDOWS - TRY_RESULT(whost, to_wstring(host)); - wchar_t punycode[MAX_DNS_NAME_LENGTH + 1]; - int result_length = - IdnToAscii(IDN_ALLOW_UNASSIGNED, whost.c_str(), narrow_cast(whost.size()), punycode, MAX_DNS_NAME_LENGTH); - if (result_length == 0) { - return Status::Error("Host can't be converted to ASCII"); - } - - TRY_RESULT(idn_host, from_wstring(punycode, result_length)); - return idn_host; -#else - auto parts = full_split(Slice(host), '.'); - bool is_first = true; - string result; - result.reserve(host.size()); - for (auto part : parts) { - if (!is_first) { - result += '.'; - } - if (is_ascii_host(part)) { - result.append(part.data(), part.size()); - } else { - // TODO nameprep should be applied first, but punycode is better than nothing. - // It is better to use libidn/ICU here if available - result += "xn--"; - punycode(result, part); - } - is_first = false; - } - return result; -#endif -} - -static CSlice get_ip_str(int family, const void *addr) { - const int buf_size = INET6_ADDRSTRLEN; - static TD_THREAD_LOCAL char *buf; - init_thread_local(buf, buf_size); - - const char *res = inet_ntop(family, -#if TD_WINDOWS - const_cast(addr), -#else - addr, -#endif - buf, buf_size); - if (res == nullptr) { - return CSlice(); - } else { - return CSlice(res); - } -} - -IPAddress::IPAddress() : is_valid_(false) { -} - -bool IPAddress::is_valid() const { - return is_valid_; -} - -bool IPAddress::is_reserved() const { - CHECK(is_valid()); - - if (is_ipv6()) { - // TODO proper check for reserved IPv6 addresses - return true; - } - - uint32 ip = get_ipv4(); - struct IpBlock { - CSlice ip; - int mask; - IpBlock(CSlice ip, int mask) : ip(ip), mask(mask) { - } - }; - static const IpBlock blocks[] = {{"0.0.0.0", 8}, {"10.0.0.0", 8}, {"100.64.0.0", 10}, {"127.0.0.0", 8}, - {"169.254.0.0", 16}, {"172.16.0.0", 12}, {"192.0.0.0", 24}, {"192.0.2.0", 24}, - {"192.88.99.0", 24}, {"192.168.0.0", 16}, {"198.18.0.0", 15}, {"198.51.100.0", 24}, - {"203.0.113.0", 24}, {"224.0.0.0", 3}}; - for (auto &block : blocks) { - IPAddress block_ip_address; - block_ip_address.init_ipv4_port(block.ip, 80).ensure(); - uint32 range = block_ip_address.get_ipv4(); - CHECK(block.mask != 0); - uint32 mask = std::numeric_limits::max() >> (32 - block.mask) << (32 - block.mask); - if ((ip & mask) == (range & mask)) { - return true; - } - } - return false; -} - -const sockaddr *IPAddress::get_sockaddr() const { - CHECK(is_valid()); - return &sockaddr_; -} - -size_t IPAddress::get_sockaddr_len() const { - CHECK(is_valid()); - switch (sockaddr_.sa_family) { - case AF_INET6: - return sizeof(ipv6_addr_); - case AF_INET: - return sizeof(ipv4_addr_); - default: - LOG(FATAL) << "Unknown address family"; - return 0; - } -} - -int IPAddress::get_address_family() const { - return get_sockaddr()->sa_family; -} - -bool IPAddress::is_ipv4() const { - return is_valid() && get_address_family() == AF_INET; -} - -bool IPAddress::is_ipv6() const { - return is_valid() && get_address_family() == AF_INET6; -} - -uint32 IPAddress::get_ipv4() const { - CHECK(is_valid()); - CHECK(is_ipv4()); - return htonl(ipv4_addr_.sin_addr.s_addr); -} - -Slice IPAddress::get_ipv6() const { - static_assert(sizeof(ipv6_addr_.sin6_addr) == 16, "ipv6 size == 16"); - CHECK(is_valid()); - CHECK(!is_ipv4()); - return Slice(ipv6_addr_.sin6_addr.s6_addr, 16); -} - -IPAddress IPAddress::get_any_addr() const { - IPAddress res; - switch (get_address_family()) { - case AF_INET6: - res.init_ipv6_any(); - break; - case AF_INET: - res.init_ipv4_any(); - break; - default: - LOG(FATAL) << "Unknown address family"; - } - return res; -} - -void IPAddress::init_ipv4_any() { - is_valid_ = true; - std::memset(&ipv4_addr_, 0, sizeof(ipv4_addr_)); - ipv4_addr_.sin_family = AF_INET; - ipv4_addr_.sin_addr.s_addr = INADDR_ANY; - ipv4_addr_.sin_port = 0; -} - -void IPAddress::init_ipv6_any() { - is_valid_ = true; - std::memset(&ipv6_addr_, 0, sizeof(ipv6_addr_)); - ipv6_addr_.sin6_family = AF_INET6; - ipv6_addr_.sin6_addr = in6addr_any; - ipv6_addr_.sin6_port = 0; -} - -Status IPAddress::init_ipv6_port(CSlice ipv6, int port) { - is_valid_ = false; - if (port <= 0 || port >= (1 << 16)) { - return Status::Error(PSLICE() << "Invalid [port=" << port << "]"); - } - std::memset(&ipv6_addr_, 0, sizeof(ipv6_addr_)); - ipv6_addr_.sin6_family = AF_INET6; - ipv6_addr_.sin6_port = htons(static_cast(port)); - int err = inet_pton(AF_INET6, ipv6.c_str(), &ipv6_addr_.sin6_addr); - if (err == 0) { - return Status::Error(PSLICE() << "Failed inet_pton(AF_INET6, " << ipv6 << ")"); - } else if (err == -1) { - return OS_SOCKET_ERROR(PSLICE() << "Failed inet_pton(AF_INET6, " << ipv6 << ")"); - } - is_valid_ = true; - return Status::OK(); -} - -Status IPAddress::init_ipv6_as_ipv4_port(CSlice ipv4, int port) { - return init_ipv6_port(string("::FFFF:").append(ipv4.begin(), ipv4.size()), port); -} - -Status IPAddress::init_ipv4_port(CSlice ipv4, int port) { - is_valid_ = false; - if (port <= 0 || port >= (1 << 16)) { - return Status::Error(PSLICE() << "Invalid [port=" << port << "]"); - } - std::memset(&ipv4_addr_, 0, sizeof(ipv4_addr_)); - ipv4_addr_.sin_family = AF_INET; - ipv4_addr_.sin_port = htons(static_cast(port)); - int err = inet_pton(AF_INET, ipv4.c_str(), &ipv4_addr_.sin_addr); - if (err == 0) { - return Status::Error(PSLICE() << "Failed inet_pton(AF_INET, " << ipv4 << ")"); - } else if (err == -1) { - return OS_SOCKET_ERROR(PSLICE() << "Failed inet_pton(AF_INET, " << ipv4 << ")"); - } - is_valid_ = true; - return Status::OK(); -} - -Result IPAddress::get_ipv4_address(CSlice host) { - // sometimes inet_addr allows much more valid IPv4 hosts than inet_pton, - // like 0x12.0x34.0x56.0x78, or 0x12345678, or 0x7f.001 - auto ipv4_numeric_addr = inet_addr(host.c_str()); - if (ipv4_numeric_addr == INADDR_NONE) { - return Status::Error("Host is not valid IPv4 address"); - } - - host = ::td::get_ip_str(AF_INET, &ipv4_numeric_addr); - IPAddress result; - auto status = result.init_ipv4_port(host, 1); - if (status.is_error()) { - return std::move(status); - } - return std::move(result); -} - -Result IPAddress::get_ipv6_address(CSlice host) { - IPAddress result; - auto status = result.init_ipv6_port(host, 1); - if (status.is_error()) { - return std::move(status); - } - return std::move(result); -} - -Status IPAddress::init_host_port(CSlice host, int port, bool prefer_ipv6) { - return init_host_port(host, PSLICE() << port, prefer_ipv6); -} - -Status IPAddress::init_host_port(CSlice host, CSlice port, bool prefer_ipv6) { - is_valid_ = false; - if (host.empty()) { - return Status::Error("Host is empty"); - } -#if TD_WINDOWS - if (host == "..localmachine") { - return Status::Error("Host is invalid"); - } -#endif - TRY_RESULT(ascii_host, idn_to_ascii(host)); - host = ascii_host; - - // some getaddrinfo implementations use inet_pton instead of inet_aton and support only decimal-dotted IPv4 form, - // and so doesn't recognize 0x12.0x34.0x56.0x78, or 0x12345678, or 0x7f.001 as valid IPv4 addresses - auto ipv4_numeric_addr = inet_addr(host.c_str()); - if (ipv4_numeric_addr != INADDR_NONE) { - host = ::td::get_ip_str(AF_INET, &ipv4_numeric_addr); - } - - addrinfo hints; - addrinfo *info = nullptr; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - LOG(DEBUG + 10) << "Try to init IP address of " << host << " with port " << port; - auto err = getaddrinfo(host.c_str(), port.c_str(), &hints, &info); - if (err != 0) { -#if TD_WINDOWS - return OS_SOCKET_ERROR("Failed to resolve host"); -#else - return Status::Error(PSLICE() << "Failed to resolve host: " << gai_strerror(err)); -#endif - } - SCOPE_EXIT { - freeaddrinfo(info); - }; - - addrinfo *best_info = nullptr; - for (auto *ptr = info; ptr != nullptr; ptr = ptr->ai_next) { - if (ptr->ai_family == AF_INET && (!prefer_ipv6 || best_info == nullptr)) { - // just use first IPv4 address if there is no IPv6 and it isn't preferred - best_info = ptr; - if (!prefer_ipv6) { - break; - } - } - if (ptr->ai_family == AF_INET6 && (prefer_ipv6 || best_info == nullptr)) { - // or first IPv6 address if there is no IPv4 and it isn't preferred - best_info = ptr; - if (prefer_ipv6) { - break; - } - } - } - if (best_info == nullptr) { - return Status::Error("Failed to find IPv4/IPv6 address"); - } - return init_sockaddr(best_info->ai_addr, narrow_cast(best_info->ai_addrlen)); -} - -Status IPAddress::init_host_port(CSlice host_port) { - auto pos = host_port.rfind(':'); - if (pos == static_cast(-1)) { - return Status::Error("Can't split string into host and port"); - } - return init_host_port(host_port.substr(0, pos).str(), host_port.substr(pos + 1).str()); -} - -Status IPAddress::init_sockaddr(sockaddr *addr) { - if (addr->sa_family == AF_INET6) { - return init_sockaddr(addr, sizeof(ipv6_addr_)); - } else if (addr->sa_family == AF_INET) { - return init_sockaddr(addr, sizeof(ipv4_addr_)); - } else { - return init_sockaddr(addr, 0); - } -} -Status IPAddress::init_sockaddr(sockaddr *addr, socklen_t len) { - if (addr->sa_family == AF_INET6) { - CHECK(len == sizeof(ipv6_addr_)); - std::memcpy(&ipv6_addr_, reinterpret_cast(addr), sizeof(ipv6_addr_)); - } else if (addr->sa_family == AF_INET) { - CHECK(len == sizeof(ipv4_addr_)); - std::memcpy(&ipv4_addr_, reinterpret_cast(addr), sizeof(ipv4_addr_)); - } else { - return Status::Error(PSLICE() << "Unknown " << tag("sa_family", addr->sa_family)); - } - - is_valid_ = true; - LOG(DEBUG + 10) << "Have address " << get_ip_str() << " with port " << get_port(); - return Status::OK(); -} - -Status IPAddress::init_socket_address(const SocketFd &socket_fd) { - is_valid_ = false; - auto socket = socket_fd.get_native_fd().socket(); - socklen_t len = storage_size(); - int ret = getsockname(socket, &sockaddr_, &len); - if (ret != 0) { - return OS_SOCKET_ERROR("Failed to get socket address"); - } - is_valid_ = true; - return Status::OK(); -} - -Status IPAddress::init_peer_address(const SocketFd &socket_fd) { - is_valid_ = false; - auto socket = socket_fd.get_native_fd().socket(); - socklen_t len = storage_size(); - int ret = getpeername(socket, &sockaddr_, &len); - if (ret != 0) { - return OS_SOCKET_ERROR("Failed to get peer socket address"); - } - is_valid_ = true; - return Status::OK(); -} - -CSlice IPAddress::ipv4_to_str(uint32 ipv4) { - ipv4 = ntohl(ipv4); - return ::td::get_ip_str(AF_INET, &ipv4); -} - -CSlice IPAddress::ipv6_to_str(Slice ipv6) { - CHECK(ipv6.size() == 16); - return ::td::get_ip_str(AF_INET6, ipv6.ubegin()); -} - -Slice IPAddress::get_ip_str() const { - if (!is_valid()) { - return Slice("0.0.0.0"); - } - - switch (get_address_family()) { - case AF_INET6: - return ::td::get_ip_str(AF_INET6, &ipv6_addr_.sin6_addr); - case AF_INET: - return ::td::get_ip_str(AF_INET, &ipv4_addr_.sin_addr); - default: - UNREACHABLE(); - return Slice(); - } -} - -int IPAddress::get_port() const { - if (!is_valid()) { - return 0; - } - - switch (get_address_family()) { - case AF_INET6: - return ntohs(ipv6_addr_.sin6_port); - case AF_INET: - return ntohs(ipv4_addr_.sin_port); - default: - UNREACHABLE(); - return 0; - } -} - -void IPAddress::set_port(int port) { - CHECK(is_valid()); - - switch (get_address_family()) { - case AF_INET6: - ipv6_addr_.sin6_port = htons(static_cast(port)); - break; - case AF_INET: - ipv4_addr_.sin_port = htons(static_cast(port)); - break; - default: - UNREACHABLE(); - } -} - -bool operator==(const IPAddress &a, const IPAddress &b) { - if (!a.is_valid() || !b.is_valid()) { - return !a.is_valid() && !b.is_valid(); - } - if (a.get_address_family() != b.get_address_family()) { - return false; - } - - if (a.get_address_family() == AF_INET) { - return a.ipv4_addr_.sin_port == b.ipv4_addr_.sin_port && - std::memcmp(&a.ipv4_addr_.sin_addr, &b.ipv4_addr_.sin_addr, sizeof(a.ipv4_addr_.sin_addr)) == 0; - } else if (a.get_address_family() == AF_INET6) { - return a.ipv6_addr_.sin6_port == b.ipv6_addr_.sin6_port && - std::memcmp(&a.ipv6_addr_.sin6_addr, &b.ipv6_addr_.sin6_addr, sizeof(a.ipv6_addr_.sin6_addr)) == 0; - } - - LOG(FATAL) << "Unknown address family"; - return false; -} - -bool operator<(const IPAddress &a, const IPAddress &b) { - if (!a.is_valid() || !b.is_valid()) { - return !a.is_valid() && b.is_valid(); - } - if (a.get_address_family() != b.get_address_family()) { - return a.get_address_family() < b.get_address_family(); - } - - if (a.get_address_family() == AF_INET) { - if (a.ipv4_addr_.sin_port != b.ipv4_addr_.sin_port) { - return a.ipv4_addr_.sin_port < b.ipv4_addr_.sin_port; - } - return std::memcmp(&a.ipv4_addr_.sin_addr, &b.ipv4_addr_.sin_addr, sizeof(a.ipv4_addr_.sin_addr)) < 0; - } else if (a.get_address_family() == AF_INET6) { - if (a.ipv6_addr_.sin6_port != b.ipv6_addr_.sin6_port) { - return a.ipv6_addr_.sin6_port < b.ipv6_addr_.sin6_port; - } - return std::memcmp(&a.ipv6_addr_.sin6_addr, &b.ipv6_addr_.sin6_addr, sizeof(a.ipv6_addr_.sin6_addr)) < 0; - } - - LOG(FATAL) << "Unknown address family"; - return false; -} - -StringBuilder &operator<<(StringBuilder &builder, const IPAddress &address) { - if (!address.is_valid()) { - return builder << "[invalid]"; - } - if (address.get_address_family() == AF_INET) { - return builder << "[" << address.get_ip_str() << ":" << address.get_port() << "]"; - } else { - CHECK(address.get_address_family() == AF_INET6); - return builder << "[[" << address.get_ip_str() << "]:" << address.get_port() << "]"; - } -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.h deleted file mode 100644 index 17386582..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/IPAddress.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" - -#if !TD_WINDOWS -#include -#include -#include -#endif - -namespace td { - -Result idn_to_ascii(CSlice host); - -class SocketFd; - -class IPAddress { - public: - IPAddress(); - - bool is_valid() const; - bool is_ipv4() const; - bool is_ipv6() const; - - bool is_reserved() const; - - int get_port() const; - void set_port(int port); - - uint32 get_ipv4() const; - Slice get_ipv6() const; - Slice get_ip_str() const; - - IPAddress get_any_addr() const; - - static Result get_ipv4_address(CSlice host); - static Result get_ipv6_address(CSlice host); - - Status init_ipv6_port(CSlice ipv6, int port) TD_WARN_UNUSED_RESULT; - Status init_ipv6_as_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT; - Status init_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT; - Status init_host_port(CSlice host, int port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT; - Status init_host_port(CSlice host, CSlice port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT; - Status init_host_port(CSlice host_port) TD_WARN_UNUSED_RESULT; - Status init_socket_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT; - Status init_peer_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT; - - friend bool operator==(const IPAddress &a, const IPAddress &b); - friend bool operator<(const IPAddress &a, const IPAddress &b); - - // for internal usage only - const sockaddr *get_sockaddr() const; - size_t get_sockaddr_len() const; - int get_address_family() const; - static CSlice ipv4_to_str(uint32 ipv4); - static CSlice ipv6_to_str(Slice ipv6); - Status init_sockaddr(sockaddr *addr); - Status init_sockaddr(sockaddr *addr, socklen_t len) TD_WARN_UNUSED_RESULT; - - private: - union { - sockaddr sockaddr_; - sockaddr_in ipv4_addr_; - sockaddr_in6 ipv6_addr_; - }; - static constexpr socklen_t storage_size() { - return sizeof(ipv6_addr_); - } - bool is_valid_; - - void init_ipv4_any(); - void init_ipv6_any(); -}; - -StringBuilder &operator<<(StringBuilder &builder, const IPAddress &address); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/IoSlice.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/IoSlice.h deleted file mode 100644 index 1ace3bfd..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/IoSlice.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/Slice.h" - -#if TD_PORT_POSIX -#include -#endif - -namespace td { - -#if TD_PORT_POSIX - -using IoSlice = struct iovec; - -inline IoSlice as_io_slice(Slice slice) { - IoSlice res; - res.iov_len = slice.size(); - res.iov_base = const_cast(slice.data()); - return res; -} - -inline Slice as_slice(const IoSlice io_slice) { - return Slice(static_cast(io_slice.iov_base), io_slice.iov_len); -} - -#else - -using IoSlice = Slice; - -inline IoSlice as_io_slice(Slice slice) { - return slice; -} - -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.cpp deleted file mode 100644 index 8a1edb54..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/MemoryMapping.h" - -#include "td/utils/logging.h" -#include "td/utils/misc.h" - -// TODO: -// windows, -// anonymous maps, -// huge pages? - -#if TD_WINDOWS -#else -#include -#include -#endif - -namespace td { - -class MemoryMapping::Impl { - public: - Impl(MutableSlice data, int64 offset) : data_(data), offset_(offset) { - } - Slice as_slice() const { - return data_.substr(narrow_cast(offset_)); - } - MutableSlice as_mutable_slice() const { - return {}; - } - - private: - MutableSlice data_; - int64 offset_; -}; - -static Result get_page_size() { -#if TD_WINDOWS - return Status::Error("Unimplemented"); -#else - static Result page_size = []() -> Result { - auto page_size = sysconf(_SC_PAGESIZE); - if (page_size < 0) { - return OS_ERROR("Can't load page size from sysconf"); - } - return page_size; - }(); - return page_size.clone(); -#endif -} - -Result MemoryMapping::create_anonymous(const MemoryMapping::Options &options) { - return Status::Error("Unsupported yet"); -} - -Result MemoryMapping::create_from_file(const FileFd &file_fd, const MemoryMapping::Options &options) { -#if TD_WINDOWS - return Status::Error("Unsupported yet"); -#else - if (file_fd.empty()) { - return Status::Error("Can't create memory mapping: file is empty"); - } - TRY_RESULT(stat, file_fd.stat()); - auto fd = file_fd.get_native_fd().fd(); - auto begin = options.offset; - if (begin < 0) { - return Status::Error(PSLICE() << "Can't create memory mapping: negative offset " << options.offset); - } - - int64 end; - if (options.size < 0) { - end = stat.size_; - } else { - end = begin + stat.size_; - } - - TRY_RESULT(page_size, get_page_size()); - auto fixed_begin = begin / page_size * page_size; - - auto data_offset = begin - fixed_begin; - TRY_RESULT(data_size, narrow_cast_safe(end - fixed_begin)); - - void *data = mmap(nullptr, data_size, PROT_READ, MAP_PRIVATE, fd, narrow_cast(fixed_begin)); - if (data == MAP_FAILED) { - return OS_ERROR("mmap call failed"); - } - - return MemoryMapping(make_unique(MutableSlice(static_cast(data), data_size), data_offset)); -#endif -} - -MemoryMapping::MemoryMapping(MemoryMapping &&other) = default; -MemoryMapping &MemoryMapping::operator=(MemoryMapping &&other) = default; -MemoryMapping::~MemoryMapping() = default; - -MemoryMapping::MemoryMapping(unique_ptr impl) : impl_(std::move(impl)) { -} - -Slice MemoryMapping::as_slice() const { - return impl_->as_slice(); -} - -MutableSlice MemoryMapping::as_mutable_slice() { - return impl_->as_mutable_slice(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.h deleted file mode 100644 index 0b4afc61..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/MemoryMapping.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -class MemoryMapping { - public: - struct Options { - int64 offset{0}; - int64 size{-1}; - - Options() { - } - Options &with_offset(int64 new_offset) { - offset = new_offset; - return *this; - } - Options &with_size(int64 new_size) { - size = new_size; - return *this; - } - }; - - static Result create_anonymous(const Options &options = {}); - static Result create_from_file(const FileFd &file, const Options &options = {}); - - Slice as_slice() const; - MutableSlice as_mutable_slice(); // returns empty slice if memory is read-only - - MemoryMapping(const MemoryMapping &other) = delete; - const MemoryMapping &operator=(const MemoryMapping &other) = delete; - MemoryMapping(MemoryMapping &&other); - MemoryMapping &operator=(MemoryMapping &&other); - ~MemoryMapping(); - - private: - class Impl; - unique_ptr impl_; - explicit MemoryMapping(unique_ptr impl); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/Poll.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/Poll.h deleted file mode 100644 index 339ae678..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/Poll.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/port/detail/Epoll.h" -#include "td/utils/port/detail/KQueue.h" -#include "td/utils/port/detail/Poll.h" -#include "td/utils/port/detail/Select.h" -#include "td/utils/port/detail/WineventPoll.h" - -namespace td { - -// clang-format off - -#if TD_POLL_EPOLL - using Poll = detail::Epoll; -#elif TD_POLL_KQUEUE - using Poll = detail::KQueue; -#elif TD_POLL_WINEVENT - using Poll = detail::WineventPoll; -#elif TD_POLL_POLL - using Poll = detail::Poll; -#elif TD_POLL_SELECT - using Poll = detail::Select; -#endif - -// clang-format on - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollBase.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/PollBase.h deleted file mode 100644 index b57a7680..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollBase.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollFlags.h" - -namespace td { -class PollBase { - public: - PollBase() = default; - PollBase(const PollBase &) = delete; - PollBase &operator=(const PollBase &) = delete; - PollBase(PollBase &&) = default; - PollBase &operator=(PollBase &&) = default; - virtual ~PollBase() = default; - virtual void init() = 0; - virtual void clear() = 0; - virtual void subscribe(PollableFd fd, PollFlags flags) = 0; - virtual void unsubscribe(PollableFdRef fd) = 0; - virtual void unsubscribe_before_close(PollableFdRef fd) = 0; - virtual void run(int timeout_ms) = 0; -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.cpp deleted file mode 100644 index 5e8b141a..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/PollFlags.h" - -namespace td { - -bool PollFlagsSet::write_flags(PollFlags flags) { - if (flags.empty()) { - return false; - } - auto old_flags = to_write_.fetch_or(flags.raw(), std::memory_order_relaxed); - return (flags.raw() & ~old_flags) != 0; -} - -bool PollFlagsSet::write_flags_local(PollFlags flags) { - return flags_.add_flags(flags); -} - -bool PollFlagsSet::flush() const { - if (to_write_.load(std::memory_order_relaxed) == 0) { - return false; - } - auto to_write = to_write_.exchange(0, std::memory_order_relaxed); - auto old_flags = flags_; - flags_.add_flags(PollFlags::from_raw(to_write)); - if (flags_.can_close()) { - flags_.remove_flags(PollFlags::Write()); - } - return flags_ != old_flags; -} - -PollFlags PollFlagsSet::read_flags() const { - flush(); - return flags_; -} - -PollFlags PollFlagsSet::read_flags_local() const { - return flags_; -} - -void PollFlagsSet::clear_flags(PollFlags flags) { - flags_.remove_flags(flags); -} - -void PollFlagsSet::clear() { - to_write_ = 0; - flags_ = {}; -} - -StringBuilder &operator<<(StringBuilder &sb, PollFlags flags) { - sb << '['; - if (flags.can_read()) { - sb << 'R'; - } - if (flags.can_write()) { - sb << 'W'; - } - if (flags.can_close()) { - sb << 'C'; - } - if (flags.has_pending_error()) { - sb << 'E'; - } - return sb << ']'; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.h deleted file mode 100644 index 685a74a4..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/PollFlags.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/StringBuilder.h" - -#include - -namespace td { - -class PollFlags { - public: - using Raw = int32; - bool can_read() const { - return has_flags(Read()); - } - bool can_write() const { - return has_flags(Write()); - } - bool can_close() const { - return has_flags(Close()); - } - bool has_pending_error() const { - return has_flags(Error()); - } - void remove_flags(PollFlags flags) { - remove_flags(flags.raw()); - } - bool add_flags(PollFlags flags) { - auto old_flags = flags_; - add_flags(flags.raw()); - return old_flags != flags_; - } - bool has_flags(PollFlags flags) const { - return has_flags(flags.raw()); - } - - bool empty() const { - return flags_ == 0; - } - Raw raw() const { - return flags_; - } - static PollFlags from_raw(Raw raw) { - return PollFlags(raw); - } - PollFlags() = default; - - bool operator==(const PollFlags &other) const { - return flags_ == other.flags_; - } - bool operator!=(const PollFlags &other) const { - return !(*this == other); - } - PollFlags operator|(const PollFlags other) const { - return from_raw(raw() | other.raw()); - } - - static PollFlags Write() { - return PollFlags(Flag::Write); - } - static PollFlags Error() { - return PollFlags(Flag::Error); - } - static PollFlags Close() { - return PollFlags(Flag::Close); - } - static PollFlags Read() { - return PollFlags(Flag::Read); - } - static PollFlags ReadWrite() { - return Read() | Write(); - } - - private: - enum class Flag : Raw { Write = 0x001, Read = 0x002, Close = 0x004, Error = 0x008, None = 0 }; - Raw flags_{static_cast(Flag::None)}; - - explicit PollFlags(Raw raw) : flags_(raw) { - } - explicit PollFlags(Flag flag) : PollFlags(static_cast(flag)) { - } - - PollFlags &add_flags(Raw flags) { - flags_ |= flags; - return *this; - } - PollFlags &remove_flags(Raw flags) { - flags_ &= ~flags; - return *this; - } - bool has_flags(Raw flags) const { - return (flags_ & flags) == flags; - } -}; - -StringBuilder &operator<<(StringBuilder &sb, PollFlags flags); - -class PollFlagsSet { - public: - // write flags from any thread - // this is the only function that should be called from other threads - bool write_flags(PollFlags flags); - - bool write_flags_local(PollFlags flags); - bool flush() const; - - PollFlags read_flags() const; - PollFlags read_flags_local() const; - void clear_flags(PollFlags flags); - void clear(); - - private: - mutable std::atomic to_write_{0}; - mutable PollFlags flags_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/RwMutex.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/RwMutex.h deleted file mode 100644 index 93ea82b5..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/RwMutex.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/Status.h" - -#if TD_PORT_POSIX -#include -#endif - -#include - -namespace td { - -class RwMutex { - public: - RwMutex() { - init(); - } - RwMutex(const RwMutex &) = delete; - RwMutex &operator=(const RwMutex &) = delete; - RwMutex(RwMutex &&other) { - init(); - other.clear(); - } - RwMutex &operator=(RwMutex &&other) { - other.clear(); - return *this; - } - ~RwMutex() { - clear(); - } - - bool empty() const { - return !is_valid_; - } - - void init(); - - void clear(); - - struct ReadUnlock { - void operator()(RwMutex *ptr) { - ptr->unlock_read_unsafe(); - } - }; - struct WriteUnlock { - void operator()(RwMutex *ptr) { - ptr->unlock_write_unsafe(); - } - }; - - using ReadLock = std::unique_ptr; - using WriteLock = std::unique_ptr; - - Result lock_read() TD_WARN_UNUSED_RESULT { - lock_read_unsafe(); - return ReadLock(this); - } - - Result lock_write() TD_WARN_UNUSED_RESULT { - lock_write_unsafe(); - return WriteLock(this); - } - - void lock_read_unsafe(); - - void lock_write_unsafe(); - - void unlock_read_unsafe(); - - void unlock_write_unsafe(); - - private: - bool is_valid_ = false; -#if TD_PORT_POSIX - pthread_rwlock_t mutex_; -#elif TD_PORT_WINDOWS - unique_ptr mutex_; -#endif -}; - -inline void RwMutex::init() { - CHECK(empty()); - is_valid_ = true; -#if TD_PORT_POSIX - pthread_rwlock_init(&mutex_, nullptr); -#elif TD_PORT_WINDOWS - mutex_ = make_unique(); - InitializeSRWLock(mutex_.get()); -#endif -} - -inline void RwMutex::clear() { - if (is_valid_) { -#if TD_PORT_POSIX - pthread_rwlock_destroy(&mutex_); -#elif TD_PORT_WINDOWS - mutex_.release(); -#endif - is_valid_ = false; - } -} - -inline void RwMutex::lock_read_unsafe() { - CHECK(!empty()); -// TODO error handling -#if TD_PORT_POSIX - pthread_rwlock_rdlock(&mutex_); -#elif TD_PORT_WINDOWS - AcquireSRWLockShared(mutex_.get()); -#endif -} - -inline void RwMutex::lock_write_unsafe() { - CHECK(!empty()); -#if TD_PORT_POSIX - pthread_rwlock_wrlock(&mutex_); -#elif TD_PORT_WINDOWS - AcquireSRWLockExclusive(mutex_.get()); -#endif -} - -inline void RwMutex::unlock_read_unsafe() { - CHECK(!empty()); -#if TD_PORT_POSIX - pthread_rwlock_unlock(&mutex_); -#elif TD_PORT_WINDOWS - ReleaseSRWLockShared(mutex_.get()); -#endif -} - -inline void RwMutex::unlock_write_unsafe() { - CHECK(!empty()); -#if TD_PORT_POSIX - pthread_rwlock_unlock(&mutex_); -#elif TD_PORT_WINDOWS - ReleaseSRWLockExclusive(mutex_.get()); -#endif -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.cpp deleted file mode 100644 index 00035640..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/ServerSocketFd.h" - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/IPAddress.h" -#include "td/utils/port/PollFlags.h" - -#if TD_PORT_POSIX - -#include -#include -#include -#include -#include -#include -#include - -#endif - -#if TD_PORT_WINDOWS -#include "td/utils/port/detail/Iocp.h" -#include "td/utils/SpinLock.h" -#include "td/utils/VectorQueue.h" -#endif - -#include -#include - -namespace td { - -namespace detail { -#if TD_PORT_WINDOWS -class ServerSocketFdImpl : private Iocp::Callback { - public: - ServerSocketFdImpl(NativeFd fd, int socket_family) : info_(std::move(fd)), socket_family_(socket_family) { - VLOG(fd) << get_native_fd() << " create ServerSocketFd"; - Iocp::get()->subscribe(get_native_fd(), this); - notify_iocp_read(); - } - void close() { - notify_iocp_close(); - } - PollableFdInfo &get_poll_info() { - return info_; - } - const PollableFdInfo &get_poll_info() const { - return info_; - } - - const NativeFd &get_native_fd() const { - return info_.native_fd(); - } - - Result accept() { - auto lock = lock_.lock(); - if (accepted_.empty()) { - get_poll_info().clear_flags(PollFlags::Read()); - return Status::Error(-1, "Operation would block"); - } - return accepted_.pop(); - } - - Status get_pending_error() { - Status res; - { - auto lock = lock_.lock(); - if (!pending_errors_.empty()) { - res = pending_errors_.pop(); - } - if (res.is_ok()) { - get_poll_info().clear_flags(PollFlags::Error()); - } - } - return res; - } - - private: - PollableFdInfo info_; - - SpinLock lock_; - VectorQueue accepted_; - VectorQueue pending_errors_; - static constexpr size_t MAX_ADDR_SIZE = sizeof(sockaddr_in6) + 16; - char addr_buf_[MAX_ADDR_SIZE * 2]; - - bool close_flag_{false}; - std::atomic refcnt_{1}; - bool is_read_active_{false}; - WSAOVERLAPPED read_overlapped_; - - char close_overlapped_; - - NativeFd accept_socket_; - int socket_family_; - - void on_close() { - close_flag_ = true; - info_.set_native_fd({}); - } - void on_read() { - VLOG(fd) << get_native_fd() << " on_read"; - if (is_read_active_) { - is_read_active_ = false; - auto r_socket = [&]() -> Result { - auto from = get_native_fd().socket(); - auto status = setsockopt(accept_socket_.socket(), SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, - reinterpret_cast(&from), sizeof(from)); - if (status != 0) { - return OS_SOCKET_ERROR("Failed to set SO_UPDATE_ACCEPT_CONTEXT options"); - } - return SocketFd::from_native_fd(std::move(accept_socket_)); - }(); - VLOG(fd) << get_native_fd() << " finish accept"; - if (r_socket.is_error()) { - return on_error(r_socket.move_as_error()); - } - { - auto lock = lock_.lock(); - accepted_.push(r_socket.move_as_ok()); - } - get_poll_info().add_flags_from_poll(PollFlags::Read()); - } - loop_read(); - } - void loop_read() { - CHECK(!is_read_active_); - accept_socket_ = NativeFd(socket(socket_family_, SOCK_STREAM, 0)); - std::memset(&read_overlapped_, 0, sizeof(read_overlapped_)); - VLOG(fd) << get_native_fd() << " start accept"; - BOOL status = AcceptEx(get_native_fd().socket(), accept_socket_.socket(), addr_buf_, 0, MAX_ADDR_SIZE, - MAX_ADDR_SIZE, nullptr, &read_overlapped_); - if (status == TRUE || check_status("Failed to accept connection")) { - inc_refcnt(); - is_read_active_ = true; - } - } - bool check_status(Slice message) { - auto last_error = WSAGetLastError(); - if (last_error == ERROR_IO_PENDING) { - return true; - } - on_error(OS_SOCKET_ERROR(message)); - return false; - } - bool dec_refcnt() { - if (--refcnt_ == 0) { - delete this; - return true; - } - return false; - } - void inc_refcnt() { - CHECK(refcnt_ != 0); - refcnt_++; - } - - void on_error(Status status) { - { - auto lock = lock_.lock(); - pending_errors_.push(std::move(status)); - } - get_poll_info().add_flags_from_poll(PollFlags::Error()); - } - - void on_iocp(Result r_size, WSAOVERLAPPED *overlapped) override { - // called from other thread - if (dec_refcnt() || close_flag_) { - VLOG(fd) << "Ignore IOCP (server socket is closing)"; - return; - } - if (r_size.is_error()) { - return on_error(get_socket_pending_error(get_native_fd(), overlapped, r_size.move_as_error())); - } - - if (overlapped == nullptr) { - return on_read(); - } - if (overlapped == &read_overlapped_) { - return on_read(); - } - - if (overlapped == reinterpret_cast(&close_overlapped_)) { - return on_close(); - } - UNREACHABLE(); - } - void notify_iocp_read() { - VLOG(fd) << get_native_fd() << " notify_read"; - inc_refcnt(); - Iocp::get()->post(0, this, nullptr); - } - void notify_iocp_close() { - VLOG(fd) << get_native_fd() << " notify_close"; - Iocp::get()->post(0, this, reinterpret_cast(&close_overlapped_)); - } -}; -void ServerSocketFdImplDeleter::operator()(ServerSocketFdImpl *impl) { - impl->close(); -} -#elif TD_PORT_POSIX -class ServerSocketFdImpl { - public: - explicit ServerSocketFdImpl(NativeFd fd) : info_(std::move(fd)) { - } - PollableFdInfo &get_poll_info() { - return info_; - } - const PollableFdInfo &get_poll_info() const { - return info_; - } - - const NativeFd &get_native_fd() const { - return info_.native_fd(); - } - Result accept() { - sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - int native_fd = get_native_fd().socket(); - int r_fd = detail::skip_eintr([&] { return ::accept(native_fd, reinterpret_cast(&addr), &addr_len); }); - auto accept_errno = errno; - if (r_fd >= 0) { - return SocketFd::from_native_fd(NativeFd(r_fd)); - } - - if (accept_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || accept_errno == EWOULDBLOCK -#endif - ) { - get_poll_info().clear_flags(PollFlags::Read()); - return Status::Error(-1, "Operation would block"); - } - - auto error = Status::PosixError(accept_errno, PSLICE() << "Accept from " << get_native_fd() << " has failed"); - switch (accept_errno) { - case EBADF: - case EFAULT: - case EINVAL: - case ENOTSOCK: - case EOPNOTSUPP: - LOG(FATAL) << error; - UNREACHABLE(); - break; - default: - LOG(ERROR) << error; - // fallthrough - case EMFILE: - case ENFILE: - case ECONNABORTED: //??? - get_poll_info().clear_flags(PollFlags::Read()); - get_poll_info().add_flags(PollFlags::Close()); - return std::move(error); - } - } - - Status get_pending_error() { - if (!get_poll_info().get_flags().has_pending_error()) { - return Status::OK(); - } - TRY_STATUS(detail::get_socket_pending_error(get_native_fd())); - get_poll_info().clear_flags(PollFlags::Error()); - return Status::OK(); - } - - private: - PollableFdInfo info_; -}; -void ServerSocketFdImplDeleter::operator()(ServerSocketFdImpl *impl) { - delete impl; -} -#endif -} // namespace detail - -ServerSocketFd::ServerSocketFd() = default; -ServerSocketFd::ServerSocketFd(ServerSocketFd &&) = default; -ServerSocketFd &ServerSocketFd::operator=(ServerSocketFd &&) = default; -ServerSocketFd::~ServerSocketFd() = default; -ServerSocketFd::ServerSocketFd(unique_ptr impl) : impl_(impl.release()) { -} -PollableFdInfo &ServerSocketFd::get_poll_info() { - return impl_->get_poll_info(); -} - -const PollableFdInfo &ServerSocketFd::get_poll_info() const { - return impl_->get_poll_info(); -} - -Status ServerSocketFd::get_pending_error() { - return impl_->get_pending_error(); -} - -const NativeFd &ServerSocketFd::get_native_fd() const { - return impl_->get_native_fd(); -} - -Result ServerSocketFd::accept() { - return impl_->accept(); -} - -void ServerSocketFd::close() { - impl_.reset(); -} - -bool ServerSocketFd::empty() const { - return !impl_; -} - -Result ServerSocketFd::open(int32 port, CSlice addr) { - IPAddress address; - TRY_STATUS(address.init_ipv4_port(addr, port)); - NativeFd fd{socket(address.get_address_family(), SOCK_STREAM, 0)}; - if (!fd) { - return OS_SOCKET_ERROR("Failed to create a socket"); - } - - TRY_STATUS(fd.set_is_blocking_unsafe(false)); - auto sock = fd.socket(); - - linger ling = {0, 0}; -#if TD_PORT_POSIX - int flags = 1; -#ifdef SO_REUSEPORT - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&flags), sizeof(flags)); -#endif -#elif TD_PORT_WINDOWS - BOOL flags = TRUE; -#endif - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&flags), sizeof(flags)); - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast(&flags), sizeof(flags)); - setsockopt(sock, SOL_SOCKET, SO_LINGER, reinterpret_cast(&ling), sizeof(ling)); - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flags), sizeof(flags)); - - int e_bind = bind(sock, address.get_sockaddr(), static_cast(address.get_sockaddr_len())); - if (e_bind != 0) { - return OS_SOCKET_ERROR("Failed to bind a socket"); - } - - // TODO: magic constant - int e_listen = listen(sock, 8192); - if (e_listen != 0) { - return OS_SOCKET_ERROR("Failed to listen on a socket"); - } - -#if TD_PORT_POSIX - auto impl = make_unique(std::move(fd)); -#elif TD_PORT_WINDOWS - auto impl = make_unique(std::move(fd), address.get_address_family()); -#endif - - return ServerSocketFd(std::move(impl)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.h deleted file mode 100644 index 1ed389fb..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/ServerSocketFd.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/SocketFd.h" - -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -#include - -namespace td { -namespace detail { -class ServerSocketFdImpl; -class ServerSocketFdImplDeleter { - public: - void operator()(ServerSocketFdImpl *impl); -}; -} // namespace detail - -class ServerSocketFd { - public: - ServerSocketFd(); - ServerSocketFd(const ServerSocketFd &) = delete; - ServerSocketFd &operator=(const ServerSocketFd &) = delete; - ServerSocketFd(ServerSocketFd &&); - ServerSocketFd &operator=(ServerSocketFd &&); - ~ServerSocketFd(); - - static Result open(int32 port, CSlice addr = CSlice("0.0.0.0")) TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info(); - const PollableFdInfo &get_poll_info() const; - - Status get_pending_error() TD_WARN_UNUSED_RESULT; - - Result accept() TD_WARN_UNUSED_RESULT; - - void close(); - bool empty() const; - - const NativeFd &get_native_fd() const; - - private: - std::unique_ptr impl_; - explicit ServerSocketFd(unique_ptr impl); -}; -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.cpp deleted file mode 100644 index c1fd515c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/SocketFd.h" - -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/PollFlags.h" - -#if TD_PORT_WINDOWS -#include "td/utils/buffer.h" -#include "td/utils/port/detail/Iocp.h" -#include "td/utils/SpinLock.h" -#include "td/utils/VectorQueue.h" -#endif - -#if TD_PORT_POSIX -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -namespace td { -namespace detail { -#if TD_PORT_WINDOWS -class SocketFdImpl : private Iocp::Callback { - public: - explicit SocketFdImpl(NativeFd native_fd) : info(std::move(native_fd)) { - VLOG(fd) << get_native_fd() << " create from native_fd"; - get_poll_info().add_flags(PollFlags::Write()); - Iocp::get()->subscribe(get_native_fd(), this); - is_read_active_ = true; - notify_iocp_connected(); - } - - SocketFdImpl(NativeFd native_fd, const IPAddress &addr) : info(std::move(native_fd)) { - VLOG(fd) << get_native_fd() << " create from native_fd and connect"; - get_poll_info().add_flags(PollFlags::Write()); - Iocp::get()->subscribe(get_native_fd(), this); - LPFN_CONNECTEX ConnectExPtr = nullptr; - GUID guid = WSAID_CONNECTEX; - DWORD numBytes; - auto error = - ::WSAIoctl(get_native_fd().socket(), SIO_GET_EXTENSION_FUNCTION_POINTER, static_cast(&guid), - sizeof(guid), static_cast(&ConnectExPtr), sizeof(ConnectExPtr), &numBytes, nullptr, nullptr); - if (error) { - on_error(OS_SOCKET_ERROR("WSAIoctl failed")); - return; - } - std::memset(&read_overlapped_, 0, sizeof(read_overlapped_)); - inc_refcnt(); - is_read_active_ = true; - auto status = ConnectExPtr(get_native_fd().socket(), addr.get_sockaddr(), narrow_cast(addr.get_sockaddr_len()), - nullptr, 0, nullptr, &read_overlapped_); - - if (status == TRUE || !check_status("Failed to connect")) { - is_read_active_ = false; - dec_refcnt(); - } - } - - void close() { - notify_iocp_close(); - } - - PollableFdInfo &get_poll_info() { - return info; - } - const PollableFdInfo &get_poll_info() const { - return info; - } - - const NativeFd &get_native_fd() const { - return info.native_fd(); - } - - Result write(Slice data) { - // LOG(ERROR) << "Write: " << format::as_hex_dump<0>(data); - output_writer_.append(data); - return write_finish(data.size()); - } - - Result writev(Span slices) { - size_t total_size = 0; - for (auto io_slice : slices) { - total_size += as_slice(io_slice).size(); - } - - auto left_size = total_size; - for (auto io_slice : slices) { - auto slice = as_slice(io_slice); - output_writer_.append(slice, left_size); - left_size -= slice.size(); - } - - return write_finish(total_size); - } - - Result write_finish(size_t total_size) { - if (is_write_waiting_) { - auto lock = lock_.lock(); - is_write_waiting_ = false; - lock.reset(); - notify_iocp_write(); - } - return total_size; - } - - Result read(MutableSlice slice) { - if (get_poll_info().get_flags().has_pending_error()) { - TRY_STATUS(get_pending_error()); - } - input_reader_.sync_with_writer(); - auto res = input_reader_.advance(td::min(slice.size(), input_reader_.size()), slice); - if (res == 0) { - get_poll_info().clear_flags(PollFlags::Read()); - } else { - // LOG(ERROR) << "Read: " << format::as_hex_dump<0>(Slice(slice.substr(0, res))); - } - return res; - } - - Status get_pending_error() { - Status res; - { - auto lock = lock_.lock(); - if (!pending_errors_.empty()) { - res = pending_errors_.pop(); - } - if (res.is_ok()) { - get_poll_info().clear_flags(PollFlags::Error()); - } - } - return res; - } - - private: - PollableFdInfo info; - SpinLock lock_; - - std::atomic refcnt_{1}; - bool close_flag_{false}; - - bool is_connected_{false}; - bool is_read_active_{false}; - ChainBufferWriter input_writer_; - ChainBufferReader input_reader_ = input_writer_.extract_reader(); - WSAOVERLAPPED read_overlapped_; - VectorQueue pending_errors_; - - bool is_write_active_{false}; - std::atomic is_write_waiting_{false}; - ChainBufferWriter output_writer_; - ChainBufferReader output_reader_ = output_writer_.extract_reader(); - WSAOVERLAPPED write_overlapped_; - - char close_overlapped_; - - bool check_status(Slice message) { - auto last_error = WSAGetLastError(); - if (last_error == ERROR_IO_PENDING) { - return true; - } - on_error(OS_SOCKET_ERROR(message)); - return false; - } - - void loop_read() { - CHECK(is_connected_); - CHECK(!is_read_active_); - if (close_flag_) { - return; - } - std::memset(&read_overlapped_, 0, sizeof(read_overlapped_)); - auto dest = input_writer_.prepare_append(); - WSABUF buf; - buf.len = narrow_cast(dest.size()); - buf.buf = dest.data(); - DWORD flags = 0; - int status = WSARecv(get_native_fd().socket(), &buf, 1, nullptr, &flags, &read_overlapped_, nullptr); - if (status == 0 || check_status("Failed to read from connection")) { - inc_refcnt(); - is_read_active_ = true; - } - } - - void loop_write() { - CHECK(is_connected_); - CHECK(!is_write_active_); - - output_reader_.sync_with_writer(); - auto to_write = output_reader_.prepare_read(); - if (to_write.empty()) { - auto lock = lock_.lock(); - output_reader_.sync_with_writer(); - to_write = output_reader_.prepare_read(); - if (to_write.empty()) { - is_write_waiting_ = true; - return; - } - } - if (to_write.empty()) { - return; - } - std::memset(&write_overlapped_, 0, sizeof(write_overlapped_)); - constexpr size_t buf_size = 20; - WSABUF buf[buf_size]; - auto it = output_reader_.clone(); - size_t buf_i; - for (buf_i = 0; buf_i < buf_size; buf_i++) { - auto src = it.prepare_read(); - if (src.empty()) { - break; - } - buf[buf_i].len = narrow_cast(src.size()); - buf[buf_i].buf = const_cast(src.data()); - it.confirm_read(src.size()); - } - int status = - WSASend(get_native_fd().socket(), buf, narrow_cast(buf_i), nullptr, 0, &write_overlapped_, nullptr); - if (status == 0 || check_status("Failed to write to connection")) { - inc_refcnt(); - is_write_active_ = true; - } - } - - void on_iocp(Result r_size, WSAOVERLAPPED *overlapped) override { - // called from other thread - if (dec_refcnt() || close_flag_) { - VLOG(fd) << "Ignore IOCP (socket is closing)"; - return; - } - if (r_size.is_error()) { - return on_error(get_socket_pending_error(get_native_fd(), overlapped, r_size.move_as_error())); - } - - if (!is_connected_ && overlapped == &read_overlapped_) { - return on_connected(); - } - - auto size = r_size.move_as_ok(); - if (overlapped == &write_overlapped_) { - return on_write(size); - } - if (overlapped == nullptr) { - CHECK(size == 0); - return on_write(size); - } - - if (overlapped == &read_overlapped_) { - return on_read(size); - } - if (overlapped == reinterpret_cast(&close_overlapped_)) { - return on_close(); - } - UNREACHABLE(); - } - - void on_error(Status status) { - VLOG(fd) << get_native_fd() << " on error " << status; - { - auto lock = lock_.lock(); - pending_errors_.push(std::move(status)); - } - get_poll_info().add_flags_from_poll(PollFlags::Error()); - } - - void on_connected() { - VLOG(fd) << get_native_fd() << " on connected"; - CHECK(!is_connected_); - CHECK(is_read_active_); - is_connected_ = true; - is_read_active_ = false; - loop_read(); - loop_write(); - } - - void on_read(size_t size) { - VLOG(fd) << get_native_fd() << " on read " << size; - CHECK(is_read_active_); - is_read_active_ = false; - if (size == 0) { - get_poll_info().add_flags_from_poll(PollFlags::Close()); - return; - } - input_writer_.confirm_append(size); - get_poll_info().add_flags_from_poll(PollFlags::Read()); - loop_read(); - } - - void on_write(size_t size) { - VLOG(fd) << get_native_fd() << " on write " << size; - if (size == 0) { - if (is_write_active_) { - return; - } - is_write_active_ = true; - } - CHECK(is_write_active_); - is_write_active_ = false; - output_reader_.advance(size); - loop_write(); - } - - void on_close() { - VLOG(fd) << get_native_fd() << " on close"; - close_flag_ = true; - info.set_native_fd({}); - } - bool dec_refcnt() { - VLOG(fd) << get_native_fd() << " dec_refcnt from " << refcnt_; - if (--refcnt_ == 0) { - delete this; - return true; - } - return false; - } - void inc_refcnt() { - CHECK(refcnt_ != 0); - refcnt_++; - VLOG(fd) << get_native_fd() << " inc_refcnt to " << refcnt_; - } - - void notify_iocp_write() { - inc_refcnt(); - Iocp::get()->post(0, this, nullptr); - } - void notify_iocp_close() { - Iocp::get()->post(0, this, reinterpret_cast(&close_overlapped_)); - } - void notify_iocp_connected() { - inc_refcnt(); - Iocp::get()->post(0, this, &read_overlapped_); - } -}; - -void SocketFdImplDeleter::operator()(SocketFdImpl *impl) { - impl->close(); -} - -class InitWSA { - public: - InitWSA() { - /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ - WORD wVersionRequested = MAKEWORD(2, 2); - WSADATA wsaData; - if (WSAStartup(wVersionRequested, &wsaData) != 0) { - auto error = OS_SOCKET_ERROR("Failed to init WSA"); - LOG(FATAL) << error; - } - } -}; - -static InitWSA init_wsa; - -#else -class SocketFdImpl { - public: - PollableFdInfo info; - explicit SocketFdImpl(NativeFd fd) : info(std::move(fd)) { - } - PollableFdInfo &get_poll_info() { - return info; - } - const PollableFdInfo &get_poll_info() const { - return info; - } - - const NativeFd &get_native_fd() const { - return info.native_fd(); - } - Result writev(Span slices) { - int native_fd = get_native_fd().socket(); - auto write_res = - detail::skip_eintr([&] { return ::writev(native_fd, slices.begin(), narrow_cast(slices.size())); }); - return write_finish(write_res); - } - Result write(Slice slice) { - int native_fd = get_native_fd().socket(); - auto write_res = detail::skip_eintr([&] { return ::write(native_fd, slice.begin(), slice.size()); }); - return write_finish(write_res); - } - Result write_finish(ssize_t write_res) { - auto write_errno = errno; - if (write_res >= 0) { - return narrow_cast(write_res); - } - - if (write_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || write_errno == EWOULDBLOCK -#endif - ) { - get_poll_info().clear_flags(PollFlags::Write()); - return 0; - } - - auto error = Status::PosixError(write_errno, PSLICE() << "Write to " << get_native_fd() << " has failed"); - switch (write_errno) { - case EBADF: - case ENXIO: - case EFAULT: - case EINVAL: - LOG(FATAL) << error; - UNREACHABLE(); - default: - LOG(WARNING) << error; - // fallthrough - case ECONNRESET: - case EDQUOT: - case EFBIG: - case EIO: - case ENETDOWN: - case ENETUNREACH: - case ENOSPC: - case EPIPE: - get_poll_info().clear_flags(PollFlags::Write()); - get_poll_info().add_flags(PollFlags::Close()); - return std::move(error); - } - } - Result read(MutableSlice slice) { - if (get_poll_info().get_flags().has_pending_error()) { - TRY_STATUS(get_pending_error()); - } - int native_fd = get_native_fd().socket(); - CHECK(slice.size() > 0); - auto read_res = detail::skip_eintr([&] { return ::read(native_fd, slice.begin(), slice.size()); }); - auto read_errno = errno; - if (read_res >= 0) { - if (read_res == 0) { - errno = 0; - get_poll_info().clear_flags(PollFlags::Read()); - get_poll_info().add_flags(PollFlags::Close()); - } - return narrow_cast(read_res); - } - if (read_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || read_errno == EWOULDBLOCK -#endif - ) { - get_poll_info().clear_flags(PollFlags::Read()); - return 0; - } - auto error = Status::PosixError(read_errno, PSLICE() << "Read from " << get_native_fd() << " has failed"); - switch (read_errno) { - case EISDIR: - case EBADF: - case ENXIO: - case EFAULT: - case EINVAL: - LOG(FATAL) << error; - UNREACHABLE(); - default: - LOG(WARNING) << error; - // fallthrough - case ENOTCONN: - case EIO: - case ENOBUFS: - case ENOMEM: - case ECONNRESET: - case ETIMEDOUT: - get_poll_info().clear_flags(PollFlags::Read()); - get_poll_info().add_flags(PollFlags::Close()); - return std::move(error); - } - } - Status get_pending_error() { - if (!get_poll_info().get_flags().has_pending_error()) { - return Status::OK(); - } - TRY_STATUS(detail::get_socket_pending_error(get_native_fd())); - get_poll_info().clear_flags(PollFlags::Error()); - return Status::OK(); - } -}; - -void SocketFdImplDeleter::operator()(SocketFdImpl *impl) { - delete impl; -} - -#endif - -#if TD_PORT_POSIX -Status get_socket_pending_error(const NativeFd &fd) { - int error = 0; - socklen_t errlen = sizeof(error); - if (getsockopt(fd.socket(), SOL_SOCKET, SO_ERROR, static_cast(&error), &errlen) == 0) { - if (error == 0) { - return Status::OK(); - } - return Status::PosixError(error, PSLICE() << "Error on " << fd); - } - auto status = OS_SOCKET_ERROR(PSLICE() << "Can't load error on socket " << fd); - LOG(INFO) << "Can't load pending socket error: " << status; - return status; -} -#elif TD_PORT_WINDOWS -Status get_socket_pending_error(const NativeFd &fd, WSAOVERLAPPED *overlapped, Status iocp_error) { - // We need to call WSAGetOverlappedResult() just so WSAGetLastError() will return the correct error. See - // https://stackoverflow.com/questions/28925003/calling-wsagetlasterror-from-an-iocp-thread-return-incorrect-result - DWORD num_bytes = 0; - DWORD flags = 0; - BOOL success = WSAGetOverlappedResult(fd.socket(), overlapped, &num_bytes, false, &flags); - if (success) { - LOG(ERROR) << "WSAGetOverlappedResult succeded after " << iocp_error; - return iocp_error; - } - return OS_SOCKET_ERROR(PSLICE() << "Error on " << fd); -} -#endif - -Status init_socket_options(NativeFd &native_fd) { - TRY_STATUS(native_fd.set_is_blocking_unsafe(false)); - - auto sock = native_fd.socket(); -#if TD_PORT_POSIX - int flags = 1; -#elif TD_PORT_WINDOWS - BOOL flags = TRUE; -#endif - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&flags), sizeof(flags)); - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast(&flags), sizeof(flags)); - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flags), sizeof(flags)); - // TODO: SO_REUSEADDR, SO_KEEPALIVE, TCP_NODELAY, SO_SNDBUF, SO_RCVBUF, TCP_QUICKACK, SO_LINGER - - return Status::OK(); -} - -} // namespace detail - -SocketFd::SocketFd() = default; -SocketFd::SocketFd(SocketFd &&) = default; -SocketFd &SocketFd::operator=(SocketFd &&) = default; -SocketFd::~SocketFd() = default; - -SocketFd::SocketFd(unique_ptr impl) : impl_(impl.release()) { -} - -Result SocketFd::from_native_fd(NativeFd fd) { - TRY_STATUS(detail::init_socket_options(fd)); - return SocketFd(make_unique(std::move(fd))); -} - -Result SocketFd::open(const IPAddress &address) { - NativeFd native_fd{socket(address.get_address_family(), SOCK_STREAM, IPPROTO_TCP)}; - if (!native_fd) { - return OS_SOCKET_ERROR("Failed to create a socket"); - } - TRY_STATUS(detail::init_socket_options(native_fd)); - -#if TD_PORT_POSIX - int e_connect = - connect(native_fd.socket(), address.get_sockaddr(), narrow_cast(address.get_sockaddr_len())); - if (e_connect == -1) { - auto connect_errno = errno; - if (connect_errno != EINPROGRESS) { - return Status::PosixError(connect_errno, PSLICE() << "Failed to connect to " << address); - } - } - return SocketFd(make_unique(std::move(native_fd))); -#elif TD_PORT_WINDOWS - auto bind_addr = address.get_any_addr(); - auto e_bind = bind(native_fd.socket(), bind_addr.get_sockaddr(), narrow_cast(bind_addr.get_sockaddr_len())); - if (e_bind != 0) { - return OS_SOCKET_ERROR("Failed to bind a socket"); - } - return SocketFd(make_unique(std::move(native_fd), address)); -#endif -} - -void SocketFd::close() { - impl_.reset(); -} - -bool SocketFd::empty() const { - return !impl_; -} - -PollableFdInfo &SocketFd::get_poll_info() { - return impl_->get_poll_info(); -} -const PollableFdInfo &SocketFd::get_poll_info() const { - return impl_->get_poll_info(); -} - -const NativeFd &SocketFd::get_native_fd() const { - return impl_->get_native_fd(); -} - -Status SocketFd::get_pending_error() { - return impl_->get_pending_error(); -} - -Result SocketFd::write(Slice slice) { - return impl_->write(slice); -} - -Result SocketFd::writev(Span slices) { - return impl_->writev(slices); -} - -Result SocketFd::read(MutableSlice slice) { - return impl_->read(slice); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.h deleted file mode 100644 index 8dc8a5ea..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/SocketFd.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/IoSlice.h" -#include "td/utils/port/IPAddress.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/Status.h" - -#include - -namespace td { - -namespace detail { -class SocketFdImpl; -class SocketFdImplDeleter { - public: - void operator()(SocketFdImpl *impl); -}; -} // namespace detail - -class SocketFd { - public: - SocketFd(); - SocketFd(const SocketFd &) = delete; - SocketFd &operator=(const SocketFd &) = delete; - SocketFd(SocketFd &&); - SocketFd &operator=(SocketFd &&); - ~SocketFd(); - - static Result open(const IPAddress &address) TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info(); - const PollableFdInfo &get_poll_info() const; - - Status get_pending_error() TD_WARN_UNUSED_RESULT; - - Result write(Slice slice) TD_WARN_UNUSED_RESULT; - Result writev(Span slices) TD_WARN_UNUSED_RESULT; - Result read(MutableSlice slice) TD_WARN_UNUSED_RESULT; - - const NativeFd &get_native_fd() const; - static Result from_native_fd(NativeFd fd); - - void close(); - bool empty() const; - - private: - std::unique_ptr impl_; - explicit SocketFd(unique_ptr impl); -}; - -namespace detail { -#if TD_PORT_POSIX -Status get_socket_pending_error(const NativeFd &fd); -#elif TD_PORT_WINDOWS -Status get_socket_pending_error(const NativeFd &fd, WSAOVERLAPPED *overlapped, Status iocp_error); -#endif -} // namespace detail - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.cpp deleted file mode 100644 index 45d09129..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/Stat.h" - -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/FileFd.h" - -#if TD_PORT_POSIX - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/Clocks.h" -#include "td/utils/ScopeGuard.h" - -#include - -#if TD_DARWIN -#include -#include -#endif - -// We don't want warnings from system headers -#if TD_GCC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif -#include -#if TD_GCC -#pragma GCC diagnostic pop -#endif - -#if TD_ANDROID || TD_TIZEN -#include -#endif - -namespace td { - -namespace detail { - -template -struct voider { - using type = void; -}; -template -using void_t = typename voider::type; - -template -struct TimeNsec { - static std::pair get(const T &) { - T().warning("Platform lacks support of precise access/modification file times, comment this line to continue"); - return {0, 0}; - } -}; - -// remove libc compatibility hacks if any: we have our own hacks -#ifdef st_atimespec -#undef st_atimespec -#endif - -#ifdef st_atimensec -#undef st_atimensec -#endif - -#ifdef st_atime_nsec -#undef st_atime_nsec -#endif - -template -struct TimeNsec> { - static std::pair get( - const T &s) { - return {s.st_atimespec.tv_nsec, s.st_mtimespec.tv_nsec}; - } -}; - -template -struct TimeNsec> { - static std::pair get(const T &s) { - return {s.st_atimensec, s.st_mtimensec}; - } -}; - -template -struct TimeNsec> { - static std::pair get(const T &s) { - return {s.st_atim.tv_nsec, s.st_mtim.tv_nsec}; - } -}; - -template -struct TimeNsec> { - static std::pair get(const T &s) { - return {s.st_atime_nsec, s.st_mtime_nsec}; - } -}; - -Stat from_native_stat(const struct ::stat &buf) { - auto time_nsec = TimeNsec::get(buf); - - Stat res; - res.atime_nsec_ = static_cast(buf.st_atime) * 1000000000 + time_nsec.first; - res.mtime_nsec_ = static_cast(buf.st_mtime) * 1000000000 + time_nsec.second / 1000 * 1000; - res.size_ = buf.st_size; - res.is_dir_ = (buf.st_mode & S_IFMT) == S_IFDIR; - res.is_reg_ = (buf.st_mode & S_IFMT) == S_IFREG; - return res; -} - -Result fstat(int native_fd) { - struct ::stat buf; - if (detail::skip_eintr([&] { return ::fstat(native_fd, &buf); }) < 0) { - return OS_ERROR(PSLICE() << "Stat for fd " << native_fd << " failed"); - } - return detail::from_native_stat(buf); -} - -Status update_atime(int native_fd) { -#if TD_LINUX - timespec times[2]; - // access time - times[0].tv_nsec = UTIME_NOW; - times[0].tv_sec = 0; - // modify time - times[1].tv_nsec = UTIME_OMIT; - times[1].tv_sec = 0; - if (futimens(native_fd, times) < 0) { - auto status = OS_ERROR(PSLICE() << "futimens " << tag("fd", native_fd)); - LOG(WARNING) << status; - return status; - } - return Status::OK(); -#elif TD_DARWIN - TRY_RESULT(info, fstat(native_fd)); - timeval upd[2]; - auto now = Clocks::system(); - // access time - upd[0].tv_sec = static_cast(now); - upd[0].tv_usec = static_cast((now - static_cast(upd[0].tv_sec)) * 1000000); - // modify time - upd[1].tv_sec = static_cast(info.mtime_nsec_ / 1000000000ll); - upd[1].tv_usec = static_cast(info.mtime_nsec_ % 1000000000ll / 1000); - if (futimes(native_fd, upd) < 0) { - auto status = OS_ERROR(PSLICE() << "futimes " << tag("fd", native_fd)); - LOG(WARNING) << status; - return status; - } - return Status::OK(); -#else - return Status::Error("Not supported"); -// timespec times[2]; -//// access time -// times[0].tv_nsec = UTIME_NOW; -//// modify time -// times[1].tv_nsec = UTIME_OMIT; -//// int err = syscall(__NR_utimensat, native_fd, nullptr, times, 0); -// if (futimens(native_fd, times) < 0) { -// auto status = OS_ERROR(PSLICE() << "futimens " << tag("fd", native_fd)); -// LOG(WARNING) << status; -// return status; -// } -// return Status::OK(); -#endif -} -} // namespace detail - -Status update_atime(CSlice path) { - TRY_RESULT(file, FileFd::open(path, FileFd::Flags::Read)); - SCOPE_EXIT { - file.close(); - }; - return detail::update_atime(file.get_native_fd().fd()); -} - -Result stat(CSlice path) { - struct ::stat buf; - int err = detail::skip_eintr([&] { return ::stat(path.c_str(), &buf); }); - if (err < 0) { - return OS_ERROR(PSLICE() << "Stat for file \"" << path << "\" failed"); - } - return detail::from_native_stat(buf); -} - -Result mem_stat() { -#if TD_DARWIN - task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - - if (KERN_SUCCESS != - task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast(&t_info), &t_info_count)) { - return Status::Error("task_info failed"); - } - MemStat res; - res.resident_size_ = t_info.resident_size; - res.virtual_size_ = t_info.virtual_size; - res.resident_size_peak_ = 0; - res.virtual_size_peak_ = 0; - return res; -#elif TD_LINUX || TD_ANDROID || TD_TIZEN - TRY_RESULT(fd, FileFd::open("/proc/self/status", FileFd::Read)); - SCOPE_EXIT { - fd.close(); - }; - - constexpr int TMEM_SIZE = 10000; - char mem[TMEM_SIZE]; - TRY_RESULT(size, fd.read(MutableSlice(mem, TMEM_SIZE - 1))); - CHECK(size < TMEM_SIZE - 1); - mem[size] = 0; - - const char *s = mem; - MemStat res; - while (*s) { - const char *name_begin = s; - while (*s != 0 && *s != '\n') { - s++; - } - auto name_end = name_begin; - while (is_alpha(*name_end)) { - name_end++; - } - Slice name(name_begin, name_end); - - uint64 *x = nullptr; - if (name == "VmPeak") { - x = &res.virtual_size_peak_; - } - if (name == "VmSize") { - x = &res.virtual_size_; - } - if (name == "VmHWM") { - x = &res.resident_size_peak_; - } - if (name == "VmRSS") { - x = &res.resident_size_; - } - if (x != nullptr) { - Slice value(name_end, s); - if (!value.empty() && value[0] == ':') { - value.remove_prefix(1); - } - value = trim(value); - value = split(value).first; - auto r_mem = to_integer_safe(value); - if (r_mem.is_error()) { - LOG(ERROR) << "Failed to parse memory stats " << tag("name", name) << tag("value", value); - *x = static_cast(-1); - } else { - *x = r_mem.ok() * 1024; // memory is in kB - } - } - if (*s == 0) { - break; - } - s++; - } - - return res; -#else - return Status::Error("Not supported"); -#endif -} - -#if TD_LINUX -Status cpu_stat_self(CpuStat &stat) { - TRY_RESULT(fd, FileFd::open("/proc/self/stat", FileFd::Read)); - SCOPE_EXIT { - fd.close(); - }; - - constexpr int TMEM_SIZE = 10000; - char mem[TMEM_SIZE]; - TRY_RESULT(size, fd.read(MutableSlice(mem, TMEM_SIZE - 1))); - CHECK(size < TMEM_SIZE - 1); - mem[size] = 0; - - char *s = mem; - char *t = mem + size; - int pass_cnt = 0; - - while (pass_cnt < 15) { - if (pass_cnt == 13) { - stat.process_user_ticks = to_integer(Slice(s, t)); - } - if (pass_cnt == 14) { - stat.process_system_ticks = to_integer(Slice(s, t)); - } - while (*s && *s != ' ') { - s++; - } - if (*s == ' ') { - s++; - pass_cnt++; - } else { - return Status::Error("unexpected end of proc file"); - } - } - return Status::OK(); -} -Status cpu_stat_total(CpuStat &stat) { - TRY_RESULT(fd, FileFd::open("/proc/stat", FileFd::Read)); - SCOPE_EXIT { - fd.close(); - }; - - constexpr int TMEM_SIZE = 10000; - char mem[TMEM_SIZE]; - TRY_RESULT(size, fd.read(MutableSlice(mem, TMEM_SIZE - 1))); - CHECK(size < TMEM_SIZE - 1); - mem[size] = 0; - - uint64 sum = 0, cur = 0; - for (size_t i = 0; i < size; i++) { - int c = mem[i]; - if (c >= '0' && c <= '9') { - cur = cur * 10 + (uint64)c - '0'; - } else { - sum += cur; - cur = 0; - if (c == '\n') { - break; - } - } - } - - stat.total_ticks = sum; - return Status::OK(); -} -#endif - -Result cpu_stat() { -#if TD_LINUX - CpuStat stat; - TRY_STATUS(cpu_stat_self(stat)); - TRY_STATUS(cpu_stat_total(stat)); - return stat; -#else - return Status::Error("Not supported"); -#endif -} -} // namespace td -#endif - -#if TD_PORT_WINDOWS -namespace td { - -Result stat(CSlice path) { - TRY_RESULT(fd, FileFd::open(path, FileFd::Flags::Read | FileFd::PrivateFlags::WinStat)); - return fd.stat(); -} - -Result cpu_stat() { - return Status::Error("Not supported"); -} - -} // namespace td -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.h deleted file mode 100644 index b3e6a74e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/Stat.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -struct Stat { - bool is_dir_; - bool is_reg_; - int64 size_; - uint64 atime_nsec_; - uint64 mtime_nsec_; -}; - -Result stat(CSlice path) TD_WARN_UNUSED_RESULT; - -struct CpuStat { - uint64 total_ticks{0}; - uint64 process_user_ticks{0}; - uint64 process_system_ticks{0}; -}; -Result cpu_stat() TD_WARN_UNUSED_RESULT; - -#if TD_PORT_POSIX - -namespace detail { -Result fstat(int native_fd); -} // namespace detail - -Status update_atime(CSlice path) TD_WARN_UNUSED_RESULT; - -struct MemStat { - uint64 resident_size_ = 0; - uint64 resident_size_peak_ = 0; - uint64 virtual_size_ = 0; - uint64 virtual_size_peak_ = 0; -}; - -Result mem_stat() TD_WARN_UNUSED_RESULT; - -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.cpp deleted file mode 100644 index fd360514..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/StdStreams.h" - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/detail/Iocp.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/port/thread.h" -#include "td/utils/Slice.h" - -#include -#include - -namespace td { - -#if TD_PORT_POSIX -template -static FileFd &get_file_fd() { - static FileFd result = FileFd::from_native_fd(NativeFd(id, true)); - static auto guard = td::ScopeExit() + [&] { result.move_as_native_fd().release(); }; - assert(!result.empty()); - return result; -} - -FileFd &Stdin() { - return get_file_fd<0>(); -} -FileFd &Stdout() { - return get_file_fd<1>(); -} -FileFd &Stderr() { - return get_file_fd<2>(); -} -#elif TD_PORT_WINDOWS -template -static FileFd &get_file_fd() { -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - static auto handle = GetStdHandle(id); - LOG_IF(FATAL, handle == INVALID_HANDLE_VALUE) << "Failed to GetStdHandle " << id; - static FileFd result = FileFd::from_native_fd(NativeFd(handle, true)); - static auto guard = td::ScopeExit() + [&] { result.move_as_native_fd().release(); }; -#else - static FileFd result; -#endif - return result; -} - -FileFd &Stdin() { - return get_file_fd(); -} -FileFd &Stdout() { - return get_file_fd(); -} -FileFd &Stderr() { - return get_file_fd(); -} -#endif - -#if TD_PORT_WINDOWS -namespace detail { -class BufferedStdinImpl : public Iocp::Callback { - public: -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - BufferedStdinImpl() : info_(NativeFd(GetStdHandle(STD_INPUT_HANDLE), true)) { - iocp_ref_ = Iocp::get()->get_ref(); - read_thread_ = td::thread([this] { this->read_loop(); }); - } -#else - BufferedStdinImpl() { - close(); - } -#endif - BufferedStdinImpl(const BufferedStdinImpl &) = delete; - BufferedStdinImpl &operator=(const BufferedStdinImpl &) = delete; - BufferedStdinImpl(BufferedStdinImpl &&) = delete; - BufferedStdinImpl &operator=(BufferedStdinImpl &&) = delete; - ~BufferedStdinImpl() { - info_.move_as_native_fd().release(); - } - void close() { - close_flag_ = true; - } - - ChainBufferReader &input_buffer() { - return reader_; - } - - PollableFdInfo &get_poll_info() { - return info_; - } - const PollableFdInfo &get_poll_info() const { - return info_; - } - - Result flush_read(size_t max_read = std::numeric_limits::max()) TD_WARN_UNUSED_RESULT { - info_.get_flags(); - info_.clear_flags(PollFlags::Read()); - reader_.sync_with_writer(); - return reader_.size(); - } - - private: - PollableFdInfo info_; - ChainBufferWriter writer_; - ChainBufferReader reader_ = writer_.extract_reader(); - td::thread read_thread_; - std::atomic close_flag_{false}; - IocpRef iocp_ref_; - std::atomic refcnt_{1}; - - void read_loop() { - while (!close_flag_) { - auto slice = writer_.prepare_append(); - auto r_size = read(slice); - if (r_size.is_error()) { - LOG(ERROR) << "Stop read stdin loop: " << r_size.error(); - break; - } - writer_.confirm_append(r_size.ok()); - if (iocp_ref_.post(0, this, nullptr)) { - inc_refcnt(); - } - } - if (!iocp_ref_.post(0, this, nullptr)) { - dec_refcnt(); - } - } - void on_iocp(Result r_size, WSAOVERLAPPED *overlapped) override { - info_.add_flags_from_poll(td::PollFlags::Read()); - dec_refcnt(); - } - - bool dec_refcnt() { - if (--refcnt_ == 0) { - delete this; - return true; - } - return false; - } - void inc_refcnt() { - CHECK(refcnt_ != 0); - refcnt_++; - } - - Result read(MutableSlice slice) { - auto native_fd = info_.native_fd().fd(); - DWORD bytes_read = 0; - auto res = ReadFile(native_fd, slice.data(), narrow_cast(slice.size()), &bytes_read, nullptr); - if (res) { - return static_cast(bytes_read); - } - return OS_ERROR(PSLICE() << "Read from " << info_.native_fd() << " has failed"); - } -}; -void BufferedStdinImplDeleter::operator()(BufferedStdinImpl *impl) { - // LOG(ERROR) << "Close"; - impl->close(); -} -} // namespace detail -#elif TD_PORT_POSIX -namespace detail { -class BufferedStdinImpl { - public: - BufferedStdinImpl() { - file_fd_ = FileFd::from_native_fd(NativeFd(Stdin().get_native_fd().fd())); - file_fd_.get_native_fd().set_is_blocking(false); - } - BufferedStdinImpl(const BufferedStdinImpl &) = delete; - BufferedStdinImpl &operator=(const BufferedStdinImpl &) = delete; - BufferedStdinImpl(BufferedStdinImpl &&) = delete; - BufferedStdinImpl &operator=(BufferedStdinImpl &&) = delete; - ~BufferedStdinImpl() { - file_fd_.get_native_fd().set_is_blocking(true); - file_fd_.move_as_native_fd().release(); - } - - ChainBufferReader &input_buffer() { - return reader_; - } - - PollableFdInfo &get_poll_info() { - return file_fd_.get_poll_info(); - } - const PollableFdInfo &get_poll_info() const { - return file_fd_.get_poll_info(); - } - - Result flush_read(size_t max_read = std::numeric_limits::max()) TD_WARN_UNUSED_RESULT { - size_t result = 0; - while (::td::can_read(*this) && max_read) { - MutableSlice slice = writer_.prepare_append().truncate(max_read); - TRY_RESULT(x, file_fd_.read(slice)); - slice.truncate(x); - writer_.confirm_append(x); - result += x; - max_read -= x; - } - if (result) { - reader_.sync_with_writer(); - } - return result; - } - - private: - FileFd file_fd_; - ChainBufferWriter writer_; - ChainBufferReader reader_ = writer_.extract_reader(); -}; -void BufferedStdinImplDeleter::operator()(BufferedStdinImpl *impl) { - delete impl; -} -} // namespace detail -#endif - -BufferedStdin::BufferedStdin() : impl_(make_unique().release()) { -} -BufferedStdin::BufferedStdin(BufferedStdin &&) = default; -BufferedStdin &BufferedStdin::operator=(BufferedStdin &&) = default; -BufferedStdin::~BufferedStdin() = default; - -ChainBufferReader &BufferedStdin::input_buffer() { - return impl_->input_buffer(); -} -PollableFdInfo &BufferedStdin::get_poll_info() { - return impl_->get_poll_info(); -} -const PollableFdInfo &BufferedStdin::get_poll_info() const { - return impl_->get_poll_info(); -} -Result BufferedStdin::flush_read(size_t max_read) { - return impl_->flush_read(max_read); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.h deleted file mode 100644 index 68e48b0f..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/StdStreams.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Status.h" - -#include -#include - -namespace td { - -FileFd &Stdin(); -FileFd &Stdout(); -FileFd &Stderr(); - -namespace detail { -class BufferedStdinImpl; -class BufferedStdinImplDeleter { - public: - void operator()(BufferedStdinImpl *impl); -}; -} // namespace detail - -class BufferedStdin { - public: - BufferedStdin(); - BufferedStdin(const BufferedStdin &) = delete; - BufferedStdin &operator=(const BufferedStdin &) = delete; - BufferedStdin(BufferedStdin &&); - BufferedStdin &operator=(BufferedStdin &&); - ~BufferedStdin(); - ChainBufferReader &input_buffer(); - PollableFdInfo &get_poll_info(); - const PollableFdInfo &get_poll_info() const; - Result flush_read(size_t max_read = std::numeric_limits::max()) TD_WARN_UNUSED_RESULT; - - private: - std::unique_ptr impl_; -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.cpp deleted file mode 100644 index 0d7c6f94..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.cpp +++ /dev/null @@ -1,873 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/UdpSocketFd.h" - -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/VectorQueue.h" - -#if TD_PORT_WINDOWS -#include "td/utils/port/detail/Iocp.h" -#include "td/utils/SpinLock.h" -#endif - -#if TD_PORT_POSIX -#include -#include -#include -#include -#include -#include -#include - -#if TD_LINUX -#include -#endif -#endif // TD_PORT_POSIX - -#include -#include -#include - -namespace td { -namespace detail { -#if TD_PORT_WINDOWS -class UdpSocketReceiveHelper { - public: - void to_native(const UdpMessage &message, WSAMSG &message_header) { - socklen_t addr_len{narrow_cast(sizeof(addr_))}; - message_header.name = reinterpret_cast(&addr_); - message_header.namelen = addr_len; - buf_.buf = const_cast(message.data.as_slice().begin()); - buf_.len = narrow_cast(message.data.size()); - message_header.lpBuffers = &buf_; - message_header.dwBufferCount = 1; - message_header.Control.buf = nullptr; // control_buf_.data(); - message_header.Control.len = 0; // narrow_cast(control_buf_.size()); - message_header.dwFlags = 0; - } - - void from_native(WSAMSG &message_header, size_t message_size, UdpMessage &message) { - message.address.init_sockaddr(reinterpret_cast(message_header.name), message_header.namelen) - .ignore(); - message.error = Status::OK(); - - if ((message_header.dwFlags & (MSG_TRUNC | MSG_CTRUNC)) != 0) { - message.error = Status::Error(501, "message too long"); - message.data = BufferSlice(); - return; - } - - CHECK(message_size <= message.data.size()); - message.data.truncate(message_size); - CHECK(message_size == message.data.size()); - } - - private: - std::array control_buf_; - sockaddr_storage addr_; - WSABUF buf_; -}; -class UdpSocketSendHelper { - public: - void to_native(const UdpMessage &message, WSAMSG &message_header) { - message_header.name = const_cast(message.address.get_sockaddr()); - message_header.namelen = narrow_cast(message.address.get_sockaddr_len()); - buf_.buf = const_cast(message.data.as_slice().begin()); - buf_.len = narrow_cast(message.data.size()); - message_header.lpBuffers = &buf_; - message_header.dwBufferCount = 1; - - message_header.Control.buf = nullptr; - message_header.Control.len = 0; - message_header.dwFlags = 0; - } - - private: - WSABUF buf_; -}; - -class UdpSocketFdImpl : private Iocp::Callback { - public: - explicit UdpSocketFdImpl(NativeFd fd) : info_(std::move(fd)) { - get_poll_info().add_flags(PollFlags::Write()); - Iocp::get()->subscribe(get_native_fd(), this); - is_receive_active_ = true; - notify_iocp_connected(); - } - PollableFdInfo &get_poll_info() { - return info_; - } - const PollableFdInfo &get_poll_info() const { - return info_; - } - - const NativeFd &get_native_fd() const { - return info_.native_fd(); - } - - void close() { - notify_iocp_close(); - } - - Result> receive() { - auto lock = lock_.lock(); - if (!pending_errors_.empty()) { - auto status = pending_errors_.pop(); - if (!UdpSocketFd::is_critical_read_error(status)) { - return UdpMessage{{}, {}, std::move(status)}; - } - return std::move(status); - } - if (!receive_queue_.empty()) { - return receive_queue_.pop(); - } - - return optional{}; - } - - void send(UdpMessage message) { - auto lock = lock_.lock(); - send_queue_.push(std::move(message)); - } - - Status flush_send() { - if (is_send_waiting_) { - auto lock = lock_.lock(); - is_send_waiting_ = false; - notify_iocp_send(); - } - return Status::OK(); - } - - private: - PollableFdInfo info_; - SpinLock lock_; - - std::atomic refcnt_{1}; - bool is_connected_{false}; - bool close_flag_{false}; - - bool is_send_active_{false}; - bool is_send_waiting_{false}; - VectorQueue send_queue_; - WSAOVERLAPPED send_overlapped_; - - bool is_receive_active_{false}; - VectorQueue receive_queue_; - VectorQueue pending_errors_; - UdpMessage to_receive_; - WSAMSG receive_message_; - UdpSocketReceiveHelper receive_helper_; - enum : size_t { MAX_PACKET_SIZE = 2048, RESERVED_SIZE = MAX_PACKET_SIZE * 8 }; - BufferSlice receive_buffer_; - - UdpMessage to_send_; - WSAOVERLAPPED receive_overlapped_; - - char close_overlapped_; - - bool check_status(Slice message) { - auto last_error = WSAGetLastError(); - if (last_error == ERROR_IO_PENDING) { - return true; - } - on_error(OS_SOCKET_ERROR(message)); - return false; - } - - void loop_receive() { - CHECK(!is_receive_active_); - if (close_flag_) { - return; - } - std::memset(&receive_overlapped_, 0, sizeof(receive_overlapped_)); - if (receive_buffer_.size() < MAX_PACKET_SIZE) { - receive_buffer_ = BufferSlice(RESERVED_SIZE); - } - to_receive_.data = receive_buffer_.clone(); - receive_helper_.to_native(to_receive_, receive_message_); - - LPFN_WSARECVMSG WSARecvMsgPtr = nullptr; - GUID guid = WSAID_WSARECVMSG; - DWORD numBytes; - auto error = ::WSAIoctl(get_native_fd().socket(), SIO_GET_EXTENSION_FUNCTION_POINTER, static_cast(&guid), - sizeof(guid), static_cast(&WSARecvMsgPtr), sizeof(WSARecvMsgPtr), &numBytes, - nullptr, nullptr); - if (error) { - on_error(OS_SOCKET_ERROR("WSAIoctl failed")); - return; - } - - auto status = WSARecvMsgPtr(get_native_fd().socket(), &receive_message_, nullptr, &receive_overlapped_, nullptr); - if (status == 0 || check_status("WSARecvMsg failed")) { - inc_refcnt(); - is_receive_active_ = true; - } - } - - void loop_send() { - CHECK(!is_send_active_); - - { - auto lock = lock_.lock(); - if (send_queue_.empty()) { - is_send_waiting_ = true; - return; - } - to_send_ = send_queue_.pop(); - } - std::memset(&send_overlapped_, 0, sizeof(send_overlapped_)); - WSAMSG message; - UdpSocketSendHelper send_helper; - send_helper.to_native(to_send_, message); - auto status = WSASendMsg(get_native_fd().socket(), &message, 0, nullptr, &send_overlapped_, nullptr); - if (status == 0 || check_status("WSASendMsg failed")) { - inc_refcnt(); - is_send_active_ = true; - } - } - - void on_iocp(Result r_size, WSAOVERLAPPED *overlapped) override { - // called from other thread - if (dec_refcnt() || close_flag_) { - VLOG(fd) << "Ignore IOCP (UDP socket is closing)"; - return; - } - if (r_size.is_error()) { - return on_error(get_socket_pending_error(get_native_fd(), overlapped, r_size.move_as_error())); - } - - if (!is_connected_ && overlapped == &receive_overlapped_) { - return on_connected(); - } - - auto size = r_size.move_as_ok(); - if (overlapped == &send_overlapped_) { - return on_send(size); - } - if (overlapped == nullptr) { - CHECK(size == 0); - return on_send(size); - } - - if (overlapped == &receive_overlapped_) { - return on_receive(size); - } - if (overlapped == reinterpret_cast(&close_overlapped_)) { - return on_close(); - } - UNREACHABLE(); - } - - void on_error(Status status) { - VLOG(fd) << get_native_fd() << " on error " << status; - { - auto lock = lock_.lock(); - pending_errors_.push(std::move(status)); - } - get_poll_info().add_flags_from_poll(PollFlags::Error()); - } - - void on_connected() { - VLOG(fd) << get_native_fd() << " on connected"; - CHECK(!is_connected_); - CHECK(is_receive_active_); - is_connected_ = true; - is_receive_active_ = false; - loop_receive(); - loop_send(); - } - - void on_receive(size_t size) { - VLOG(fd) << get_native_fd() << " on receive " << size; - CHECK(is_receive_active_); - is_receive_active_ = false; - receive_helper_.from_native(receive_message_, size, to_receive_); - receive_buffer_.confirm_read((to_receive_.data.size() + 7) & ~7); - { - auto lock = lock_.lock(); - // LOG(ERROR) << format::escaped(to_receive_.data.as_slice()); - receive_queue_.push(std::move(to_receive_)); - } - get_poll_info().add_flags_from_poll(PollFlags::Read()); - loop_receive(); - } - - void on_send(size_t size) { - VLOG(fd) << get_native_fd() << " on send " << size; - if (size == 0) { - if (is_send_active_) { - return; - } - is_send_active_ = true; - } - CHECK(is_send_active_); - is_send_active_ = false; - loop_send(); - } - - void on_close() { - VLOG(fd) << get_native_fd() << " on close"; - close_flag_ = true; - info_.set_native_fd({}); - } - - bool dec_refcnt() { - if (--refcnt_ == 0) { - delete this; - return true; - } - return false; - } - - void inc_refcnt() { - CHECK(refcnt_ != 0); - refcnt_++; - } - - void notify_iocp_send() { - inc_refcnt(); - Iocp::get()->post(0, this, nullptr); - } - void notify_iocp_close() { - Iocp::get()->post(0, this, reinterpret_cast(&close_overlapped_)); - } - void notify_iocp_connected() { - inc_refcnt(); - Iocp::get()->post(0, this, reinterpret_cast(&receive_overlapped_)); - } -}; - -void UdpSocketFdImplDeleter::operator()(UdpSocketFdImpl *impl) { - impl->close(); -} - -#elif TD_PORT_POSIX -//struct iovec { [> Scatter/gather array items <] -// void *iov_base; [> Starting address <] -// size_t iov_len; [> Number of bytes to transfer <] -//}; - -//struct msghdr { -// void *msg_name; [> optional address <] -// socklen_t msg_namelen; [> size of address <] -// struct iovec *msg_iov; [> scatter/gather array <] -// size_t msg_iovlen; [> # elements in msg_iov <] -// void *msg_control; [> ancillary data, see below <] -// size_t msg_controllen; [> ancillary data buffer len <] -// int msg_flags; [> flags on received message <] -//}; - -class UdpSocketReceiveHelper { - public: - void to_native(const UdpSocketFd::InboundMessage &message, struct msghdr &message_header) { - socklen_t addr_len{narrow_cast(sizeof(addr_))}; - - message_header.msg_name = &addr_; - message_header.msg_namelen = addr_len; - io_vec_.iov_base = message.data.begin(); - io_vec_.iov_len = message.data.size(); - message_header.msg_iov = &io_vec_; - message_header.msg_iovlen = 1; - message_header.msg_control = control_buf_.data(); - message_header.msg_controllen = narrow_cast(control_buf_.size()); - message_header.msg_flags = 0; - } - - void from_native(struct msghdr &message_header, size_t message_size, UdpSocketFd::InboundMessage &message) { -#if TD_LINUX - struct cmsghdr *cmsg; - struct sock_extended_err *ee = nullptr; - for (cmsg = CMSG_FIRSTHDR(&message_header); cmsg != nullptr; cmsg = CMSG_NXTHDR(&message_header, cmsg)) { - if (cmsg->cmsg_type == IP_PKTINFO && cmsg->cmsg_level == IPPROTO_IP) { - //auto *pi = reinterpret_cast(CMSG_DATA(cmsg)); - } else if (cmsg->cmsg_type == IPV6_PKTINFO && cmsg->cmsg_level == IPPROTO_IPV6) { - //auto *pi = reinterpret_cast(CMSG_DATA(cmsg)); - } else if ((cmsg->cmsg_type == IP_RECVERR && cmsg->cmsg_level == IPPROTO_IP) || - (cmsg->cmsg_type == IPV6_RECVERR && cmsg->cmsg_level == IPPROTO_IPV6)) { - ee = reinterpret_cast(CMSG_DATA(cmsg)); - } - } - if (ee != nullptr) { - auto *addr = reinterpret_cast(SO_EE_OFFENDER(ee)); - IPAddress address; - address.init_sockaddr(addr).ignore(); - if (message.from != nullptr) { - *message.from = address; - } - if (message.error) { - *message.error = Status::PosixError(ee->ee_errno, ""); - } - //message.data = MutableSlice(); - message.data.truncate(0); - return; - } -#endif - if (message.from != nullptr) { - message.from - ->init_sockaddr(reinterpret_cast(message_header.msg_name), message_header.msg_namelen) - .ignore(); - } - if (message.error) { - *message.error = Status::OK(); - } - if (message_header.msg_flags & MSG_TRUNC) { - if (message.error) { - *message.error = Status::Error(501, "message too long"); - } - message.data.truncate(0); - return; - } - CHECK(message_size <= message.data.size()); - message.data.truncate(message_size); - CHECK(message_size == message.data.size()); - } - - private: - std::array control_buf_; - sockaddr_storage addr_; - struct iovec io_vec_; -}; - -class UdpSocketSendHelper { - public: - void to_native(const UdpSocketFd::OutboundMessage &message, struct msghdr &message_header) { - CHECK(message.to != nullptr && message.to->is_valid()); - message_header.msg_name = const_cast(message.to->get_sockaddr()); - message_header.msg_namelen = narrow_cast(message.to->get_sockaddr_len()); - io_vec_.iov_base = const_cast(message.data.begin()); - io_vec_.iov_len = message.data.size(); - message_header.msg_iov = &io_vec_; - message_header.msg_iovlen = 1; - //TODO - message_header.msg_control = nullptr; - message_header.msg_controllen = 0; - message_header.msg_flags = 0; - } - - private: - struct iovec io_vec_; -}; - -class UdpSocketFdImpl { - public: - explicit UdpSocketFdImpl(NativeFd fd) : info_(std::move(fd)) { - } - PollableFdInfo &get_poll_info() { - return info_; - } - const PollableFdInfo &get_poll_info() const { - return info_; - } - - const NativeFd &get_native_fd() const { - return info_.native_fd(); - } - Status get_pending_error() { - if (!get_poll_info().get_flags().has_pending_error()) { - return Status::OK(); - } - TRY_STATUS(detail::get_socket_pending_error(get_native_fd())); - get_poll_info().clear_flags(PollFlags::Error()); - return Status::OK(); - } - Status receive_message(UdpSocketFd::InboundMessage &message, bool &is_received) { - is_received = false; - int flags = 0; - if (get_poll_info().get_flags().has_pending_error()) { -#ifdef MSG_ERRQUEUE - flags = MSG_ERRQUEUE; -#else - return get_pending_error(); -#endif - } - - struct msghdr message_header; - detail::UdpSocketReceiveHelper helper; - helper.to_native(message, message_header); - - auto native_fd = get_native_fd().socket(); - auto recvmsg_res = detail::skip_eintr([&] { return recvmsg(native_fd, &message_header, flags); }); - auto recvmsg_errno = errno; - if (recvmsg_res >= 0) { - helper.from_native(message_header, recvmsg_res, message); - is_received = true; - return Status::OK(); - } - return process_recvmsg_error(recvmsg_errno, is_received); - } - - Status process_recvmsg_error(int recvmsg_errno, bool &is_received) { - is_received = false; - if (recvmsg_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || recvmsg_errno == EWOULDBLOCK -#endif - ) { - if (get_poll_info().get_flags_local().has_pending_error()) { - get_poll_info().clear_flags(PollFlags::Error()); - } else { - get_poll_info().clear_flags(PollFlags::Read()); - } - return Status::OK(); - } - - auto error = Status::PosixError(recvmsg_errno, PSLICE() << "Receive from " << get_native_fd() << " has failed"); - switch (recvmsg_errno) { - case EBADF: - case EFAULT: - case EINVAL: - case ENOTCONN: - case ECONNRESET: - case ETIMEDOUT: - LOG(FATAL) << error; - UNREACHABLE(); - default: - LOG(WARNING) << "Unknown error: " << error; - // fallthrough - case ENOBUFS: - case ENOMEM: -#ifdef MSG_ERRQUEUE - get_poll_info().add_flags(PollFlags::Error()); -#endif - return error; - } - } - - Status send_message(const UdpSocketFd::OutboundMessage &message, bool &is_sent) { - is_sent = false; - struct msghdr message_header; - detail::UdpSocketSendHelper helper; - helper.to_native(message, message_header); - - auto native_fd = get_native_fd().socket(); - auto sendmsg_res = detail::skip_eintr([&] { return sendmsg(native_fd, &message_header, 0); }); - auto sendmsg_errno = errno; - if (sendmsg_res >= 0) { - is_sent = true; - return Status::OK(); - } - return process_sendmsg_error(sendmsg_errno, is_sent); - } - Status process_sendmsg_error(int sendmsg_errno, bool &is_sent) { - if (sendmsg_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || sendmsg_errno == EWOULDBLOCK -#endif - ) { - get_poll_info().clear_flags(PollFlags::Write()); - return Status::OK(); - } - - auto error = Status::PosixError(sendmsg_errno, PSLICE() << "Send from " << get_native_fd() << " has failed"); - switch (sendmsg_errno) { - // Still may send some other packets, but there is no point to resend this particular message - case EACCES: - case EMSGSIZE: - case EPERM: - LOG(WARNING) << "Silently drop packet :( " << error; - //TODO: get errors from MSG_ERRQUEUE is possible - is_sent = true; - return error; - - // Some general problems, which may be fixed in future - case ENOMEM: - case EDQUOT: - case EFBIG: - case ENETDOWN: - case ENETUNREACH: - case ENOSPC: - case EHOSTUNREACH: - case ENOBUFS: - default: -#ifdef MSG_ERRQUEUE - get_poll_info().add_flags(PollFlags::Error()); -#endif - return error; - - case EBADF: // impossible - case ENOTSOCK: // impossible - case EPIPE: // impossible for udp - case ECONNRESET: // impossible for udp - case EDESTADDRREQ: // we checked that address is valid - case ENOTCONN: // we checked that address is valid - case EINTR: // we already skipped all EINTR - case EISCONN: // impossible for udp socket - case EOPNOTSUPP: - case ENOTDIR: - case EFAULT: - case EINVAL: - case EAFNOSUPPORT: - LOG(FATAL) << error; - UNREACHABLE(); - return error; - } - } - - Status send_messages(Span messages, size_t &cnt) { -#if TD_HAS_MMSG - return send_messages_fast(messages, cnt); -#else - return send_messages_slow(messages, cnt); -#endif - } - - Status receive_messages(MutableSpan messages, size_t &cnt) { -#if TD_HAS_MMSG - return receive_messages_fast(messages, cnt); -#else - return receive_messages_slow(messages, cnt); -#endif - } - - private: - PollableFdInfo info_; - - Status send_messages_slow(Span messages, size_t &cnt) { - cnt = 0; - for (auto &message : messages) { - CHECK(!message.data.empty()); - bool is_sent; - auto error = send_message(message, is_sent); - cnt += is_sent; - TRY_STATUS(std::move(error)); - } - return Status::OK(); - } - -#if TD_HAS_MMSG - Status send_messages_fast(Span messages, size_t &cnt) { - //struct mmsghdr { - // struct msghdr msg_hdr; [> Message header <] - // unsigned int msg_len; [> Number of bytes transmitted <] - //}; - struct std::array helpers; - struct std::array headers; - size_t to_send = min(messages.size(), headers.size()); - for (size_t i = 0; i < to_send; i++) { - helpers[i].to_native(messages[i], headers[i].msg_hdr); - headers[i].msg_len = 0; - } - - auto native_fd = get_native_fd().socket(); - auto sendmmsg_res = - detail::skip_eintr([&] { return sendmmsg(native_fd, headers.data(), narrow_cast(to_send), 0); }); - auto sendmmsg_errno = errno; - if (sendmmsg_res >= 0) { - cnt = sendmmsg_res; - return Status::OK(); - } - - bool is_sent = false; - auto status = process_sendmsg_error(sendmmsg_errno, is_sent); - cnt = is_sent; - return status; - } -#endif - Status receive_messages_slow(MutableSpan messages, size_t &cnt) { - cnt = 0; - while (cnt < messages.size() && get_poll_info().get_flags().can_read()) { - auto &message = messages[cnt]; - CHECK(!message.data.empty()); - bool is_received; - auto error = receive_message(message, is_received); - cnt += is_received; - TRY_STATUS(std::move(error)); - } - return Status::OK(); - } - -#if TD_HAS_MMSG - Status receive_messages_fast(MutableSpan messages, size_t &cnt) { - int flags = 0; - cnt = 0; - if (get_poll_info().get_flags().has_pending_error()) { -#ifdef MSG_ERRQUEUE - flags = MSG_ERRQUEUE; -#else - return get_pending_error(); -#endif - } - //struct mmsghdr { - // struct msghdr msg_hdr; [> Message header <] - // unsigned int msg_len; [> Number of bytes transmitted <] - //}; - struct std::array helpers; - struct std::array headers; - size_t to_receive = min(messages.size(), headers.size()); - for (size_t i = 0; i < to_receive; i++) { - helpers[i].to_native(messages[i], headers[i].msg_hdr); - headers[i].msg_len = 0; - } - - auto native_fd = get_native_fd().socket(); - auto recvmmsg_res = detail::skip_eintr( - [&] { return recvmmsg(native_fd, headers.data(), narrow_cast(to_receive), flags, nullptr); }); - auto recvmmsg_errno = errno; - if (recvmmsg_res >= 0) { - cnt = narrow_cast(recvmmsg_res); - for (size_t i = 0; i < cnt; i++) { - helpers[i].from_native(headers[i].msg_hdr, headers[i].msg_len, messages[i]); - } - return Status::OK(); - } - - bool is_received; - auto status = process_recvmsg_error(recvmmsg_errno, is_received); - cnt = is_received; - return status; - } -#endif -}; -void UdpSocketFdImplDeleter::operator()(UdpSocketFdImpl *impl) { - delete impl; -} -#endif -} // namespace detail - -UdpSocketFd::UdpSocketFd() = default; -UdpSocketFd::UdpSocketFd(UdpSocketFd &&) = default; -UdpSocketFd &UdpSocketFd::operator=(UdpSocketFd &&) = default; -UdpSocketFd::~UdpSocketFd() = default; -PollableFdInfo &UdpSocketFd::get_poll_info() { - return impl_->get_poll_info(); -} -const PollableFdInfo &UdpSocketFd::get_poll_info() const { - return impl_->get_poll_info(); -} - -Result UdpSocketFd::open(const IPAddress &address) { - NativeFd native_fd{socket(address.get_address_family(), SOCK_DGRAM, IPPROTO_UDP)}; - if (!native_fd) { - return OS_SOCKET_ERROR("Failed to create a socket"); - } - TRY_STATUS(native_fd.set_is_blocking_unsafe(false)); - - auto sock = native_fd.socket(); -#if TD_PORT_POSIX - int flags = 1; -#elif TD_PORT_WINDOWS - BOOL flags = TRUE; -#endif - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&flags), sizeof(flags)); - // TODO: SO_REUSEADDR, SO_KEEPALIVE, TCP_NODELAY, SO_SNDBUF, SO_RCVBUF, TCP_QUICKACK, SO_LINGER - - auto bind_addr = address.get_any_addr(); - bind_addr.set_port(address.get_port()); - auto e_bind = bind(sock, bind_addr.get_sockaddr(), narrow_cast(bind_addr.get_sockaddr_len())); - if (e_bind != 0) { - return OS_SOCKET_ERROR("Failed to bind a socket"); - } - return UdpSocketFd(make_unique(std::move(native_fd))); -} - -UdpSocketFd::UdpSocketFd(unique_ptr impl) : impl_(impl.release()) { -} - -void UdpSocketFd::close() { - impl_.reset(); -} - -bool UdpSocketFd::empty() const { - return !impl_; -} - -const NativeFd &UdpSocketFd::get_native_fd() const { - return get_poll_info().native_fd(); -} - -#if TD_PORT_POSIX -static Result maximize_buffer(int socket_fd, int optname, uint32 max) { - /* Start with the default size. */ - uint32 old_size; - socklen_t intsize = sizeof(old_size); - if (getsockopt(socket_fd, SOL_SOCKET, optname, &old_size, &intsize)) { - return OS_ERROR("getsockopt() failed"); - } - - /* Binary-search for the real maximum. */ - uint32 last_good = old_size; - uint32 min = old_size; - while (min <= max) { - uint32 avg = min + (max - min) / 2; - if (setsockopt(socket_fd, SOL_SOCKET, optname, &avg, intsize) == 0) { - last_good = avg; - min = avg + 1; - } else { - max = avg - 1; - } - } - return last_good; -} - -Result UdpSocketFd::maximize_snd_buffer(uint32 max) { - return maximize_buffer(get_native_fd().fd(), SO_SNDBUF, max == 0 ? default_udp_max_snd_buffer_size : max); -} - -Result UdpSocketFd::maximize_rcv_buffer(uint32 max) { - return maximize_buffer(get_native_fd().fd(), SO_RCVBUF, max == 0 ? default_udp_max_rcv_buffer_size : max); -} -#else -Result UdpSocketFd::maximize_snd_buffer(uint32 max) { - return 0; -} -Result UdpSocketFd::maximize_rcv_buffer(uint32 max) { - return 0; -} -#endif - -#if TD_PORT_POSIX -Status UdpSocketFd::send_message(const OutboundMessage &message, bool &is_sent) { - return impl_->send_message(message, is_sent); -} -Status UdpSocketFd::receive_message(InboundMessage &message, bool &is_received) { - return impl_->receive_message(message, is_received); -} - -Status UdpSocketFd::send_messages(Span messages, size_t &count) { - return impl_->send_messages(messages, count); -} -Status UdpSocketFd::receive_messages(MutableSpan messages, size_t &count) { - return impl_->receive_messages(messages, count); -} -#endif -#if TD_PORT_WINDOWS -Result> UdpSocketFd::receive() { - return impl_->receive(); -} - -void UdpSocketFd::send(UdpMessage message) { - return impl_->send(std::move(message)); -} - -Status UdpSocketFd::flush_send() { - return impl_->flush_send(); -} -#endif - -bool UdpSocketFd::is_critical_read_error(const Status &status) { - return status.code() == ENOMEM || status.code() == ENOBUFS; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.h deleted file mode 100644 index 840576f3..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/UdpSocketFd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/buffer.h" -#include "td/utils/optional.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/IPAddress.h" -#include "td/utils/Slice.h" -#include "td/utils/Span.h" -#include "td/utils/Status.h" - -#include - -namespace td { -// Udp and errors -namespace detail { -class UdpSocketFdImpl; -class UdpSocketFdImplDeleter { - public: - void operator()(UdpSocketFdImpl *impl); -}; -} // namespace detail - -struct UdpMessage { - IPAddress address; - BufferSlice data; - Status error; -}; - -class UdpSocketFd { - public: - UdpSocketFd(); - UdpSocketFd(UdpSocketFd &&); - UdpSocketFd &operator=(UdpSocketFd &&); - ~UdpSocketFd(); - - UdpSocketFd(const UdpSocketFd &) = delete; - UdpSocketFd &operator=(const UdpSocketFd &) = delete; - - Result maximize_snd_buffer(uint32 max_buffer_size = 0); - Result maximize_rcv_buffer(uint32 max_buffer_size = 0); - - static Result open(const IPAddress &address) TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info(); - const PollableFdInfo &get_poll_info() const; - const NativeFd &get_native_fd() const; - - void close(); - bool empty() const; - - static bool is_critical_read_error(const Status &status); - -#if TD_PORT_POSIX - struct OutboundMessage { - const IPAddress *to; - Slice data; - }; - struct InboundMessage { - IPAddress *from; - MutableSlice data; - Status *error; - }; - - Status send_message(const OutboundMessage &message, bool &is_sent) TD_WARN_UNUSED_RESULT; - Status receive_message(InboundMessage &message, bool &is_received) TD_WARN_UNUSED_RESULT; - - Status send_messages(Span messages, size_t &count) TD_WARN_UNUSED_RESULT; - Status receive_messages(MutableSpan messages, size_t &count) TD_WARN_UNUSED_RESULT; -#elif TD_PORT_WINDOWS - Result > receive(); - - void send(UdpMessage message); - - Status flush_send(); -#endif - - private: - static constexpr uint32 default_udp_max_snd_buffer_size = (1 << 24); - static constexpr uint32 default_udp_max_rcv_buffer_size = (1 << 24); - std::unique_ptr impl_; - explicit UdpSocketFd(unique_ptr impl); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/config.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/config.h deleted file mode 100644 index 2bd671b0..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/config.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/platform.h" - -// clang-format off - -#if TD_WINDOWS - #define TD_PORT_WINDOWS 1 -#else - #define TD_PORT_POSIX 1 -#endif - -#if TD_LINUX || TD_ANDROID || TD_TIZEN - #define TD_POLL_EPOLL 1 - #define TD_EVENTFD_LINUX 1 -#elif TD_FREEBSD || TD_OPENBSD || TD_NETBSD - #define TD_POLL_KQUEUE 1 - #define TD_EVENTFD_BSD 1 -#elif TD_CYGWIN - #define TD_POLL_SELECT 1 - #define TD_EVENTFD_BSD 1 -#elif TD_EMSCRIPTEN - #define TD_POLL_POLL 1 - #define TD_EVENTFD_UNSUPPORTED 1 -#elif TD_DARWIN - #define TD_POLL_KQUEUE 1 - #define TD_EVENTFD_BSD 1 -#elif TD_WINDOWS - #define TD_POLL_WINEVENT 1 - #define TD_EVENTFD_WINDOWS 1 -#else - #error "Poll's implementation is not defined" -#endif - -#if TD_EMSCRIPTEN - #define TD_THREAD_UNSUPPORTED 1 -#elif TD_TIZEN || TD_LINUX || TD_DARWIN - #define TD_THREAD_PTHREAD 1 -#else - #define TD_THREAD_STL 1 -#endif - -#if TD_LINUX - #define TD_HAS_MMSG 1 -#endif - -// clang-format on diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.cpp deleted file mode 100644 index ca89db4c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/Epoll.h" - -char disable_linker_warning_about_empty_file_epoll_cpp TD_UNUSED; - -#ifdef TD_POLL_EPOLL - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/Status.h" - -#include - -namespace td { -namespace detail { -void Epoll::init() { - CHECK(!epoll_fd_); - epoll_fd_ = NativeFd(epoll_create(1)); - auto epoll_create_errno = errno; - LOG_IF(FATAL, !epoll_fd_) << Status::PosixError(epoll_create_errno, "epoll_create failed"); - - events_.resize(1000); -} - -void Epoll::clear() { - if (!epoll_fd_) { - return; - } - events_.clear(); - - epoll_fd_.close(); - - for (auto *list_node = list_root_.next; list_node != &list_root_;) { - auto pollable_fd = PollableFd::from_list_node(list_node); - list_node = list_node->next; - } -} - -void Epoll::subscribe(PollableFd fd, PollFlags flags) { - epoll_event event; - event.events = EPOLLHUP | EPOLLERR | EPOLLET; -#ifdef EPOLLRDHUP - event.events |= EPOLLRDHUP; -#endif - if (flags.can_read()) { - event.events |= EPOLLIN; - } - if (flags.can_write()) { - event.events |= EPOLLOUT; - } - auto native_fd = fd.native_fd().fd(); - auto *list_node = fd.release_as_list_node(); - list_root_.put(list_node); - event.data.ptr = list_node; - - int err = epoll_ctl(epoll_fd_.fd(), EPOLL_CTL_ADD, native_fd, &event); - auto epoll_ctl_errno = errno; - LOG_IF(FATAL, err == -1) << Status::PosixError(epoll_ctl_errno, "epoll_ctl ADD failed") - << ", epoll_fd = " << epoll_fd_.fd() << ", fd = " << native_fd; -} - -void Epoll::unsubscribe(PollableFdRef fd_ref) { - auto fd = fd_ref.lock(); - auto native_fd = fd.native_fd().fd(); - int err = epoll_ctl(epoll_fd_.fd(), EPOLL_CTL_DEL, native_fd, nullptr); - auto epoll_ctl_errno = errno; - LOG_IF(FATAL, err == -1) << Status::PosixError(epoll_ctl_errno, "epoll_ctl DEL failed") - << ", epoll_fd = " << epoll_fd_.fd() << ", fd = " << native_fd << fd.native_fd().validate(); -} - -void Epoll::unsubscribe_before_close(PollableFdRef fd) { - unsubscribe(fd); -} - -void Epoll::run(int timeout_ms) { - int ready_n = epoll_wait(epoll_fd_.fd(), &events_[0], static_cast(events_.size()), timeout_ms); - auto epoll_wait_errno = errno; - LOG_IF(FATAL, ready_n == -1 && epoll_wait_errno != EINTR) - << Status::PosixError(epoll_wait_errno, "epoll_wait failed"); - - for (int i = 0; i < ready_n; i++) { - PollFlags flags; - epoll_event *event = &events_[i]; - if (event->events & EPOLLIN) { - event->events &= ~EPOLLIN; - flags = flags | PollFlags::Read(); - } - if (event->events & EPOLLOUT) { - event->events &= ~EPOLLOUT; - flags = flags | PollFlags::Write(); - } -#ifdef EPOLLRDHUP - if (event->events & EPOLLRDHUP) { - event->events &= ~EPOLLRDHUP; - flags = flags | PollFlags::Close(); - // flags |= Fd::Close; - // TODO - } -#endif - if (event->events & EPOLLHUP) { - event->events &= ~EPOLLHUP; - flags = flags | PollFlags::Close(); - } - if (event->events & EPOLLERR) { - event->events &= ~EPOLLERR; - flags = flags | PollFlags::Error(); - } - if (event->events) { - LOG(FATAL) << "Unsupported epoll events: " << event->events; - } - //LOG(DEBUG) << "Epoll event " << tag("fd", event->data.fd) << tag("flags", format::as_binary(flags)); - auto pollable_fd = PollableFd::from_list_node(static_cast(event->data.ptr)); - pollable_fd.add_flags(flags); - pollable_fd.release_as_list_node(); - } -} -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.h deleted file mode 100644 index a8e25e3a..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Epoll.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_POLL_EPOLL - -#include "td/utils/common.h" -#include "td/utils/List.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollBase.h" -#include "td/utils/port/PollFlags.h" - -#include - -namespace td { -namespace detail { - -class Epoll final : public PollBase { - public: - Epoll() = default; - Epoll(const Epoll &) = delete; - Epoll &operator=(const Epoll &) = delete; - Epoll(Epoll &&) = delete; - Epoll &operator=(Epoll &&) = delete; - ~Epoll() override = default; - - void init() override; - - void clear() override; - - void subscribe(PollableFd fd, PollFlags flags) override; - - void unsubscribe(PollableFdRef fd) override; - - void unsubscribe_before_close(PollableFdRef fd) override; - - void run(int timeout_ms) override; - - static bool is_edge_triggered() { - return true; - } - - private: - NativeFd epoll_fd_; - vector events_; - ListNode list_root_; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.cpp deleted file mode 100644 index 12bf4828..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/EventFdBsd.h" - -char disable_linker_warning_about_empty_file_event_fd_bsd_cpp TD_UNUSED; - -#ifdef TD_EVENTFD_BSD - -#include "td/utils/logging.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/Slice.h" - -#include -#include -#include -#include - -namespace td { -namespace detail { - -// TODO: it is extremely non optimal on Darwin. kqueue events should be used instead -void EventFdBsd::init() { - int fds[2]; - int err = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); - auto socketpair_errno = errno; -#if TD_CYGWIN - // it looks like CYGWIN bug - int max_retries = 1000000; - while (err == -1 && socketpair_errno == EADDRINUSE && max_retries-- > 0) { - err = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); - socketpair_errno = errno; - } -// LOG_IF(ERROR, max_retries < 1000000) << max_retries; -#endif - LOG_IF(FATAL, err == -1) << Status::PosixError(socketpair_errno, "socketpair failed"); - - auto fd_a = NativeFd(fds[0]); - auto fd_b = NativeFd(fds[1]); - fd_a.set_is_blocking_unsafe(false).ensure(); - fd_b.set_is_blocking_unsafe(false).ensure(); - - in_ = SocketFd::from_native_fd(std::move(fd_a)).move_as_ok(); - out_ = SocketFd::from_native_fd(std::move(fd_b)).move_as_ok(); -} - -bool EventFdBsd::empty() { - return in_.empty(); -} - -void EventFdBsd::close() { - in_.close(); - out_.close(); -} - -Status EventFdBsd::get_pending_error() { - return Status::OK(); -} - -PollableFdInfo &EventFdBsd::get_poll_info() { - return out_.get_poll_info(); -} - -void EventFdBsd::release() { - int value = 1; - auto result = in_.write(Slice(reinterpret_cast(&value), sizeof(value))); - if (result.is_error()) { - LOG(FATAL) << "EventFdBsd write failed: " << result.error(); - } - size_t size = result.ok(); - if (size != sizeof(value)) { - LOG(FATAL) << "EventFdBsd write returned " << value << " instead of " << sizeof(value); - } -} - -void EventFdBsd::acquire() { - out_.get_poll_info().add_flags(PollFlags::Read()); - while (can_read(out_)) { - uint8 value[1024]; - auto result = out_.read(MutableSlice(value, sizeof(value))); - if (result.is_error()) { - LOG(FATAL) << "EventFdBsd read failed:" << result.error(); - } - } -} - -void EventFdBsd::wait(int timeout_ms) { - pollfd fd; - fd.fd = get_poll_info().native_fd().fd(); - fd.events = POLLIN; - poll(&fd, 1, timeout_ms); -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.h deleted file mode 100644 index 18a3a260..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdBsd.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_EVENTFD_BSD - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/EventFdBase.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/Status.h" - -namespace td { -namespace detail { - -class EventFdBsd final : public EventFdBase { - SocketFd in_; - SocketFd out_; - - public: - EventFdBsd() = default; - - void init() override; - - bool empty() override; - - void close() override; - - Status get_pending_error() override TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info() override; - - void release() override; - - void acquire() override; - - void wait(int timeout_ms) override; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.cpp deleted file mode 100644 index 641f5565..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/EventFdLinux.h" - -char disable_linker_warning_about_empty_file_event_fd_linux_cpp TD_UNUSED; - -#ifdef TD_EVENTFD_LINUX - -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Slice.h" - -#include -#include -#include - -namespace td { -namespace detail { -class EventFdLinuxImpl { - public: - PollableFdInfo info; -}; - -EventFdLinux::EventFdLinux() = default; -EventFdLinux::EventFdLinux(EventFdLinux &&) = default; -EventFdLinux &EventFdLinux::operator=(EventFdLinux &&) = default; -EventFdLinux::~EventFdLinux() = default; - -void EventFdLinux::init() { - auto fd = NativeFd(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)); - auto eventfd_errno = errno; - LOG_IF(FATAL, !fd) << Status::PosixError(eventfd_errno, "eventfd call failed"); - impl_ = make_unique(); - impl_->info.set_native_fd(std::move(fd)); -} - -bool EventFdLinux::empty() { - return !impl_; -} - -void EventFdLinux::close() { - impl_.reset(); -} - -Status EventFdLinux::get_pending_error() { - return Status::OK(); -} - -PollableFdInfo &EventFdLinux::get_poll_info() { - return impl_->info; -} - -// NB: will be called from multiple threads -void EventFdLinux::release() { - const uint64 value = 1; - auto slice = Slice(reinterpret_cast(&value), sizeof(value)); - auto native_fd = impl_->info.native_fd().fd(); - - auto result = [&]() -> Result { - auto write_res = detail::skip_eintr([&] { return ::write(native_fd, slice.begin(), slice.size()); }); - auto write_errno = errno; - if (write_res >= 0) { - return narrow_cast(write_res); - } - return Status::PosixError(write_errno, PSLICE() << "Write to fd " << native_fd << " has failed"); - }(); - - if (result.is_error()) { - LOG(FATAL) << "EventFdLinux write failed: " << result.error(); - } - size_t size = result.ok(); - if (size != sizeof(value)) { - LOG(FATAL) << "EventFdLinux write returned " << value << " instead of " << sizeof(value); - } -} - -void EventFdLinux::acquire() { - impl_->info.get_flags(); - SCOPE_EXIT { - // Clear flags without EAGAIN and EWOULDBLOCK - // Looks like it is safe thing to do with eventfd - get_poll_info().clear_flags(PollFlags::Read()); - }; - uint64 res; - auto slice = MutableSlice(reinterpret_cast(&res), sizeof(res)); - auto native_fd = impl_->info.native_fd().fd(); - auto result = [&]() -> Result { - CHECK(slice.size() > 0); - auto read_res = detail::skip_eintr([&] { return ::read(native_fd, slice.begin(), slice.size()); }); - auto read_errno = errno; - if (read_res >= 0) { - CHECK(read_res != 0); - return narrow_cast(read_res); - } - if (read_errno == EAGAIN -#if EAGAIN != EWOULDBLOCK - || read_errno == EWOULDBLOCK -#endif - ) { - return 0; - } - return Status::PosixError(read_errno, PSLICE() << "Read from fd " << native_fd << " has failed"); - }(); - if (result.is_error()) { - LOG(FATAL) << "EventFdLinux read failed: " << result.error(); - } -} - -void EventFdLinux::wait(int timeout_ms) { - pollfd fd; - fd.fd = get_poll_info().native_fd().fd(); - fd.events = POLLIN; - poll(&fd, 1, timeout_ms); -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.h deleted file mode 100644 index 6fa748d9..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdLinux.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_EVENTFD_LINUX - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/EventFdBase.h" -#include "td/utils/Status.h" - -namespace td { -namespace detail { -class EventFdLinuxImpl; - -class EventFdLinux final : public EventFdBase { - unique_ptr impl_; - - public: - EventFdLinux(); - EventFdLinux(EventFdLinux &&); - EventFdLinux &operator=(EventFdLinux &&); - ~EventFdLinux(); - - void init() override; - - bool empty() override; - - void close() override; - - Status get_pending_error() override TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info() override; - - void release() override; - - void acquire() override; - - void wait(int timeout_ms) override; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.cpp deleted file mode 100644 index e4656b44..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/EventFdWindows.h" - -char disable_linker_warning_about_empty_file_event_fd_windows_cpp TD_UNUSED; - -#ifdef TD_EVENTFD_WINDOWS - -#include "td/utils/logging.h" - -namespace td { -namespace detail { - -void EventFdWindows::init() { - auto handle = CreateEventW(nullptr, true, false, nullptr); - if (handle == nullptr) { - auto error = OS_ERROR("CreateEventW failed"); - LOG(FATAL) << error; - } - event_ = NativeFd(handle); -} - -bool EventFdWindows::empty() { - return !event_; -} - -void EventFdWindows::close() { - event_.close(); -} - -Status EventFdWindows::get_pending_error() { - return Status::OK(); -} - -PollableFdInfo &EventFdWindows::get_poll_info() { - UNREACHABLE(); -} - -void EventFdWindows::release() { - if (SetEvent(event_.fd()) == 0) { - auto error = OS_ERROR("SetEvent failed"); - LOG(FATAL) << error; - } -} - -void EventFdWindows::acquire() { - if (ResetEvent(event_.fd()) == 0) { - auto error = OS_ERROR("ResetEvent failed"); - LOG(FATAL) << error; - } -} - -void EventFdWindows::wait(int timeout_ms) { - WaitForSingleObject(event_.fd(), timeout_ms); - if (ResetEvent(event_.fd()) == 0) { - auto error = OS_ERROR("ResetEvent failed"); - LOG(FATAL) << error; - } -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.h deleted file mode 100644 index 442020bd..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/EventFdWindows.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_EVENTFD_WINDOWS - -#include "td/utils/common.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/EventFdBase.h" -#include "td/utils/Status.h" - -namespace td { -namespace detail { - -class EventFdWindows final : public EventFdBase { - NativeFd event_; - - public: - EventFdWindows() = default; - - void init() override; - - bool empty() override; - - void close() override; - - Status get_pending_error() override TD_WARN_UNUSED_RESULT; - - PollableFdInfo &get_poll_info() override; - - void release() override; - - void acquire() override; - - void wait(int timeout_ms) override; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.cpp deleted file mode 100644 index af97d2c8..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/Iocp.h" - -char disable_linker_warning_about_empty_file_iocp_cpp TD_UNUSED; - -#ifdef TD_PORT_WINDOWS - -#include "td/utils/logging.h" - -namespace td { -namespace detail { -Iocp::~Iocp() { - clear(); -} - -void Iocp::loop() { - Iocp::Guard guard(this); - while (true) { - DWORD bytes = 0; - ULONG_PTR key = 0; - WSAOVERLAPPED *overlapped = nullptr; - BOOL ok = - GetQueuedCompletionStatus(iocp_handle_->fd(), &bytes, &key, reinterpret_cast(&overlapped), 1000); - if (bytes || key || overlapped) { - // LOG(ERROR) << "Got IOCP " << bytes << " " << key << " " << overlapped; - } - if (ok) { - auto callback = reinterpret_cast(key); - if (callback == nullptr) { - // LOG(ERROR) << "Interrupt IOCP loop"; - return; - } - callback->on_iocp(bytes, overlapped); - } else { - if (overlapped != nullptr) { - auto error = OS_ERROR("Received from IOCP"); - auto callback = reinterpret_cast(key); - CHECK(callback != nullptr); - callback->on_iocp(std::move(error), overlapped); - } - } - } -} - -void Iocp::interrupt_loop() { - post(0, nullptr, nullptr); -} - -void Iocp::init() { - CHECK(!iocp_handle_); - auto res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0); - if (res == nullptr) { - auto error = OS_ERROR("IOCP creation failed"); - LOG(FATAL) << error; - } - iocp_handle_ = std::make_shared(res); -} - -void Iocp::clear() { - iocp_handle_.reset(); -} - -void Iocp::subscribe(const NativeFd &native_fd, Callback *callback) { - CHECK(iocp_handle_); - auto iocp_handle = - CreateIoCompletionPort(native_fd.fd(), iocp_handle_->fd(), reinterpret_cast(callback), 0); - if (iocp_handle == nullptr) { - auto error = OS_ERROR("CreateIoCompletionPort"); - LOG(FATAL) << error; - } - LOG_CHECK(iocp_handle == iocp_handle_->fd()) << iocp_handle << " " << iocp_handle_->fd(); -} - -IocpRef Iocp::get_ref() const { - return IocpRef(iocp_handle_); -} - -static void iocp_post(NativeFd &iocp_handle, size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped) { - if (PostQueuedCompletionStatus(iocp_handle.fd(), DWORD(size), reinterpret_cast(callback), - reinterpret_cast(overlapped)) == 0) { - auto error = OS_ERROR("IOCP post failed"); - LOG(FATAL) << error; - } -} - -void Iocp::post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped) { - iocp_post(*iocp_handle_, size, callback, overlapped); -} - -IocpRef::IocpRef(std::weak_ptr iocp_handle) : iocp_handle_(std::move(iocp_handle)) { -} - -bool IocpRef::post(size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped) { - auto iocp_handle = iocp_handle_.lock(); - if (!iocp_handle) { - return false; - } - iocp_post(*iocp_handle, size, callback, overlapped); - return true; -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.h deleted file mode 100644 index 6947d85e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Iocp.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_PORT_WINDOWS - -#include "td/utils/common.h" -#include "td/utils/Context.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/Status.h" - -#include - -namespace td { -namespace detail { - -class IocpRef; -class Iocp final : public Context { - public: - Iocp() = default; - Iocp(const Iocp &) = delete; - Iocp &operator=(const Iocp &) = delete; - Iocp(Iocp &&) = delete; - Iocp &operator=(Iocp &&) = delete; - ~Iocp(); - - class Callback { - public: - virtual ~Callback() = default; - virtual void on_iocp(Result r_size, WSAOVERLAPPED *overlapped) = 0; - }; - - void init(); - void subscribe(const NativeFd &fd, Callback *callback); - void post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped); - void loop(); - void interrupt_loop(); - void clear(); - - IocpRef get_ref() const; - - private: - std::shared_ptr iocp_handle_; -}; - -class IocpRef { - public: - IocpRef() = default; - IocpRef(const Iocp &) = delete; - IocpRef &operator=(const Iocp &) = delete; - IocpRef(IocpRef &&) = default; - IocpRef &operator=(IocpRef &&) = default; - - explicit IocpRef(std::weak_ptr iocp_handle); - - bool post(size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped); - - private: - std::weak_ptr iocp_handle_; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.cpp deleted file mode 100644 index 3ed0a3ad..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/KQueue.h" - -char disable_linker_warning_about_empty_file_kqueue_cpp TD_UNUSED; - -#ifdef TD_POLL_KQUEUE - -#include "td/utils/logging.h" -#include "td/utils/Status.h" - -#include - -#include -#include - -namespace td { -namespace detail { - -KQueue::~KQueue() { - clear(); -} -void KQueue::init() { - kq_ = NativeFd(kqueue()); - auto kqueue_errno = errno; - LOG_IF(FATAL, !kq_) << Status::PosixError(kqueue_errno, "kqueue creation failed"); - - // TODO: const - events_.resize(1000); - changes_n_ = 0; -} - -void KQueue::clear() { - if (!kq_) { - return; - } - events_.clear(); - kq_.close(); - for (auto *list_node = list_root_.next; list_node != &list_root_;) { - auto pollable_fd = PollableFd::from_list_node(list_node); - list_node = list_node->next; - } -} - -int KQueue::update(int nevents, const timespec *timeout, bool may_fail) { - int err = kevent(kq_.fd(), &events_[0], changes_n_, &events_[0], nevents, timeout); - auto kevent_errno = errno; - - bool is_fatal_error = [&] { - if (err != -1) { - return false; - } - if (may_fail) { - return kevent_errno != ENOENT; - } - return kevent_errno != EINTR; - }(); - LOG_IF(FATAL, is_fatal_error) << Status::PosixError(kevent_errno, "kevent failed"); - - changes_n_ = 0; - if (err < 0) { - return 0; - } - return err; -} - -void KQueue::flush_changes(bool may_fail) { - if (!changes_n_) { - return; - } - int n = update(0, nullptr, may_fail); - CHECK(n == 0); -} - -void KQueue::add_change(std::uintptr_t ident, int16 filter, uint16 flags, uint32 fflags, std::intptr_t data, - void *udata) { - if (changes_n_ == static_cast(events_.size())) { - flush_changes(); - } -#if TD_NETBSD - auto set_udata = reinterpret_cast(udata); -#else - auto set_udata = udata; -#endif - EV_SET(&events_[changes_n_], ident, filter, flags, fflags, data, set_udata); - VLOG(fd) << "Subscribe [fd:" << ident << "] [filter:" << filter << "] [udata: " << udata << "]"; - changes_n_++; -} - -void KQueue::subscribe(PollableFd fd, PollFlags flags) { - auto native_fd = fd.native_fd().fd(); - auto list_node = fd.release_as_list_node(); - list_root_.put(list_node); - if (flags.can_read()) { - add_change(native_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, list_node); - } - if (flags.can_write()) { - add_change(native_fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, list_node); - } -} - -void KQueue::invalidate(int native_fd) { - for (int i = 0; i < changes_n_; i++) { - if (events_[i].ident == static_cast(native_fd)) { - changes_n_--; - std::swap(events_[i], events_[changes_n_]); - i--; - } - } -} - -void KQueue::unsubscribe(PollableFdRef fd_ref) { - auto pollable_fd = fd_ref.lock(); - auto native_fd = pollable_fd.native_fd().fd(); - - // invalidate(fd); - flush_changes(); - add_change(native_fd, EVFILT_READ, EV_DELETE, 0, 0, nullptr); - flush_changes(true); - add_change(native_fd, EVFILT_WRITE, EV_DELETE, 0, 0, nullptr); - flush_changes(true); -} - -void KQueue::unsubscribe_before_close(PollableFdRef fd_ref) { - auto pollable_fd = fd_ref.lock(); - invalidate(pollable_fd.native_fd().fd()); - - // just to avoid O(changes_n ^ 2) - if (changes_n_ != 0) { - flush_changes(); - } -} - -void KQueue::run(int timeout_ms) { - timespec timeout_data; - timespec *timeout_ptr; - if (timeout_ms == -1) { - timeout_ptr = nullptr; - } else { - timeout_data.tv_sec = timeout_ms / 1000; - timeout_data.tv_nsec = timeout_ms % 1000 * 1000000; - timeout_ptr = &timeout_data; - } - - int n = update(static_cast(events_.size()), timeout_ptr); - for (int i = 0; i < n; i++) { - struct kevent *event = &events_[i]; - PollFlags flags; - if (event->filter == EVFILT_WRITE) { - flags.add_flags(PollFlags::Write()); - } - if (event->filter == EVFILT_READ) { - flags.add_flags(PollFlags::Read()); - } - if (event->flags & EV_EOF) { - flags.add_flags(PollFlags::Close()); - } - if (event->fflags & EV_ERROR) { - LOG(FATAL) << "EV_ERROR in kqueue is not supported"; - } -#if TD_NETBSD - auto udata = reinterpret_cast(event->udata); -#else - auto udata = event->udata; -#endif - VLOG(fd) << "Event [fd:" << event->ident << "] [filter:" << event->filter << "] [udata: " << udata << "]"; - // LOG(WARNING) << "Have event->ident = " << event->ident << "event->filter = " << event->filter; - auto pollable_fd = PollableFd::from_list_node(static_cast(udata)); - pollable_fd.add_flags(flags); - pollable_fd.release_as_list_node(); - } -} -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.h deleted file mode 100644 index f5a8c693..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/KQueue.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_POLL_KQUEUE - -#include "td/utils/common.h" -#include "td/utils/List.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollBase.h" -#include "td/utils/port/PollFlags.h" - -#include - -#include // must be included before sys/event.h, which depends on sys/types.h on FreeBSD - -#include - -namespace td { -namespace detail { - -class KQueue final : public PollBase { - public: - KQueue() = default; - KQueue(const KQueue &) = delete; - KQueue &operator=(const KQueue &) = delete; - KQueue(KQueue &&) = delete; - KQueue &operator=(KQueue &&) = delete; - ~KQueue() override; - - void init() override; - - void clear() override; - - void subscribe(PollableFd fd, PollFlags flags) override; - - void unsubscribe(PollableFdRef fd) override; - - void unsubscribe_before_close(PollableFdRef fd) override; - - void run(int timeout_ms) override; - - static bool is_edge_triggered() { - return true; - } - - private: - vector events_; - int changes_n_; - NativeFd kq_; - ListNode list_root_; - - int update(int nevents, const timespec *timeout, bool may_fail = false); - - void invalidate(int native_fd); - - void flush_changes(bool may_fail = false); - - void add_change(std::uintptr_t ident, int16 filter, uint16 flags, uint32 fflags, std::intptr_t data, void *udata); -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.cpp deleted file mode 100644 index a21cc281..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/NativeFd.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/Status.h" - -#if TD_PORT_POSIX -#include -#include -#endif - -#if TD_FD_DEBUG -#include -#include -#endif - -namespace td { - -#if TD_FD_DEBUG -class FdSet { - public: - void on_create_fd(NativeFd::Fd fd) { - CHECK(is_valid(fd)); - if (is_stdio(fd)) { - return; - } - std::unique_lock guard(mutex_); - if (fds_.count(fd) >= 1) { - LOG(FATAL) << "Create duplicated fd: " << fd; - } - fds_.insert(fd); - } - - Status validate(NativeFd::Fd fd) { - if (!is_valid(fd)) { - return Status::Error(PSLICE() << "Invalid fd: " << fd); - } - if (is_stdio(fd)) { - return Status::OK(); - } - std::unique_lock guard(mutex_); - if (fds_.count(fd) != 1) { - return Status::Error(PSLICE() << "Unknown fd: " << fd); - } - return Status::OK(); - } - - void on_close_fd(NativeFd::Fd fd) { - CHECK(is_valid(fd)); - if (is_stdio(fd)) { - return; - } - std::unique_lock guard(mutex_); - if (fds_.count(fd) != 1) { - LOG(FATAL) << "Close unknown fd: " << fd; - } - fds_.erase(fd); - } - - private: - std::mutex mutex_; - std::set fds_; - - bool is_stdio(NativeFd::Fd fd) const { -#if TD_PORT_WINDOWS -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - return fd == GetStdHandle(STD_INPUT_HANDLE) || fd == GetStdHandle(STD_OUTPUT_HANDLE) || - fd == GetStdHandle(STD_ERROR_HANDLE); -#else - return false; -#endif -#else - return fd >= 0 && fd <= 2; -#endif - } - - bool is_valid(NativeFd::Fd fd) const { -#if TD_PORT_WINDOWS - return fd != INVALID_HANDLE_VALUE; -#else - return fd >= 0; -#endif - } -}; - -namespace { -FdSet &get_fd_set() { - static FdSet res; - return res; -} -} // namespace - -#endif - -Status NativeFd::validate() const { -#if TD_FD_DEBUG - return get_fd_set().validate(fd_.get()); -#else - return Status::OK(); -#endif -} - -NativeFd::NativeFd(Fd fd) : fd_(fd) { - VLOG(fd) << *this << " create"; -#if TD_FD_DEBUG - get_fd_set().on_create_fd(fd_.get()); -#endif -} - -NativeFd::NativeFd(Fd fd, bool nolog) : fd_(fd) { -#if TD_FD_DEBUG - get_fd_set().on_create_fd(fd_.get()); -#endif -} - -#if TD_PORT_WINDOWS -NativeFd::NativeFd(Socket socket) : fd_(reinterpret_cast(socket)), is_socket_(true) { - VLOG(fd) << *this << " create"; -#if TD_FD_DEBUG - get_fd_set().on_create_fd(fd_.get()); -#endif -} -#endif - -NativeFd &NativeFd::operator=(NativeFd &&from) { - CHECK(this != &from); - close(); - fd_ = std::move(from.fd_); -#if TD_PORT_WINDOWS - is_socket_ = from.is_socket_; -#endif - return *this; -} - -NativeFd::~NativeFd() { - close(); -} - -NativeFd::operator bool() const { - return fd_.get() != empty_fd(); -} - -NativeFd::Fd NativeFd::empty_fd() { -#if TD_PORT_POSIX - return -1; -#elif TD_PORT_WINDOWS - return INVALID_HANDLE_VALUE; -#endif -} - -NativeFd::Fd NativeFd::fd() const { - return fd_.get(); -} - -NativeFd::Socket NativeFd::socket() const { -#if TD_PORT_POSIX - return fd(); -#elif TD_PORT_WINDOWS - CHECK(is_socket_); - return reinterpret_cast(fd_.get()); -#endif -} - -Status NativeFd::set_is_blocking(bool is_blocking) const { -#if TD_PORT_POSIX - auto old_flags = fcntl(fd(), F_GETFL); - if (old_flags == -1) { - return OS_SOCKET_ERROR("Failed to get socket flags"); - } - auto new_flags = is_blocking ? old_flags & ~O_NONBLOCK : old_flags | O_NONBLOCK; - if (new_flags != old_flags && fcntl(fd(), F_SETFL, new_flags) == -1) { - return OS_SOCKET_ERROR("Failed to set socket flags"); - } - - return Status::OK(); -#elif TD_PORT_WINDOWS - return set_is_blocking_unsafe(is_blocking); -#endif -} - -Status NativeFd::set_is_blocking_unsafe(bool is_blocking) const { -#if TD_PORT_POSIX - if (fcntl(fd(), F_SETFL, is_blocking ? 0 : O_NONBLOCK) == -1) { -#elif TD_PORT_WINDOWS - u_long mode = is_blocking; - if (ioctlsocket(socket(), FIONBIO, &mode) != 0) { -#endif - return OS_SOCKET_ERROR("Failed to change socket flags"); - } - return Status::OK(); -} - -Status NativeFd::duplicate(const NativeFd &to) const { -#if TD_PORT_POSIX - CHECK(*this); - CHECK(to); - if (dup2(fd(), to.fd()) == -1) { - return OS_ERROR("Failed to duplicate file descriptor"); - } - return Status::OK(); -#elif TD_PORT_WINDOWS - return Status::Error("Not supported"); -#endif -} - -void NativeFd::close() { - if (!*this) { - return; - } - -#if TD_FD_DEBUG - get_fd_set().on_close_fd(fd()); -#endif - - VLOG(fd) << *this << " close"; -#if TD_PORT_WINDOWS - if (is_socket_ ? closesocket(socket()) : !CloseHandle(fd())) { -#elif TD_PORT_POSIX - if (::close(fd()) < 0) { -#endif - auto error = OS_ERROR("Close fd"); - LOG(ERROR) << error; - } - fd_ = {}; -} - -NativeFd::Fd NativeFd::release() { - VLOG(fd) << *this << " release"; - auto res = fd_.get(); - fd_ = {}; -#if TD_FD_DEBUG - get_fd_set().on_close_fd(res); -#endif - return res; -} - -StringBuilder &operator<<(StringBuilder &sb, const NativeFd &fd) { - return sb << tag("fd", fd.fd()); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.h deleted file mode 100644 index fac6b4ed..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/NativeFd.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/MovableValue.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" - -namespace td { - -class NativeFd { - public: -#if TD_PORT_POSIX - using Fd = int; - using Socket = int; -#elif TD_PORT_WINDOWS - using Fd = HANDLE; - using Socket = SOCKET; -#endif - NativeFd() = default; - NativeFd(NativeFd &&) = default; - NativeFd &operator=(NativeFd &&); - explicit NativeFd(Fd fd); - NativeFd(Fd fd, bool nolog); -#if TD_PORT_WINDOWS - explicit NativeFd(Socket socket); -#endif - NativeFd(const NativeFd &) = delete; - NativeFd &operator=(const NativeFd &) = delete; - ~NativeFd(); - - explicit operator bool() const; - - static Fd empty_fd(); - - Fd fd() const; - Socket socket() const; - - Status set_is_blocking(bool is_blocking) const; - - Status set_is_blocking_unsafe(bool is_blocking) const; // may drop other Fd flags on non-Windows - - Status duplicate(const NativeFd &to) const; - - void close(); - Fd release(); - - Status validate() const; - - private: -#if TD_PORT_POSIX - MovableValue fd_; -#elif TD_PORT_WINDOWS - MovableValue fd_; - bool is_socket_{false}; -#endif -}; - -StringBuilder &operator<<(StringBuilder &sb, const NativeFd &fd); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.cpp deleted file mode 100644 index f43804ee..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/Poll.h" - -char disable_linker_warning_about_empty_file_poll_cpp TD_UNUSED; - -#ifdef TD_POLL_POLL - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Status.h" - -namespace td { -namespace detail { - -void Poll::init() { -} - -void Poll::clear() { - pollfds_.clear(); -} - -void Poll::subscribe(PollableFd fd, PollFlags flags) { - unsubscribe(fd.ref()); - struct pollfd pollfd; - pollfd.fd = fd.native_fd().fd(); - pollfd.events = 0; - if (flags.can_read()) { - pollfd.events |= POLLIN; - } - if (flags.can_write()) { - pollfd.events |= POLLOUT; - } - pollfd.revents = 0; - pollfds_.push_back(pollfd); - fds_.push_back(std::move(fd)); -} - -void Poll::unsubscribe(PollableFdRef fd_ref) { - auto fd = fd_ref.lock(); - SCOPE_EXIT { - fd.release_as_list_node(); - }; - for (auto it = pollfds_.begin(); it != pollfds_.end(); ++it) { - if (it->fd == fd.native_fd().fd()) { - pollfds_.erase(it); - fds_.erase(fds_.begin() + (it - pollfds_.begin())); - return; - } - } -} - -void Poll::unsubscribe_before_close(PollableFdRef fd) { - unsubscribe(fd); -} - -void Poll::run(int timeout_ms) { - int err = poll(pollfds_.data(), narrow_cast(pollfds_.size()), timeout_ms); - auto poll_errno = errno; - LOG_IF(FATAL, err == -1 && poll_errno != EINTR) << Status::PosixError(poll_errno, "poll failed"); - - for (size_t i = 0; i < pollfds_.size(); i++) { - auto &pollfd = pollfds_[i]; - auto &fd = fds_[i]; - - PollFlags flags; - if (pollfd.revents & POLLIN) { - pollfd.revents &= ~POLLIN; - flags = flags | PollFlags::Read(); - } - if (pollfd.revents & POLLOUT) { - pollfd.revents &= ~POLLOUT; - flags = flags | PollFlags::Write(); - } - if (pollfd.revents & POLLHUP) { - pollfd.revents &= ~POLLHUP; - flags = flags | PollFlags::Close(); - } - if (pollfd.revents & POLLERR) { - pollfd.revents &= ~POLLERR; - flags = flags | PollFlags::Error(); - } - if (pollfd.revents & POLLNVAL) { - LOG(FATAL) << "Unexpected POLLNVAL " << tag("fd", pollfd.fd); - } - if (pollfd.revents) { - LOG(FATAL) << "Unsupported poll events: " << pollfd.revents; - } - fd.add_flags(flags); - } -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.h deleted file mode 100644 index 81ffd6eb..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Poll.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_POLL_POLL - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollBase.h" -#include "td/utils/port/PollFlags.h" - -#include - -namespace td { -namespace detail { - -class Poll final : public PollBase { - public: - Poll() = default; - Poll(const Poll &) = delete; - Poll &operator=(const Poll &) = delete; - Poll(Poll &&) = delete; - Poll &operator=(Poll &&) = delete; - ~Poll() override = default; - - void init() override; - - void clear() override; - - void subscribe(PollableFd fd, PollFlags flags) override; - - void unsubscribe(PollableFdRef fd) override; - - void unsubscribe_before_close(PollableFdRef fd) override; - - void run(int timeout_ms) override; - - static bool is_edge_triggered() { - return false; - } - - private: - vector pollfds_; - vector fds_; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/PollableFd.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/PollableFd.h deleted file mode 100644 index 73c6dd7d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/PollableFd.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/List.h" -#include "td/utils/logging.h" -#include "td/utils/Observer.h" -#include "td/utils/port/detail/NativeFd.h" -#include "td/utils/port/PollFlags.h" -#include "td/utils/SpinLock.h" - -#include -#include -#include - -namespace td { - -class PollableFdInfo; -class PollableFdInfoUnlock { - public: - void operator()(PollableFdInfo *ptr); -}; - -class PollableFd; -class PollableFdRef { - public: - explicit PollableFdRef(ListNode *list_node) : list_node_(list_node) { - } - PollableFd lock(); - - private: - ListNode *list_node_; -}; - -class PollableFd { - public: - // Interface for kqueue, epoll and e.t.c. - const NativeFd &native_fd() const; - - ListNode *release_as_list_node(); - PollableFdRef ref(); - static PollableFd from_list_node(ListNode *node); - void add_flags(PollFlags flags); - PollFlags get_flags_unsafe() const; - - private: - std::unique_ptr fd_info_; - friend class PollableFdInfo; - - explicit PollableFd(std::unique_ptr fd_info) : fd_info_(std::move(fd_info)) { - } -}; - -inline PollableFd PollableFdRef::lock() { - return PollableFd::from_list_node(list_node_); -} - -class PollableFdInfo : private ListNode { - public: - PollableFdInfo() = default; - PollableFdInfo(const PollableFdInfo &) = delete; - PollableFdInfo &operator=(const PollableFdInfo &) = delete; - PollableFdInfo(PollableFdInfo &&) = delete; - PollableFdInfo &operator=(PollableFdInfo &&) = delete; - - PollableFd extract_pollable_fd(ObserverBase *observer) { - VLOG(fd) << native_fd() << " extract pollable fd " << tag("observer", observer); - CHECK(!empty()); - bool was_locked = lock_.test_and_set(std::memory_order_acquire); - CHECK(!was_locked); - set_observer(observer); - return PollableFd{std::unique_ptr{this}}; - } - PollableFdRef get_pollable_fd_ref() { - CHECK(!empty()); - bool was_locked = lock_.test_and_set(std::memory_order_acquire); - CHECK(was_locked); - return PollableFdRef{as_list_node()}; - } - - void add_flags(PollFlags flags) { - flags_.write_flags_local(flags); - } - - void clear_flags(PollFlags flags) { - flags_.clear_flags(flags); - } - PollFlags get_flags() const { - return flags_.read_flags(); - } - PollFlags get_flags_local() const { - return flags_.read_flags_local(); - } - - bool empty() const { - return !fd_; - } - - void set_native_fd(NativeFd new_native_fd) { - if (fd_) { - CHECK(!new_native_fd); - bool was_locked = lock_.test_and_set(std::memory_order_acquire); - CHECK(!was_locked); - lock_.clear(std::memory_order_release); - } - - fd_ = std::move(new_native_fd); - } - explicit PollableFdInfo(NativeFd native_fd) { - set_native_fd(std::move(native_fd)); - } - const NativeFd &native_fd() const { - //CHECK(!empty()); - return fd_; - } - NativeFd move_as_native_fd() { - return std::move(fd_); - } - - ~PollableFdInfo() { - VLOG(fd) << native_fd() << " destroy PollableFdInfo"; - bool was_locked = lock_.test_and_set(std::memory_order_acquire); - CHECK(!was_locked); - } - - void add_flags_from_poll(PollFlags flags) { - VLOG(fd) << native_fd() << " add flags from poll " << flags; - if (flags_.write_flags(flags)) { - notify_observer(); - } - } - - private: - NativeFd fd_{}; - std::atomic_flag lock_ = ATOMIC_FLAG_INIT; - PollFlagsSet flags_; -#if TD_PORT_WINDOWS - SpinLock observer_lock_; -#endif - ObserverBase *observer_{nullptr}; - - friend class PollableFd; - friend class PollableFdInfoUnlock; - - void set_observer(ObserverBase *observer) { -#if TD_PORT_WINDOWS - auto lock = observer_lock_.lock(); -#endif - CHECK(!observer_); - observer_ = observer; - } - void clear_observer() { -#if TD_PORT_WINDOWS - auto lock = observer_lock_.lock(); -#endif - observer_ = nullptr; - } - void notify_observer() { -#if TD_PORT_WINDOWS - auto lock = observer_lock_.lock(); -#endif - VLOG(fd) << native_fd() << " notify " << tag("observer", observer_); - if (observer_) { - observer_->notify(); - } - } - - void unlock() { - clear_observer(); - lock_.clear(std::memory_order_release); - as_list_node()->remove(); - } - - ListNode *as_list_node() { - return static_cast(this); - } - static PollableFdInfo *from_list_node(ListNode *list_node) { - return static_cast(list_node); - } -}; -inline void PollableFdInfoUnlock::operator()(PollableFdInfo *ptr) { - ptr->unlock(); -} - -inline ListNode *PollableFd::release_as_list_node() { - return fd_info_.release()->as_list_node(); -} -inline PollableFdRef PollableFd::ref() { - return PollableFdRef{fd_info_->as_list_node()}; -} -inline PollableFd PollableFd::from_list_node(ListNode *node) { - return PollableFd(std::unique_ptr(PollableFdInfo::from_list_node(node))); -} - -inline void PollableFd::add_flags(PollFlags flags) { - fd_info_->add_flags_from_poll(flags); -} -inline PollFlags PollableFd::get_flags_unsafe() const { - return fd_info_->get_flags_local(); -} -inline const NativeFd &PollableFd::native_fd() const { - return fd_info_->native_fd(); -} - -#if TD_PORT_POSIX -namespace detail { -template -auto skip_eintr(F &&f) { - decltype(f()) res; - static_assert(std::is_integral::value, "integral type expected"); - do { - errno = 0; // just in case - res = f(); - } while (res < 0 && errno == EINTR); - return res; -} -template -auto skip_eintr_cstr(F &&f) { - char *res; - do { - errno = 0; // just in case - res = f(); - } while (res == nullptr && errno == EINTR); - return res; -} -} // namespace detail -#endif - -template -bool can_read(const FdT &fd) { - return fd.get_poll_info().get_flags().can_read() || fd.get_poll_info().get_flags().has_pending_error(); -} - -template -bool can_write(const FdT &fd) { - return fd.get_poll_info().get_flags().can_write(); -} - -template -bool can_close(const FdT &fd) { - return fd.get_poll_info().get_flags().can_close(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.cpp deleted file mode 100644 index eab58e7e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/Select.h" - -char disable_linker_warning_about_empty_file_select_cpp TD_UNUSED; - -#ifdef TD_POLL_SELECT - -#include "td/utils/logging.h" - -#include - -namespace td { -namespace detail { - -void Select::init() { - FD_ZERO(&all_fd_); - FD_ZERO(&read_fd_); - FD_ZERO(&write_fd_); - FD_ZERO(&except_fd_); - max_fd_ = -1; -} - -void Select::clear() { - fds_.clear(); -} - -void Select::subscribe(PollableFd fd, PollFlags flags) { - int native_fd = fd.native_fd().fd(); - for (auto &it : fds_) { - CHECK(it.fd.native_fd().fd() != native_fd); - } - fds_.push_back(FdInfo{std::move(fd), flags}); - LOG_CHECK(0 <= native_fd && native_fd < FD_SETSIZE) << native_fd << " " << FD_SETSIZE; - FD_SET(native_fd, &all_fd_); - if (native_fd > max_fd_) { - max_fd_ = native_fd; - } -} - -void Select::unsubscribe(PollableFdRef fd) { - auto fd_locked = fd.lock(); - int native_fd = fd_locked.native_fd().fd(); - fd_locked.release_as_list_node(); - - LOG_CHECK(0 <= native_fd && native_fd < FD_SETSIZE) << native_fd << " " << FD_SETSIZE; - FD_CLR(native_fd, &all_fd_); - FD_CLR(native_fd, &read_fd_); - FD_CLR(native_fd, &write_fd_); - FD_CLR(native_fd, &except_fd_); - while (max_fd_ >= 0 && !FD_ISSET(max_fd_, &all_fd_)) { - max_fd_--; - } - for (auto it = fds_.begin(); it != fds_.end();) { - if (it->fd.native_fd().fd() == native_fd) { - std::swap(*it, fds_.back()); - fds_.pop_back(); - break; - } else { - ++it; - } - } -} - -void Select::unsubscribe_before_close(PollableFdRef fd) { - unsubscribe(fd); -} - -void Select::run(int timeout_ms) { - timeval timeout_data; - timeval *timeout_ptr; - if (timeout_ms == -1) { - timeout_ptr = nullptr; - } else { - timeout_data.tv_sec = timeout_ms / 1000; - timeout_data.tv_usec = timeout_ms % 1000 * 1000; - timeout_ptr = &timeout_data; - } - - for (auto &it : fds_) { - int native_fd = it.fd.native_fd().fd(); - PollFlags fd_flags = it.fd.get_flags_unsafe(); // concurrent calls are UB - if (it.flags.can_write() && !fd_flags.can_write()) { - FD_SET(native_fd, &write_fd_); - } else { - FD_CLR(native_fd, &write_fd_); - } - if (it.flags.can_read() && !fd_flags.can_read()) { - FD_SET(native_fd, &read_fd_); - } else { - FD_CLR(native_fd, &read_fd_); - } - FD_SET(native_fd, &except_fd_); - } - - select(max_fd_ + 1, &read_fd_, &write_fd_, &except_fd_, timeout_ptr); - for (auto &it : fds_) { - int native_fd = it.fd.native_fd().fd(); - PollFlags flags; - if (FD_ISSET(native_fd, &read_fd_)) { - flags = flags | PollFlags::Read(); - } - if (FD_ISSET(native_fd, &write_fd_)) { - flags = flags | PollFlags::Write(); - } - if (FD_ISSET(native_fd, &except_fd_)) { - flags = flags | PollFlags::Error(); - } - it.fd.add_flags(flags); - } -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.h deleted file mode 100644 index a50c26e9..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/Select.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_POLL_SELECT - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollBase.h" -#include "td/utils/port/PollFlags.h" - -#include - -namespace td { -namespace detail { - -class Select final : public PollBase { - public: - Select() = default; - Select(const Select &) = delete; - Select &operator=(const Select &) = delete; - Select(Select &&) = delete; - Select &operator=(Select &&) = delete; - ~Select() override = default; - - void init() override; - - void clear() override; - - void subscribe(PollableFd fd, PollFlags flags) override; - - void unsubscribe(PollableFdRef fd) override; - - void unsubscribe_before_close(PollableFdRef fd) override; - - void run(int timeout_ms) override; - - static bool is_edge_triggered() { - return false; - } - - private: - struct FdInfo { - PollableFd fd; - PollFlags flags; - }; - vector fds_; - fd_set all_fd_; - fd_set read_fd_; - fd_set write_fd_; - fd_set except_fd_; - int max_fd_; -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.cpp deleted file mode 100644 index 8e4b89ed..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/ThreadIdGuard.h" - -#include "td/utils/common.h" -#include "td/utils/port/thread_local.h" - -#include -#include - -namespace td { -namespace detail { -class ThreadIdManager { - public: - int32 register_thread() { - std::lock_guard guard(mutex_); - if (unused_thread_ids_.empty()) { - return ++max_thread_id_; - } - auto it = unused_thread_ids_.begin(); - auto result = *it; - unused_thread_ids_.erase(it); - return result; - } - void unregister_thread(int32 thread_id) { - std::lock_guard guard(mutex_); - CHECK(0 < thread_id && thread_id <= max_thread_id_); - bool is_inserted = unused_thread_ids_.insert(thread_id).second; - CHECK(is_inserted); - } - - private: - std::mutex mutex_; - std::set unused_thread_ids_; - int32 max_thread_id_ = 0; -}; -static ThreadIdManager thread_id_manager; - -ThreadIdGuard::ThreadIdGuard() { - thread_id_ = thread_id_manager.register_thread(); - set_thread_id(thread_id_); -} -ThreadIdGuard::~ThreadIdGuard() { - thread_id_manager.unregister_thread(thread_id_); - set_thread_id(0); -} -} // namespace detail -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.h deleted file mode 100644 index 7b64b833..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadIdGuard.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { -namespace detail { -class ThreadIdGuard { - public: - ThreadIdGuard(); - ~ThreadIdGuard(); - ThreadIdGuard(const ThreadIdGuard &) = delete; - ThreadIdGuard &operator=(const ThreadIdGuard &) = delete; - ThreadIdGuard(ThreadIdGuard &&) = delete; - ThreadIdGuard &operator=(ThreadIdGuard &&) = delete; - - private: - int32 thread_id_; -}; -} // namespace detail -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadPthread.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadPthread.h deleted file mode 100644 index 5d45d5a3..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadPthread.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_THREAD_PTHREAD - -#include "td/utils/common.h" -#include "td/utils/Destructor.h" -#include "td/utils/invoke.h" -#include "td/utils/MovableValue.h" -#include "td/utils/port/detail/ThreadIdGuard.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/Slice.h" - -#include -#include -#include - -#include -#include - -namespace td { -namespace detail { -class ThreadPthread { - public: - ThreadPthread() = default; - ThreadPthread(const ThreadPthread &other) = delete; - ThreadPthread &operator=(const ThreadPthread &other) = delete; - ThreadPthread(ThreadPthread &&) = default; - ThreadPthread &operator=(ThreadPthread &&other) { - join(); - is_inited_ = std::move(other.is_inited_); - thread_ = other.thread_; - return *this; - } - template - explicit ThreadPthread(Function &&f, Args &&... args) { - auto func = create_destructor([args = std::make_tuple(decay_copy(std::forward(f)), - decay_copy(std::forward(args))...)]() mutable { - invoke_tuple(std::move(args)); - clear_thread_locals(); - }); - pthread_create(&thread_, nullptr, run_thread, func.release()); - is_inited_ = true; - } - void set_name(CSlice name) { -#if defined(_GNU_SOURCE) && defined(__GLIBC_PREREQ) -#if __GLIBC_PREREQ(2, 12) - pthread_setname_np(thread_, name.c_str()); -#endif -#endif - } - void join() { - if (is_inited_.get()) { - is_inited_ = false; - pthread_join(thread_, nullptr); - } - } - - void detach() { - if (is_inited_.get()) { - is_inited_ = false; - pthread_detach(thread_); - } - } - ~ThreadPthread() { - join(); - } - - static unsigned hardware_concurrency() { - return 8; - } - - using id = pthread_t; - - private: - MovableValue is_inited_; - pthread_t thread_; - - template - std::decay_t decay_copy(T &&v) { - return std::forward(v); - } - - static void *run_thread(void *ptr) { - ThreadIdGuard thread_id_guard; - auto func = unique_ptr(static_cast(ptr)); - return nullptr; - } -}; - -namespace this_thread_pthread { -inline void yield() { - sched_yield(); -} -inline ThreadPthread::id get_id() { - return pthread_self(); -} -} // namespace this_thread_pthread -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadStl.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadStl.h deleted file mode 100644 index d7928f17..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/ThreadStl.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_THREAD_STL - -#include "td/utils/common.h" -#include "td/utils/invoke.h" -#include "td/utils/port/detail/ThreadIdGuard.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/Slice.h" - -#include -#include -#include -#include - -namespace td { -namespace detail { -class ThreadStl { - public: - ThreadStl() = default; - ThreadStl(const ThreadStl &other) = delete; - ThreadStl &operator=(const ThreadStl &other) = delete; - ThreadStl(ThreadStl &&) = default; - ThreadStl &operator=(ThreadStl &&) = default; - ~ThreadStl() { - join(); - } - template - explicit ThreadStl(Function &&f, Args &&... args) { - thread_ = std::thread([args = std::make_tuple(decay_copy(std::forward(f)), - decay_copy(std::forward(args))...)]() mutable { - ThreadIdGuard thread_id_guard; - invoke_tuple(std::move(args)); - clear_thread_locals(); - }); - } - - void join() { - if (thread_.joinable()) { - thread_.join(); - } - } - void detach() { - if (thread_.joinable()) { - thread_.detach(); - } - } - void set_name(CSlice name) { - } - - static unsigned hardware_concurrency() { - return std::thread::hardware_concurrency(); - } - - using id = std::thread::id; - - private: - std::thread thread_; - - template - std::decay_t decay_copy(T &&v) { - return std::forward(v); - } -}; -namespace this_thread_stl = std::this_thread; -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.cpp deleted file mode 100644 index f93b2606..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/detail/WineventPoll.h" - -char disable_linker_warning_about_empty_file_wineventpoll_cpp TD_UNUSED; - -#ifdef TD_POLL_WINEVENT - -#include "td/utils/common.h" - -namespace td { -namespace detail { - -void WineventPoll::init() { -} - -void WineventPoll::clear() { -} - -void WineventPoll::subscribe(PollableFd fd, PollFlags flags) { - fd.release_as_list_node(); -} - -void WineventPoll::unsubscribe(PollableFdRef fd) { - auto pollable_fd = fd.lock(); // unlocked in destructor -} - -void WineventPoll::unsubscribe_before_close(PollableFdRef fd) { - unsubscribe(std::move(fd)); -} - -void WineventPoll::run(int timeout_ms) { - UNREACHABLE(); -} - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.h deleted file mode 100644 index 7bca8d47..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/detail/WineventPoll.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#ifdef TD_POLL_WINEVENT - -#include "td/utils/common.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/port/PollBase.h" -#include "td/utils/port/PollFlags.h" - -namespace td { -namespace detail { - -class WineventPoll final : public PollBase { - public: - WineventPoll() = default; - WineventPoll(const WineventPoll &) = delete; - WineventPoll &operator=(const WineventPoll &) = delete; - WineventPoll(WineventPoll &&) = delete; - WineventPoll &operator=(WineventPoll &&) = delete; - ~WineventPoll() override = default; - - void init() override; - - void clear() override; - - void subscribe(PollableFd fd, PollFlags flags) override; - - void unsubscribe(PollableFdRef fd) override; - - void unsubscribe_before_close(PollableFdRef fd) override; - - void run(int timeout_ms) override; - - static bool is_edge_triggered() { - return true; - } -}; - -} // namespace detail -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/path.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/path.cpp deleted file mode 100644 index 2d9c11b0..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/path.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/path.h" - -#include "td/utils/port/config.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/port/detail/PollableFd.h" -#include "td/utils/ScopeGuard.h" - -#if TD_PORT_WINDOWS -#include "td/utils/port/wstring_convert.h" -#include "td/utils/Random.h" -#endif - -#if TD_PORT_POSIX - -#include -#include -#include - -// We don't want warnings from system headers -#if TD_GCC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif -#include -#if TD_GCC -#pragma GCC diagnostic pop -#endif - -#include -#include - -#endif - -#if TD_DARWIN -#include -#endif - -#include -#include - -namespace td { - -static string temporary_dir; - -Status set_temporary_dir(CSlice dir) { - string input_dir = dir.str(); - if (!dir.empty() && dir.back() != TD_DIR_SLASH) { - input_dir += TD_DIR_SLASH; - } - TRY_STATUS(mkpath(input_dir, 0750)); - TRY_RESULT(real_dir, realpath(input_dir)); - temporary_dir = std::move(real_dir); - return Status::OK(); -} - -Status mkpath(CSlice path, int32 mode) { - Status first_error = Status::OK(); - Status last_error = Status::OK(); - for (size_t i = 1; i < path.size(); i++) { - if (path[i] == TD_DIR_SLASH) { - last_error = mkdir(PSLICE() << path.substr(0, i), mode); - if (last_error.is_error() && first_error.is_ok()) { - first_error = last_error.clone(); - } - } - } - if (last_error.is_error()) { - return first_error; - } - return Status::OK(); -} - -Status rmrf(CSlice path) { - return walk_path(path, [](CSlice path, WalkPath::Type type) { - switch (type) { - case WalkPath::Type::EnterDir: - break; - case WalkPath::Type::ExitDir: - rmdir(path).ignore(); - break; - case WalkPath::Type::NotDir: - unlink(path).ignore(); - break; - } - }); -} - -#if TD_PORT_POSIX - -Status mkdir(CSlice dir, int32 mode) { - int mkdir_res = [&] { - int res; - do { - errno = 0; // just in case - res = ::mkdir(dir.c_str(), static_cast(mode)); - } while (res < 0 && (errno == EINTR || errno == EAGAIN)); - return res; - }(); - if (mkdir_res == 0) { - return Status::OK(); - } - auto mkdir_errno = errno; - if (mkdir_errno == EEXIST) { - // TODO check that it is a directory - return Status::OK(); - } - return Status::PosixError(mkdir_errno, PSLICE() << "Can't create directory \"" << dir << '"'); -} - -Status rename(CSlice from, CSlice to) { - int rename_res = detail::skip_eintr([&] { return ::rename(from.c_str(), to.c_str()); }); - if (rename_res < 0) { - return OS_ERROR(PSLICE() << "Can't rename \"" << from << "\" to \"" << to << '\"'); - } - return Status::OK(); -} - -Result realpath(CSlice slice, bool ignore_access_denied) { - char full_path[PATH_MAX + 1]; - string res; - char *err = detail::skip_eintr_cstr([&] { return ::realpath(slice.c_str(), full_path); }); - if (err != full_path) { - if (ignore_access_denied && (errno == EACCES || errno == EPERM)) { - res = slice.str(); - } else { - return OS_ERROR(PSLICE() << "Realpath failed for \"" << slice << '"'); - } - } else { - res = full_path; - } - if (res.empty()) { - return Status::Error("Empty path"); - } - if (!slice.empty() && slice.end()[-1] == TD_DIR_SLASH) { - if (res.back() != TD_DIR_SLASH) { - res += TD_DIR_SLASH; - } - } - return res; -} - -Status chdir(CSlice dir) { - int chdir_res = detail::skip_eintr([&] { return ::chdir(dir.c_str()); }); - if (chdir_res) { - return OS_ERROR(PSLICE() << "Can't change directory to \"" << dir << '"'); - } - return Status::OK(); -} - -Status rmdir(CSlice dir) { - int rmdir_res = detail::skip_eintr([&] { return ::rmdir(dir.c_str()); }); - if (rmdir_res) { - return OS_ERROR(PSLICE() << "Can't delete directory \"" << dir << '"'); - } - return Status::OK(); -} - -Status unlink(CSlice path) { - int unlink_res = detail::skip_eintr([&] { return ::unlink(path.c_str()); }); - if (unlink_res) { - return OS_ERROR(PSLICE() << "Can't unlink \"" << path << '"'); - } - return Status::OK(); -} - -CSlice get_temporary_dir() { - static bool is_inited = [] { - if (temporary_dir.empty()) { - const char *s = std::getenv("TMPDIR"); - if (s != nullptr && s[0] != '\0') { - temporary_dir = s; - } else if (P_tmpdir != nullptr && P_tmpdir[0] != '\0') { - temporary_dir = P_tmpdir; - } else { - return false; - } - } - if (temporary_dir.size() > 1 && temporary_dir.back() == TD_DIR_SLASH) { - temporary_dir.pop_back(); - } - return true; - }(); - LOG_IF(FATAL, !is_inited) << "Can't find temporary directory"; - return temporary_dir; -} - -Result> mkstemp(CSlice dir) { - if (dir.empty()) { - dir = get_temporary_dir(); - if (dir.empty()) { - return Status::Error("Can't find temporary directory"); - } - } - - TRY_RESULT(dir_real, realpath(dir)); - CHECK(!dir_real.empty()); - - string file_pattern; - file_pattern.reserve(dir_real.size() + 14); - file_pattern = dir_real; - if (file_pattern.back() != TD_DIR_SLASH) { - file_pattern += TD_DIR_SLASH; - } - file_pattern += "tmpXXXXXXXXXX"; - - int fd = detail::skip_eintr([&] { return ::mkstemp(&file_pattern[0]); }); - if (fd == -1) { - return OS_ERROR(PSLICE() << "Can't create temporary file \"" << file_pattern << '"'); - } - if (close(fd)) { - return OS_ERROR(PSLICE() << "Can't close temporary file \"" << file_pattern << '"'); - } - // TODO create file from fd - TRY_RESULT(file, FileFd::open(file_pattern, FileFd::Write | FileFd::Truncate | FileFd::Append)); - return std::make_pair(std::move(file), std::move(file_pattern)); -} - -Result mkdtemp(CSlice dir, Slice prefix) { - if (dir.empty()) { - dir = get_temporary_dir(); - if (dir.empty()) { - return Status::Error("Can't find temporary directory"); - } - } - - TRY_RESULT(dir_real, realpath(dir)); - CHECK(!dir_real.empty()); - - string dir_pattern; - dir_pattern.reserve(dir_real.size() + prefix.size() + 7); - dir_pattern = dir_real; - if (dir_pattern.back() != TD_DIR_SLASH) { - dir_pattern += TD_DIR_SLASH; - } - dir_pattern.append(prefix.begin(), prefix.size()); - dir_pattern += "XXXXXX"; - - char *result = detail::skip_eintr_cstr([&] { return ::mkdtemp(&dir_pattern[0]); }); - if (result == nullptr) { - return OS_ERROR(PSLICE() << "Can't create temporary directory \"" << dir_pattern << '"'); - } - return result; -} - -namespace detail { -using WalkFunction = std::function; -Result walk_path_dir(string &path, FileFd fd, const WalkFunction &func) TD_WARN_UNUSED_RESULT; - -Result walk_path_dir(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT; - -Result walk_path_file(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT; - -Result walk_path(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT; - -Result walk_path_subdir(string &path, DIR *dir, const WalkFunction &func) { - while (true) { - errno = 0; - auto *entry = readdir(dir); - auto readdir_errno = errno; - if (readdir_errno) { - return Status::PosixError(readdir_errno, "readdir"); - } - if (entry == nullptr) { - return true; - } - Slice name = Slice(static_cast(entry->d_name)); - if (name == "." || name == "..") { - continue; - } - auto size = path.size(); - if (path.back() != TD_DIR_SLASH) { - path += TD_DIR_SLASH; - } - path.append(name.begin(), name.size()); - SCOPE_EXIT { - path.resize(size); - }; - Result status = true; -#ifdef DT_DIR - if (entry->d_type == DT_UNKNOWN) { - status = walk_path(path, func); - } else if (entry->d_type == DT_DIR) { - status = walk_path_dir(path, func); - } else if (entry->d_type == DT_REG) { - status = walk_path_file(path, func); - } -#else -#warning "Slow walk_path" - status = walk_path(path, func); -#endif - if (status.is_error() || !status.ok()) { - return status; - } - } -} - -Result walk_path_dir(string &path, DIR *subdir, const WalkFunction &func) { - SCOPE_EXIT { - closedir(subdir); - }; - switch (func(path, WalkPath::Type::EnterDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - return true; - case WalkPath::Action::Continue: - break; - } - auto status = walk_path_subdir(path, subdir, func); - if (status.is_error() || !status.ok()) { - return status; - } - switch (func(path, WalkPath::Type::ExitDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - case WalkPath::Action::Continue: - break; - } - return true; -} - -Result walk_path_dir(string &path, FileFd fd, const WalkFunction &func) { - auto native_fd = fd.move_as_native_fd(); - auto *subdir = fdopendir(native_fd.fd()); - if (subdir == nullptr) { - return OS_ERROR("fdopendir"); - } - native_fd.release(); - return walk_path_dir(path, subdir, func); -} - -Result walk_path_dir(string &path, const WalkFunction &func) { - auto *subdir = opendir(path.c_str()); - if (subdir == nullptr) { - return OS_ERROR(PSLICE() << tag("opendir", path)); - } - return walk_path_dir(path, subdir, func); -} - -Result walk_path_file(string &path, const WalkFunction &func) { - switch (func(path, WalkPath::Type::NotDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - case WalkPath::Action::Continue: - break; - } - return true; -} - -Result walk_path(string &path, const WalkFunction &func) { - TRY_RESULT(fd, FileFd::open(path, FileFd::Read)); - TRY_RESULT(stat, fd.stat()); - - bool is_dir = stat.is_dir_; - bool is_reg = stat.is_reg_; - if (is_dir) { - return walk_path_dir(path, std::move(fd), func); - } - - fd.close(); - if (is_reg) { - return walk_path_file(path, func); - } - - return true; -} -} // namespace detail - -Status WalkPath::do_run(CSlice path, const detail::WalkFunction &func) { - string curr_path; - curr_path.reserve(PATH_MAX + 10); - curr_path = path.c_str(); - TRY_STATUS(detail::walk_path(curr_path, func)); - return Status::OK(); -} - -#endif - -#if TD_PORT_WINDOWS - -Status mkdir(CSlice dir, int32 mode) { - TRY_RESULT(wdir, to_wstring(dir)); - auto status = CreateDirectoryW(wdir.c_str(), nullptr); - if (status == 0 && GetLastError() != ERROR_ALREADY_EXISTS) { - return OS_ERROR(PSLICE() << "Can't create directory \"" << dir << '"'); - } - return Status::OK(); -} - -Status rename(CSlice from, CSlice to) { - TRY_RESULT(wfrom, to_wstring(from)); - TRY_RESULT(wto, to_wstring(to)); - auto status = MoveFileExW(wfrom.c_str(), wto.c_str(), MOVEFILE_REPLACE_EXISTING); - if (status == 0) { - return OS_ERROR(PSLICE() << "Can't rename \"" << from << "\" to \"" << to << '\"'); - } - return Status::OK(); -} - -Result realpath(CSlice slice, bool ignore_access_denied) { - wchar_t buf[MAX_PATH + 1]; - TRY_RESULT(wslice, to_wstring(slice)); - auto status = GetFullPathNameW(wslice.c_str(), MAX_PATH, buf, nullptr); - string res; - if (status == 0) { - if (ignore_access_denied && errno == ERROR_ACCESS_DENIED) { - res = slice.str(); - } else { - return OS_ERROR(PSLICE() << "GetFullPathNameW failed for \"" << slice << '"'); - } - } else { - TRY_RESULT(t_res, from_wstring(buf)); - res = std::move(t_res); - } - if (res.empty()) { - return Status::Error("Empty path"); - } - if (!slice.empty() && slice.end()[-1] == TD_DIR_SLASH) { - if (res.back() != TD_DIR_SLASH) { - res += TD_DIR_SLASH; - } - } - return res; -} - -Status chdir(CSlice dir) { - TRY_RESULT(wdir, to_wstring(dir)); - auto res = SetCurrentDirectoryW(wdir.c_str()); - if (res == 0) { - return OS_ERROR(PSLICE() << "Can't change directory to \"" << dir << '"'); - } - return Status::OK(); -} - -Status rmdir(CSlice dir) { - TRY_RESULT(wdir, to_wstring(dir)); - int status = RemoveDirectoryW(wdir.c_str()); - if (!status) { - return OS_ERROR(PSLICE() << "Can't delete directory \"" << dir << '"'); - } - return Status::OK(); -} - -Status unlink(CSlice path) { - TRY_RESULT(wpath, to_wstring(path)); - int status = DeleteFileW(wpath.c_str()); - if (!status) { - return OS_ERROR(PSLICE() << "Can't unlink \"" << path << '"'); - } - return Status::OK(); -} - -CSlice get_temporary_dir() { - static bool is_inited = [] { - if (temporary_dir.empty()) { - wchar_t buf[MAX_PATH + 1]; - if (GetTempPathW(MAX_PATH, buf) == 0) { - auto error = OS_ERROR("GetTempPathW failed"); - LOG(FATAL) << error; - } - auto rs = from_wstring(buf); - LOG_IF(FATAL, rs.is_error()) << "GetTempPathW failed: " << rs.error(); - temporary_dir = rs.ok(); - } - if (temporary_dir.size() > 1 && temporary_dir.back() == TD_DIR_SLASH) { - temporary_dir.pop_back(); - } - return true; - }(); - LOG_IF(FATAL, !is_inited) << "Can't find temporary directory"; - return temporary_dir; -} - -Result mkdtemp(CSlice dir, Slice prefix) { - if (dir.empty()) { - dir = get_temporary_dir(); - if (dir.empty()) { - return Status::Error("Can't find temporary directory"); - } - } - - TRY_RESULT(dir_real, realpath(dir)); - CHECK(!dir_real.empty()); - - string dir_pattern; - dir_pattern.reserve(dir_real.size() + prefix.size() + 7); - dir_pattern = dir_real; - if (dir_pattern.back() != TD_DIR_SLASH) { - dir_pattern += TD_DIR_SLASH; - } - dir_pattern.append(prefix.begin(), prefix.size()); - - for (auto iter = 0; iter < 20; iter++) { - auto path = dir_pattern; - for (int i = 0; i < 6 + iter / 5; i++) { - path += static_cast(Random::fast('a', 'z')); - } - auto status = mkdir(path); - if (status.is_ok()) { - return path; - } - } - return Status::Error(PSLICE() << "Can't create temporary directory \"" << dir_pattern << '"'); -} - -Result> mkstemp(CSlice dir) { - if (dir.empty()) { - dir = get_temporary_dir(); - if (dir.empty()) { - return Status::Error("Can't find temporary directory"); - } - } - - TRY_RESULT(dir_real, realpath(dir)); - CHECK(!dir_real.empty()); - - string file_pattern; - file_pattern.reserve(dir_real.size() + 14); - file_pattern = dir_real; - if (file_pattern.back() != TD_DIR_SLASH) { - file_pattern += TD_DIR_SLASH; - } - file_pattern += "tmp"; - - for (auto iter = 0; iter < 20; iter++) { - auto path = file_pattern; - for (int i = 0; i < 6 + iter / 5; i++) { - path += static_cast(Random::fast('a', 'z')); - } - auto r_file = FileFd::open(path, FileFd::Write | FileFd::Read | FileFd::CreateNew); - if (r_file.is_ok()) { - return std::make_pair(r_file.move_as_ok(), path); - } - } - - return Status::Error(PSLICE() << "Can't create temporary file \"" << file_pattern << '"'); -} - -static Result walk_path_dir(const std::wstring &dir_name, - const std::function &func) { - std::wstring name = dir_name + L"\\*"; - WIN32_FIND_DATA file_data; - auto handle = FindFirstFileExW(name.c_str(), FindExInfoStandard, &file_data, FindExSearchNameMatch, nullptr, 0); - if (handle == INVALID_HANDLE_VALUE) { - return OS_ERROR(PSLICE() << "FindFirstFileEx" << tag("name", from_wstring(name).ok())); - } - - SCOPE_EXIT { - FindClose(handle); - }; - - TRY_RESULT(dir_entry_name, from_wstring(dir_name)); - switch (func(dir_entry_name, WalkPath::Type::EnterDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - return true; - case WalkPath::Action::Continue: - break; - } - - while (true) { - auto full_name = dir_name + L"\\" + file_data.cFileName; - TRY_RESULT(entry_name, from_wstring(full_name)); - if (file_data.cFileName[0] != '.') { - if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - TRY_RESULT(is_ok, walk_path_dir(full_name, func)); - if (!is_ok) { - return false; - } - } else { - switch (func(entry_name, WalkPath::Type::NotDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - case WalkPath::Action::Continue: - break; - } - } - } - auto status = FindNextFileW(handle, &file_data); - if (status == 0) { - auto last_error = GetLastError(); - if (last_error == ERROR_NO_MORE_FILES) { - break; - } - return OS_ERROR("FindNextFileW"); - } - } - switch (func(dir_entry_name, WalkPath::Type::ExitDir)) { - case WalkPath::Action::Abort: - return false; - case WalkPath::Action::SkipDir: - case WalkPath::Action::Continue: - break; - } - return true; -} - -Status WalkPath::do_run(CSlice path, const std::function &func) { - TRY_RESULT(wpath, to_wstring(path)); - Slice path_slice = path; - while (!path_slice.empty() && (path_slice.back() == '/' || path_slice.back() == '\\')) { - path_slice.remove_suffix(1); - wpath.pop_back(); - } - TRY_STATUS(walk_path_dir(wpath, func)); - return Status::OK(); -} - -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/path.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/path.h deleted file mode 100644 index 99daa368..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/path.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -#include -#include -#include - -namespace td { - -Status mkdir(CSlice dir, int32 mode = 0700) TD_WARN_UNUSED_RESULT; - -Status mkpath(CSlice path, int32 mode = 0700) TD_WARN_UNUSED_RESULT; - -Status rename(CSlice from, CSlice to) TD_WARN_UNUSED_RESULT; - -Result realpath(CSlice slice, bool ignore_access_denied = false) TD_WARN_UNUSED_RESULT; - -Status chdir(CSlice dir) TD_WARN_UNUSED_RESULT; - -Status rmdir(CSlice dir) TD_WARN_UNUSED_RESULT; - -Status unlink(CSlice path) TD_WARN_UNUSED_RESULT; - -Status rmrf(CSlice path) TD_WARN_UNUSED_RESULT; - -Status set_temporary_dir(CSlice dir) TD_WARN_UNUSED_RESULT; - -CSlice get_temporary_dir(); - -Result> mkstemp(CSlice dir) TD_WARN_UNUSED_RESULT; - -Result mkdtemp(CSlice dir, Slice prefix) TD_WARN_UNUSED_RESULT; - -class WalkPath { - public: - enum class Action { Continue, Abort, SkipDir }; - enum class Type { EnterDir, ExitDir, NotDir }; - - template ()("", Type::ExitDir))> - static TD_WARN_UNUSED_RESULT std::enable_if_t::value, Status> run(CSlice path, F &&func) { - return do_run(path, func); - } - template ()("", Type::ExitDir))> - static TD_WARN_UNUSED_RESULT std::enable_if_t::value, Status> run(CSlice path, F &&func) { - return do_run(path, [&](CSlice name, Type type) { - func(name, type); - return Action::Continue; - }); - } - - private: - static TD_WARN_UNUSED_RESULT Status do_run(CSlice path, - const std::function &func); -}; - -// deprecated interface -template -TD_WARN_UNUSED_RESULT Status walk_path(CSlice path, F &&func) { - return WalkPath::run(path, func); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/platform.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/platform.h deleted file mode 100644 index 783dd399..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/platform.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -// clang-format off - -/*** Platform macros ***/ -#if defined(_WIN32) || defined(_WINDOWS) // _WINDOWS is defined by CMake - #if defined(__cplusplus_winrt) - #define TD_WINRT 1 - #endif - #if defined(__cplusplus_cli) - #define TD_CLI 1 - #endif - #define TD_WINDOWS 1 -#elif defined(__APPLE__) - #include "TargetConditionals.h" - #if TARGET_OS_IPHONE - // iOS/watchOS/tvOS - #if TARGET_OS_IOS - #define TD_DARWIN_IOS 1 - #elif TARGET_OS_TV - #define TD_DARWIN_TV_OS 1 - #elif TARGET_OS_WATCH - #define TD_DARWIN_WATCH_OS 1 - #else - #warning "Probably unsupported Apple iPhone platform. Feel free to try to compile" - #endif - #elif TARGET_OS_MAC - // Other kinds of macOS - #define TD_DARWIN_MAC 1 - #else - #warning "Probably unsupported Apple platform. Feel free to try to compile" - #endif - #define TD_DARWIN 1 -#elif defined(ANDROID) || defined(__ANDROID__) - #define TD_ANDROID 1 -#elif defined(TIZEN_DEPRECATION) - #define TD_TIZEN 1 -#elif defined(__linux__) - #define TD_LINUX 1 -#elif defined(__FreeBSD__) - #define TD_FREEBSD 1 -#elif defined(__OpenBSD__) - #define TD_OPENBSD 1 -#elif defined(__NetBSD__) - #define TD_NETBSD 1 -#elif defined(__CYGWIN__) - #define TD_CYGWIN 1 -#elif defined(__EMSCRIPTEN__) - #define TD_EMSCRIPTEN 1 -#elif defined(__unix__) // all unices not caught above - #warning "Probably unsupported Unix platform. Feel free to try to compile" - #define TD_CYGWIN 1 -#else - #error "Probably unsupported platform. Feel free to remove the error and try to recompile" -#endif - -#if defined(__ICC) || defined(__INTEL_COMPILER) - #define TD_INTEL 1 -#elif defined(__clang__) - #define TD_CLANG 1 -#elif defined(__GNUC__) || defined(__GNUG__) - #define TD_GCC 1 -#elif defined(_MSC_VER) - #define TD_MSVC 1 -#else - #warning "Probably unsupported compiler. Feel free to try to compile" -#endif - -#if TD_GCC || TD_CLANG || TD_INTEL - #define TD_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) - #define TD_ATTRIBUTE_FORMAT_PRINTF(from, to) __attribute__((format(printf, from, to))) -#else - #define TD_WARN_UNUSED_RESULT - #define TD_ATTRIBUTE_FORMAT_PRINTF(from, to) -#endif - -#if TD_MSVC - #define TD_UNUSED __pragma(warning(suppress : 4100)) -#elif TD_CLANG || TD_GCC || TD_INTEL - #define TD_UNUSED __attribute__((unused)) -#else - #define TD_UNUSED -#endif - -#define TD_HAVE_ATOMIC_SHARED_PTR 1 - -// No atomic operations on std::shared_ptr in libstdc++ before 5.0 -// see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250 -#ifdef __GLIBCXX__ - #undef TD_HAVE_ATOMIC_SHARED_PTR -#endif - -// Also no atomic operations on std::shared_ptr when clang __has_feature(cxx_atomic) is defined and zero -#if defined(__has_feature) - #if !__has_feature(cxx_atomic) - #undef TD_HAVE_ATOMIC_SHARED_PTR - #endif -#endif - -#ifdef TD_HAVE_ATOMIC_SHARED_PTR // unfortunately we can't check for __GLIBCXX__ here, it is not defined yet - #undef TD_HAVE_ATOMIC_SHARED_PTR -#endif - -#define TD_CONCURRENCY_PAD 128 - -#if !TD_WINDOWS && defined(__SIZEOF_INT128__) -#define TD_HAVE_INT128 1 -#endif - -// clang-format on diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.cpp deleted file mode 100644 index 5833961c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "rlimit.h" -#if TD_LINUX || TD_ANDROID -#include -#include -#include -#include -#endif - -namespace td { - -#if TD_PORT_POSIX - -namespace { - -int get_rlimit_type(RlimitType rlim_type) { - switch (rlim_type) { - case RlimitType::nofile: - return RLIMIT_NOFILE; - case RlimitType::rss: - return RLIMIT_RSS; - default: - UNREACHABLE(); - } -} - -} // namespace - -td::Status change_rlimit(RlimitType rlim_type, td::uint64 value, td::uint64 cap) { - if (cap && value > cap) { - return td::Status::Error("setrlimit(): bad argument"); - } - int resource = get_rlimit_type(rlim_type); - - struct rlimit r; - if (getrlimit(resource, &r) < 0) { - return td::Status::PosixError(errno, "failed getrlimit()"); - } - - if (cap) { - r.rlim_max = cap; - } else if (r.rlim_max < value) { - r.rlim_max = value; - } - r.rlim_cur = value; - if (setrlimit(resource, &r) < 0) { - return td::Status::PosixError(errno, "failed setrlimit()"); - } - return td::Status::OK(); -} - -td::Status change_maximize_rlimit(RlimitType rlim_type, td::uint64 value) { - int resource = get_rlimit_type(rlim_type); - - struct rlimit r; - if (getrlimit(resource, &r) < 0) { - return td::Status::PosixError(errno, "failed getrlimit()"); - } - - if (r.rlim_max < value) { - auto t = r; - t.rlim_cur = value; - t.rlim_max = value; - if (setrlimit(resource, &t) >= 0) { - return td::Status::OK(); - } - } - - r.rlim_cur = value < r.rlim_max ? value : r.rlim_max; - if (setrlimit(resource, &r) < 0) { - return td::Status::PosixError(errno, "failed setrlimit()"); - } - return td::Status::OK(); -} -#else -td::Status change_rlimit(RlimitType rlim, td::uint64 value) { - return td::Status::Error("setrlimit not implemented on WINDOWS"); -} -td::Status change_maximize_rlimit(RlimitType rlim, td::uint64 value) { - return td::Status::OK(); -} -#endif - -} // namespace td - diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.h deleted file mode 100644 index 9f6a6524..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/rlimit.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" -#include "td/utils/port/platform.h" -#include "td/utils/Status.h" - -namespace td { - -enum class RlimitType { nofile, rss }; - -td::Status change_rlimit(RlimitType rlim_type, td::uint64 value, td::uint64 cap = 0); -td::Status change_maximize_rlimit(RlimitType rlim, td::uint64 value); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.cpp deleted file mode 100644 index fc49b628..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/signals.h" - -#include "td/utils/port/config.h" -#include "td/utils/port/stacktrace.h" -#include "td/utils/port/StdStreams.h" - -#include "td/utils/common.h" -#include "td/utils/format.h" - -#if TD_PORT_POSIX -#include -#include -#include -#endif -#if TD_PORT_WINDOWS -#include -#endif - -#include -#include -#include -#include -#include -#include - -namespace td { - -#if TD_PORT_POSIX && !TD_DARWIN_TV_OS && !TD_DARWIN_WATCH_OS -static Status protect_memory(void *addr, size_t len) { - if (mprotect(addr, len, PROT_NONE) != 0) { - return OS_ERROR("mprotect failed"); - } - return Status::OK(); -} -#endif - -Status setup_signals_alt_stack() { -#if TD_PORT_POSIX && !TD_DARWIN_TV_OS && !TD_DARWIN_WATCH_OS - auto page_size = getpagesize(); - auto stack_size = (MINSIGSTKSZ + 16 * page_size - 1) / page_size * page_size; - - void *stack = mmap(nullptr, stack_size + 2 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (stack == MAP_FAILED) { - return OS_ERROR("Mmap failed"); - } - - TRY_STATUS(protect_memory(stack, page_size)); - TRY_STATUS(protect_memory(static_cast(stack) + stack_size + page_size, page_size)); - - stack_t signal_stack; - signal_stack.ss_sp = static_cast(stack) + page_size; - signal_stack.ss_size = stack_size; - signal_stack.ss_flags = 0; - - if (sigaltstack(&signal_stack, nullptr) != 0) { - return OS_ERROR("sigaltstack failed"); - } -#endif - return Status::OK(); -} - -#if TD_PORT_POSIX -static void set_handler(struct sigaction &act, decltype(act.sa_handler) handler) { - act.sa_handler = handler; -} -static void set_handler(struct sigaction &act, decltype(act.sa_sigaction) handler) { - act.sa_sigaction = handler; - act.sa_flags |= SA_SIGINFO; -} -template -static Status set_signal_handler_impl(vector signals, F func) { - struct sigaction act; - std::memset(&act, '\0', sizeof(act)); - - sigemptyset(&act.sa_mask); - for (auto signal : signals) { - sigaddset(&act.sa_mask, signal); - } - act.sa_flags = SA_RESTART | SA_ONSTACK; - set_handler(act, func); - - for (auto signal : signals) { - if (sigaction(signal, &act, nullptr) != 0) { - return OS_ERROR("sigaction failed"); - } - } - return Status::OK(); -} - -static vector get_native_signals(SignalType type) { - switch (type) { - case SignalType::Abort: - return {SIGABRT, SIGXCPU, SIGXFSZ}; - case SignalType::Error: - return {SIGILL, SIGFPE, SIGBUS, SIGSEGV, SIGSYS}; - case SignalType::Quit: - return {SIGINT, SIGTERM, SIGQUIT}; - case SignalType::Pipe: - return {SIGPIPE}; - case SignalType::HangUp: - return {SIGHUP}; - case SignalType::User: - return {SIGUSR1, SIGUSR2}; - case SignalType::Other: - return {SIGTRAP, SIGALRM, SIGVTALRM, SIGPROF, SIGTSTP, SIGTTIN, SIGTTOU}; - default: - return {}; - } -} -#endif -#if TD_PORT_WINDOWS -static Status set_signal_handler_impl(vector signals, void (*func)(int sig)) { - for (auto signal : signals) { - if (std::signal(signal, func) == SIG_ERR) { - return Status::Error("Failed to set signal handler"); - } - } - return Status::OK(); -} - -static vector get_native_signals(SignalType type) { - switch (type) { - case SignalType::Abort: - return {SIGABRT}; - case SignalType::Error: - return {SIGILL, SIGFPE, SIGSEGV}; - case SignalType::Quit: - return {SIGINT, SIGTERM}; - case SignalType::Pipe: - return {}; - case SignalType::HangUp: - return {}; - case SignalType::User: - return {}; - case SignalType::Other: - return {}; - default: - return {}; - } -} -#endif - -Status set_signal_handler(SignalType type, void (*func)(int)) { - return set_signal_handler_impl(get_native_signals(type), func == nullptr ? SIG_DFL : func); -} - -using extended_signal_handler = void (*)(int sig, void *addr); -static extended_signal_handler extended_signal_handlers[NSIG] = {}; - -#if TD_PORT_POSIX -static void siginfo_handler(int signum, siginfo_t *info, void *data) { - auto handler = extended_signal_handlers[signum]; - handler(signum, info->si_addr); -} -#elif TD_PORT_WINDOWS -static void siginfo_handler(int signum) { - auto handler = extended_signal_handlers[signum]; - handler(signum, nullptr); -} -#endif - -Status set_extended_signal_handler(SignalType type, extended_signal_handler func) { - CHECK(func != nullptr); - auto signals = get_native_signals(type); - for (auto signal : signals) { - if (0 <= signal && signal < NSIG) { - extended_signal_handlers[signal] = func; - } else { - UNREACHABLE(); - } - } - return set_signal_handler_impl(std::move(signals), siginfo_handler); -} - -Status set_runtime_signal_handler(int runtime_signal_number, void (*func)(int)) { -#ifdef SIGRTMIN - CHECK(SIGRTMIN + runtime_signal_number <= SIGRTMAX); - return set_signal_handler_impl({SIGRTMIN + runtime_signal_number}, func == nullptr ? SIG_DFL : func); -#else - return Status::OK(); -#endif -} - -Status ignore_signal(SignalType type) { - return set_signal_handler_impl(get_native_signals(type), SIG_IGN); -} - -static void signal_safe_append_int(char **s, Slice name, int number) { - if (number < 0) { - number = std::numeric_limits::max(); - } - - *--*s = ' '; - *--*s = ']'; - - do { - *--*s = static_cast(number % 10 + '0'); - number /= 10; - } while (number > 0); - - *--*s = ' '; - - for (auto pos = static_cast(name.size()) - 1; pos >= 0; pos--) { - *--*s = name[pos]; - } - - *--*s = '['; -} - -static void signal_safe_write_data(Slice data) { -#if TD_PORT_POSIX - while (!data.empty()) { - auto res = write(2, data.begin(), data.size()); - if (res < 0 && errno == EINTR) { - continue; - } - if (res <= 0) { - break; - } - - if (res > 0) { - data.remove_prefix(res); - } - } -#elif TD_PORT_WINDOWS -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE); - DWORD bytes_written; - WriteFile(stderr_handle, data.data(), static_cast(data.size()), &bytes_written, nullptr); -#else -// there is no stderr -#endif -#endif -} - -static int get_process_id() { -#if TD_PORT_POSIX - return getpid(); -#elif TD_PORT_WINDOWS - return GetCurrentProcessId(); -#endif -} - -void signal_safe_write(Slice data, bool add_header) { - auto old_errno = errno; - - if (add_header) { - constexpr size_t HEADER_BUF_SIZE = 100; - char header[HEADER_BUF_SIZE]; - char *header_end = header + HEADER_BUF_SIZE; - char *header_begin = header_end; - - signal_safe_append_int(&header_begin, "time", static_cast(std::time(nullptr))); - signal_safe_append_int(&header_begin, "pid", get_process_id()); - - signal_safe_write_data(Slice(header_begin, header_end)); - } - - signal_safe_write_data(data); - - errno = old_errno; -} - -void signal_safe_write_signal_number(int sig, bool add_header) { - char buf[100]; - char *end = buf + sizeof(buf); - char *ptr = end; - *--ptr = '\n'; - do { - *--ptr = static_cast(sig % 10 + '0'); - sig /= 10; - } while (sig != 0); - - ptr -= 8; - std::memcpy(ptr, "Signal: ", 8); - signal_safe_write(Slice(ptr, end), add_header); -} - -void signal_safe_write_pointer(void *p, bool add_header) { - std::uintptr_t addr = reinterpret_cast(p); - char buf[100]; - char *end = buf + sizeof(buf); - char *ptr = end; - *--ptr = '\n'; - do { - *--ptr = td::format::hex_digit(addr % 16); - addr /= 16; - } while (addr != 0); - *--ptr = 'x'; - *--ptr = '0'; - ptr -= 9; - std::memcpy(ptr, "Address: ", 9); - signal_safe_write(Slice(ptr, end), add_header); -} - -static void block_stdin() { -#if TD_PORT_POSIX - Stdin().get_native_fd().set_is_blocking(true).ignore(); -#endif -} - -static void default_failure_signal_handler(int sig) { - signal_safe_write_signal_number(sig); - - Stacktrace::PrintOptions options; - options.use_gdb = true; - Stacktrace::print_to_stderr(options); - - block_stdin(); - _Exit(EXIT_FAILURE); -} - -Status set_default_failure_signal_handler() { -#if TD_PORT_POSIX - Stdin(); // init static variables before atexit -#endif - std::atexit(block_stdin); - TRY_STATUS(setup_signals_alt_stack()); - TRY_STATUS(set_signal_handler(SignalType::Abort, default_failure_signal_handler)); - TRY_STATUS(set_signal_handler(SignalType::Error, default_failure_signal_handler)); - return Status::OK(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.h deleted file mode 100644 index 50d59bb4..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/signals.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -namespace td { - -Status setup_signals_alt_stack() TD_WARN_UNUSED_RESULT; - -enum class SignalType { Abort, Error, Quit, Pipe, HangUp, User, Other }; - -Status set_signal_handler(SignalType type, void (*func)(int sig)) TD_WARN_UNUSED_RESULT; - -Status set_extended_signal_handler(SignalType type, void (*func)(int sig, void *addr)) TD_WARN_UNUSED_RESULT; - -Status set_runtime_signal_handler(int runtime_signal_number, void (*func)(int sig)) TD_WARN_UNUSED_RESULT; - -Status ignore_signal(SignalType type) TD_WARN_UNUSED_RESULT; - -// writes data to the standard error stream in a signal-safe way -void signal_safe_write(Slice data, bool add_header = true); - -void signal_safe_write_signal_number(int sig, bool add_header = true); - -void signal_safe_write_pointer(void *p, bool add_header = true); - -Status set_default_failure_signal_handler(); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.cpp deleted file mode 100644 index 7351e608..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/sleep.h" - -#include "td/utils/port/config.h" - -#if TD_PORT_POSIX -#if _POSIX_C_SOURCE >= 199309L -#include -#else -#include -#endif -#endif - -namespace td { - -void usleep_for(int32 microseconds) { -#if TD_PORT_WINDOWS - int32 milliseconds = microseconds / 1000 + (microseconds % 1000 ? 1 : 0); - Sleep(milliseconds); -#else -#if _POSIX_C_SOURCE >= 199309L - timespec ts; - ts.tv_sec = microseconds / 1000000; - ts.tv_nsec = (microseconds % 1000000) * 1000; - nanosleep(&ts, nullptr); -#else - usleep(microseconds); -#endif -#endif -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.h deleted file mode 100644 index e1630a40..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/sleep.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { - -void usleep_for(int32 microseconds); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.cpp deleted file mode 100644 index d2bfafa5..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/stacktrace.h" - -#include "td/utils/port/signals.h" - -#if __GLIBC__ -#include -#endif - -#if TD_LINUX || TD_FREEBSD -#include -#include -#include - -#if TD_LINUX -#include -#endif -#endif - -namespace td { - -namespace { - -void print_backtrace(void) { -#if __GLIBC__ - void *buffer[128]; - int nptrs = backtrace(buffer, 128); - signal_safe_write("------- Stack Backtrace -------\n", false); - backtrace_symbols_fd(buffer, nptrs, 2); - signal_safe_write("-------------------------------\n", false); -#endif -} - -void print_backtrace_gdb(void) { -#if TD_LINUX || TD_FREEBSD - char pid_buf[30]; - char *pid_buf_begin = pid_buf + sizeof(pid_buf); - pid_t pid = getpid(); - *--pid_buf_begin = '\0'; - do { - *--pid_buf_begin = static_cast(pid % 10 + '0'); - pid /= 10; - } while (pid > 0); - - char name_buf[512]; - ssize_t res = readlink("/proc/self/exe", name_buf, 511); // TODO works only under Linux - if (res >= 0) { - name_buf[res] = 0; - -#if TD_LINUX - if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { - signal_safe_write("Can't set dumpable\n"); - return; - } -#if defined(PR_SET_PTRACER) - // We can't use event fd because we are in a signal handler - int fds[2]; - bool need_set_ptracer = true; - if (pipe(fds) < 0) { - need_set_ptracer = false; - signal_safe_write("Can't create a pipe\n"); - } -#endif -#endif - - int child_pid = fork(); - if (child_pid < 0) { - signal_safe_write("Can't fork() to run gdb\n"); - return; - } - if (!child_pid) { -#if TD_LINUX && defined(PR_SET_PTRACER) - if (need_set_ptracer) { - char c; - if (read(fds[0], &c, 1) < 0) { - signal_safe_write("Failed to read from pipe\n"); - } - } -#endif - dup2(2, 1); // redirect output to stderr - execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "thread apply all bt full", name_buf, pid_buf_begin, - nullptr); - return; - } else { -#if TD_LINUX && defined(PR_SET_PTRACER) - if (need_set_ptracer) { - if (prctl(PR_SET_PTRACER, child_pid, 0, 0, 0) < 0) { - signal_safe_write("Can't set ptracer\n"); - } - if (write(fds[1], "a", 1) != 1) { - signal_safe_write("Can't write to pipe\n"); - } - } -#endif - waitpid(child_pid, nullptr, 0); - } - } else { - signal_safe_write("Can't get name of executable file to pass to gdb\n"); - } -#endif -} - -} // namespace - -void Stacktrace::print_to_stderr(const PrintOptions &options) { - if (options.use_gdb) { - print_backtrace_gdb(); - } - print_backtrace(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.h deleted file mode 100644 index ed9117bf..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/stacktrace.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace td { - -class Stacktrace { - public: - struct PrintOptions { - bool use_gdb = false; - PrintOptions() { - } - }; - static void print_to_stderr(const PrintOptions &options = PrintOptions()); -}; - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/thread.h deleted file mode 100644 index d7955c55..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/port/detail/ThreadPthread.h" -#include "td/utils/port/detail/ThreadStl.h" - -namespace td { - -// clang-format off - -#if TD_THREAD_PTHREAD - using thread = detail::ThreadPthread; - namespace this_thread = detail::this_thread_pthread; -#elif TD_THREAD_STL - using thread = detail::ThreadStl; - namespace this_thread = detail::this_thread_stl; -#elif TD_THREAD_UNSUPPORTED - namespace this_thread { - inline void yield() {} - } -#else - #error "Thread's implementation is not defined" -#endif - -// clang-format on - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.cpp deleted file mode 100644 index 3ac552dd..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/thread_local.h" - -namespace td { - -namespace detail { - -static TD_THREAD_LOCAL int32 thread_id_; -static TD_THREAD_LOCAL std::vector> *thread_local_destructors; - -void add_thread_local_destructor(unique_ptr destructor) { - if (thread_local_destructors == nullptr) { - thread_local_destructors = new std::vector>(); - } - thread_local_destructors->push_back(std::move(destructor)); -} - -} // namespace detail - -void clear_thread_locals() { - // ensure that no destructors were added during destructors invokation - auto to_delete = detail::thread_local_destructors; - detail::thread_local_destructors = nullptr; - delete to_delete; - CHECK(detail::thread_local_destructors == nullptr); -} - -void set_thread_id(int32 id) { - detail::thread_id_ = id; -} - -int32 get_thread_id() { - return detail::thread_id_; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.h deleted file mode 100644 index eb5ca77d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/thread_local.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#include "td/utils/common.h" -#include "td/utils/Destructor.h" - -#include -#include - -namespace td { - -// clang-format off -#if TD_GCC || TD_CLANG - #define TD_THREAD_LOCAL __thread -#elif TD_INTEL || TD_MSVC - #define TD_THREAD_LOCAL thread_local -#else - #warning "TD_THREAD_LOCAL is not defined, trying 'thread_local'" - #define TD_THREAD_LOCAL thread_local -#endif -// clang-format on - -// If raw_ptr is not nullptr, allocate T as in std::make_unique(args...) and store pointer into raw_ptr -template -bool init_thread_local(P &raw_ptr, ArgsT &&... args); - -// Destroy all thread locals, and store nullptr into corresponding pointers -void clear_thread_locals(); - -void set_thread_id(int32 id); - -int32 get_thread_id(); - -namespace detail { -void add_thread_local_destructor(unique_ptr destructor); - -template -void do_init_thread_local(P &raw_ptr, ArgsT &&... args) { - auto ptr = std::make_unique(std::forward(args)...); - raw_ptr = ptr.get(); - - detail::add_thread_local_destructor(create_destructor([ptr = std::move(ptr), &raw_ptr]() mutable { - ptr.reset(); - raw_ptr = nullptr; - })); -} -} // namespace detail - -template -bool init_thread_local(P &raw_ptr, ArgsT &&... args) { - if (likely(raw_ptr != nullptr)) { - return false; - } - detail::do_init_thread_local(raw_ptr, std::forward(args)...); - return true; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/user.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/user.cpp deleted file mode 100644 index 2e77eff8..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/user.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "user.h" -#if TD_LINUX -#include -#include -#include -#include -#endif - -namespace td { - -#if TD_LINUX -td::Status change_user(td::Slice user) { - struct passwd *pw; - if (getuid() != 0 || geteuid() != 0) { - return td::Status::PosixError(errno, "cannot setuid() as not root"); - } - if ((pw = getpwnam(user.str().c_str())) == 0) { - return td::Status::PosixError(errno, PSTRING() << "bad user '" << user << "'"); - } - gid_t gid = pw->pw_gid; - if (setgroups(1, &gid) < 0) { - return td::Status::PosixError(errno, "failed to clear supplementary groups list"); - } - if (initgroups(user.str().c_str(), gid) != 0) { - return td::Status::PosixError(errno, "failed to load groups of user"); - } - if (setgid(pw->pw_gid) < 0) { - return td::Status::PosixError(errno, "failed to setgid()"); - } - if (setuid(pw->pw_uid) < 0) { - return td::Status::PosixError(errno, "failed to setuid()"); - } - return td::Status::OK(); -} -#else -td::Status change_user(td::Slice username) { - return td::Status::Error("not implemented"); -} -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/user.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/user.h deleted file mode 100644 index 9c53c2fc..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/user.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" -#include "td/utils/port/platform.h" -#include "td/utils/Status.h" - -namespace td { - -td::Status change_user(td::Slice username); - -} diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.cpp deleted file mode 100644 index 0e0515d5..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/port/wstring_convert.h" - -char disable_linker_warning_about_empty_file_wstring_convert_cpp TD_UNUSED; - -#if TD_PORT_WINDOWS - -#include "td/utils/utf8.h" - -#include - -namespace td { - -Result to_wstring(CSlice slice) { - if (!check_utf8(slice)) { - return Status::Error("Wrong encoding"); - } - - size_t wstring_len = 0; - for (auto c : slice) { - wstring_len += ((c & 0xc0) != 0x80) + ((c & 0xf8) == 0xf0); - } - - std::wstring result(wstring_len, static_cast(0)); - if (wstring_len) { - wchar_t *res = &result[0]; - for (size_t i = 0; i < slice.size();) { - unsigned int a = static_cast(slice[i++]); - if (a >= 0x80) { - unsigned int b = static_cast(slice[i++]); - if (a >= 0xe0) { - unsigned int c = static_cast(slice[i++]); - if (a >= 0xf0) { - unsigned int d = static_cast(slice[i++]); - unsigned int val = ((a & 0x07) << 18) + ((b & 0x3f) << 12) + ((c & 0x3f) << 6) + (d & 0x3f) - 0x10000; - *res++ = static_cast(0xD800 + (val >> 10)); - *res++ = static_cast(0xDC00 + (val & 0x3ff)); - } else { - *res++ = static_cast(((a & 0x0f) << 12) + ((b & 0x3f) << 6) + (c & 0x3f)); - } - } else { - *res++ = static_cast(((a & 0x1f) << 6) + (b & 0x3f)); - } - } else { - *res++ = static_cast(a); - } - } - CHECK(res == &result[0] + wstring_len); - } - return result; -} - -Result from_wstring(const wchar_t *begin, size_t size) { - size_t result_len = 0; - for (size_t i = 0; i < size; i++) { - unsigned int cur = begin[i]; - if ((cur & 0xF800) == 0xD800) { - if (i < size) { - unsigned int next = begin[++i]; - if ((next & 0xFC00) == 0xDC00 && (cur & 0x400) == 0) { - result_len += 4; - continue; - } - } - - return Status::Error("Wrong encoding"); - } - result_len += 1 + (cur >= 0x80) + (cur >= 0x800); - } - - std::string result(result_len, '\0'); - if (result_len) { - char *res = &result[0]; - for (size_t i = 0; i < size; i++) { - unsigned int cur = begin[i]; - // TODO conversion unsigned int -> signed char is implementation defined - if (cur <= 0x7f) { - *res++ = static_cast(cur); - } else if (cur <= 0x7ff) { - *res++ = static_cast(0xc0 | (cur >> 6)); - *res++ = static_cast(0x80 | (cur & 0x3f)); - } else if ((cur & 0xF800) != 0xD800) { - *res++ = static_cast(0xe0 | (cur >> 12)); - *res++ = static_cast(0x80 | ((cur >> 6) & 0x3f)); - *res++ = static_cast(0x80 | (cur & 0x3f)); - } else { - unsigned int next = begin[++i]; - unsigned int val = ((cur - 0xD800) << 10) + next - 0xDC00 + 0x10000; - - *res++ = static_cast(0xf0 | (val >> 18)); - *res++ = static_cast(0x80 | ((val >> 12) & 0x3f)); - *res++ = static_cast(0x80 | ((val >> 6) & 0x3f)); - *res++ = static_cast(0x80 | (val & 0x3f)); - } - } - } - return result; -} - -Result from_wstring(const std::wstring &str) { - return from_wstring(str.data(), str.size()); -} - -Result from_wstring(const wchar_t *begin) { - return from_wstring(begin, std::wcslen(begin)); -} - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.h b/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.h deleted file mode 100644 index 18b008c7..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/port/wstring_convert.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/config.h" - -#if TD_PORT_WINDOWS - -#include "td/utils/common.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -#include - -namespace td { - -Result to_wstring(CSlice slice); - -Result from_wstring(const std::wstring &str); - -Result from_wstring(const wchar_t *begin, size_t size); - -Result from_wstring(const wchar_t *begin); - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/queue.h b/submodules/ton/tonlib-src/tdutils/td/utils/queue.h deleted file mode 100644 index f1d9f58c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/queue.h +++ /dev/null @@ -1,484 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/port/EventFd.h" -#include "td/utils/port/thread.h" - -#if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED - -#include -#include -#include - -namespace td { - -namespace detail { -class Backoff { - int cnt = 0; - - public: - bool next() { - // TODO: find out better strategy - // TODO: try adaptive backoff - // TODO: different strategy one core cpu - // return false; - - cnt++; - if (cnt < 1) { // 50 - return true; - } else { - td::this_thread::yield(); - return cnt < 3; // 500 - } - } -}; - -class InfBackoff { - int cnt = 0; - - public: - bool next() { - cnt++; - if (cnt < 50) { - return true; - } else { - td::this_thread::yield(); - return true; - } - } -}; - -} // namespace detail - -template -class SPSCBlockQueue { - public: - using ValueType = T; - - private: - static constexpr int buffer_size() { - static_assert(P >= 1 && P <= 20, "Bad size of BlockQueue"); - return 1 << P; - } - - struct Position { - std::atomic i{0}; - char pad[64 - sizeof(std::atomic)]; - uint32 local_writer_i; - char pad2[64 - sizeof(uint32)]; - uint32 local_reader_i; - char pad3[64 - sizeof(uint32)]; - - void init() { - i = 0; - local_reader_i = 0; - local_writer_i = 0; - } - }; - - typename std::aligned_storage::type data_[buffer_size()]; - Position writer_; - Position reader_; - - static int fix_i(int i) { - return i & (buffer_size() - 1); - } - - ValueType *at_ptr(int i) { - return reinterpret_cast(&data_[fix_i(i)]); - } - - ValueType &at(int i) { - return *at_ptr(i); - } - - public: - void init() { - writer_.init(); - reader_.init(); - } - - void destroy() { - } - - int writer_size() { - return static_cast(writer_.local_reader_i + buffer_size() - writer_.local_writer_i); - } - - bool writer_empty() { - return writer_.local_reader_i + buffer_size() == writer_.local_writer_i; - } - - template - void writer_put_unsafe(PutValueType &&value) { - at(writer_.local_writer_i++) = std::forward(value); - } - - int writer_update() { - writer_.local_reader_i = reader_.i.load(std::memory_order_acquire); - return writer_size(); - } - - void writer_flush() { - writer_.i.store(writer_.local_writer_i, std::memory_order_release); - } - - int reader_size() { - return static_cast(reader_.local_writer_i - reader_.local_reader_i); - } - - int reader_empty() { - return reader_.local_writer_i == reader_.local_reader_i; - } - - ValueType reader_get_unsafe() { - return std::move(at(reader_.local_reader_i++)); - } - - int reader_update() { - reader_.local_writer_i = writer_.i.load(std::memory_order_acquire); - return reader_size(); - } - - void reader_flush() { - reader_.i.store(reader_.local_reader_i, std::memory_order_release); - } -}; - -template > -class SPSCChainQueue { - public: - using ValueType = T; - - void init() { - head_ = tail_ = create_node(); - } - - SPSCChainQueue() = default; - SPSCChainQueue(const SPSCChainQueue &) = delete; - SPSCChainQueue &operator=(const SPSCChainQueue &) = delete; - SPSCChainQueue(SPSCChainQueue &&) = delete; - SPSCChainQueue &operator=(SPSCChainQueue &&) = delete; - ~SPSCChainQueue() { - destroy(); - } - - void destroy() { - while (head_ != nullptr) { - Node *to_delete = head_; - head_ = head_->next_; - delete_node(to_delete); - } - tail_ = nullptr; - } - - int writer_size() { - return tail_->q_.writer_size(); - } - - bool writer_empty() { - return tail_->q_.writer_empty(); - } - - template - void writer_put_unsafe(PutValueType &&value) { - tail_->q_.writer_put_unsafe(std::forward(value)); - } - - int writer_update() { - int res = tail_->q_.writer_update(); - if (res != 0) { - return res; - } - - writer_flush(); - - Node *new_tail = create_node(); - tail_->next_ = new_tail; - tail_->is_closed_.store(true, std::memory_order_release); - tail_ = new_tail; - return tail_->q_.writer_update(); - } - - void writer_flush() { - tail_->q_.writer_flush(); - } - - int reader_size() { - return head_->q_.reader_size(); - } - - int reader_empty() { - return head_->q_.reader_empty(); - } - - ValueType reader_get_unsafe() { - return std::move(head_->q_.reader_get_unsafe()); - } - - int reader_update() { - int res = head_->q_.reader_update(); - if (res != 0) { - return res; - } - - if (!head_->is_closed_.load(std::memory_order_acquire)) { - return 0; - } - - res = head_->q_.reader_update(); - if (res != 0) { - return res; - } - - // reader_flush(); - - Node *old_head = head_; - head_ = head_->next_; - delete_node(old_head); - - return head_->q_.reader_update(); - } - - void reader_flush() { - head_->q_.reader_flush(); - } - - private: - struct Node { - BlockQueueT q_; - std::atomic is_closed_{false}; - Node *next_; - - void init() { - q_.init(); - is_closed_ = false; - next_ = nullptr; - } - - void destroy() { - q_.destroy(); - next_ = nullptr; - } - }; - - Node *head_; - char pad[64 - sizeof(Node *)]; - Node *tail_; - char pad2[64 - sizeof(Node *)]; - - Node *create_node() { - Node *res = new Node(); - res->init(); - return res; - } - - void delete_node(Node *node) { - node->destroy(); - delete node; - } -}; - -template , class BackoffT = detail::Backoff> -class BackoffQueue : public QueueT { - public: - using ValueType = T; - - template - void writer_put(PutValueType &&value) { - if (this->writer_empty()) { - int sz = this->writer_update(); - CHECK(sz != 0); - } - this->writer_put_unsafe(std::forward(value)); - } - - int reader_wait() { - BackoffT backoff; - int res = 0; - do { - res = this->reader_update(); - } while (res == 0 && backoff.next()); - return res; - } -}; - -template > -using InfBackoffQueue = BackoffQueue; - -template > -class PollQueue : public QueueT { - public: - using ValueType = T; - using QueueType = QueueT; - - void init() { - QueueType::init(); - event_fd_.init(); - wait_state_ = 0; - writer_wait_state_ = 0; - } - - PollQueue() = default; - PollQueue(const PollQueue &) = delete; - PollQueue &operator=(const PollQueue &) = delete; - PollQueue(PollQueue &&) = delete; - PollQueue &operator=(PollQueue &&) = delete; - ~PollQueue() { - destroy_impl(); - } - void destroy() { - destroy_impl(); - QueueType::destroy(); - } - - void writer_flush() { - int old_wait_state = get_wait_state(); - - std::atomic_thread_fence(std::memory_order_seq_cst); - - QueueType::writer_flush(); - - std::atomic_thread_fence(std::memory_order_seq_cst); - - int wait_state = get_wait_state(); - if ((wait_state & 1) && wait_state != writer_wait_state_) { - event_fd_.release(); - writer_wait_state_ = old_wait_state; - } - } - - EventFd &reader_get_event_fd() { - return event_fd_; - } - - // if 0 is returned than it is useless to rerun it before fd is - // ready to read. - int reader_wait_nonblock() { - int res; - - if ((get_wait_state() & 1) == 0) { - res = this->QueueType::reader_wait(); - if (res != 0) { - return res; - } - - inc_wait_state(); - - std::atomic_thread_fence(std::memory_order_seq_cst); - - res = this->reader_update(); - if (res != 0) { - inc_wait_state(); - return res; - } - } - - event_fd_.acquire(); - std::atomic_thread_fence(std::memory_order_seq_cst); - res = this->reader_update(); - if (res != 0) { - inc_wait_state(); - } - return res; - } - - // Just an example of usage - int reader_wait() { - int res; - while ((res = reader_wait_nonblock()) == 0) { - reader_get_event_fd().wait(1000); - } - return res; - } - - private: - EventFd event_fd_; - std::atomic wait_state_{0}; - int writer_wait_state_; - - int get_wait_state() { - return wait_state_.load(std::memory_order_relaxed); - } - - void inc_wait_state() { - wait_state_.store(get_wait_state() + 1, std::memory_order_relaxed); - } - - void destroy_impl() { - if (!event_fd_.empty()) { - event_fd_.close(); - } - } -}; - -} // namespace td - -#else - -#include "td/utils/common.h" - -namespace td { - -// dummy implementation which shouldn't be used - -template -class PollQueue { - public: - using ValueType = T; - - void init() { - UNREACHABLE(); - } - - template - void writer_put(PutValueType &&value) { - UNREACHABLE(); - } - - void writer_flush() { - UNREACHABLE(); - } - - int reader_wait_nonblock() { - UNREACHABLE(); - return 0; - } - - ValueType reader_get_unsafe() { - UNREACHABLE(); - return ValueType(); - } - - void reader_flush() { - UNREACHABLE(); - } - - PollQueue() = default; - PollQueue(const PollQueue &) = delete; - PollQueue &operator=(const PollQueue &) = delete; - PollQueue(PollQueue &&) = delete; - PollQueue &operator=(PollQueue &&) = delete; - ~PollQueue() = default; -}; - -} // namespace td - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tests.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/tests.cpp deleted file mode 100644 index 6263c60b..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tests.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/utils/crypto.h" -#include "td/utils/filesystem.h" -#include "td/utils/Parser.h" -#include "td/utils/PathView.h" -#include "td/utils/port/path.h" -#include "td/utils/port/Stat.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/StringBuilder.h" -#include "td/utils/Time.h" - -#include - -namespace td { - -struct TestInfo { - string name; - string result_hash; // base64 -}; -StringBuilder &operator<<(StringBuilder &sb, const TestInfo &info) { - // should I use JSON? - CHECK(!info.name.empty()); - CHECK(!info.result_hash.empty()); - return sb << info.name << " " << info.result_hash << "\n"; -} - -class RegressionTesterImpl : public RegressionTester { - public: - static void destroy(CSlice db_path) { - unlink(db_path).ignore(); - } - - RegressionTesterImpl(string db_path, string db_cache_dir) : db_path_(db_path), db_cache_dir_(db_cache_dir) { - load_db(db_path); - if (db_cache_dir_.empty()) { - db_cache_dir_ = PathView(db_path).without_extension().str() + ".cache/"; - } - mkdir(db_cache_dir_).ensure(); - } - - Status verify_test(Slice name, Slice result) override { -#if TD_HAVE_OPENSSL - auto hash = PSTRING() << format::as_hex_dump<0>(Slice(sha256(result))); -#else - auto hash = to_string(crc64(result)); -#endif - TestInfo &old_test_info = tests_[name.str()]; - if (!old_test_info.result_hash.empty() && old_test_info.result_hash != hash) { - auto wa_path = db_cache_dir_ + "WA"; - write_file(wa_path, result).ensure(); - return Status::Error(PSLICE() << "Test " << name << " changed: " << tag("expected", old_test_info.result_hash) - << tag("got", hash)); - } - auto result_cache_path = db_cache_dir_ + hash; - if (stat(result_cache_path).is_error()) { - write_file(result_cache_path, result).ensure(); - } - if (!old_test_info.result_hash.empty()) { - return Status::OK(); - } - old_test_info.name = name.str(); - old_test_info.result_hash = hash; - is_dirty_ = true; - - return Status::OK(); - } - - void save_db() override { - if (!is_dirty_) { - return; - } - SCOPE_EXIT { - is_dirty_ = false; - }; - string buf(2000000, ' '); - StringBuilder sb(buf); - save_db(sb); - string new_db_path = db_path_ + ".new"; - write_file(new_db_path, sb.as_cslice()).ensure(); - rename(new_db_path, db_path_).ensure(); - } - - Slice magic() const { - return Slice("abce"); - } - - void save_db(StringBuilder &sb) { - sb << magic() << "\n"; - for (auto it : tests_) { - sb << it.second; - } - } - - Status load_db(CSlice path) { - TRY_RESULT(data, read_file(path)); - ConstParser parser(data.as_slice()); - auto db_magic = parser.read_word(); - if (db_magic != magic()) { - return Status::Error(PSLICE() << "Wrong magic " << db_magic); - } - while (true) { - TestInfo info; - info.name = parser.read_word().str(); - if (info.name.empty()) { - break; - } - info.result_hash = parser.read_word().str(); - tests_[info.name] = info; - } - return Status::OK(); - } - - private: - string db_path_; - string db_cache_dir_; - bool is_dirty_{false}; - - std::map tests_; -}; - -void RegressionTester::destroy(CSlice path) { - RegressionTesterImpl::destroy(path); -} - -unique_ptr RegressionTester::create(string db_path, string db_cache_dir) { - return td::make_unique(std::move(db_path), std::move(db_cache_dir)); -} - -TestsRunner &TestsRunner::get_default() { - static TestsRunner default_runner; - return default_runner; -} - -void TestsRunner::add_test(string name, unique_ptr test) { - for (auto &it : tests_) { - if (it.first == name) { - LOG(FATAL) << "Test name collision " << name; - } - } - tests_.emplace_back(name, std::move(test)); -} - -void TestsRunner::add_substr_filter(string str) { - if (str[0] != '+' && str[0] != '-') { - str = "+" + str; - } - substr_filters_.push_back(std::move(str)); -} - -void TestsRunner::set_regression_tester(unique_ptr regression_tester) { - regression_tester_ = std::move(regression_tester); -} - -void TestsRunner::set_stress_flag(bool flag) { - stress_flag_ = flag; -} - -void TestsRunner::run_all() { - while (run_all_step()) { - } -} - -bool TestsRunner::run_all_step() { - Guard guard(this); - if (state_.it == state_.end) { - state_.end = tests_.size(); - state_.it = 0; - } - - while (state_.it != state_.end) { - auto &name = tests_[state_.it].first; - auto test = tests_[state_.it].second.get(); - if (!state_.is_running) { - bool ok = true; - for (const auto &filter : substr_filters_) { - bool is_match = name.find(filter.substr(1)) != string::npos; - if (is_match != (filter[0] == '+')) { - ok = false; - break; - } - } - if (!ok) { - ++state_.it; - continue; - } - LOG(ERROR) << "Run test " << tag("name", name); - state_.start = Time::now(); - state_.is_running = true; - } - - if (test->step()) { - break; - } - - LOG(ERROR) << format::as_time(Time::now() - state_.start); - if (regression_tester_) { - regression_tester_->save_db(); - } - state_.is_running = false; - ++state_.it; - } - - auto ret = state_.it != state_.end; - if (!ret) { - state_ = State(); - } - return ret || stress_flag_; -} - -Slice TestsRunner::name() { - CHECK(state_.is_running); - return tests_[state_.it].first; -} - -Status TestsRunner::verify(Slice data) { - if (!regression_tester_) { - LOG(INFO) << data; - LOG(ERROR) << "Cannot verify and save <" << name() << "> answer. Use --regression option"; - return Status::OK(); - } - return regression_tester_->verify_test(PSLICE() << name() << "_default", data); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tests.h b/submodules/ton/tonlib-src/tdutils/td/utils/tests.h deleted file mode 100644 index d7a6e343..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tests.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Context.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -#include -#include - -#define REGISTER_TESTS(x) \ - void TD_CONCAT(register_tests_, x)() { \ - } -#define DESC_TESTS(x) void TD_CONCAT(register_tests_, x)() -#define LOAD_TESTS(x) TD_CONCAT(register_tests_, x)() - -namespace td { - -class RandomSteps { - public: - struct Step { - std::function func; - td::uint32 weight; - }; - RandomSteps(std::vector steps) : steps_(std::move(steps)) { - for (auto &step : steps_) { - steps_sum_ += step.weight; - } - } - template - void step(Random &rnd) { - auto w = rnd() % steps_sum_; - for (auto &step : steps_) { - if (w < step.weight) { - step.func(); - break; - } - w -= step.weight; - } - } - - private: - std::vector steps_; - td::int32 steps_sum_ = 0; -}; - -class RegressionTester { - public: - virtual ~RegressionTester() = default; - static void destroy(CSlice db_path); - static unique_ptr create(string db_path, string db_cache_dir = ""); - - virtual Status verify_test(Slice name, Slice result) = 0; - virtual void save_db() = 0; -}; - -class Test { - public: - virtual ~Test() = default; - virtual void run() { - while (step()) { - } - } - virtual bool step() { - run(); - return false; - } - Test() = default; - Test(const Test &) = delete; - Test &operator=(const Test &) = delete; - Test(Test &&) = delete; - Test &operator=(Test &&) = delete; -}; - -class TestContext : public Context { - public: - virtual ~TestContext() = default; - virtual Slice name() = 0; - virtual Status verify(Slice data) = 0; -}; - -class TestsRunner : public TestContext { - public: - static TestsRunner &get_default(); - - void add_test(string name, unique_ptr test); - void add_substr_filter(string str); - void set_stress_flag(bool flag); - void run_all(); - bool run_all_step(); - void set_regression_tester(unique_ptr regression_tester); - - private: - struct State { - size_t it{0}; - bool is_running = false; - double start{0}; - size_t end{0}; - }; - bool stress_flag_{false}; - vector substr_filters_; - vector>> tests_; - State state_; - unique_ptr regression_tester_; - - Slice name() override; - Status verify(Slice data) override; -}; - -template -class RegisterTest { - public: - RegisterTest(string name, TestsRunner &runner = TestsRunner::get_default()) { - runner.add_test(name, make_unique()); - } -}; - -class Stage { - public: - void wait(uint64 need) { - value_.fetch_add(1, std::memory_order_release); - while (value_.load(std::memory_order_acquire) < need) { - td::this_thread::yield(); - } - }; - - private: - std::atomic value_{0}; -}; - -inline string rand_string(char from, char to, int len) { - string res(len, 0); - for (auto &c : res) { - c = static_cast(Random::fast(from, to)); - } - return res; -} - -inline vector rand_split(Slice str) { - vector res; - size_t pos = 0; - while (pos < str.size()) { - size_t len; - if (Random::fast(0, 1) == 1) { - len = Random::fast(1, 10); - } else { - len = Random::fast(100, 200); - } - res.push_back(str.substr(pos, len).str()); - pos += len; - } - return res; -} - -template -void assert_eq_impl(const T1 &expected, const T2 &got, const char *file, int line) { - LOG_CHECK(expected == got) << tag("expected", expected) << tag("got", got) << " in " << file << " at line " << line; -} - -template -void assert_true_impl(const T &got, const char *file, int line) { - LOG_CHECK(got) << "Expected true in " << file << " at line " << line; -} - -} // namespace td - -#define ASSERT_EQ(expected, got) ::td::assert_eq_impl((expected), (got), __FILE__, __LINE__) - -#define ASSERT_TRUE(got) ::td::assert_true_impl((got), __FILE__, __LINE__) - -#define ASSERT_STREQ(expected, got) \ - ::td::assert_eq_impl(::td::Slice((expected)), ::td::Slice((got)), __FILE__, __LINE__) - -#define REGRESSION_VERIFY(data) ::td::TestContext::get()->verify(data).ensure() - -#define TEST_NAME(test_case_name, test_name) \ - TD_CONCAT(Test, TD_CONCAT(_, TD_CONCAT(test_case_name, TD_CONCAT(_, test_name)))) - -#define TEST(test_case_name, test_name) TEST_IMPL(TEST_NAME(test_case_name, test_name)) - -#define TEST_IMPL(test_name) \ - class test_name : public ::td::Test { \ - public: \ - using Test::Test; \ - void run() final; \ - }; \ - ::td::RegisterTest TD_CONCAT(test_instance_, TD_CONCAT(test_name, __LINE__))(TD_DEFINE_STR(test_name)); \ - void test_name::run() diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tl_helpers.h b/submodules/ton/tonlib-src/tdutils/td/utils/tl_helpers.h deleted file mode 100644 index b44ac6c4..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tl_helpers.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Slice.h" -#include "td/utils/SharedSlice.h" -#include "td/utils/StackAllocator.h" -#include "td/utils/Status.h" -#include "td/utils/tl_parsers.h" -#include "td/utils/tl_storers.h" -#include "td/utils/Variant.h" - -#include -#include - -#define BEGIN_STORE_FLAGS() \ - do { \ - td::uint32 flags_store = 0; \ - td::uint32 bit_offset_store = 0 - -#define STORE_FLAG(flag) \ - flags_store |= (flag) << bit_offset_store; \ - bit_offset_store++ - -#define END_STORE_FLAGS() \ - CHECK(bit_offset_store < 31); \ - td::store(flags_store, storer); \ - } \ - while (false) - -#define BEGIN_PARSE_FLAGS() \ - do { \ - td::uint32 flags_parse; \ - td::uint32 bit_offset_parse = 0; \ - td::parse(flags_parse, parser) - -#define PARSE_FLAG(flag) \ - flag = ((flags_parse >> bit_offset_parse) & 1) != 0; \ - bit_offset_parse++ - -#define END_PARSE_FLAGS() \ - CHECK(bit_offset_parse < 31); \ - if ((flags_parse & ~((1 << bit_offset_parse) - 1)) != 0) { \ - parser.set_error(PSTRING() << "Invalid flags " << flags_parse << " left, current bit is " << bit_offset_parse); \ - } \ - } \ - while (false) - -namespace td { - -template -void store(bool x, StorerT &storer) { - storer.store_binary(static_cast(x)); -} -template -void parse(bool &x, ParserT &parser) { - x = parser.fetch_int() != 0; -} - -template -void store(int32 x, StorerT &storer) { - storer.store_binary(x); -} -template -void parse(int32 &x, ParserT &parser) { - x = parser.fetch_int(); -} - -template -void store(uint32 x, StorerT &storer) { - storer.store_binary(x); -} -template -void parse(uint32 &x, ParserT &parser) { - x = static_cast(parser.fetch_int()); -} - -template -void store(int64 x, StorerT &storer) { - storer.store_binary(x); -} -template -void parse(int64 &x, ParserT &parser) { - x = parser.fetch_long(); -} -template -void store(uint64 x, StorerT &storer) { - storer.store_binary(x); -} -template -void parse(uint64 &x, ParserT &parser) { - x = static_cast(parser.fetch_long()); -} - -template -void store(double x, StorerT &storer) { - storer.store_binary(x); -} -template -void parse(double &x, ParserT &parser) { - x = parser.fetch_double(); -} - -template -void store(Slice x, StorerT &storer) { - storer.store_string(x); -} -template -void store(const string &x, StorerT &storer) { - storer.store_string(x); -} -template -void store(const SecureString &x, StorerT &storer) { - storer.store_string(x.as_slice()); -} -template -void parse(string &x, ParserT &parser) { - x = parser.template fetch_string(); -} - -template -void parse(SecureString &x, ParserT &parser) { - x = parser.template fetch_string(); -} - -template -void store(const vector &vec, StorerT &storer) { - storer.store_binary(narrow_cast(vec.size())); - for (auto &val : vec) { - store(val, storer); - } -} -template -void parse(vector &vec, ParserT &parser) { - uint32 size = parser.fetch_int(); - if (parser.get_left_len() < size) { - parser.set_error("Wrong vector length"); - return; - } - vec = vector(size); - for (auto &val : vec) { - parse(val, parser); - } -} - -template -void store(const std::unordered_set &s, StorerT &storer) { - storer.store_binary(narrow_cast(s.size())); - for (auto &val : s) { - store(val, storer); - } -} -template -void parse(std::unordered_set &s, ParserT &parser) { - uint32 size = parser.fetch_int(); - if (parser.get_left_len() < size) { - parser.set_error("Wrong set length"); - return; - } - s.clear(); - for (uint32 i = 0; i < size; i++) { - Key val; - parse(val, parser); - s.insert(std::move(val)); - } -} - -template -std::enable_if_t::value> store(const T &val, StorerT &storer) { - store(static_cast(val), storer); -} -template -std::enable_if_t::value> parse(T &val, ParserT &parser) { - int32 result; - parse(result, parser); - val = static_cast(result); -} - -template -std::enable_if_t::value> store(const T &val, StorerT &storer) { - val.store(storer); -} -template -std::enable_if_t::value> parse(T &val, ParserT &parser) { - val.parse(parser); -} - -template -void store(const Variant &variant, StorerT &storer) { - store(variant.get_offset(), storer); - variant.visit([&storer](auto &&value) { - using td::store; - store(value, storer); - }); -} -template -void parse(Variant &variant, ParserT &parser) { - auto type_offset = parser.fetch_int(); - if (type_offset < 0 || type_offset >= static_cast(sizeof...(Types))) { - return parser.set_error("Invalid type"); - } - variant.for_each([type_offset, &parser, &variant](int offset, auto *ptr) { - using T = std::decay_t; - if (offset == type_offset) { - variant = T(); - parse(variant.template get(), parser); - } - }); -} - -template -string serialize(const T &object) { - TlStorerCalcLength calc_length; - store(object, calc_length); - size_t length = calc_length.get_length(); - - string key(length, '\0'); - if (!is_aligned_pointer<4>(key.data())) { - auto ptr = StackAllocator::alloc(length); - MutableSlice data = ptr.as_slice(); - TlStorerUnsafe storer(data.ubegin()); - store(object, storer); - CHECK(storer.get_buf() == data.uend()); - key.assign(data.begin(), data.size()); - } else { - MutableSlice data = key; - TlStorerUnsafe storer(data.ubegin()); - store(object, storer); - CHECK(storer.get_buf() == data.uend()); - } - return key; -} - -template -SecureString serialize_secure(const T &object) { - TlStorerCalcLength calc_length; - store(object, calc_length); - size_t length = calc_length.get_length(); - - SecureString key(length, '\0'); - CHECK(is_aligned_pointer<4>(key.data())); - MutableSlice data = key.as_mutable_slice(); - TlStorerUnsafe storer(data.ubegin()); - store(object, storer); - CHECK(storer.get_buf() == data.uend()); - return key; -} - -template -TD_WARN_UNUSED_RESULT Status unserialize(T &object, Slice data) { - TlParser parser(data); - parse(object, parser); - parser.fetch_end(); - return parser.get_status(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.cpp deleted file mode 100644 index af660964..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tl_parsers.h" - -namespace td { - -alignas(4) const unsigned char TlParser::empty_data[sizeof(UInt256)] = {}; // static zero-initialized - -void TlParser::set_error(const string &error_message) { - if (error.empty()) { - CHECK(!error_message.empty()); - error = error_message; - error_pos = data_len - left_len; - data = empty_data; - left_len = 0; - data_len = 0; - } else { - data = empty_data; - CHECK(error_pos != std::numeric_limits::max()); - LOG_CHECK(data_len == 0) << data_len << " " << left_len << " " << data << " " << &empty_data[0] << " " << error_pos - << " " << error; - CHECK(left_len == 0); - } -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.h b/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.h deleted file mode 100644 index 8f13492c..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tl_parsers.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/buffer.h" -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/UInt.h" -#include "td/utils/utf8.h" - -#include -#include -#include -#include -#include - -namespace td { - -class TlParser { - const unsigned char *data = nullptr; - size_t data_len = 0; - size_t left_len = 0; - size_t error_pos = std::numeric_limits::max(); - std::string error; - - std::unique_ptr data_buf; - static constexpr size_t SMALL_DATA_ARRAY_SIZE = 6; - std::array small_data_array; - - alignas(4) static const unsigned char empty_data[sizeof(UInt256)]; - - public: - explicit TlParser(Slice slice) { - data_len = left_len = slice.size(); - if (is_aligned_pointer<4>(slice.begin())) { - data = slice.ubegin(); - } else { - int32 *buf; - if (data_len <= small_data_array.size() * sizeof(int32)) { - buf = &small_data_array[0]; - } else { - LOG(ERROR) << "Unexpected big unaligned data pointer of length " << slice.size() << " at " << slice.begin(); - data_buf = std::make_unique(1 + data_len / sizeof(int32)); - buf = data_buf.get(); - } - std::memcpy(buf, slice.begin(), slice.size()); - data = reinterpret_cast(buf); - } - } - - TlParser(const TlParser &other) = delete; - TlParser &operator=(const TlParser &other) = delete; - - void set_error(const string &error_message); - - const char *get_error() const { - if (error.empty()) { - return nullptr; - } - return error.c_str(); - } - - size_t get_error_pos() const { - return error_pos; - } - - Status get_status() const { - if (error.empty()) { - return Status::OK(); - } - return Status::Error(PSLICE() << error << " at " << error_pos); - } - - void check_len(const size_t len) { - if (unlikely(left_len < len)) { - set_error("Not enough data to read"); - } else { - left_len -= len; - } - } - - bool can_prefetch_int() const { - return get_left_len() >= sizeof(int32); - } - - int32 prefetch_int_unsafe() const { - int32 result; - std::memcpy(&result, data, sizeof(int32)); - return result; - } - - int32 fetch_int_unsafe() { - int32 result; - std::memcpy(&result, data, sizeof(int32)); - data += sizeof(int32); - return result; - } - - int32 fetch_int() { - check_len(sizeof(int32)); - return fetch_int_unsafe(); - } - - int64 fetch_long_unsafe() { - int64 result; - std::memcpy(&result, data, sizeof(int64)); - data += sizeof(int64); - return result; - } - - int64 fetch_long() { - check_len(sizeof(int64)); - return fetch_long_unsafe(); - } - - double fetch_double_unsafe() { - double result; - std::memcpy(&result, data, sizeof(double)); - data += sizeof(double); - return result; - } - - double fetch_double() { - check_len(sizeof(double)); - return fetch_double_unsafe(); - } - - template - T fetch_binary_unsafe() { - T result; - std::memcpy(&result, data, sizeof(T)); - data += sizeof(T); - return result; - } - - template - T fetch_binary() { - static_assert(sizeof(T) <= sizeof(empty_data), "too big fetch_binary"); - //static_assert(sizeof(T) % sizeof(int32) == 0, "wrong call to fetch_binary"); - check_len(sizeof(T)); - return fetch_binary_unsafe(); - } - - template - T fetch_string() { - check_len(sizeof(int32)); - size_t result_len = *data; - const char *result_begin; - size_t result_aligned_len; - if (result_len < 254) { - result_begin = reinterpret_cast(data + 1); - result_aligned_len = (result_len >> 2) << 2; - data += sizeof(int32); - } else if (result_len == 254) { - result_len = data[1] + (data[2] << 8) + (data[3] << 16); - result_begin = reinterpret_cast(data + 4); - result_aligned_len = ((result_len + 3) >> 2) << 2; - data += sizeof(int32); - } else { - check_len(sizeof(int32)); - result_len = narrow_cast(data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24) + - (static_cast(data[5]) << 32) + (static_cast(data[6]) << 40) + - (static_cast(data[7]) << 48)); - if (result_len > std::numeric_limits::max() - 3) { - set_error("Too big string found"); - return T(); - } - result_begin = reinterpret_cast(data + 8); - result_aligned_len = ((result_len + 3) >> 2) << 2; - data += sizeof(int64); - } - check_len(result_aligned_len); - if (!error.empty()) { - return T(); - } - data += result_aligned_len; - return T(result_begin, result_len); - } - - template - T fetch_string_raw(const size_t size) { - //CHECK(size % sizeof(int32) == 0); - check_len(size); - if (!error.empty()) { - return T(); - } - const char *result = reinterpret_cast(data); - data += size; - return T(result, size); - } - - void fetch_end() { - if (left_len) { - set_error("Too much data to fetch"); - } - } - - size_t get_left_len() const { - return left_len; - } -}; - -class TlBufferParser : public TlParser { - public: - explicit TlBufferParser(const BufferSlice *buffer_slice) : TlParser(buffer_slice->as_slice()), parent_(buffer_slice) { - } - template - T fetch_string() { - auto result = TlParser::fetch_string(); - for (auto &c : result) { - if (c == '\0') { - c = ' '; - } - } - if (check_utf8(result)) { - return result; - } - CHECK(!result.empty()); - LOG(WARNING) << "Wrong UTF-8 string [[" << result << "]] in " << format::as_hex_dump<4>(parent_->as_slice()); - - // trying to remove last character - size_t new_size = result.size() - 1; - while (new_size != 0 && !is_utf8_character_first_code_unit(static_cast(result[new_size]))) { - new_size--; - } - result.resize(new_size); - if (check_utf8(result)) { - return result; - } - - return T(); - } - template - T fetch_string_raw(const size_t size) { - return TlParser::fetch_string_raw(size); - } - - private: - const BufferSlice *parent_; - - BufferSlice as_buffer_slice(Slice slice) { - if (is_aligned_pointer<4>(slice.data())) { - return parent_->from_slice(slice); - } - return BufferSlice(slice); - } -}; - -template <> -inline BufferSlice TlBufferParser::fetch_string() { - return as_buffer_slice(TlParser::fetch_string()); -} - -template <> -inline BufferSlice TlBufferParser::fetch_string_raw(const size_t size) { - return as_buffer_slice(TlParser::fetch_string_raw(size)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tl_storers.h b/submodules/ton/tonlib-src/tdutils/td/utils/tl_storers.h deleted file mode 100644 index 3190fb05..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tl_storers.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/SharedSlice.h" -#include "td/utils/Slice.h" -#include "td/utils/StorerBase.h" -#include "td/utils/UInt.h" - -//FIXME -#include "crypto/common/bitstring.h" - -#include - -namespace td { - -class TlStorerUnsafe { - unsigned char *buf_; - - public: - explicit TlStorerUnsafe(unsigned char *buf) : buf_(buf) { - LOG_CHECK(is_aligned_pointer<4>(buf_)) << buf_; - } - - TlStorerUnsafe(const TlStorerUnsafe &other) = delete; - TlStorerUnsafe &operator=(const TlStorerUnsafe &other) = delete; - - template - void store_binary(const T &x) { - std::memcpy(buf_, &x, sizeof(T)); - buf_ += sizeof(T); - } - - void store_int(int32 x) { - store_binary(x); - } - - void store_long(int64 x) { - store_binary(x); - } - - void store_slice(Slice slice) { - std::memcpy(buf_, slice.begin(), slice.size()); - buf_ += slice.size(); - } - void store_storer(const Storer &storer) { - size_t size = storer.store(buf_); - buf_ += size; - } - - template - void store_string(const T &str) { - size_t len = str.size(); - if (len < 254) { - *buf_++ = static_cast(len); - len++; - } else if (len < (1 << 24)) { - *buf_++ = static_cast(254); - *buf_++ = static_cast(len & 255); - *buf_++ = static_cast((len >> 8) & 255); - *buf_++ = static_cast(len >> 16); - } else if (len < (1ull << 32)) { - *buf_++ = static_cast(255); - *buf_++ = static_cast(len & 255); - *buf_++ = static_cast((len >> 8) & 255); - *buf_++ = static_cast((len >> 16) & 255); - *buf_++ = static_cast((len >> 24) & 255); - *buf_++ = static_cast(0); - *buf_++ = static_cast(0); - *buf_++ = static_cast(0); - } else { - LOG(FATAL) << "String size " << len << " is too big to be stored"; - } - std::memcpy(buf_, str.data(), str.size()); - buf_ += str.size(); - - switch (len & 3) { - case 1: - *buf_++ = 0; - // fallthrough - case 2: - *buf_++ = 0; - // fallthrough - case 3: - *buf_++ = 0; - } - } - - unsigned char *get_buf() const { - return buf_; - } -}; - -class TlStorerCalcLength { - size_t length = 0; - - public: - TlStorerCalcLength() = default; - TlStorerCalcLength(const TlStorerCalcLength &other) = delete; - TlStorerCalcLength &operator=(const TlStorerCalcLength &other) = delete; - - template - void store_binary(const T &x) { - length += sizeof(T); - } - - void store_int(int32 x) { - store_binary(x); - } - - void store_long(int64 x) { - store_binary(x); - } - - void store_slice(Slice slice) { - length += slice.size(); - } - - void store_storer(const Storer &storer) { - length += storer.size(); - } - - template - void store_string(const T &str) { - size_t add = str.size(); - if (add < 254) { - add += 1; - } else if (add < (1 << 24)) { - add += 4; - } else { - add += 8; - } - add = (add + 3) & -4; - length += add; - } - - size_t get_length() const { - return length; - } -}; - -class TlStorerToString { - std::string result; - int shift = 0; - - void store_field_begin(const char *name) { - for (int i = 0; i < shift; i++) { - result += ' '; - } - if (name && name[0]) { - result += name; - result += " = "; - } - } - - void store_field_end() { - result += "\n"; - } - - void store_long(int64 value) { - result += (PSLICE() << value).c_str(); - } - - void store_binary(Slice data) { - static const char *hex = "0123456789ABCDEF"; - - result.append("{ "); - for (auto c : data) { - unsigned char byte = c; - result += hex[byte >> 4]; - result += hex[byte & 15]; - result += ' '; - } - result.append("}"); - } - - public: - TlStorerToString() = default; - TlStorerToString(const TlStorerToString &other) = delete; - TlStorerToString &operator=(const TlStorerToString &other) = delete; - - void store_field(const char *name, bool value) { - store_field_begin(name); - result += (value ? "true" : "false"); - store_field_end(); - } - - void store_field(const char *name, int32 value) { - store_field(name, static_cast(value)); - } - - void store_field(const char *name, int64 value) { - store_field_begin(name); - store_long(value); - store_field_end(); - } - - void store_field(const char *name, double value) { - store_field_begin(name); - result += (PSLICE() << value).c_str(); - store_field_end(); - } - - void store_field(const char *name, const char *value) { - store_field_begin(name); - result += value; - store_field_end(); - } - - void store_field(const char *name, const string &value) { - store_field_begin(name); - result += '"'; - result.append(value.data(), value.size()); - result += '"'; - store_field_end(); - } - - void store_field(const char *name, const SecureString &value) { - store_field_begin(name); - result.append(""); - store_field_end(); - } - - template - void store_field(const char *name, const T &value) { - store_field_begin(name); - result.append(value.data(), value.size()); - store_field_end(); - } - - void store_bytes_field(const char *name, const SecureString &value) { - store_field_begin(name); - result.append(""); - store_field_end(); - } - - template - void store_bytes_field(const char *name, const BytesT &value) { - static const char *hex = "0123456789ABCDEF"; - - store_field_begin(name); - result.append("bytes ["); - store_long(static_cast(value.size())); - result.append("] { "); - size_t len = min(static_cast(64), value.size()); - for (size_t i = 0; i < len; i++) { - int b = value[static_cast(i)] & 0xff; - result += hex[b >> 4]; - result += hex[b & 15]; - result += ' '; - } - if (len < value.size()) { - result.append("..."); - } - result += '}'; - store_field_end(); - } - - //FIXME - void store_field(const char *name, const Bits128 &value) { - store_field_begin(name); - store_binary(as_slice(value)); - store_field_end(); - } - - void store_field(const char *name, const Bits256 &value) { - store_field_begin(name); - store_binary(as_slice(value)); - store_field_end(); - } - - void store_field(const char *name, const UInt128 &value) { - store_field_begin(name); - store_binary(as_slice(value)); - store_field_end(); - } - - void store_field(const char *name, const UInt256 &value) { - store_field_begin(name); - store_binary(as_slice(value)); - store_field_end(); - } - - void store_class_begin(const char *field_name, const char *class_name) { - store_field_begin(field_name); - result += class_name; - result += " {\n"; - shift += 2; - } - - void store_class_end() { - shift -= 2; - for (int i = 0; i < shift; i++) { - result += ' '; - } - result += "}\n"; - CHECK(shift >= 0); - } - - std::string str() const { - return result; - } -}; - -template -size_t tl_calc_length(const T &data) { - TlStorerCalcLength storer_calc_length; - data.store(storer_calc_length); - return storer_calc_length.get_length(); -} - -template -size_t tl_store_unsafe(const T &data, unsigned char *dst) TD_WARN_UNUSED_RESULT; - -template -size_t tl_store_unsafe(const T &data, unsigned char *dst) { - TlStorerUnsafe storer_unsafe(dst); - data.store(storer_unsafe); - return static_cast(storer_unsafe.get_buf() - dst); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/translit.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/translit.cpp deleted file mode 100644 index f63e0e91..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/translit.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/translit.h" - -#include "td/utils/misc.h" -#include "td/utils/utf8.h" - -#include -#include -#include - -namespace td { - -static const std::unordered_map &get_en_to_ru_simple_rules() { - static const std::unordered_map rules{ - {'a', "а"}, {'b', "б"}, {'c', "к"}, {'d', "д"}, {'e', "е"}, {'f', "ф"}, {'g', "г"}, {'h', "х"}, {'i', "и"}, - {'j', "й"}, {'k', "к"}, {'l', "л"}, {'m', "м"}, {'n', "н"}, {'o', "о"}, {'p', "п"}, {'q', "к"}, {'r', "р"}, - {'s', "с"}, {'t', "т"}, {'u', "у"}, {'v', "в"}, {'w', "в"}, {'x', "кс"}, {'y', "и"}, {'z', "з"}}; - return rules; -} - -static const std::vector> &get_en_to_ru_complex_rules() { - static const std::vector> rules{ - {"ch", "ч"}, {"ei", "ей"}, {"ey", "ей"}, {"ia", "ия"}, {"iy", "ий"}, {"jo", "е"}, - {"ju", "ю"}, {"ja", "я"}, {"kh", "х"}, {"shch", "щ"}, {"sh", "ш"}, {"sch", "щ"}, - {"ts", "ц"}, {"yo", "е"}, {"yu", "ю"}, {"ya", "я"}, {"zh", "ж"}}; - return rules; -} - -static const std::unordered_map &get_ru_to_en_simple_rules() { - static const std::unordered_map rules{ - {0x430, "a"}, {0x431, "b"}, {0x432, "v"}, {0x433, "g"}, {0x434, "d"}, {0x435, "e"}, {0x451, "e"}, - {0x436, "zh"}, {0x437, "z"}, {0x438, "i"}, {0x439, "y"}, {0x43a, "k"}, {0x43b, "l"}, {0x43c, "m"}, - {0x43d, "n"}, {0x43e, "o"}, {0x43f, "p"}, {0x440, "r"}, {0x441, "s"}, {0x442, "t"}, {0x443, "u"}, - {0x444, "f"}, {0x445, "kh"}, {0x446, "ts"}, {0x447, "ch"}, {0x448, "sh"}, {0x449, "sch"}, {0x44a, ""}, - {0x44b, "y"}, {0x44c, ""}, {0x44d, "e"}, {0x44e, "yu"}, {0x44f, "ya"}}; - return rules; -} - -static const std::vector> &get_ru_to_en_complex_rules() { - static const std::vector> rules{ - {"ий", "y"}, {"ия", "ia"}, {"кс", "x"}, {"yo", "e"}, {"jo", "e"}}; - return rules; -} - -void add_word_transliterations(vector &result, Slice word, bool allow_partial, - const std::unordered_map &simple_rules, - const std::vector> &complex_rules) { - string s; - auto pos = word.ubegin(); - auto end = word.uend(); - while (pos != end) { - uint32 code; - pos = next_utf8_unsafe(pos, &code, "add_word_transliterations"); - auto it = simple_rules.find(code); - if (it != simple_rules.end()) { - s += it->second; - } else { - append_utf8_character(s, code); - } - } - if (!s.empty()) { - result.push_back(std::move(s)); - s.clear(); - } - - pos = word.ubegin(); - while (pos != end) { - auto suffix = Slice(pos, end); - bool found = false; - for (auto &rule : complex_rules) { - if (begins_with(suffix, rule.first)) { - found = true; - pos += rule.first.size(); - s.append(rule.second); - break; - } - if (allow_partial && begins_with(rule.first, suffix)) { - result.push_back(s + rule.second); - } - } - if (found) { - continue; - } - - uint32 code; - pos = next_utf8_unsafe(pos, &code, "add_word_transliterations 2"); - auto it = simple_rules.find(code); - if (it != simple_rules.end()) { - s += it->second; - } else { - append_utf8_character(s, code); - } - } - if (!s.empty()) { - result.push_back(std::move(s)); - } -} - -vector get_word_transliterations(Slice word, bool allow_partial) { - vector result; - - add_word_transliterations(result, word, allow_partial, get_en_to_ru_simple_rules(), get_en_to_ru_complex_rules()); - add_word_transliterations(result, word, allow_partial, get_ru_to_en_simple_rules(), get_ru_to_en_complex_rules()); - - std::sort(result.begin(), result.end()); - result.erase(std::unique(result.begin(), result.end()), result.end()); - return result; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/translit.h b/submodules/ton/tonlib-src/tdutils/td/utils/translit.h deleted file mode 100644 index dd8a1f72..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/translit.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" - -namespace td { - -vector get_word_transliterations(Slice word, bool allow_partial); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/type_traits.h b/submodules/ton/tonlib-src/tdutils/td/utils/type_traits.h deleted file mode 100644 index f9ced606..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/type_traits.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -namespace td { - -template -struct member_function_class; - -template -struct member_function_class { - using type = Type; - static constexpr size_t argument_count() { - return sizeof...(Args); - } -}; - -template -using member_function_class_t = typename member_function_class::type; - -template -constexpr size_t member_function_argument_count() { - return member_function_class::argument_count(); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/uint128.h b/submodules/ton/tonlib-src/tdutils/td/utils/uint128.h deleted file mode 100644 index 8e17493a..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/uint128.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/bits.h" -#include "td/utils/common.h" - -#include -#include - -namespace td { - -class uint128_emulated { - public: - using uint128 = uint128_emulated; - uint128_emulated(uint64 hi, uint64 lo) : hi_(hi), lo_(lo) { - } - template ::value>> - uint128_emulated(T lo) : uint128_emulated(0, lo) { - } - uint128_emulated() = default; - - uint64 hi() const { - return hi_; - } - uint64 lo() const { - return lo_; - } - uint64 rounded_hi() const { - return hi_ + (lo_ >> 63); - } - static uint128 from_signed(int64 x) { - if (x >= 0) { - return uint128(0, x); - } - return uint128(std::numeric_limits::max(), static_cast(x)); - } - static uint128 from_unsigned(uint64 x) { - return uint128(0, x); - } - - uint128 add(uint128 other) const { - uint128 res(other.hi() + hi(), other.lo() + lo()); - if (res.lo() < lo()) { - res.hi_++; - } - return res; - } - - uint128 shl(int cnt) const { - if (cnt == 0) { - return *this; - } - if (cnt < 64) { - return uint128((hi() << cnt) | (lo() >> (64 - cnt)), lo() << cnt); - } - if (cnt < 128) { - return uint128(lo() << (cnt - 64), 0); - } - return uint128(); - } - uint128 shr(int cnt) const { - if (cnt == 0) { - return *this; - } - if (cnt < 64) { - return uint128(hi() >> cnt, (lo() >> cnt) | (hi() << (64 - cnt))); - } - if (cnt < 128) { - return uint128(0, hi() >> (cnt - 64)); - } - return uint128(); - } - - uint128 mult(uint128 other) const { - uint64 a_lo = lo() & 0xffffffff; - uint64 a_hi = lo() >> 32; - uint64 b_lo = other.lo() & 0xffffffff; - uint64 b_hi = other.lo() >> 32; - uint128 res(lo() * other.hi() + hi() * other.lo() + a_hi * b_hi, a_lo * b_lo); - uint128 add1(0, a_lo * b_hi); - uint128 add2(0, a_hi * b_lo); - return res.add(add1.shl(32)).add(add2.shl(32)); - } - uint128 mult(uint64 other) const { - return mult(uint128(0, other)); - } - uint128 mult_signed(int64 other) const { - return mult(uint128::from_signed(other)); - } - bool is_zero() const { - return lo() == 0 && hi() == 0; - } - uint128 sub(uint128 other) const { - uint32 carry = 0; - if (other.lo() > lo()) { - carry = 1; - } - return uint128(hi() - other.hi() - carry, lo() - other.lo()); - } - void divmod(uint128 other, uint128 *div_res, uint128 *mod_res) const { - CHECK(!other.is_zero()); - - auto from = *this; - auto ctz = from.count_leading_zeroes(); - auto other_ctz = other.count_leading_zeroes(); - if (ctz > other_ctz) { - *div_res = uint128(); - *mod_res = from; - return; - } - auto shift = other_ctz - ctz; - auto res = uint128(); - for (int i = shift; i >= 0; i--) { - auto sub = other.shl(i); - res = res.shl(1); - if (from.greater_or_equal(sub)) { - from = from.sub(sub); - res = res.set_lower_bit(); - } - } - - *div_res = res; - *mod_res = from; - } - uint128 div(uint128 other) const { - uint128 a, b; - divmod(other, &a, &b); - return a; - } - uint128 mod(uint128 other) const { - uint128 a, b; - divmod(other, &a, &b); - return b; - } - - void divmod_signed(int64 y, int64 *quot, int64 *rem) const { - CHECK(y != 0); - auto x = *this; - int x_sgn = x.is_negative(); - int y_sgn = y < 0; - if (x_sgn) { - x = x.negate(); - } - uint128 uy = from_signed(y); - if (uy.is_negative()) { - uy = uy.negate(); - } - - uint128 t_quot, t_mod; - x.divmod(uy, &t_quot, &t_mod); - *quot = t_quot.lo(); - *rem = t_mod.lo(); - if (x_sgn != y_sgn) { - *quot = -*quot; - } - if (x_sgn) { - *rem = -*rem; - } - } - - private: - uint64 hi_{0}; - uint64 lo_{0}; - - bool is_negative() const { - return (hi_ >> 63) == 1; - } - - int32 count_leading_zeroes() const { - if (hi() == 0) { - return 64 + count_leading_zeroes64(lo()); - } - return count_leading_zeroes64(hi()); - } - uint128 set_lower_bit() const { - return uint128(hi(), lo() | 1); - } - bool greater_or_equal(uint128 other) const { - return hi() > other.hi() || (hi() == other.hi() && lo() >= other.lo()); - } - uint128 negate() const { - uint128 res(~hi(), ~lo() + 1); - if (res.lo() == 0) { - return uint128(res.hi() + 1, 0); - } - return res; - } -}; - -#if TD_HAVE_INT128 -class uint128_intrinsic { - public: - using ValueT = unsigned __int128; - using uint128 = uint128_intrinsic; - explicit uint128_intrinsic(ValueT value) : value_(value) { - } - uint128_intrinsic(uint64 hi, uint64 lo) : value_((ValueT(hi) << 64) | lo) { - } - uint128_intrinsic() = default; - - static uint128 from_signed(int64 x) { - return uint128(static_cast(x)); - } - static uint128 from_unsigned(uint64 x) { - return uint128(static_cast(x)); - } - uint64 hi() const { - return uint64(value() >> 64); - } - uint64 lo() const { - return uint64(value() & std::numeric_limits::max()); - } - uint64 rounded_hi() const { - return uint64((value() + (1ULL << 63)) >> 64); - } - uint128 add(uint128 other) const { - return uint128(value() + other.value()); - } - uint128 sub(uint128 other) const { - return uint128(value() - other.value()); - } - - uint128 shl(int cnt) const { - if (cnt >= 128) { - return uint128(); - } - return uint128(value() << cnt); - } - - uint128 shr(int cnt) const { - if (cnt >= 128) { - return uint128(); - } - return uint128(value() >> cnt); - } - - uint128 mult(uint128 other) const { - return uint128(value() * other.value()); - } - uint128 mult(uint64 other) const { - return uint128(value() * other); - } - uint128 mult_signed(int64 other) const { - return uint128(value() * other); - } - bool is_zero() const { - return value() == 0; - } - void divmod(uint128 other, uint128 *div_res, uint128 *mod_res) const { - CHECK(!other.is_zero()); - *div_res = uint128(value() / other.value()); - *mod_res = uint128(value() % other.value()); - } - uint128 div(uint128 other) const { - CHECK(!other.is_zero()); - return uint128(value() / other.value()); - } - uint128 mod(uint128 other) const { - CHECK(!other.is_zero()); - return uint128(value() % other.value()); - } - void divmod_signed(int64 y, int64 *quot, int64 *rem) const { - CHECK(y != 0); - *quot = (int64)(signed_value() / y); - *rem = (int64)(signed_value() % y); - } - - private: - unsigned __int128 value_{0}; - ValueT value() const { - return value_; - } - __int128 signed_value() const { - return static_cast<__int128>(value()); - } -}; -#endif - -#if TD_HAVE_INT128 -using uint128 = uint128_intrinsic; -#else -using uint128 = uint128_emulated; -#endif - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/unicode.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/unicode.cpp deleted file mode 100644 index 6e98592d..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/unicode.cpp +++ /dev/null @@ -1,1194 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/unicode.h" - -#include "td/utils/logging.h" - -#include -#include - -namespace td { - -// list of [(range_begin << 5) + range_type] -static const uint32 unicode_simple_category_ranges[] = { - 0, 1028, 1056, 1538, 1856, 2081, 2912, 3105, 3936, 5124, 5152, 5441, - 5472, 5699, 5760, 5793, 5824, 5923, 5953, 5984, 6019, 6112, 6145, 6880, - 6913, 7904, 7937, 22592, 22721, 23104, 23553, 23712, 23937, 23968, 24001, 24032, - 28161, 28320, 28353, 28416, 28481, 28608, 28641, 28672, 28865, 28896, 28929, 29024, - 29057, 29088, 29121, 29760, 29793, 32448, 32481, 36928, 37185, 42496, 42529, 43744, - 43809, 43840, 44065, 45312, 47617, 48480, 48641, 48736, 50177, 51552, 52226, 52544, - 52673, 52736, 52769, 55936, 55969, 56000, 56481, 56544, 56769, 56834, 57153, 57248, - 57313, 57344, 57857, 57888, 57921, 58880, 59809, 62656, 63009, 63040, 63490, 63809, - 64864, 65153, 65216, 65345, 65376, 65537, 66240, 66369, 66400, 66689, 66720, 66817, - 66848, 67585, 68384, 70657, 71328, 71361, 71616, 73857, 75584, 75681, 75712, 76289, - 76320, 76545, 76864, 76994, 77312, 77345, 77856, 77985, 78240, 78305, 78368, 78433, - 79136, 79169, 79392, 79425, 79456, 79553, 79680, 79777, 79808, 80321, 80352, 80769, - 80832, 80865, 80960, 81090, 81409, 81472, 81539, 81728, 82081, 82272, 82401, 82464, - 82529, 83232, 83265, 83488, 83521, 83584, 83617, 83680, 83713, 83776, 84769, 84896, - 84929, 84960, 85186, 85504, 85569, 85664, 86177, 86464, 86497, 86592, 86625, 87328, - 87361, 87584, 87617, 87680, 87713, 87872, 87969, 88000, 88577, 88608, 89089, 89152, - 89282, 89600, 89889, 89920, 90273, 90528, 90593, 90656, 90721, 91424, 91457, 91680, - 91713, 91776, 91809, 91968, 92065, 92096, 93057, 93120, 93153, 93248, 93378, 93696, - 93729, 93763, 93952, 94305, 94336, 94369, 94560, 94657, 94752, 94785, 94912, 95009, - 95072, 95105, 95136, 95169, 95232, 95329, 95392, 95489, 95584, 95681, 96064, 96769, - 96800, 97474, 97795, 97888, 98465, 98720, 98753, 98848, 98881, 99616, 99649, 100160, - 100257, 100288, 101121, 101216, 101377, 101440, 101570, 101888, 102147, 102368, 102401, 102432, - 102561, 102816, 102849, 102944, 102977, 103712, 103745, 104064, 104097, 104256, 104353, 104384, - 105409, 105440, 105473, 105536, 105666, 105984, 106017, 106080, 106657, 106912, 106945, 107040, - 107073, 108384, 108449, 108480, 108993, 109024, 109185, 109280, 109315, 109537, 109632, 109762, - 110083, 110368, 110401, 110592, 110753, 111328, 111425, 112192, 112225, 112512, 112545, 112576, - 112641, 112864, 113858, 114176, 114721, 116256, 116289, 116352, 116737, 116960, 117250, 117568, - 118817, 118880, 118913, 118944, 119009, 119072, 119105, 119136, 119201, 119232, 119425, 119552, - 119585, 119808, 119841, 119936, 119969, 120000, 120033, 120064, 120129, 120192, 120225, 120352, - 120385, 120448, 120737, 120768, 120833, 120992, 121025, 121056, 121346, 121664, 121729, 121856, - 122881, 122912, 123906, 124227, 124544, 124929, 125184, 125217, 126368, 127233, 127392, 131073, - 132448, 133089, 133122, 133440, 133633, 133824, 133953, 134080, 134177, 134208, 134305, 134368, - 134593, 134688, 134817, 135232, 135617, 135648, 135682, 136000, 136193, 137408, 137441, 137472, - 137633, 137664, 137729, 139104, 139137, 149792, 149825, 149952, 150017, 150240, 150273, 150304, - 150337, 150464, 150529, 151840, 151873, 152000, 152065, 153120, 153153, 153280, 153345, 153568, - 153601, 153632, 153665, 153792, 153857, 154336, 154369, 156192, 156225, 156352, 156417, 158560, - 159011, 159648, 159745, 160256, 160769, 163520, 163585, 163776, 163873, 183712, 183777, 184324, - 184353, 185184, 185345, 187744, 187843, 187937, 188192, 188417, 188832, 188865, 188992, 189441, - 190016, 190465, 191040, 191489, 191904, 191937, 192032, 192513, 194176, 195297, 195328, 195457, - 195488, 195586, 195904, 196099, 196416, 197122, 197440, 197633, 200448, 200705, 200864, 200929, - 202016, 202049, 202080, 202241, 204480, 204801, 205792, 207042, 207361, 208320, 208385, 208544, - 208897, 210304, 210433, 211264, 211458, 211779, 211808, 212993, 213728, 214017, 215712, 217090, - 217408, 217602, 217920, 218337, 218368, 221345, 222848, 223393, 223616, 223746, 224064, 225377, - 226336, 226753, 226818, 227137, 228544, 229377, 230528, 231426, 231744, 231841, 231938, 232257, - 233408, 233473, 233760, 236833, 236960, 236993, 237120, 237217, 237280, 237569, 243712, 245761, - 254656, 254721, 254912, 254977, 256192, 256257, 256448, 256513, 256768, 256801, 256832, 256865, - 256896, 256929, 256960, 256993, 257984, 258049, 259744, 259777, 260000, 260033, 260064, 260161, - 260256, 260289, 260512, 260609, 260736, 260801, 260992, 261121, 261536, 261697, 261792, 261825, - 262048, 262148, 262496, 263428, 263488, 263652, 263680, 265188, 265216, 265731, 265761, 265792, - 265859, 266048, 266209, 266243, 266560, 266753, 267168, 270401, 270432, 270561, 270592, 270657, - 270976, 271009, 271040, 271137, 271296, 271489, 271520, 271553, 271584, 271617, 271648, 271681, - 271808, 271841, 272192, 272257, 272384, 272545, 272704, 272833, 272864, 272899, 274529, 274595, - 274752, 297987, 299904, 302403, 303104, 323267, 324224, 360449, 361952, 361985, 363488, 363521, - 367776, 367969, 368096, 368193, 368256, 368547, 368576, 368641, 369856, 369889, 369920, 370081, - 370112, 370177, 371968, 372193, 372224, 372737, 373472, 373761, 373984, 374017, 374240, 374273, - 374496, 374529, 374752, 374785, 375008, 375041, 375264, 375297, 375520, 375553, 375776, 378337, - 378368, 393220, 393248, 393377, 393443, 393472, 394275, 394560, 394785, 394944, 395011, 395105, - 395168, 395297, 398048, 398241, 398336, 398369, 401248, 401281, 401408, 401569, 402880, 402977, - 405984, 406083, 406208, 406529, 407392, 409089, 409600, 410627, 410944, 411907, 412160, 412195, - 412672, 413699, 414016, 415267, 415744, 425985, 636608, 638977, 1309376, 1310721, 1348000, 1350145, - 1351616, 1351681, 1360288, 1360385, 1360898, 1361217, 1361280, 1361921, 1363424, 1363937, 1364928, 1364993, - 1367235, 1367552, 1368801, 1369088, 1369153, 1372448, 1372513, 1373664, 1373697, 1373952, 1375969, 1376320, - 1376353, 1376448, 1376481, 1376608, 1376641, 1377376, 1377795, 1377984, 1378305, 1379968, 1380417, 1382016, - 1382914, 1383232, 1384001, 1384192, 1384289, 1384320, 1384353, 1384384, 1384450, 1384769, 1385664, 1385985, - 1386720, 1387521, 1388448, 1388673, 1390176, 1391073, 1391106, 1391424, 1391617, 1391776, 1391809, 1392130, - 1392449, 1392608, 1392641, 1393952, 1394689, 1394784, 1394817, 1395072, 1395202, 1395520, 1395713, 1396448, - 1396545, 1396576, 1396673, 1398272, 1398305, 1398336, 1398433, 1398496, 1398561, 1398720, 1398785, 1398816, - 1398849, 1398880, 1399649, 1399744, 1399809, 1400160, 1400385, 1400480, 1400865, 1401056, 1401121, 1401312, - 1401377, 1401568, 1401857, 1402080, 1402113, 1402336, 1402369, 1403744, 1403777, 1404096, 1404417, 1408096, - 1408514, 1408832, 1409025, 1766528, 1766913, 1767648, 1767777, 1769344, 2039809, 2051520, 2051585, 2054976, - 2056193, 2056416, 2056801, 2056960, 2057121, 2057152, 2057185, 2057504, 2057537, 2057952, 2057985, 2058144, - 2058177, 2058208, 2058241, 2058304, 2058337, 2058400, 2058433, 2061888, 2062945, 2074560, 2075137, 2077184, - 2077249, 2078976, 2080257, 2080640, 2084353, 2084512, 2084545, 2088864, 2089474, 2089792, 2090017, 2090848, - 2091041, 2091872, 2092225, 2095072, 2095169, 2095360, 2095425, 2095616, 2095681, 2095872, 2095937, 2096032, - 2097153, 2097536, 2097569, 2098400, 2098433, 2099040, 2099073, 2099136, 2099169, 2099648, 2099713, 2100160, - 2101249, 2105184, 2105571, 2107008, 2107395, 2109216, 2109763, 2109824, 2117633, 2118560, 2118657, 2120224, - 2120739, 2121600, 2121729, 2122755, 2122880, 2123265, 2123811, 2123841, 2124099, 2124128, 2124289, 2125504, - 2125825, 2126784, 2126849, 2128000, 2128129, 2128384, 2128419, 2128576, 2129921, 2134976, 2135042, 2135360, - 2135553, 2136704, 2136833, 2137984, 2138113, 2139392, 2139649, 2141312, 2146305, 2156256, 2156545, 2157248, - 2157569, 2157824, 2162689, 2162880, 2162945, 2162976, 2163009, 2164416, 2164449, 2164512, 2164609, 2164640, - 2164705, 2165440, 2165507, 2165761, 2166496, 2166563, 2166785, 2167776, 2168035, 2168320, 2169857, 2170464, - 2170497, 2170560, 2170723, 2170881, 2171587, 2171776, 2171905, 2172736, 2174977, 2176768, 2176899, 2176961, - 2177027, 2177536, 2177603, 2179073, 2179104, 2179585, 2179712, 2179745, 2179840, 2179873, 2180736, 2181123, - 2181376, 2182145, 2183075, 2183136, 2183169, 2184099, 2184192, 2185217, 2185472, 2185505, 2186400, 2186595, - 2186752, 2187265, 2188992, 2189313, 2190016, 2190083, 2190337, 2190944, 2191107, 2191361, 2191936, 2192675, - 2192896, 2195457, 2197792, 2199553, 2201184, 2201601, 2203232, 2203459, 2203648, 2214915, 2215904, 2228321, - 2230016, 2230851, 2231490, 2231808, 2232417, 2233856, 2234881, 2235680, 2235906, 2236224, 2236513, 2237664, - 2238146, 2238464, 2238977, 2240096, 2240193, 2240224, 2240609, 2242144, 2242593, 2242720, 2243074, 2243393, - 2243424, 2243457, 2243488, 2243619, 2244256, 2244609, 2245184, 2245217, 2246016, 2248705, 2248928, 2248961, - 2248992, 2249025, 2249152, 2249185, 2249664, 2249697, 2250016, 2250241, 2251744, 2252290, 2252608, 2252961, - 2253216, 2253281, 2253344, 2253409, 2254112, 2254145, 2254368, 2254401, 2254464, 2254497, 2254656, 2254753, - 2254784, 2255361, 2255392, 2255777, 2255936, 2260993, 2262688, 2263265, 2263392, 2263554, 2263872, 2265089, - 2266624, 2267265, 2267328, 2267361, 2267392, 2267650, 2267968, 2273281, 2274784, 2276097, 2276224, 2277377, - 2278912, 2279553, 2279584, 2279938, 2280256, 2281473, 2282848, 2283522, 2283840, 2285569, 2286400, 2287106, - 2287427, 2287488, 2298881, 2300930, 2301251, 2301536, 2301921, 2301952, 2316289, 2318112, 2326529, 2326816, - 2326849, 2328032, 2328577, 2328608, 2329090, 2329411, 2330016, 2330177, 2331136, 2359297, 2388800, 2392067, - 2395616, 2396161, 2402432, 2490369, 2524640, 2654209, 2672864, 2949121, 2967328, 2967553, 2968544, 2968578, - 2968896, 2972161, 2973120, 2973697, 2975232, 2975745, 2975872, 2976258, 2976576, 2976611, 2976832, 2976865, - 2977536, 2977697, 2978304, 3006465, 3008672, 3009025, 3009056, 3011169, 3011584, 3013633, 3013664, 3014657, - 3210656, 3211265, 3235424, 3538945, 3539008, 3637249, 3640672, 3640833, 3641248, 3641345, 3641632, 3641857, - 3642176, 3828739, 3829312, 3833857, 3836576, 3836609, 3838880, 3838913, 3838976, 3839041, 3839072, 3839137, - 3839200, 3839265, 3839392, 3839425, 3839808, 3839841, 3839872, 3839905, 3840128, 3840161, 3842240, 3842273, - 3842400, 3842465, 3842720, 3842753, 3842976, 3843009, 3843904, 3843937, 3844064, 3844097, 3844256, 3844289, - 3844320, 3844417, 3844640, 3844673, 3855552, 3855617, 3856416, 3856449, 3857248, 3857281, 3858272, 3858305, - 3859104, 3859137, 3860128, 3860161, 3860960, 3860993, 3861984, 3862017, 3862816, 3862849, 3863840, 3863873, - 3864672, 3864705, 3864960, 3865026, 3866624, 3997697, 4004000, 4004067, 4004352, 4005889, 4008064, 4008450, - 4008768, 4046849, 4046976, 4047009, 4047872, 4047905, 4047968, 4048001, 4048032, 4048097, 4048128, 4048161, - 4048480, 4048513, 4048640, 4048673, 4048704, 4048737, 4048768, 4048961, 4048992, 4049121, 4049152, 4049185, - 4049216, 4049249, 4049280, 4049313, 4049408, 4049441, 4049504, 4049537, 4049568, 4049633, 4049664, 4049697, - 4049728, 4049761, 4049792, 4049825, 4049856, 4049889, 4049920, 4049953, 4050016, 4050049, 4050080, 4050145, - 4050272, 4050305, 4050528, 4050561, 4050688, 4050721, 4050848, 4050881, 4050912, 4050945, 4051264, 4051297, - 4051840, 4052001, 4052096, 4052129, 4052288, 4052321, 4052864, 4071427, 4071840, 4194305, 5561056, 5562369, - 5695136, 5695489, 5702592, 5702657, 5887040, 6225921, 6243264, 4294967295}; - -static constexpr uint32 TABLE_SIZE = 1280; - -static const int16 prepare_search_character_table[TABLE_SIZE] = { - 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 32, 32, 32, 32, 32, 32, 32, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 32, 32, - 32, 32, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 170, - 32, 32, 0, 32, 32, 32, 32, 178, 179, 32, 956, 32, 0, 32, 185, 186, 32, 188, 189, - 190, 32, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 32, 248, 249, 250, 251, 252, 253, 254, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 32, 248, 249, 250, 251, 252, 253, 254, 255, 257, 257, 259, 259, 261, 261, 263, 263, 265, 265, - 267, 267, 269, 269, 271, 271, 273, 273, 275, 275, 277, 277, 279, 279, 281, 281, 283, 283, 285, - 285, 287, 287, 289, 289, 291, 291, 293, 293, 295, 295, 297, 297, 299, 299, 301, 301, 303, 303, - 105, 305, 307, 307, 309, 309, 311, 311, 312, 314, 314, 316, 316, 318, 318, 320, 320, 322, 322, - 324, 324, 326, 326, 328, 328, 329, 331, 331, 333, 333, 335, 335, 337, 337, 339, 339, 341, 341, - 343, 343, 345, 345, 347, 347, 349, 349, 351, 351, 353, 353, 355, 355, 357, 357, 359, 359, 361, - 361, 363, 363, 365, 365, 367, 367, 369, 369, 371, 371, 373, 373, 375, 375, 255, 378, 378, 380, - 380, 382, 382, 115, 384, 595, 387, 387, 389, 389, 596, 392, 392, 598, 599, 396, 396, 397, 477, - 601, 603, 402, 402, 608, 611, 405, 617, 616, 409, 409, 410, 411, 623, 626, 414, 629, 417, 417, - 419, 419, 421, 421, 640, 424, 424, 643, 426, 427, 429, 429, 648, 432, 432, 650, 651, 436, 436, - 438, 438, 658, 441, 441, 442, 443, 445, 445, 446, 447, 448, 449, 450, 451, 454, 454, 454, 457, - 457, 457, 460, 460, 460, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, - 476, 476, 477, 479, 479, 481, 481, 483, 483, 485, 485, 487, 487, 489, 489, 491, 491, 493, 493, - 495, 495, 496, 499, 499, 499, 501, 501, 405, 447, 505, 505, 507, 507, 509, 509, 511, 511, 513, - 513, 515, 515, 517, 517, 519, 519, 521, 521, 523, 523, 525, 525, 527, 527, 529, 529, 531, 531, - 533, 533, 535, 535, 537, 537, 539, 539, 541, 541, 543, 543, 414, 545, 547, 547, 549, 549, 551, - 551, 553, 553, 555, 555, 557, 557, 559, 559, 561, 561, 563, 563, 564, 565, 566, 567, 568, 569, - 11365, 572, 572, 410, 11366, 575, 576, 578, 578, 384, 649, 652, 583, 583, 585, 585, 587, 587, 589, - 589, 591, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, - 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, - 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, - 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, - 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 0, 701, 0, - 703, 704, 705, 32, 32, 32, 32, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 736, 737, 738, 739, 740, - 32, 32, 32, 32, 32, 32, 32, 748, 32, 750, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 881, 881, 883, 883, 884, 32, 887, 887, 888, 889, 890, 891, 892, - 893, 32, 1011, 896, 897, 898, 899, 32, 32, 940, 32, 941, 942, 943, 907, 972, 909, 973, 974, - 912, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 930, - 963, 964, 965, 966, 967, 968, 969, 970, 971, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, - 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 963, 963, 964, 965, 966, 967, 968, - 969, 970, 971, 972, 973, 974, 983, 946, 952, 965, 965, 965, 966, 960, 983, 985, 985, 987, 987, - 989, 989, 991, 991, 993, 993, 995, 995, 997, 997, 999, 999, 1001, 1001, 1003, 1003, 1005, 1005, 1007, - 1007, 954, 961, 963, 1011, 952, 949, 32, 1016, 1016, 1010, 1019, 1019, 1020, 891, 892, 893, 1104, 1105, - 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, - 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, - 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, - 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, - 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1121, - 1121, 1123, 1123, 1125, 1125, 1127, 1127, 1129, 1129, 1131, 1131, 1133, 1133, 1135, 1135, 1137, 1137, 1139, 1139, - 1141, 1141, 1143, 1143, 1145, 1145, 1147, 1147, 1149, 1149, 1151, 1151, 1153, 1153, 32, 0, 0, 0, 0, - 0, 0, 0, 1163, 1163, 1165, 1165, 1167, 1167, 1169, 1169, 1171, 1171, 1173, 1173, 1175, 1175, 1177, 1177, - 1179, 1179, 1181, 1181, 1183, 1183, 1185, 1185, 1187, 1187, 1189, 1189, 1191, 1191, 1193, 1193, 1195, 1195, 1197, - 1197, 1199, 1199, 1201, 1201, 1203, 1203, 1205, 1205, 1207, 1207, 1209, 1209, 1211, 1211, 1213, 1213, 1215, 1215, - 1231, 1218, 1218, 1220, 1220, 1222, 1222, 1224, 1224, 1226, 1226, 1228, 1228, 1230, 1230, 1231, 1233, 1233, 1235, - 1235, 1237, 1237, 1239, 1239, 1241, 1241, 1243, 1243, 1245, 1245, 1247, 1247, 1249, 1249, 1251, 1251, 1253, 1253, - 1255, 1255, 1257, 1257, 1259, 1259, 1261, 1261, 1263, 1263, 1265, 1265, 1267, 1267, 1269, 1269, 1271, 1271, 1273, - 1273, 1275, 1275, 1277, 1277, 1279, 1279}; - -static const int32 prepare_search_character_ranges[] = { - 1280, 2097153, 1328, 1328, 1329, -1378, 1367, -1368, 1370, 32, 1376, -1377, - 1417, 32, 1419, -1420, 1421, 32, 1424, 1424, 1425, 0, 1470, 32, - 1471, 0, 1472, 32, 1473, 0, 1475, 32, 1476, 0, 1478, 32, - 1479, 0, 1480, -1481, 1523, 32, 1525, -1526, 1536, 0, 1542, 32, - 1552, 0, 1563, 32, 1564, 0, 1565, 1565, 1566, 32, 1568, -1569, - 1611, 0, 1632, -1633, 1642, 32, 1646, -1647, 1648, 0, 1649, -1650, - 1748, 32, 1749, 1749, 1750, 0, 1758, 32, 1759, 0, 1765, -1766, - 1767, 0, 1769, 32, 1770, 0, 1774, -1775, 1789, 32, 1791, 1791, - 1792, 32, 1806, 1806, 1807, 0, 1808, 1808, 1809, 0, 1810, -1811, - 1840, 0, 1867, -1868, 1958, 0, 1969, -1970, 2027, 0, 2036, -2037, - 2038, 32, 2042, -2043, 2070, 0, 2074, 2074, 2075, 0, 2084, 2084, - 2085, 0, 2088, 2088, 2089, 0, 2094, -2095, 2096, 32, 2111, -2112, - 2137, 0, 2140, -2141, 2142, 32, 2143, -2144, 2260, 0, 2308, -2309, - 2362, 0, 2365, 2365, 2366, 0, 2384, 2384, 2385, 0, 2392, -2393, - 2402, 0, 2404, 32, 2406, -2407, 2416, 32, 2417, -2418, 2433, 0, - 2436, -2437, 2492, 0, 2493, 2493, 2494, 0, 2501, -2502, 2503, 0, - 2505, -2506, 2507, 0, 2510, -2511, 2519, 0, 2520, -2521, 2530, 0, - 2532, -2533, 2546, 32, 2548, -2549, 2554, 32, 2556, -2557, 2561, 0, - 2564, -2565, 2620, 0, 2621, 2621, 2622, 0, 2627, -2628, 2631, 0, - 2633, -2634, 2635, 0, 2638, -2639, 2641, 0, 2642, -2643, 2672, 0, - 2674, -2675, 2677, 0, 2678, -2679, 2689, 0, 2692, -2693, 2748, 0, - 2749, 2749, 2750, 0, 2758, 2758, 2759, 0, 2762, 2762, 2763, 0, - 2766, -2767, 2786, 0, 2788, -2789, 2800, 32, 2802, -2803, 2817, 0, - 2820, -2821, 2876, 0, 2877, 2877, 2878, 0, 2885, -2886, 2887, 0, - 2889, -2890, 2891, 0, 2894, -2895, 2902, 0, 2904, -2905, 2914, 0, - 2916, -2917, 2928, 32, 2929, -2930, 2946, 0, 2947, -2948, 3006, 0, - 3011, -3012, 3014, 0, 3017, 3017, 3018, 0, 3022, -3023, 3031, 0, - 3032, -3033, 3059, 32, 3067, -3068, 3072, 0, 3076, -3077, 3134, 0, - 3141, 3141, 3142, 0, 3145, 3145, 3146, 0, 3150, -3151, 3157, 0, - 3159, -3160, 3170, 0, 3172, -3173, 3199, 32, 3200, 3200, 3201, 0, - 3204, -3205, 3260, 0, 3261, 3261, 3262, 0, 3269, 3269, 3270, 0, - 3273, 3273, 3274, 0, 3278, -3279, 3285, 0, 3287, -3288, 3298, 0, - 3300, -3301, 3329, 0, 3332, -3333, 3390, 0, 3397, 3397, 3398, 0, - 3401, 3401, 3402, 0, 3406, 3406, 3407, 32, 3408, -3409, 3415, 0, - 3416, -3417, 3426, 0, 3428, -3429, 3449, 32, 3450, -3451, 3458, 0, - 3460, -3461, 3530, 0, 3531, -3532, 3535, 0, 3541, 3541, 3542, 0, - 3543, 3543, 3544, 0, 3552, -3553, 3570, 0, 3572, 32, 3573, -3574, - 3633, 0, 3634, -3635, 3636, 0, 3643, -3644, 3647, 32, 3648, -3649, - 3655, 0, 3663, 32, 3664, -3665, 3674, 32, 3676, -3677, 3761, 0, - 3762, -3763, 3764, 0, 3770, 3770, 3771, 0, 3773, -3774, 3784, 0, - 3790, -3791, 3841, 32, 3864, 0, 3866, 32, 3872, -3873, 3892, 32, - 3893, 0, 3894, 32, 3895, 0, 3896, 32, 3897, 0, 3898, 32, - 3902, 0, 3904, -3905, 3953, 0, 3973, 32, 3974, 0, 3976, -3977, - 3981, 0, 3992, 3992, 3993, 0, 4029, 4029, 4030, 32, 4038, 0, - 4039, 32, 4045, 4045, 4046, 32, 4059, -4060, 4139, 0, 4159, -4160, - 4170, 32, 4176, -4177, 4182, 0, 4186, -4187, 4190, 0, 4193, 4193, - 4194, 0, 4197, -4198, 4199, 0, 4206, -4207, 4209, 0, 4213, -4214, - 4226, 0, 4238, 4238, 4239, 0, 4240, -4241, 4250, 0, 4254, 32, - 4256, -11521, 4294, 4294, 4295, 11559, 4296, -4297, 4301, 11565, 4302, -4303, - 4347, 32, 4348, -4349, 4957, 0, 4960, 32, 4969, -4970, 5008, 32, - 5018, -5019, 5112, -5105, 5118, -5119, 5120, 32, 5121, -5122, 5741, 32, - 5743, -5744, 5760, 32, 5761, -5762, 5787, 32, 5789, -5790, 5867, 32, - 5870, -5871, 5906, 0, 5909, -5910, 5938, 0, 5941, 32, 5943, -5944, - 5970, 0, 5972, -5973, 6002, 0, 6004, -6005, 6068, 0, 6100, 32, - 6103, 6103, 6104, 32, 6108, 6108, 6109, 0, 6110, -6111, 6144, 32, - 6155, 0, 6159, -6160, 6277, 0, 6279, -6280, 6313, 0, 6314, -6315, - 6432, 0, 6444, -6445, 6448, 0, 6460, -6461, 6464, 32, 6465, -6466, - 6468, 32, 6470, -6471, 6622, 32, 6656, -6657, 6679, 0, 6684, -6685, - 6686, 32, 6688, -6689, 6741, 0, 6751, 6751, 6752, 0, 6781, -6782, - 6783, 0, 6784, -6785, 6816, 32, 6823, 6823, 6824, 32, 6830, -6831, - 6832, 0, 6847, -6848, 6912, 0, 6917, -6918, 6964, 0, 6981, -6982, - 7002, 32, 7019, 0, 7028, 32, 7037, -7038, 7040, 0, 7043, -7044, - 7073, 0, 7086, -7087, 7142, 0, 7156, -7157, 7164, 32, 7168, -7169, - 7204, 0, 7224, -7225, 7227, 32, 7232, -7233, 7294, 32, 7296, 1074, - 7297, 1076, 7298, 1086, 7299, -1090, 7301, 1090, 7302, 1098, 7303, 1123, - 7304, 42571, 7305, -7306, 7360, 32, 7368, -7369, 7376, 0, 7379, 32, - 7380, 0, 7401, -7402, 7405, 0, 7406, -7407, 7410, 0, 7413, -7414, - 7416, 0, 7418, -7419, 7468, 97, 7469, 230, 7470, 98, 7471, 7471, - 7472, -101, 7474, 477, 7475, -104, 7483, 7483, 7484, 111, 7485, 547, - 7486, 112, 7487, 114, 7488, -117, 7490, 119, 7491, -7492, 7616, 0, - 7670, -7671, 7675, 0, 7680, 2097153, 7830, -7831, 7835, 7777, 7836, -7837, - 7838, 223, 7839, 2097153, 7936, -7937, 7944, -7937, 7952, -7953, 7960, -7953, - 7966, -7967, 7976, -7969, 7984, -7985, 7992, -7985, 8000, -8001, 8008, -8001, - 8014, -8015, 8025, 8017, 8026, 8026, 8027, 8019, 8028, 8028, 8029, 8021, - 8030, 8030, 8031, 8023, 8032, -8033, 8040, -8033, 8048, -8049, 8072, -8065, - 8080, -8081, 8088, -8081, 8096, -8097, 8104, -8097, 8112, -8113, 8120, -8113, - 8122, -8049, 8124, 8115, 8125, 32, 8126, 953, 8127, 32, 8130, -8131, - 8136, -8051, 8140, 8131, 8141, 32, 8144, -8145, 8152, -8145, 8154, -8055, - 8156, 8156, 8157, 32, 8160, -8161, 8168, -8161, 8170, -8059, 8172, 8165, - 8173, 32, 8176, -8177, 8184, -8057, 8186, -8061, 8188, 8179, 8189, 32, - 8191, 8191, 8192, 32, 8203, 0, 8208, 32, 8234, 0, 8239, 32, - 8288, 0, 8293, 8293, 8294, 0, 8304, -8305, 8314, 32, 8319, -8320, - 8330, 32, 8335, -8336, 8352, 32, 8383, -8384, 8400, 0, 8433, -8434, - 8448, 32, 8450, 99, 8452, 32, 8455, 603, 8456, 32, 8457, 102, - 8458, 8458, 8459, 104, 8462, -8463, 8464, 105, 8466, 108, 8467, 8467, - 8468, 32, 8469, 110, 8470, 32, 8473, -113, 8476, 114, 8478, 32, - 8484, 122, 8485, 32, 8486, 969, 8487, 32, 8488, 122, 8489, 32, - 8490, 107, 8491, 229, 8492, -99, 8494, 32, 8495, 8495, 8496, -102, - 8498, 8526, 8499, 109, 8500, -8501, 8506, 32, 8508, -8509, 8510, 947, - 8511, 960, 8512, 32, 8517, 100, 8518, -8519, 8522, 32, 8526, 8526, - 8527, 32, 8528, -8529, 8544, -8561, 8560, -8561, 8579, 8580, 8581, -8582, - 8586, 32, 8588, -8589, 8592, 32, 9215, 9215, 9216, 32, 9255, -9256, - 9280, 32, 9291, -9292, 9372, 32, 9398, -9425, 9424, -9425, 9472, 32, - 10102, -10103, 10132, 32, 11124, -11125, 11126, 32, 11158, -11159, 11160, 32, - 11194, -11195, 11197, 32, 11209, 11209, 11210, 32, 11218, -11219, 11244, 32, - 11248, -11249, 11264, -11313, 11311, -11312, 11360, 11361, 11362, 619, 11363, 7549, - 11364, 637, 11365, -11366, 11367, 11368, 11369, 11370, 11371, 11372, 11373, 593, - 11374, 625, 11375, 592, 11376, 594, 11377, 2097153, 11380, 11380, 11381, 11382, - 11383, -11384, 11389, 118, 11390, -576, 11392, 2097153, 11492, 11492, 11493, 32, - 11499, 11500, 11501, 11502, 11503, 0, 11506, 11507, 11508, -11509, 11513, 32, - 11517, 11517, 11518, 32, 11520, -11521, 11632, 32, 11633, -11634, 11647, 0, - 11648, -11649, 11744, 0, 11776, 32, 11823, 11823, 11824, 32, 11845, -11846, - 11904, 32, 11930, 11930, 11931, 32, 11935, 11935, 11936, 32, 12019, -12020, - 12272, 32, 12284, -12285, 12288, 32, 12293, -12294, 12296, 32, 12321, -12322, - 12330, 0, 12336, 32, 12337, -12338, 12342, 32, 12344, -12345, 12349, 32, - 12352, -12353, 12441, 0, 12443, 32, 12445, -12446, 12448, 32, 12449, -12450, - 12539, 32, 12540, 0, 12541, -12542, 12688, 32, 12690, -12691, 12736, 32, - 12772, -12773, 12800, 32, 12831, -12832, 12842, 32, 12868, -12869, 12880, 32, - 12881, -12882, 12910, 32, 12928, -12929, 12992, 32, 13008, -13009, 13056, 32, - 13312, -13313, 19904, 32, 19968, -19969, 42128, 32, 42183, -42184, 42238, 32, - 42240, -42241, 42509, 32, 42512, -42513, 42560, 2097153, 42606, 42606, 42607, 0, - 42611, 32, 42612, 0, 42622, 32, 42623, 2097153, 42652, -42653, 42654, 0, - 42656, -42657, 42736, 0, 42738, 32, 42744, -42745, 42752, 32, 42775, -42776, - 42784, 32, 42786, 2097153, 42800, -42801, 42802, 2097153, 42864, -42865, 42873, 42874, - 42875, 42876, 42877, 7545, 42878, 2097153, 42888, 42888, 42889, 32, 42891, 42892, - 42893, 613, 42894, -42895, 42896, 2097153, 42900, -42901, 42902, 2097153, 42922, 614, - 42923, 604, 42924, 609, 42925, 620, 42926, 618, 42927, 42927, 42928, 670, - 42929, 647, 42930, 669, 42931, 43859, 42932, 2097153, 42936, -42937, 43000, 295, - 43001, -43002, 43010, 0, 43011, -43012, 43014, 0, 43015, -43016, 43019, 0, - 43020, -43021, 43043, 0, 43048, 32, 43052, -43053, 43062, 32, 43066, -43067, - 43124, 32, 43128, -43129, 43136, 0, 43138, -43139, 43188, 0, 43206, -43207, - 43214, 32, 43216, -43217, 43232, 0, 43250, -43251, 43256, 32, 43259, 43259, - 43260, 32, 43261, -43262, 43302, 0, 43310, 32, 43312, -43313, 43335, 0, - 43348, -43349, 43359, 32, 43360, -43361, 43392, 0, 43396, -43397, 43443, 0, - 43457, 32, 43470, -43471, 43486, 32, 43488, -43489, 43493, 0, 43494, -43495, - 43561, 0, 43575, -43576, 43587, 0, 43588, -43589, 43596, 0, 43598, -43599, - 43612, 32, 43616, -43617, 43639, 32, 43642, 43642, 43643, 0, 43646, -43647, - 43696, 0, 43697, 43697, 43698, 0, 43701, -43702, 43703, 0, 43705, -43706, - 43710, 0, 43712, 43712, 43713, 0, 43714, -43715, 43742, 32, 43744, -43745, - 43755, 0, 43760, 32, 43762, -43763, 43765, 0, 43767, -43768, 43867, 32, - 43868, -43869, 43888, -5025, 43968, -43969, 44003, 0, 44011, 32, 44012, 0, - 44014, -44015, 55296, 0, 57344, -57345, 64286, 0, 64287, -64288, 64297, 32, - 64298, -64299, 64434, 32, 64450, -64451, 64830, 32, 64832, -64833, 64976, 32, - 65008, -65009, 65020, 32, 65022, -65023, 65024, 0, 65040, 32, 65050, -65051, - 65056, 0, 65072, 32, 65107, 65107, 65108, 32, 65127, 65127, 65128, 32, - 65132, -65133, 65279, 0, 65280, 65280, 65281, 32, 65296, -65297, 65306, 32, - 65313, -65346, 65339, 32, 65345, -65346, 65371, 32, 65382, -65383, 65504, 32, - 65511, 65511, 65512, 32, 65519, -65520, 65529, 0, 65532, 32, 65536, -65537, - 65792, 32, 65795, -65796, 65847, 32, 65856, -65857, 65913, 32, 65930, -65931, - 65932, 32, 65935, 65935, 65936, 32, 65948, -65949, 65952, 32, 65953, -65954, - 66000, 32, 66045, 0, 66046, -66047, 66272, 0, 66273, -66274, 66422, 0, - 66427, -66428, 66463, 32, 66464, -66465, 66512, 32, 66513, -66514, 66560, -66601, - 66600, -66601, 66736, -66777, 66772, -66773, 66927, 32, 66928, -66929, 67671, 32, - 67672, -67673, 67703, 32, 67705, -67706, 67871, 32, 67872, -67873, 67903, 32, - 67904, -67905, 68097, 0, 68100, 68100, 68101, 0, 68103, -68104, 68108, 0, - 68112, -68113, 68152, 0, 68155, -68156, 68159, 0, 68160, -68161, 68176, 32, - 68185, -68186, 68223, 32, 68224, -68225, 68296, 32, 68297, -68298, 68325, 0, - 68327, -68328, 68336, 32, 68343, -68344, 68409, 32, 68416, -68417, 68505, 32, - 68509, -68510, 68736, -68801, 68787, -68788, 69632, 0, 69635, -69636, 69688, 0, - 69703, 32, 69710, -69711, 69759, 0, 69763, -69764, 69808, 0, 69819, 32, - 69821, 0, 69822, 32, 69826, -69827, 69888, 0, 69891, -69892, 69927, 0, - 69941, -69942, 69952, 32, 69956, -69957, 70003, 0, 70004, 32, 70006, -70007, - 70016, 0, 70019, -70020, 70067, 0, 70081, -70082, 70085, 32, 70090, 0, - 70093, 32, 70094, -70095, 70107, 32, 70108, 70108, 70109, 32, 70112, -70113, - 70188, 0, 70200, 32, 70206, 0, 70207, -70208, 70313, 32, 70314, -70315, - 70367, 0, 70379, -70380, 70400, 0, 70404, -70405, 70460, 0, 70461, 70461, - 70462, 0, 70469, -70470, 70471, 0, 70473, -70474, 70475, 0, 70478, -70479, - 70487, 0, 70488, -70489, 70498, 0, 70500, -70501, 70502, 0, 70509, -70510, - 70512, 0, 70517, -70518, 70709, 0, 70727, -70728, 70731, 32, 70736, -70737, - 70747, 32, 70748, 70748, 70749, 32, 70750, -70751, 70832, 0, 70852, -70853, - 70854, 32, 70855, -70856, 71087, 0, 71094, -71095, 71096, 0, 71105, 32, - 71128, -71129, 71132, 0, 71134, -71135, 71216, 0, 71233, 32, 71236, -71237, - 71264, 32, 71277, -71278, 71339, 0, 71352, -71353, 71453, 0, 71468, -71469, - 71484, 32, 71488, -71489, 71840, -71873, 71872, -71873, 72751, 0, 72759, 72759, - 72760, 0, 72768, 72768, 72769, 32, 72774, -72775, 72816, 32, 72818, -72819, - 72850, 0, 72872, 72872, 72873, 0, 72887, -72888, 74864, 32, 74869, -74870, - 92782, 32, 92784, -92785, 92912, 0, 92917, 32, 92918, -92919, 92976, 0, - 92983, 32, 92992, -92993, 92996, 32, 92998, -92999, 94033, 0, 94079, -94080, - 94095, 0, 94099, -94100, 113820, 32, 113821, 0, 113823, 32, 113824, 0, - 113828, -113829, 118784, 32, 119030, -119031, 119040, 32, 119079, -119080, 119081, 32, - 119141, 0, 119146, 32, 119149, 0, 119171, 32, 119173, 0, 119180, 32, - 119210, 0, 119214, 32, 119273, -119274, 119296, 32, 119362, 0, 119365, 32, - 119366, -119367, 119552, 32, 119639, -119640, 119808, -98, 119834, -119835, 119860, -98, - 119886, -119887, 119912, -98, 119938, -119939, 119964, 97, 119965, 119965, 119966, -100, - 119968, -119969, 119970, 103, 119971, -119972, 119973, -107, 119975, -119976, 119977, -111, - 119981, 119981, 119982, -116, 119990, -119991, 120016, -98, 120042, -120043, 120068, -98, - 120070, 120070, 120071, -101, 120075, -120076, 120077, -107, 120085, 120085, 120086, -116, - 120093, -120094, 120120, -98, 120122, 120122, 120123, -101, 120127, 120127, 120128, -106, - 120133, 120133, 120134, 111, 120135, -120136, 120138, -116, 120145, -120146, 120172, -98, - 120198, -120199, 120224, -98, 120250, -120251, 120276, -98, 120302, -120303, 120328, -98, - 120354, -120355, 120380, -98, 120406, -120407, 120432, -98, 120458, -120459, 120488, -946, - 120505, 952, 120506, -964, 120513, 32, 120514, -120515, 120531, 963, 120532, -120533, - 120539, 32, 120540, -120541, 120546, -946, 120563, 952, 120564, -964, 120571, 32, - 120572, -120573, 120589, 963, 120590, -120591, 120597, 32, 120598, -120599, 120604, -946, - 120621, 952, 120622, -964, 120629, 32, 120630, -120631, 120647, 963, 120648, -120649, - 120655, 32, 120656, -120657, 120662, -946, 120679, 952, 120680, -964, 120687, 32, - 120688, -120689, 120705, 963, 120706, -120707, 120713, 32, 120714, -120715, 120720, -946, - 120737, 952, 120738, -964, 120745, 32, 120746, -120747, 120763, 963, 120764, -120765, - 120771, 32, 120772, -120773, 120778, 989, 120779, -120780, 120832, 32, 121344, 0, - 121399, 32, 121403, 0, 121453, 32, 121461, 0, 121462, 32, 121476, 0, - 121477, 32, 121484, -121485, 121499, 0, 121504, 121504, 121505, 0, 121520, -121521, - 122880, 0, 122887, 122887, 122888, 0, 122905, -122906, 122907, 0, 122914, 122914, - 122915, 0, 122917, 122917, 122918, 0, 122923, -122924, 125136, 0, 125143, -125144, - 125184, -125219, 125218, -125219, 125252, 0, 125259, -125260, 125278, 32, 125280, -125281, - 126704, 32, 126706, -126707, 126976, 32, 127020, -127021, 127024, 32, 127124, -127125, - 127136, 32, 127151, -127152, 127153, 32, 127168, 127168, 127169, 32, 127184, 127184, - 127185, 32, 127222, -127223, 127248, 32, 127275, 99, 127276, 114, 127277, 32, - 127279, 127279, 127280, -98, 127306, 32, 127340, -127341, 127344, 32, 127405, -127406, - 127462, 32, 127490, -127491, 127552, 32, 127561, -127562, 127744, 32, 128723, -128724, - 128736, 32, 128749, -128750, 128752, 32, 128759, -128760, 128768, 32, 128884, -128885, - 128896, 32, 128981, -128982, 129024, 32, 129036, -129037, 129040, 32, 129096, -129097, - 129104, 32, 129114, -129115, 129120, 32, 129160, -129161, 129168, 32, 129198, -129199, - 129296, 32, 129311, 129311, 129312, 32, 129320, -129321, 129328, 32, 129329, -129330, - 129331, 32, 129343, 129343, 129344, 32, 129356, -129357, 129360, 32, 129375, -129376, - 129408, 32, 129426, -129427, 129472, 32, 129473, -129474, 131070, 32, 131072, -131073, - 196606, 32, 196608, -196609, 262142, 32, 262144, -262145, 327678, 32, 327680, -327681, - 393214, 32, 393216, -393217, 458750, 32, 458752, -458753, 524286, 32, 524288, -524289, - 589822, 32, 589824, -589825, 655358, 32, 655360, -655361, 720894, 32, 720896, -720897, - 786430, 32, 786432, -786433, 851966, 32, 851968, -851969, 917502, 32, 917504, 917504, - 917505, 0, 917506, -917507, 917536, 0, 917632, -917633, 917760, 0, 918000, -918001, - 983038, 32, 983040, -983041, 1048574, 32, 1048576, -1048577, 1114110, 32, 2147483647, 0}; - -static const int16 to_lower_table[TABLE_SIZE] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 257, 257, 259, 259, 261, 261, 263, 263, 265, 265, - 267, 267, 269, 269, 271, 271, 273, 273, 275, 275, 277, 277, 279, 279, 281, 281, 283, 283, 285, - 285, 287, 287, 289, 289, 291, 291, 293, 293, 295, 295, 297, 297, 299, 299, 301, 301, 303, 303, - 105, 305, 307, 307, 309, 309, 311, 311, 312, 314, 314, 316, 316, 318, 318, 320, 320, 322, 322, - 324, 324, 326, 326, 328, 328, 329, 331, 331, 333, 333, 335, 335, 337, 337, 339, 339, 341, 341, - 343, 343, 345, 345, 347, 347, 349, 349, 351, 351, 353, 353, 355, 355, 357, 357, 359, 359, 361, - 361, 363, 363, 365, 365, 367, 367, 369, 369, 371, 371, 373, 373, 375, 375, 255, 378, 378, 380, - 380, 382, 382, 383, 384, 595, 387, 387, 389, 389, 596, 392, 392, 598, 599, 396, 396, 397, 477, - 601, 603, 402, 402, 608, 611, 405, 617, 616, 409, 409, 410, 411, 623, 626, 414, 629, 417, 417, - 419, 419, 421, 421, 640, 424, 424, 643, 426, 427, 429, 429, 648, 432, 432, 650, 651, 436, 436, - 438, 438, 658, 441, 441, 442, 443, 445, 445, 446, 447, 448, 449, 450, 451, 454, 454, 454, 457, - 457, 457, 460, 460, 460, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, - 476, 476, 477, 479, 479, 481, 481, 483, 483, 485, 485, 487, 487, 489, 489, 491, 491, 493, 493, - 495, 495, 496, 499, 499, 499, 501, 501, 405, 447, 505, 505, 507, 507, 509, 509, 511, 511, 513, - 513, 515, 515, 517, 517, 519, 519, 521, 521, 523, 523, 525, 525, 527, 527, 529, 529, 531, 531, - 533, 533, 535, 535, 537, 537, 539, 539, 541, 541, 543, 543, 414, 545, 547, 547, 549, 549, 551, - 551, 553, 553, 555, 555, 557, 557, 559, 559, 561, 561, 563, 563, 564, 565, 566, 567, 568, 569, - 11365, 572, 572, 410, 11366, 575, 576, 578, 578, 384, 649, 652, 583, 583, 585, 585, 587, 587, 589, - 589, 591, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, - 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, - 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, - 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, - 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, - 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, - 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, - 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, - 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, - 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, - 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, - 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, - 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, - 874, 875, 876, 877, 878, 879, 881, 881, 883, 883, 884, 885, 887, 887, 888, 889, 890, 891, 892, - 893, 894, 1011, 896, 897, 898, 899, 900, 901, 940, 903, 941, 942, 943, 907, 972, 909, 973, 974, - 912, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 930, - 963, 964, 965, 966, 967, 968, 969, 970, 971, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, - 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, - 969, 970, 971, 972, 973, 974, 983, 976, 977, 978, 979, 980, 981, 982, 983, 985, 985, 987, 987, - 989, 989, 991, 991, 993, 993, 995, 995, 997, 997, 999, 999, 1001, 1001, 1003, 1003, 1005, 1005, 1007, - 1007, 1008, 1009, 1010, 1011, 952, 1013, 1014, 1016, 1016, 1010, 1019, 1019, 1020, 891, 892, 893, 1104, 1105, - 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, - 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, - 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, - 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, - 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1121, - 1121, 1123, 1123, 1125, 1125, 1127, 1127, 1129, 1129, 1131, 1131, 1133, 1133, 1135, 1135, 1137, 1137, 1139, 1139, - 1141, 1141, 1143, 1143, 1145, 1145, 1147, 1147, 1149, 1149, 1151, 1151, 1153, 1153, 1154, 1155, 1156, 1157, 1158, - 1159, 1160, 1161, 1163, 1163, 1165, 1165, 1167, 1167, 1169, 1169, 1171, 1171, 1173, 1173, 1175, 1175, 1177, 1177, - 1179, 1179, 1181, 1181, 1183, 1183, 1185, 1185, 1187, 1187, 1189, 1189, 1191, 1191, 1193, 1193, 1195, 1195, 1197, - 1197, 1199, 1199, 1201, 1201, 1203, 1203, 1205, 1205, 1207, 1207, 1209, 1209, 1211, 1211, 1213, 1213, 1215, 1215, - 1231, 1218, 1218, 1220, 1220, 1222, 1222, 1224, 1224, 1226, 1226, 1228, 1228, 1230, 1230, 1231, 1233, 1233, 1235, - 1235, 1237, 1237, 1239, 1239, 1241, 1241, 1243, 1243, 1245, 1245, 1247, 1247, 1249, 1249, 1251, 1251, 1253, 1253, - 1255, 1255, 1257, 1257, 1259, 1259, 1261, 1261, 1263, 1263, 1265, 1265, 1267, 1267, 1269, 1269, 1271, 1271, 1273, - 1273, 1275, 1275, 1277, 1277, 1279, 1279}; - -static const int32 to_lower_ranges[] = { - 1280, 2097153, 1328, 1328, 1329, -1378, 1367, -1368, 4256, -11521, 4294, 4294, 4295, - 11559, 4296, -4297, 4301, 11565, 4302, -4303, 5024, -43889, 5104, -5113, 5110, -5111, - 7680, 2097153, 7830, -7831, 7838, 223, 7839, 2097153, 7936, -7937, 7944, -7937, 7952, - -7953, 7960, -7953, 7966, -7967, 7976, -7969, 7984, -7985, 7992, -7985, 8000, -8001, - 8008, -8001, 8014, -8015, 8025, 8017, 8026, 8026, 8027, 8019, 8028, 8028, 8029, - 8021, 8030, 8030, 8031, 8023, 8032, -8033, 8040, -8033, 8048, -8049, 8072, -8065, - 8080, -8081, 8088, -8081, 8096, -8097, 8104, -8097, 8112, -8113, 8120, -8113, 8122, - -8049, 8124, 8115, 8125, -8126, 8136, -8051, 8140, 8131, 8141, -8142, 8152, -8145, - 8154, -8055, 8156, -8157, 8168, -8161, 8170, -8059, 8172, 8165, 8173, -8174, 8184, - -8057, 8186, -8061, 8188, 8179, 8189, -8190, 8486, 969, 8487, -8488, 8490, 107, - 8491, 229, 8492, -8493, 8498, 8526, 8499, -8500, 8544, -8561, 8560, -8561, 8579, - 8580, 8581, -8582, 9398, -9425, 9424, -9425, 11264, -11313, 11311, -11312, 11360, 11361, - 11362, 619, 11363, 7549, 11364, 637, 11365, -11366, 11367, 11368, 11369, 11370, 11371, - 11372, 11373, 593, 11374, 625, 11375, 592, 11376, 594, 11377, 2097153, 11380, 11380, - 11381, 11382, 11383, -11384, 11390, -576, 11392, 2097153, 11492, -11493, 11499, 11500, 11501, - 11502, 11503, -11504, 11506, 11507, 11508, -11509, 42560, 2097153, 42606, -42607, 42624, 2097153, - 42652, -42653, 42786, 2097153, 42800, -42801, 42802, 2097153, 42864, -42865, 42873, 42874, 42875, - 42876, 42877, 7545, 42878, 2097153, 42888, -42889, 42891, 42892, 42893, 613, 42894, -42895, - 42896, 2097153, 42900, -42901, 42902, 2097153, 42922, 614, 42923, 604, 42924, 609, 42925, - 620, 42926, 618, 42927, 42927, 42928, 670, 42929, 647, 42930, 669, 42931, 43859, - 42932, 2097153, 42936, -42937, 65313, -65346, 65339, -65340, 66560, -66601, 66600, -66601, 66736, - -66777, 66772, -66773, 68736, -68801, 68787, -68788, 71840, -71873, 71872, -71873, 125184, -125219, - 125218, -125219, 2147483647, 0}; - -static const int16 without_diacritics_table[TABLE_SIZE] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 32, 161, 162, 163, 164, 165, 166, 167, 32, 169, 97, - 171, 172, 0, 174, 32, 176, 177, 50, 51, 32, 956, 182, 0, 32, 49, 111, 187, 188, 189, - 190, 191, 65, 65, 65, 65, 65, 65, 198, 67, 69, 69, 69, 69, 73, 73, 73, 73, 208, - 78, 79, 79, 79, 79, 79, 215, 216, 85, 85, 85, 85, 89, 222, 223, 97, 97, 97, 97, - 97, 97, 230, 99, 101, 101, 101, 101, 105, 105, 105, 105, 240, 110, 111, 111, 111, 111, 111, - 247, 248, 117, 117, 117, 117, 121, 254, 121, 65, 97, 65, 97, 65, 97, 67, 99, 67, 99, - 67, 99, 67, 99, 68, 100, 272, 273, 69, 101, 69, 101, 69, 101, 69, 101, 69, 101, 71, - 103, 71, 103, 71, 103, 71, 103, 72, 104, 294, 295, 73, 105, 73, 105, 73, 105, 73, 105, - 73, 305, 306, 307, 74, 106, 75, 107, 312, 76, 108, 76, 108, 76, 108, 76, 108, 321, 322, - 78, 110, 78, 110, 78, 110, 110, 330, 331, 79, 111, 79, 111, 79, 111, 338, 339, 82, 114, - 82, 114, 82, 114, 83, 115, 83, 115, 83, 115, 83, 115, 84, 116, 84, 116, 358, 359, 85, - 117, 85, 117, 85, 117, 85, 117, 85, 117, 85, 117, 87, 119, 89, 121, 89, 90, 122, 90, - 122, 90, 122, 115, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 79, 111, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 85, 117, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 65, 97, 73, 105, 79, 111, 85, 117, 85, 117, 85, 117, 85, 117, - 85, 117, 477, 65, 97, 65, 97, 198, 230, 484, 485, 71, 103, 75, 107, 79, 111, 79, 111, - 439, 658, 106, 497, 498, 499, 71, 103, 502, 503, 78, 110, 65, 97, 198, 230, 216, 248, 65, - 97, 65, 97, 69, 101, 69, 101, 73, 105, 73, 105, 79, 111, 79, 111, 82, 114, 82, 114, - 85, 117, 85, 117, 83, 115, 84, 116, 540, 541, 72, 104, 544, 545, 546, 547, 548, 549, 65, - 97, 69, 101, 79, 111, 79, 111, 79, 111, 79, 111, 89, 121, 564, 565, 566, 567, 568, 569, - 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, - 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, - 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, - 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, - 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, - 684, 685, 686, 687, 104, 614, 106, 114, 633, 635, 641, 119, 121, 697, 698, 699, 0, 701, 0, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, - 722, 723, 724, 725, 726, 727, 32, 32, 32, 32, 32, 32, 734, 735, 611, 108, 115, 120, 661, - 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, - 760, 761, 762, 763, 764, 765, 766, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 880, 881, 882, 883, 697, 885, 886, 887, 888, 889, 32, 891, 892, - 893, 59, 895, 896, 897, 898, 899, 32, 32, 913, 903, 917, 919, 921, 907, 927, 909, 933, 937, - 953, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, - 931, 932, 933, 934, 935, 936, 937, 921, 933, 945, 949, 951, 953, 965, 945, 946, 947, 948, 949, - 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, - 969, 953, 965, 959, 965, 969, 975, 946, 952, 933, 933, 933, 966, 960, 983, 984, 985, 986, 987, - 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, - 1007, 954, 961, 962, 1011, 920, 949, 1014, 1015, 1016, 931, 1018, 1019, 1020, 1021, 1022, 1023, 1045, 1045, - 1026, 1043, 1028, 1029, 1030, 1030, 1032, 1033, 1034, 1035, 1050, 1048, 1059, 1039, 1040, 1041, 1042, 1043, 1044, - 1045, 1046, 1047, 1048, 1048, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, - 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1080, 1082, - 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, - 1102, 1103, 1077, 1077, 1106, 1075, 1108, 1109, 1110, 1110, 1112, 1113, 1114, 1115, 1082, 1080, 1091, 1119, 1120, - 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, - 1140, 1141, 1140, 1141, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 0, 0, 0, 0, - 0, 0, 0, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, - 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, - 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, - 1216, 1046, 1078, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1040, 1072, 1040, - 1072, 1236, 1237, 1045, 1077, 1240, 1241, 1240, 1241, 1046, 1078, 1047, 1079, 1248, 1249, 1048, 1080, 1048, 1080, - 1054, 1086, 1256, 1257, 1256, 1257, 1069, 1101, 1059, 1091, 1059, 1091, 1059, 1091, 1063, 1095, 1270, 1271, 1067, - 1099, 1274, 1275, 1276, 1277, 1278, 1279}; - -static const int32 without_diacritics_ranges[] = { - 1280, -1281, 1425, 0, 1470, 1470, 1471, 0, 1472, 1472, 1473, 0, - 1475, 1475, 1476, 0, 1478, 1478, 1479, 0, 1480, -1481, 1536, 0, - 1542, -1543, 1552, 0, 1563, 1563, 1564, 0, 1565, -1566, 1570, 1575, - 1572, 1608, 1573, 1575, 1574, 1610, 1575, -1576, 1611, 0, 1632, -1633, - 1648, 0, 1649, -1650, 1728, 1749, 1729, 2097154, 1732, -1733, 1747, 2097152, - 1749, 1749, 1750, 0, 1758, 1758, 1759, 0, 1765, -1766, 1767, 0, - 1769, 1769, 1770, 0, 1774, -1775, 1807, 0, 1808, 1808, 1809, 0, - 1810, -1811, 1840, 0, 1867, -1868, 1958, 0, 1969, -1970, 2027, 0, - 2036, -2037, 2070, 0, 2074, 2074, 2075, 0, 2084, 2084, 2085, 0, - 2088, 2088, 2089, 0, 2094, -2095, 2137, 0, 2140, -2141, 2260, 0, - 2308, -2309, 2345, 2097152, 2347, -2348, 2353, 2097152, 2355, 2097154, 2358, -2359, - 2362, 0, 2365, 2365, 2366, 0, 2384, 2384, 2385, 0, 2392, -2326, - 2395, 2332, 2396, -2338, 2398, 2347, 2399, 2351, 2400, -2401, 2402, 0, - 2404, -2405, 2433, 0, 2436, -2437, 2492, 0, 2493, 2493, 2494, 0, - 2501, -2502, 2503, 0, 2505, -2506, 2507, 0, 2510, -2511, 2519, 0, - 2520, -2521, 2524, -2466, 2526, 2526, 2527, 2479, 2528, -2529, 2530, 0, - 2532, -2533, 2561, 0, 2564, -2565, 2611, 2097152, 2613, 2613, 2614, 2616, - 2615, -2616, 2620, 0, 2621, 2621, 2622, 0, 2627, -2628, 2631, 0, - 2633, -2634, 2635, 0, 2638, -2639, 2641, 0, 2642, -2643, 2649, -2583, - 2651, 2588, 2652, -2653, 2654, 2603, 2655, -2656, 2672, 0, 2674, -2675, - 2677, 0, 2678, -2679, 2689, 0, 2692, -2693, 2748, 0, 2749, 2749, - 2750, 0, 2758, 2758, 2759, 0, 2762, 2762, 2763, 0, 2766, -2767, - 2786, 0, 2788, -2789, 2817, 0, 2820, -2821, 2876, 0, 2877, 2877, - 2878, 0, 2885, -2886, 2887, 0, 2889, -2890, 2891, 0, 2894, -2895, - 2902, 0, 2904, -2905, 2908, -2850, 2910, -2911, 2914, 0, 2916, -2917, - 2946, 0, 2947, -2948, 2964, 2962, 2965, -2966, 3006, 0, 3011, -3012, - 3014, 0, 3017, 3017, 3018, 0, 3022, -3023, 3031, 0, 3032, -3033, - 3072, 0, 3076, -3077, 3134, 0, 3141, 3141, 3142, 0, 3145, 3145, - 3146, 0, 3150, -3151, 3157, 0, 3159, -3160, 3170, 0, 3172, -3173, - 3201, 0, 3204, -3205, 3260, 0, 3261, 3261, 3262, 0, 3269, 3269, - 3270, 0, 3273, 3273, 3274, 0, 3278, -3279, 3285, 0, 3287, -3288, - 3298, 0, 3300, -3301, 3329, 0, 3332, -3333, 3390, 0, 3397, 3397, - 3398, 0, 3401, 3401, 3402, 0, 3406, -3407, 3415, 0, 3416, -3417, - 3426, 0, 3428, -3429, 3458, 0, 3460, -3461, 3530, 0, 3531, -3532, - 3535, 0, 3541, 3541, 3542, 0, 3543, 3543, 3544, 0, 3552, -3553, - 3570, 0, 3572, -3573, 3633, 0, 3634, 3634, 3636, 0, 3643, -3644, - 3655, 0, 3663, -3664, 3761, 0, 3762, 3762, 3764, 0, 3770, 3770, - 3771, 0, 3773, -3774, 3784, 0, 3790, -3791, 3852, 2097154, 3854, -3855, - 3864, 0, 3866, -3867, 3893, 0, 3894, 3894, 3895, 0, 3896, 3896, - 3897, 0, 3898, -3899, 3902, 0, 3904, -3905, 3907, 2097152, 3909, -3910, - 3917, 2097152, 3919, -3920, 3922, 2097154, 3924, -3925, 3927, 2097152, 3929, -3930, - 3932, 2097154, 3934, -3935, 3945, 3904, 3946, -3947, 3953, 0, 3973, 3973, - 3974, 0, 3976, -3977, 3981, 0, 3992, 3992, 3993, 0, 4029, -4030, - 4038, 0, 4039, -4040, 4134, 2097154, 4136, -4137, 4139, 0, 4159, -4160, - 4182, 0, 4186, -4187, 4190, 0, 4193, 4193, 4194, 0, 4197, -4198, - 4199, 0, 4206, -4207, 4209, 0, 4213, -4214, 4226, 0, 4238, 4238, - 4239, 0, 4240, -4241, 4250, 0, 4254, -4255, 4348, 4316, 4349, -4350, - 4957, 0, 4960, -4961, 5906, 0, 5909, -5910, 5938, 0, 5941, -5942, - 5970, 0, 5972, -5973, 6002, 0, 6004, -6005, 6068, 0, 6100, -6101, - 6109, 0, 6110, -6111, 6155, 0, 6159, -6160, 6277, 0, 6279, -6280, - 6313, 0, 6314, -6315, 6432, 0, 6444, -6445, 6448, 0, 6460, -6461, - 6679, 0, 6684, -6685, 6741, 0, 6751, 6751, 6752, 0, 6781, -6782, - 6783, 0, 6784, -6785, 6832, 0, 6847, -6848, 6912, 0, 6917, 2097154, - 6928, -6929, 6930, 2097154, 6932, -6933, 6964, 0, 6981, -6982, 7019, 0, - 7028, -7029, 7040, 0, 7043, -7044, 7073, 0, 7086, -7087, 7142, 0, - 7156, -7157, 7204, 0, 7224, -7225, 7376, 0, 7379, 7379, 7380, 0, - 7401, -7402, 7405, 0, 7406, -7407, 7410, 0, 7413, -7414, 7416, 0, - 7418, -7419, 7468, 65, 7469, 198, 7470, 66, 7471, 7471, 7472, -69, - 7474, 398, 7475, -72, 7483, 7483, 7484, 79, 7485, 546, 7486, 80, - 7487, 82, 7488, -85, 7490, 87, 7491, 97, 7492, -593, 7494, 7426, - 7495, 98, 7496, -101, 7498, 601, 7499, -604, 7501, 103, 7502, 7502, - 7503, 107, 7504, 109, 7505, 331, 7506, 111, 7507, 596, 7508, -7447, - 7510, 112, 7511, -117, 7513, 7453, 7514, 623, 7515, 118, 7516, 7461, - 7517, -947, 7520, -967, 7522, 105, 7523, 114, 7524, -118, 7526, -947, - 7528, 961, 7529, -967, 7531, -7532, 7544, 1085, 7545, -7546, 7579, 594, - 7580, 99, 7581, 597, 7582, 240, 7583, 604, 7584, 102, 7585, 607, - 7586, 609, 7587, 613, 7588, -617, 7591, 7547, 7592, 669, 7593, 621, - 7594, 7557, 7595, 671, 7596, 625, 7597, 624, 7598, -627, 7602, 632, - 7603, -643, 7605, 427, 7606, -650, 7608, 7452, 7609, -652, 7611, 122, - 7612, -657, 7615, 952, 7616, 0, 7670, -7671, 7675, 0, 7680, 65, - 7681, 97, 7682, 66, 7683, 98, 7684, 66, 7685, 98, 7686, 66, - 7687, 98, 7688, 67, 7689, 99, 7690, 68, 7691, 100, 7692, 68, - 7693, 100, 7694, 68, 7695, 100, 7696, 68, 7697, 100, 7698, 68, - 7699, 100, 7700, 69, 7701, 101, 7702, 69, 7703, 101, 7704, 69, - 7705, 101, 7706, 69, 7707, 101, 7708, 69, 7709, 101, 7710, 70, - 7711, 102, 7712, 71, 7713, 103, 7714, 72, 7715, 104, 7716, 72, - 7717, 104, 7718, 72, 7719, 104, 7720, 72, 7721, 104, 7722, 72, - 7723, 104, 7724, 73, 7725, 105, 7726, 73, 7727, 105, 7728, 75, - 7729, 107, 7730, 75, 7731, 107, 7732, 75, 7733, 107, 7734, 76, - 7735, 108, 7736, 76, 7737, 108, 7738, 76, 7739, 108, 7740, 76, - 7741, 108, 7742, 77, 7743, 109, 7744, 77, 7745, 109, 7746, 77, - 7747, 109, 7748, 78, 7749, 110, 7750, 78, 7751, 110, 7752, 78, - 7753, 110, 7754, 78, 7755, 110, 7756, 79, 7757, 111, 7758, 79, - 7759, 111, 7760, 79, 7761, 111, 7762, 79, 7763, 111, 7764, 80, - 7765, 112, 7766, 80, 7767, 112, 7768, 82, 7769, 114, 7770, 82, - 7771, 114, 7772, 82, 7773, 114, 7774, 82, 7775, 114, 7776, 83, - 7777, 115, 7778, 83, 7779, 115, 7780, 83, 7781, 115, 7782, 83, - 7783, 115, 7784, 83, 7785, 115, 7786, 84, 7787, 116, 7788, 84, - 7789, 116, 7790, 84, 7791, 116, 7792, 84, 7793, 116, 7794, 85, - 7795, 117, 7796, 85, 7797, 117, 7798, 85, 7799, 117, 7800, 85, - 7801, 117, 7802, 85, 7803, 117, 7804, 86, 7805, 118, 7806, 86, - 7807, 118, 7808, 87, 7809, 119, 7810, 87, 7811, 119, 7812, 87, - 7813, 119, 7814, 87, 7815, 119, 7816, 87, 7817, 119, 7818, 88, - 7819, 120, 7820, 88, 7821, 120, 7822, 89, 7823, 121, 7824, 90, - 7825, 122, 7826, 90, 7827, 122, 7828, 90, 7829, 122, 7830, 104, - 7831, 116, 7832, 119, 7833, 121, 7834, 97, 7835, 115, 7836, -7837, - 7840, 65, 7841, 97, 7842, 65, 7843, 97, 7844, 65, 7845, 97, - 7846, 65, 7847, 97, 7848, 65, 7849, 97, 7850, 65, 7851, 97, - 7852, 65, 7853, 97, 7854, 65, 7855, 97, 7856, 65, 7857, 97, - 7858, 65, 7859, 97, 7860, 65, 7861, 97, 7862, 65, 7863, 97, - 7864, 69, 7865, 101, 7866, 69, 7867, 101, 7868, 69, 7869, 101, - 7870, 69, 7871, 101, 7872, 69, 7873, 101, 7874, 69, 7875, 101, - 7876, 69, 7877, 101, 7878, 69, 7879, 101, 7880, 73, 7881, 105, - 7882, 73, 7883, 105, 7884, 79, 7885, 111, 7886, 79, 7887, 111, - 7888, 79, 7889, 111, 7890, 79, 7891, 111, 7892, 79, 7893, 111, - 7894, 79, 7895, 111, 7896, 79, 7897, 111, 7898, 79, 7899, 111, - 7900, 79, 7901, 111, 7902, 79, 7903, 111, 7904, 79, 7905, 111, - 7906, 79, 7907, 111, 7908, 85, 7909, 117, 7910, 85, 7911, 117, - 7912, 85, 7913, 117, 7914, 85, 7915, 117, 7916, 85, 7917, 117, - 7918, 85, 7919, 117, 7920, 85, 7921, 117, 7922, 89, 7923, 121, - 7924, 89, 7925, 121, 7926, 89, 7927, 121, 7928, 89, 7929, 121, - 7930, -7931, 7936, 945, 7944, 913, 7952, 949, 7958, -7959, 7960, 917, - 7966, -7967, 7968, 951, 7976, 919, 7984, 953, 7992, 921, 8000, 959, - 8006, -8007, 8008, 927, 8014, -8015, 8016, 965, 8024, 8024, 8025, 933, - 8026, 8026, 8027, 933, 8028, 8028, 8029, 933, 8030, 8030, 8031, 933, - 8032, 969, 8040, 937, 8048, 945, 8050, 949, 8052, 951, 8054, 953, - 8056, 959, 8058, 965, 8060, 969, 8062, -8063, 8064, 945, 8072, 913, - 8080, 951, 8088, 919, 8096, 969, 8104, 937, 8112, 945, 8117, 8117, - 8118, 945, 8120, 913, 8125, 32, 8126, 953, 8127, 32, 8130, 951, - 8133, 8133, 8134, 951, 8136, 917, 8138, 919, 8141, 32, 8144, 953, - 8148, -8149, 8150, 953, 8152, 921, 8156, 8156, 8157, 32, 8160, 965, - 8164, 961, 8166, 965, 8168, 933, 8172, 929, 8173, 32, 8175, 96, - 8176, -8177, 8178, 969, 8181, 8181, 8182, 969, 8184, 927, 8186, 937, - 8189, 32, 8191, 8191, 8192, 32, 8203, 0, 8208, 2097152, 8211, -8212, - 8215, 32, 8216, -8217, 8228, 46, 8229, -8230, 8234, 0, 8239, 32, - 8240, -8241, 8254, 32, 8255, -8256, 8287, 32, 8288, 0, 8293, 8293, - 8294, 0, 8304, 48, 8305, 105, 8306, -8307, 8308, -53, 8314, 43, - 8315, 8722, 8316, 61, 8317, -41, 8319, 110, 8320, -49, 8330, 43, - 8331, 8722, 8332, 61, 8333, -41, 8335, 8335, 8336, 97, 8337, 101, - 8338, 111, 8339, 120, 8340, 601, 8341, 104, 8342, -108, 8346, 112, - 8347, -116, 8349, -8350, 8400, 0, 8433, -8434, 8450, 67, 8452, -8453, - 8455, 400, 8456, 8456, 8457, 70, 8458, 103, 8459, 72, 8462, 104, - 8463, 295, 8464, 73, 8466, 76, 8467, 108, 8468, 8468, 8469, 78, - 8470, -8471, 8473, -81, 8476, 82, 8478, -8479, 8484, 90, 8485, 8485, - 8486, 937, 8487, 8487, 8488, 90, 8489, 8489, 8490, 75, 8491, -66, - 8494, 8494, 8495, 101, 8496, -70, 8498, 8498, 8499, 77, 8500, 111, - 8501, -1489, 8505, 105, 8506, -8507, 8508, 960, 8509, 947, 8510, 915, - 8511, 928, 8512, 8721, 8513, -8514, 8517, 68, 8518, -101, 8520, -106, - 8522, -8523, 8543, 49, 8544, 73, 8545, -8546, 8548, 86, 8549, -8550, - 8553, 88, 8554, -8555, 8556, 76, 8557, -68, 8559, 77, 8560, 105, - 8561, -8562, 8564, 118, 8565, -8566, 8569, 120, 8570, -8571, 8572, 108, - 8573, -100, 8575, 109, 8576, -8577, 8602, 8592, 8603, 8594, 8604, -8605, - 8622, 8596, 8623, -8624, 8653, 8656, 8654, 8660, 8655, 8658, 8656, -8657, - 8708, 2097154, 8710, -8711, 8713, 2097152, 8715, 2097154, 8718, -8719, 8740, 2097154, - 8744, -8745, 8769, 8764, 8770, -8771, 8772, 2097154, 8774, 8774, 8775, 8773, - 8776, 2097152, 8779, -8780, 8800, 61, 8801, 2097154, 8804, -8805, 8813, 8781, - 8814, 60, 8815, 62, 8816, -8805, 8818, -8819, 8820, -8819, 8822, -8823, - 8824, -8823, 8826, -8827, 8832, -8827, 8834, -8835, 8836, -8835, 8838, -8839, - 8840, -8839, 8842, -8843, 8876, 8866, 8877, -8873, 8879, 8875, 8880, -8881, - 8928, -8829, 8930, -8850, 8932, -8933, 8938, -8883, 8942, -8943, 9001, -12297, - 9003, -9004, 9312, -50, 9321, -9322, 9352, -50, 9361, -9362, 9398, -66, - 9424, -98, 9450, 48, 9451, -9452, 10972, 10973, 10974, -10975, 11388, 106, - 11389, 86, 11390, -11391, 11503, 0, 11506, -11507, 11631, 11617, 11632, -11633, - 11647, 0, 11648, -11649, 11744, 0, 11776, -11777, 11935, 27597, 11936, -11937, - 12019, 40863, 12020, -12021, 12032, 19968, 12033, 20008, 12034, 20022, 12035, 20031, - 12036, 20057, 12037, 20101, 12038, 20108, 12039, 20128, 12040, 20154, 12041, 20799, - 12042, 20837, 12043, 20843, 12044, 20866, 12045, 20886, 12046, 20907, 12047, 20960, - 12048, 20981, 12049, 20992, 12050, 21147, 12051, 21241, 12052, 21269, 12053, 21274, - 12054, 21304, 12055, 21313, 12056, 21340, 12057, 21353, 12058, 21378, 12059, 21430, - 12060, 21448, 12061, 21475, 12062, 22231, 12063, 22303, 12064, 22763, 12065, 22786, - 12066, 22794, 12067, 22805, 12068, 22823, 12069, 22899, 12070, 23376, 12071, 23424, - 12072, 23544, 12073, 23567, 12074, 23586, 12075, 23608, 12076, 23662, 12077, 23665, - 12078, 24027, 12079, 24037, 12080, 24049, 12081, 24062, 12082, 24178, 12083, 24186, - 12084, 24191, 12085, 24308, 12086, 24318, 12087, 24331, 12088, 24339, 12089, 24400, - 12090, 24417, 12091, 24435, 12092, 24515, 12093, 25096, 12094, 25142, 12095, 25163, - 12096, 25903, 12097, 25908, 12098, 25991, 12099, 26007, 12100, 26020, 12101, 26041, - 12102, 26080, 12103, 26085, 12104, 26352, 12105, 26376, 12106, 26408, 12107, 27424, - 12108, 27490, 12109, 27513, 12110, 27571, 12111, 27595, 12112, 27604, 12113, 27611, - 12114, 27663, 12115, 27668, 12116, 27700, 12117, 28779, 12118, 29226, 12119, 29238, - 12120, 29243, 12121, 29247, 12122, 29255, 12123, 29273, 12124, 29275, 12125, 29356, - 12126, 29572, 12127, 29577, 12128, 29916, 12129, 29926, 12130, 29976, 12131, 29983, - 12132, 29992, 12133, 30000, 12134, 30091, 12135, 30098, 12136, 30326, 12137, 30333, - 12138, 30382, 12139, 30399, 12140, 30446, 12141, 30683, 12142, 30690, 12143, 30707, - 12144, 31034, 12145, 31160, 12146, 31166, 12147, 31348, 12148, 31435, 12149, 31481, - 12150, 31859, 12151, 31992, 12152, 32566, 12153, 32593, 12154, 32650, 12155, 32701, - 12156, 32769, 12157, 32780, 12158, 32786, 12159, 32819, 12160, 32895, 12161, 32905, - 12162, 33251, 12163, 33258, 12164, 33267, 12165, 33276, 12166, 33292, 12167, 33307, - 12168, 33311, 12169, 33390, 12170, 33394, 12171, 33400, 12172, 34381, 12173, 34411, - 12174, 34880, 12175, 34892, 12176, 34915, 12177, 35198, 12178, 35211, 12179, 35282, - 12180, 35328, 12181, 35895, 12182, 35910, 12183, 35925, 12184, 35960, 12185, 35997, - 12186, 36196, 12187, 36208, 12188, 36275, 12189, 36523, 12190, 36554, 12191, 36763, - 12192, 36784, 12193, 36789, 12194, 37009, 12195, 37193, 12196, 37318, 12197, 37324, - 12198, 37329, 12199, 38263, 12200, 38272, 12201, 38428, 12202, 38582, 12203, 38585, - 12204, 38632, 12205, 38737, 12206, 38750, 12207, 38754, 12208, 38761, 12209, 38859, - 12210, 38893, 12211, 38899, 12212, 38913, 12213, 39080, 12214, 39131, 12215, 39135, - 12216, 39318, 12217, 39321, 12218, 39340, 12219, 39592, 12220, 39640, 12221, 39647, - 12222, 39717, 12223, 39727, 12224, 39730, 12225, 39740, 12226, 39770, 12227, 40165, - 12228, 40565, 12229, 40575, 12230, 40613, 12231, 40635, 12232, 40643, 12233, 40653, - 12234, 40657, 12235, 40697, 12236, 40701, 12237, 40718, 12238, 40723, 12239, 40736, - 12240, 40763, 12241, 40778, 12242, 40786, 12243, 40845, 12244, 40860, 12245, 40864, - 12246, -12247, 12288, 32, 12289, -12290, 12330, 0, 12336, -12337, 12342, 12306, - 12343, 12343, 12344, 21313, 12345, -21317, 12347, -12348, 12364, 2097154, 12388, 2097152, - 12395, -12396, 12400, 12399, 12402, 12402, 12405, 12405, 12408, 12408, 12411, 12411, - 12414, -12415, 12436, 12358, 12437, -12438, 12441, 0, 12443, 32, 12445, 2097154, - 12448, -12449, 12460, 2097154, 12484, 2097152, 12491, -12492, 12496, 12495, 12498, 12498, - 12501, 12501, 12504, 12504, 12507, 12507, 12510, -12511, 12532, 12454, 12533, -12534, - 12535, -12528, 12539, 12539, 12540, 0, 12541, 2097154, 12544, -12545, 12593, -4353, - 12595, 4522, 12596, 4354, 12597, -4525, 12599, -4356, 12602, -4529, 12608, 4378, - 12609, -4359, 12612, 4385, 12613, -4362, 12623, -4450, 12644, 4448, 12645, -4373, - 12647, -4552, 12649, 4556, 12650, 4558, 12651, 4563, 12652, 4567, 12653, 4569, - 12654, 4380, 12655, 4573, 12656, 4575, 12657, -4382, 12659, 4384, 12660, -4387, - 12662, 4391, 12663, 4393, 12664, -4396, 12669, 4402, 12670, 4406, 12671, 4416, - 12672, 4423, 12673, 4428, 12674, -4594, 12676, -4440, 12679, -4485, 12681, 4488, - 12682, -4498, 12684, 4500, 12685, 4510, 12686, 4513, 12687, -12688, 12690, 19968, - 12691, 20108, 12692, 19977, 12693, 22235, 12694, 19978, 12695, 20013, 12696, 19979, - 12697, 30002, 12698, 20057, 12699, 19993, 12700, 19969, 12701, 22825, 12702, 22320, - 12703, 20154, 12704, -12705, 12868, 21839, 12869, 24188, 12870, 25991, 12871, 31631, - 12872, -12873, 12896, 4352, 12897, -4355, 12899, -4358, 12902, 4361, 12903, -4364, - 12905, -4367, 12910, -12911, 12928, 19968, 12929, 20108, 12930, 19977, 12931, 22235, - 12932, 20116, 12933, 20845, 12934, 19971, 12935, 20843, 12936, 20061, 12937, 21313, - 12938, 26376, 12939, 28779, 12940, 27700, 12941, 26408, 12942, 37329, 12943, 22303, - 12944, 26085, 12945, 26666, 12946, 26377, 12947, 31038, 12948, 21517, 12949, 29305, - 12950, 36001, 12951, 31069, 12952, 21172, 12953, 31192, 12954, 30007, 12955, 22899, - 12956, 36969, 12957, 20778, 12958, 21360, 12959, 27880, 12960, 38917, 12961, 20241, - 12962, 20889, 12963, 27491, 12964, 19978, 12965, 20013, 12966, 19979, 12967, 24038, - 12968, 21491, 12969, 21307, 12970, 23447, 12971, 23398, 12972, 30435, 12973, 20225, - 12974, 36039, 12975, 21332, 12976, 22812, 12977, -12978, 13008, 12450, 13009, 12452, - 13010, 12454, 13011, 12456, 13012, -12459, 13014, 12461, 13015, 12463, 13016, 12465, - 13017, 12467, 13018, 12469, 13019, 12471, 13020, 12473, 13021, 12475, 13022, 12477, - 13023, 12479, 13024, 12481, 13025, 12484, 13026, 12486, 13027, 12488, 13028, -12491, - 13034, 12498, 13035, 12501, 13036, 12504, 13037, 12507, 13038, -12511, 13043, 12516, - 13044, 12518, 13045, -12521, 13051, -12528, 13055, -13056, 42607, 0, 42611, 42611, - 42612, 0, 42622, -42623, 42652, 1098, 42653, 1100, 42654, 0, 42656, -42657, - 42736, 0, 42738, -42739, 42864, 2097154, 42866, -42867, 43000, 294, 43001, 339, - 43002, -43003, 43010, 0, 43011, -43012, 43014, 0, 43015, -43016, 43019, 0, - 43020, -43021, 43043, 0, 43048, -43049, 43136, 0, 43138, -43139, 43188, 0, - 43206, -43207, 43232, 0, 43250, -43251, 43302, 0, 43310, -43311, 43335, 0, - 43348, -43349, 43392, 0, 43396, -43397, 43443, 0, 43457, -43458, 43493, 0, - 43494, -43495, 43561, 0, 43575, -43576, 43587, 0, 43588, -43589, 43596, 0, - 43598, -43599, 43643, 0, 43646, -43647, 43696, 0, 43697, 43697, 43698, 0, - 43701, -43702, 43703, 0, 43705, -43706, 43710, 0, 43712, 43712, 43713, 0, - 43714, -43715, 43755, 0, 43760, -43761, 43765, 0, 43767, -43768, 43868, 42791, - 43869, 43831, 43870, 619, 43871, 43858, 43872, -43873, 44003, 0, 44011, 44011, - 44012, 0, 44014, -44015, 55296, 0, 57344, -57345, 63744, 35912, 63745, 26356, - 63746, 36554, 63747, 36040, 63748, 28369, 63749, 20018, 63750, 21477, 63751, 40860, - 63753, 22865, 63754, 37329, 63755, 21895, 63756, 22856, 63757, 25078, 63758, 30313, - 63759, 32645, 63760, 34367, 63761, 34746, 63762, 35064, 63763, 37007, 63764, 27138, - 63765, 27931, 63766, 28889, 63767, 29662, 63768, 33853, 63769, 37226, 63770, 39409, - 63771, 20098, 63772, 21365, 63773, 27396, 63774, 29211, 63775, 34349, 63776, 40478, - 63777, 23888, 63778, 28651, 63779, 34253, 63780, 35172, 63781, 25289, 63782, 33240, - 63783, 34847, 63784, 24266, 63785, 26391, 63786, 28010, 63787, 29436, 63788, 37070, - 63789, 20358, 63790, 20919, 63791, 21214, 63792, 25796, 63793, 27347, 63794, 29200, - 63795, 30439, 63796, 32769, 63797, 34310, 63798, 34396, 63799, 36335, 63800, 38706, - 63801, 39791, 63802, 40442, 63803, 30860, 63804, 31103, 63805, 32160, 63806, 33737, - 63807, 37636, 63808, 40575, 63809, 35542, 63810, 22751, 63811, 24324, 63812, 31840, - 63813, 32894, 63814, 29282, 63815, 30922, 63816, 36034, 63817, 38647, 63818, 22744, - 63819, 23650, 63820, 27155, 63821, 28122, 63822, 28431, 63823, 32047, 63824, 32311, - 63825, 38475, 63826, 21202, 63827, 32907, 63828, 20956, 63829, 20940, 63830, 31260, - 63831, 32190, 63832, 33777, 63833, 38517, 63834, 35712, 63835, 25295, 63836, 27138, - 63837, 35582, 63838, 20025, 63839, 23527, 63840, 24594, 63841, 29575, 63842, 30064, - 63843, 21271, 63844, 30971, 63845, 20415, 63846, 24489, 63847, 19981, 63848, 27852, - 63849, 25976, 63850, 32034, 63851, 21443, 63852, 22622, 63853, 30465, 63854, 33865, - 63855, 35498, 63856, 27578, 63857, 36784, 63858, 27784, 63859, 25342, 63860, 33509, - 63861, 25504, 63862, 30053, 63863, 20142, 63864, 20841, 63865, 20937, 63866, 26753, - 63867, 31975, 63868, 33391, 63869, 35538, 63870, 37327, 63871, 21237, 63872, 21570, - 63873, 22899, 63874, 24300, 63875, 26053, 63876, 28670, 63877, 31018, 63878, 38317, - 63879, 39530, 63880, 40599, 63881, 40654, 63882, 21147, 63883, 26310, 63884, 27511, - 63885, 36706, 63886, 24180, 63887, 24976, 63888, 25088, 63889, 25754, 63890, 28451, - 63891, 29001, 63892, 29833, 63893, 31178, 63894, 32244, 63895, 32879, 63896, 36646, - 63897, 34030, 63898, 36899, 63899, 37706, 63900, 21015, 63901, 21155, 63902, 21693, - 63903, 28872, 63904, 35010, 63905, 35498, 63906, 24265, 63907, 24565, 63908, 25467, - 63909, 27566, 63910, 31806, 63911, 29557, 63912, 20196, 63913, 22265, 63914, 23527, - 63915, 23994, 63916, 24604, 63917, 29618, 63918, 29801, 63919, 32666, 63920, 32838, - 63921, 37428, 63922, 38646, 63923, 38728, 63924, 38936, 63925, 20363, 63926, 31150, - 63927, 37300, 63928, 38584, 63929, 24801, 63930, 20102, 63931, 20698, 63932, 23534, - 63933, 23615, 63934, 26009, 63935, 27138, 63936, 29134, 63937, 30274, 63938, 34044, - 63939, 36988, 63940, 40845, 63941, 26248, 63942, 38446, 63943, 21129, 63944, 26491, - 63945, 26611, 63946, 27969, 63947, 28316, 63948, 29705, 63949, 30041, 63950, 30827, - 63951, 32016, 63952, 39006, 63953, 20845, 63954, 25134, 63955, 38520, 63956, 20523, - 63957, 23833, 63958, 28138, 63959, 36650, 63960, 24459, 63961, 24900, 63962, 26647, - 63963, 29575, 63964, 38534, 63965, 21033, 63966, 21519, 63967, 23653, 63968, 26131, - 63969, 26446, 63970, 26792, 63971, 27877, 63972, 29702, 63973, 30178, 63974, 32633, - 63975, 35023, 63976, 35041, 63977, 37324, 63978, 38626, 63979, 21311, 63980, 28346, - 63981, 21533, 63982, 29136, 63983, 29848, 63984, 34298, 63985, 38563, 63986, 40023, - 63987, 40607, 63988, 26519, 63989, 28107, 63990, 33256, 63991, 31435, 63992, 31520, - 63993, 31890, 63994, 29376, 63995, 28825, 63996, 35672, 63997, 20160, 63998, 33590, - 63999, 21050, 64000, 20999, 64001, 24230, 64002, 25299, 64003, 31958, 64004, 23429, - 64005, 27934, 64006, 26292, 64007, 36667, 64008, 34892, 64009, 38477, 64010, 35211, - 64011, 24275, 64012, 20800, 64013, 21952, 64014, -64015, 64016, 22618, 64017, 64017, - 64018, 26228, 64019, -64020, 64021, 20958, 64022, 29482, 64023, 30410, 64024, 31036, - 64025, 31070, 64026, 31077, 64027, 31119, 64028, 38742, 64029, 31934, 64030, 32701, - 64031, 64031, 64032, 34322, 64033, 64033, 64034, 35576, 64035, -64036, 64037, 36920, - 64038, 37117, 64039, -64040, 64042, 39151, 64043, 39164, 64044, 39208, 64045, 40372, - 64046, 37086, 64047, 38583, 64048, 20398, 64049, 20711, 64050, 20813, 64051, 21193, - 64052, 21220, 64053, 21329, 64054, 21917, 64055, 22022, 64056, 22120, 64057, 22592, - 64058, 22696, 64059, 23652, 64060, 23662, 64061, 24724, 64062, 24936, 64063, 24974, - 64064, 25074, 64065, 25935, 64066, 26082, 64067, 26257, 64068, 26757, 64069, 28023, - 64070, 28186, 64071, 28450, 64072, 29038, 64073, 29227, 64074, 29730, 64075, 30865, - 64076, 31038, 64077, 31049, 64078, 31048, 64079, 31056, 64080, 31062, 64081, 31069, - 64082, -31118, 64084, 31296, 64085, 31361, 64086, 31680, 64087, 32244, 64088, 32265, - 64089, 32321, 64090, 32626, 64091, 32773, 64092, 33261, 64093, 33401, 64095, 33879, - 64096, 35088, 64097, 35222, 64098, 35585, 64099, 35641, 64100, 36051, 64101, 36104, - 64102, 36790, 64103, 36920, 64104, 38627, 64105, 38911, 64106, 38971, 64107, 24693, - 64108, 148206, 64109, 33304, 64110, -64111, 64112, 20006, 64113, 20917, 64114, 20840, - 64115, 20352, 64116, 20805, 64117, 20864, 64118, 21191, 64119, 21242, 64120, 21917, - 64121, 21845, 64122, 21913, 64123, 21986, 64124, 22618, 64125, 22707, 64126, 22852, - 64127, 22868, 64128, 23138, 64129, 23336, 64130, 24274, 64131, 24281, 64132, 24425, - 64133, 24493, 64134, 24792, 64135, 24910, 64136, 24840, 64137, 24974, 64138, 24928, - 64139, 25074, 64140, 25140, 64141, 25540, 64142, 25628, 64143, 25682, 64144, 25942, - 64145, 26228, 64146, 26391, 64147, 26395, 64148, 26454, 64149, 27513, 64150, 27578, - 64151, 27969, 64152, 28379, 64153, 28363, 64154, 28450, 64155, 28702, 64156, 29038, - 64157, 30631, 64158, 29237, 64159, 29359, 64160, 29482, 64161, 29809, 64162, 29958, - 64163, 30011, 64164, 30237, 64165, 30239, 64166, 30410, 64167, 30427, 64168, 30452, - 64169, 30538, 64170, 30528, 64171, 30924, 64172, 31409, 64173, 31680, 64174, 31867, - 64175, 32091, 64176, 32244, 64177, 32574, 64178, 32773, 64179, 33618, 64180, 33775, - 64181, 34681, 64182, 35137, 64183, 35206, 64184, 35222, 64185, 35519, 64186, 35576, - 64187, 35531, 64188, 35585, 64189, 35582, 64190, 35565, 64191, 35641, 64192, 35722, - 64193, 36104, 64194, 36664, 64195, 36978, 64196, 37273, 64197, 37494, 64198, 38524, - 64199, 38627, 64200, 38742, 64201, 38875, 64202, 38911, 64203, 38923, 64204, 38971, - 64205, 39698, 64206, 40860, 64207, 141386, 64208, 141380, 64209, 144341, 64210, 15261, - 64211, 16408, 64212, 16441, 64213, 152137, 64214, 154832, 64215, 163539, 64216, 40771, - 64217, 40846, 64218, -64219, 64285, 1497, 64286, 0, 64287, 1522, 64288, 1506, - 64289, 1488, 64290, -1492, 64292, -1500, 64295, 1512, 64296, 1514, 64297, 43, - 64298, 1513, 64302, 1488, 64305, -1490, 64311, 64311, 64312, -1497, 64317, 64317, - 64318, 1502, 64319, 64319, 64320, -1505, 64322, 64322, 64323, -1508, 64325, 64325, - 64326, -1511, 64331, 1493, 64332, 1489, 64333, 1499, 64334, 1508, 64335, 64335, - 64336, 1649, 64338, 1659, 64342, 1662, 64346, 1664, 64350, 1658, 64354, 1663, - 64358, 1657, 64362, 1700, 64366, 1702, 64370, 1668, 64374, 1667, 64378, 1670, - 64382, 1671, 64386, 1677, 64388, 1676, 64390, 1678, 64392, 1672, 64394, 1688, - 64396, 1681, 64398, 1705, 64402, 1711, 64406, 1715, 64410, 1713, 64414, 1722, - 64416, 1723, 64420, 1749, 64422, 1729, 64426, 1726, 64430, 1746, 64434, -64435, - 64467, 1709, 64471, 1735, 64473, 1734, 64475, 1736, 64477, 1655, 64478, 1739, - 64480, 1733, 64482, 1737, 64484, 1744, 64488, 1609, 64490, -64491, 64508, 1740, - 64512, -64513, 64603, -1585, 64605, 1609, 64606, 32, 64612, -64613, 64656, 1609, - 64657, -64658, 64729, 1607, 64730, -64731, 64754, 1600, 64757, -64758, 64828, 1575, - 64830, -64831, 65024, 0, 65040, 44, 65041, -12290, 65043, -59, 65045, 33, - 65046, 63, 65047, -12311, 65049, 8230, 65050, -65051, 65056, 0, 65072, 8229, - 65073, 8212, 65074, 8211, 65075, 95, 65077, -41, 65079, 123, 65080, 125, - 65081, -12309, 65083, -12305, 65085, -12299, 65087, -12297, 65089, -12301, 65093, -65094, - 65095, 91, 65096, 93, 65097, 32, 65101, 95, 65104, 44, 65105, 12289, - 65106, 46, 65107, 65107, 65108, 59, 65109, 58, 65110, 63, 65111, 33, - 65112, 8212, 65113, -41, 65115, 123, 65116, 125, 65117, -12309, 65119, 35, - 65120, 38, 65121, -43, 65123, 45, 65124, 60, 65125, 62, 65126, 61, - 65127, 65127, 65128, 92, 65129, -37, 65131, 64, 65132, -65133, 65136, 32, - 65137, 1600, 65138, 32, 65139, 65139, 65140, 32, 65141, 65141, 65142, 32, - 65143, 1600, 65144, 32, 65145, 1600, 65146, 32, 65147, 1600, 65148, 32, - 65149, 1600, 65150, 32, 65151, 1600, 65152, 1569, 65153, 1575, 65157, 1608, - 65159, 1575, 65161, 1610, 65165, 1575, 65167, 1576, 65171, 1577, 65173, 1578, - 65177, 1579, 65181, 1580, 65185, 1581, 65189, 1582, 65193, 1583, 65195, 1584, - 65197, 1585, 65199, 1586, 65201, 1587, 65205, 1588, 65209, 1589, 65213, 1590, - 65217, 1591, 65221, 1592, 65225, 1593, 65229, 1594, 65233, 1601, 65237, 1602, - 65241, 1603, 65245, 1604, 65249, 1605, 65253, 1606, 65257, 1607, 65261, 1608, - 65263, 1609, 65265, 1610, 65269, -65270, 65279, 0, 65280, 65280, 65281, -34, - 65375, -10630, 65377, 12290, 65378, -12301, 65380, 12289, 65381, 12539, 65382, 12530, - 65383, 12449, 65384, 12451, 65385, 12453, 65386, 12455, 65387, 12457, 65388, 12515, - 65389, 12517, 65390, 12519, 65391, 12483, 65392, 65392, 65393, 12450, 65394, 12452, - 65395, 12454, 65396, 12456, 65397, -12459, 65399, 12461, 65400, 12463, 65401, 12465, - 65402, 12467, 65403, 12469, 65404, 12471, 65405, 12473, 65406, 12475, 65407, 12477, - 65408, 12479, 65409, 12481, 65410, 12484, 65411, 12486, 65412, 12488, 65413, -12491, - 65419, 12498, 65420, 12501, 65421, 12504, 65422, 12507, 65423, -12511, 65428, 12516, - 65429, 12518, 65430, -12521, 65436, 12527, 65437, 12531, 65438, -65439, 65440, 4448, - 65441, -4353, 65443, 4522, 65444, 4354, 65445, -4525, 65447, -4356, 65450, -4529, - 65456, 4378, 65457, -4359, 65460, 4385, 65461, -4362, 65471, -65472, 65474, -4450, - 65480, -65481, 65482, -4456, 65488, -65489, 65490, -4462, 65496, -65497, 65498, -4468, - 65501, -65502, 65504, -163, 65506, 172, 65507, 32, 65508, 166, 65509, 165, - 65510, 8361, 65511, 65511, 65512, 9474, 65513, -8593, 65517, 9632, 65518, 9675, - 65519, -65520, 65529, 0, 65532, -65533, 66045, 0, 66046, -66047, 66272, 0, - 66273, -66274, 66422, 0, 66427, -66428, 68097, 0, 68100, 68100, 68101, 0, - 68103, -68104, 68108, 0, 68112, -68113, 68152, 0, 68155, -68156, 68159, 0, - 68160, -68161, 68325, 0, 68327, -68328, 69632, 0, 69635, -69636, 69688, 0, - 69703, -69704, 69759, 0, 69763, -69764, 69786, 2097154, 69790, -69791, 69803, 69797, - 69804, -69805, 69808, 0, 69819, -69820, 69821, 0, 69822, -69823, 69888, 0, - 69891, -69892, 69927, 0, 69941, -69942, 70003, 0, 70004, -70005, 70016, 0, - 70019, -70020, 70067, 0, 70081, -70082, 70090, 0, 70093, -70094, 70188, 0, - 70200, -70201, 70206, 0, 70207, -70208, 70367, 0, 70379, -70380, 70400, 0, - 70404, -70405, 70460, 0, 70461, 70461, 70462, 0, 70469, -70470, 70471, 0, - 70473, -70474, 70475, 0, 70478, -70479, 70487, 0, 70488, -70489, 70498, 0, - 70500, -70501, 70502, 0, 70509, -70510, 70512, 0, 70517, -70518, 70709, 0, - 70727, -70728, 70832, 0, 70852, -70853, 71087, 0, 71094, -71095, 71096, 0, - 71105, -71106, 71132, 0, 71134, -71135, 71216, 0, 71233, -71234, 71339, 0, - 71352, -71353, 71453, 0, 71468, -71469, 72751, 0, 72759, 72759, 72760, 0, - 72768, -72769, 72850, 0, 72872, 72872, 72873, 0, 72887, -72888, 92912, 0, - 92917, -92918, 92976, 0, 92983, -92984, 94033, 0, 94079, -94080, 94095, 0, - 94099, -94100, 113821, 0, 113823, 113823, 113824, 0, 113828, -113829, 119134, -119128, - 119136, 119128, 119141, 0, 119146, -119147, 119149, 0, 119171, -119172, 119173, 0, - 119180, -119181, 119210, 0, 119214, -119215, 119227, -119226, 119229, -119226, 119231, -119226, - 119233, -119234, 119362, 0, 119365, -119366, 119808, -66, 119834, -98, 119860, -66, - 119886, -98, 119893, 119893, 119894, -106, 119912, -66, 119938, -98, 119964, 65, - 119965, 119965, 119966, -68, 119968, -119969, 119970, 71, 119971, -119972, 119973, -75, - 119975, -119976, 119977, -79, 119981, 119981, 119982, -84, 119990, -98, 119994, 119994, - 119995, 102, 119996, 119996, 119997, -105, 120004, 120004, 120005, -113, 120016, -66, - 120042, -98, 120068, -66, 120070, 120070, 120071, -69, 120075, -120076, 120077, -75, - 120085, 120085, 120086, -84, 120093, 120093, 120094, -98, 120120, -66, 120122, 120122, - 120123, -69, 120127, 120127, 120128, -74, 120133, 120133, 120134, 79, 120135, -120136, - 120138, -84, 120145, 120145, 120146, -98, 120172, -66, 120198, -98, 120224, -66, - 120250, -98, 120276, -66, 120302, -98, 120328, -66, 120354, -98, 120380, -66, - 120406, -98, 120432, -66, 120458, -98, 120484, 305, 120485, 567, 120486, -120487, - 120488, -914, 120505, 920, 120506, -932, 120513, 8711, 120514, -946, 120539, 8706, - 120540, 949, 120541, 952, 120542, 954, 120543, 966, 120544, 961, 120545, 960, - 120546, -914, 120563, 920, 120564, -932, 120571, 8711, 120572, -946, 120597, 8706, - 120598, 949, 120599, 952, 120600, 954, 120601, 966, 120602, 961, 120603, 960, - 120604, -914, 120621, 920, 120622, -932, 120629, 8711, 120630, -946, 120655, 8706, - 120656, 949, 120657, 952, 120658, 954, 120659, 966, 120660, 961, 120661, 960, - 120662, -914, 120679, 920, 120680, -932, 120687, 8711, 120688, -946, 120713, 8706, - 120714, 949, 120715, 952, 120716, 954, 120717, 966, 120718, 961, 120719, 960, - 120720, -914, 120737, 920, 120738, -932, 120745, 8711, 120746, -946, 120771, 8706, - 120772, 949, 120773, 952, 120774, 954, 120775, 966, 120776, 961, 120777, 960, - 120778, -989, 120780, -120781, 120782, -49, 120792, -49, 120802, -49, 120812, -49, - 120822, -49, 120832, -120833, 121344, 0, 121399, -121400, 121403, 0, 121453, -121454, - 121461, 0, 121462, -121463, 121476, 0, 121477, -121478, 121499, 0, 121504, 121504, - 121505, 0, 121520, -121521, 122880, 0, 122887, 122887, 122888, 0, 122905, -122906, - 122907, 0, 122914, 122914, 122915, 0, 122917, 122917, 122918, 0, 122923, -122924, - 125136, 0, 125143, -125144, 125252, 0, 125259, -125260, 126464, -1576, 126466, 1580, - 126467, 1583, 126468, 126468, 126469, 1608, 126470, 1586, 126471, 1581, 126472, 1591, - 126473, 1610, 126474, -1604, 126478, 1587, 126479, 1593, 126480, 1601, 126481, 1589, - 126482, 1602, 126483, 1585, 126484, 1588, 126485, -1579, 126487, 1582, 126488, 1584, - 126489, 1590, 126490, 1592, 126491, 1594, 126492, 1646, 126493, 1722, 126494, 1697, - 126495, 1647, 126496, 126496, 126497, 1576, 126498, 1580, 126499, 126499, 126500, 1607, - 126501, -126502, 126503, 1581, 126504, 126504, 126505, 1610, 126506, -1604, 126510, 1587, - 126511, 1593, 126512, 1601, 126513, 1589, 126514, 1602, 126515, 126515, 126516, 1588, - 126517, -1579, 126519, 1582, 126520, 126520, 126521, 1590, 126522, 126522, 126523, 1594, - 126524, -126525, 126530, 1580, 126531, -126532, 126535, 1581, 126536, 126536, 126537, 1610, - 126538, 126538, 126539, 1604, 126540, 126540, 126541, 1606, 126542, 1587, 126543, 1593, - 126544, 126544, 126545, 1589, 126546, 1602, 126547, 126547, 126548, 1588, 126549, -126550, - 126551, 1582, 126552, 126552, 126553, 1590, 126554, 126554, 126555, 1594, 126556, 126556, - 126557, 1722, 126558, 126558, 126559, 1647, 126560, 126560, 126561, 1576, 126562, 1580, - 126563, 126563, 126564, 1607, 126565, -126566, 126567, 1581, 126568, 1591, 126569, 1610, - 126570, 1603, 126571, 126571, 126572, -1606, 126574, 1587, 126575, 1593, 126576, 1601, - 126577, 1589, 126578, 1602, 126579, 126579, 126580, 1588, 126581, -1579, 126583, 1582, - 126584, 126584, 126585, 1590, 126586, 1592, 126587, 1594, 126588, 1646, 126589, 126589, - 126590, 1697, 126591, 126591, 126592, -1576, 126594, 1580, 126595, 1583, 126596, -1608, - 126598, 1586, 126599, 1581, 126600, 1591, 126601, 1610, 126602, 126602, 126603, -1605, - 126606, 1587, 126607, 1593, 126608, 1601, 126609, 1589, 126610, 1602, 126611, 1585, - 126612, 1588, 126613, -1579, 126615, 1582, 126616, 1584, 126617, 1590, 126618, 1592, - 126619, 1594, 126620, -126621, 126625, 1576, 126626, 1580, 126627, 1583, 126628, 126628, - 126629, 1608, 126630, 1586, 126631, 1581, 126632, 1591, 126633, 1610, 126634, 126634, - 126635, -1605, 126638, 1587, 126639, 1593, 126640, 1601, 126641, 1589, 126642, 1602, - 126643, 1585, 126644, 1588, 126645, -1579, 126647, 1582, 126648, 1584, 126649, 1590, - 126650, 1592, 126651, 1594, 126652, -126653, 127232, 48, 127234, -50, 127243, -127244, - 127275, 67, 127276, 82, 127277, -127278, 127280, -66, 127306, -127307, 127490, 12469, - 127491, -127492, 127504, 25163, 127505, 23383, 127506, 21452, 127507, 12486, 127508, 20108, - 127509, 22810, 127510, 35299, 127511, 22825, 127512, 20132, 127513, 26144, 127514, 28961, - 127515, 26009, 127516, 21069, 127517, 24460, 127518, 20877, 127519, 26032, 127520, 21021, - 127521, 32066, 127522, 29983, 127523, 36009, 127524, 22768, 127525, 21561, 127526, 28436, - 127527, 25237, 127528, 25429, 127529, 19968, 127530, 19977, 127531, 36938, 127532, 24038, - 127533, 20013, 127534, 21491, 127535, 25351, 127536, 36208, 127537, 25171, 127538, 31105, - 127539, 31354, 127540, 21512, 127541, 28288, 127542, 26377, 127543, 26376, 127544, 30003, - 127545, 21106, 127546, 21942, 127547, 37197, 127548, -127549, 127568, 24471, 127569, 21487, - 127570, -127571, 194560, 20029, 194561, 20024, 194562, 20033, 194563, 131362, 194564, 20320, - 194565, 20398, 194566, 20411, 194567, 20482, 194568, 20602, 194569, 20633, 194570, 20711, - 194571, 20687, 194572, 13470, 194573, 132666, 194574, 20813, 194575, 20820, 194576, 20836, - 194577, 20855, 194578, 132380, 194579, 13497, 194580, 20839, 194581, 20877, 194582, 132427, - 194583, 20887, 194584, 20900, 194585, 20172, 194586, 20908, 194587, 20917, 194588, 168415, - 194589, 20981, 194590, 20995, 194591, 13535, 194592, 21051, 194593, 21062, 194594, 21106, - 194595, 21111, 194596, 13589, 194597, 21191, 194598, 21193, 194599, 21220, 194600, 21242, - 194601, -21254, 194603, 21271, 194604, 21321, 194605, 21329, 194606, 21338, 194607, 21363, - 194608, 21373, 194609, 21375, 194612, 133676, 194613, 28784, 194614, 21450, 194615, 21471, - 194616, 133987, 194617, 21483, 194618, 21489, 194619, 21510, 194620, 21662, 194621, 21560, - 194622, 21576, 194623, 21608, 194624, 21666, 194625, 21750, 194626, 21776, 194627, 21843, - 194628, 21859, 194629, 21892, 194631, 21913, 194632, 21931, 194633, 21939, 194634, 21954, - 194635, 22294, 194636, 22022, 194637, 22295, 194638, 22097, 194639, 22132, 194640, 20999, - 194641, 22766, 194642, 22478, 194643, 22516, 194644, 22541, 194645, 22411, 194646, 22578, - 194647, 22577, 194648, 22700, 194649, 136420, 194650, 22770, 194651, 22775, 194652, 22790, - 194653, 22810, 194654, 22818, 194655, 22882, 194656, 136872, 194657, 136938, 194658, 23020, - 194659, 23067, 194660, 23079, 194661, 23000, 194662, 23142, 194663, 14062, 194664, 14076, - 194665, 23304, 194666, 23358, 194668, 137672, 194669, 23491, 194670, 23512, 194671, 23527, - 194672, 23539, 194673, 138008, 194674, 23551, 194675, 23558, 194676, 24403, 194677, 23586, - 194678, 14209, 194679, 23648, 194680, 23662, 194681, 23744, 194682, 23693, 194683, 138724, - 194684, 23875, 194685, 138726, 194686, 23918, 194687, 23915, 194688, 23932, 194689, -24034, - 194691, 14383, 194692, 24061, 194693, 24104, 194694, 24125, 194695, 24169, 194696, 14434, - 194697, 139651, 194698, 14460, 194699, 24240, 194700, 24243, 194701, 24246, 194702, 24266, - 194703, 172946, 194704, 24318, 194705, 140081, 194707, 33281, 194708, 24354, 194710, 14535, - 194711, 144056, 194712, 156122, 194713, 24418, 194714, 24427, 194715, 14563, 194716, 24474, - 194717, 24525, 194718, 24535, 194719, 24569, 194720, 24705, 194721, 14650, 194722, 14620, - 194723, 24724, 194724, 141012, 194725, 24775, 194726, 24904, 194727, 24908, 194728, 24910, - 194729, 24908, 194730, 24954, 194731, 24974, 194732, 25010, 194733, 24996, 194734, 25007, - 194735, 25054, 194736, 25074, 194737, 25078, 194738, 25104, 194739, 25115, 194740, 25181, - 194741, 25265, 194742, 25300, 194743, 25424, 194744, 142092, 194745, 25405, 194746, 25340, - 194747, 25448, 194748, 25475, 194749, 25572, 194750, 142321, 194751, 25634, 194752, 25541, - 194753, 25513, 194754, 14894, 194755, 25705, 194756, 25726, 194757, 25757, 194758, 25719, - 194759, 14956, 194760, 25935, 194761, 25964, 194762, 143370, 194763, 26083, 194764, 26360, - 194765, 26185, 194766, 15129, 194767, 26257, 194768, 15112, 194769, 15076, 194770, 20882, - 194771, 20885, 194772, 26368, 194773, 26268, 194774, 32941, 194775, 17369, 194776, 26391, - 194777, 26395, 194778, 26401, 194779, 26462, 194780, 26451, 194781, 144323, 194782, 15177, - 194783, 26618, 194784, 26501, 194785, 26706, 194786, 26757, 194787, 144493, 194788, 26766, - 194789, 26655, 194790, 26900, 194791, 15261, 194792, 26946, 194793, 27043, 194794, 27114, - 194795, 27304, 194796, 145059, 194797, 27355, 194798, 15384, 194799, 27425, 194800, 145575, - 194801, 27476, 194802, 15438, 194803, 27506, 194804, 27551, 194805, -27579, 194807, 146061, - 194808, 138507, 194809, 146170, 194810, 27726, 194811, 146620, 194812, 27839, 194813, 27853, - 194814, 27751, 194815, 27926, 194816, 27966, 194817, 28023, 194818, 27969, 194819, 28009, - 194820, 28024, 194821, 28037, 194822, 146718, 194823, 27956, 194824, 28207, 194825, 28270, - 194826, 15667, 194827, 28363, 194828, 28359, 194829, 147153, 194830, 28153, 194831, 28526, - 194832, 147294, 194833, 147342, 194834, 28614, 194835, 28729, 194836, 28702, 194837, 28699, - 194838, 15766, 194839, 28746, 194840, 28797, 194841, 28791, 194842, 28845, 194843, 132389, - 194844, 28997, 194845, 148067, 194846, 29084, 194847, 148395, 194848, 29224, 194849, 29237, - 194850, 29264, 194851, 149000, 194852, 29312, 194853, 29333, 194854, 149301, 194855, 149524, - 194856, 29562, 194857, 29579, 194858, 16044, 194859, 29605, 194860, 16056, 194862, 29767, - 194863, 29788, 194864, 29809, 194865, 29829, 194866, 29898, 194867, 16155, 194868, 29988, - 194869, 150582, 194870, 30014, 194871, 150674, 194872, 30064, 194873, 139679, 194874, 30224, - 194875, 151457, 194876, 151480, 194877, 151620, 194878, 16380, 194879, 16392, 194880, 30452, - 194881, 151795, 194882, 151794, 194883, 151833, 194884, 151859, 194885, -30495, 194887, 30495, - 194888, 30538, 194889, 16441, 194890, 30603, 194891, 16454, 194892, 16534, 194893, 152605, - 194894, 30798, 194895, 30860, 194896, 30924, 194897, 16611, 194898, 153126, 194899, 31062, - 194900, 153242, 194901, 153285, 194902, 31119, 194903, 31211, 194904, 16687, 194905, 31296, - 194906, 31306, 194907, 31311, 194908, 153980, 194909, 154279, 194911, 31470, 194912, 16898, - 194913, 154539, 194914, 31686, 194915, 31689, 194916, 16935, 194917, 154752, 194918, 31954, - 194919, 17056, 194920, 31976, 194921, 31971, 194922, 32000, 194923, 155526, 194924, 32099, - 194925, 17153, 194926, 32199, 194927, 32258, 194928, 32325, 194929, 17204, 194930, 156200, - 194931, 156231, 194932, 17241, 194933, 156377, 194934, 32634, 194935, 156478, 194936, 32661, - 194937, 32762, 194938, 32773, 194939, 156890, 194940, 156963, 194941, 32864, 194942, 157096, - 194943, 32880, 194944, 144223, 194945, 17365, 194946, 32946, 194947, 33027, 194948, 17419, - 194949, 33086, 194950, 23221, 194951, 157607, 194952, 157621, 194953, 144275, 194954, 144284, - 194955, 33281, 194956, 33284, 194957, 36766, 194958, 17515, 194959, 33425, 194960, 33419, - 194961, 33437, 194962, 21171, 194963, 33457, 194964, 33459, 194965, 33469, 194966, 33510, - 194967, 158524, 194968, 33509, 194969, 33565, 194970, 33635, 194971, 33709, 194972, 33571, - 194973, 33725, 194974, 33767, 194975, 33879, 194976, 33619, 194977, 33738, 194978, 33740, - 194979, 33756, 194980, 158774, 194981, 159083, 194982, 158933, 194983, 17707, 194984, 34033, - 194985, 34035, 194986, 34070, 194987, 160714, 194988, 34148, 194989, 159532, 194990, 17757, - 194991, 17761, 194992, 159665, 194993, 159954, 194994, 17771, 194995, 34384, 194996, 34396, - 194997, 34407, 194998, 34409, 194999, 34473, 195000, 34440, 195001, 34574, 195002, 34530, - 195003, 34681, 195004, 34600, 195005, 34667, 195006, 34694, 195007, 17879, 195008, 34785, - 195009, 34817, 195010, 17913, 195011, 34912, 195012, 34915, 195013, 161383, 195014, 35031, - 195015, 35038, 195016, 17973, 195017, 35066, 195018, 13499, 195019, 161966, 195020, 162150, - 195021, 18110, 195022, 18119, 195023, 35488, 195024, 35565, 195025, 35722, 195026, 35925, - 195027, 162984, 195028, 36011, 195029, 36033, 195030, 36123, 195031, 36215, 195032, 163631, - 195033, 133124, 195034, 36299, 195035, 36284, 195036, 36336, 195037, 133342, 195038, 36564, - 195039, 36664, 195040, 165330, 195041, 165357, 195042, 37012, 195043, 37105, 195044, 37137, - 195045, 165678, 195046, 37147, 195047, 37432, 195048, -37592, 195050, 37500, 195051, 37881, - 195052, 37909, 195053, 166906, 195054, 38283, 195055, 18837, 195056, 38327, 195057, 167287, - 195058, 18918, 195059, 38595, 195060, 23986, 195061, 38691, 195062, 168261, 195063, 168474, - 195064, 19054, 195065, 19062, 195066, 38880, 195067, 168970, 195068, 19122, 195069, 169110, - 195070, 38923, 195072, 38953, 195073, 169398, 195074, 39138, 195075, 19251, 195076, 39209, - 195077, 39335, 195078, 39362, 195079, 39422, 195080, 19406, 195081, 170800, 195082, 39698, - 195083, 40000, 195084, 40189, 195085, 19662, 195086, 19693, 195087, 40295, 195088, 172238, - 195089, 19704, 195090, 172293, 195091, 172558, 195092, 172689, 195093, 40635, 195094, 19798, - 195095, 40697, 195096, 40702, 195097, 40709, 195098, 40719, 195099, 40726, 195100, 40763, - 195101, 173568, 195102, -195103, 917505, 0, 917506, -917507, 917536, 0, 917632, -917633, - 917760, 0, 918000, -918001, 2147483647, 0}; - -UnicodeSimpleCategory get_unicode_simple_category(uint32 code) { - auto it = std::upper_bound(std::begin(unicode_simple_category_ranges), std::end(unicode_simple_category_ranges), - (code << 5) + 30); - return static_cast(*(it - 1) & 31); -} - -/** - * Search pregenerated ranges of pairs for the replacement of specified character - */ -template -static uint32 binary_search_ranges(const int32 (&ranges)[N], uint32 code) { - if (code > 0x10ffff) { - return 0; - } - - int32 code_int = static_cast(code); - size_t l = 0, r = N; - while (l < r) { - size_t m = ((l + r + 2) >> 2) << 1; - if (ranges[m] <= code_int) { - l = m; - } else { - r = m - 2; - } - } - - int32 t = ranges[l + 1]; - if (t < 0) { - return code - ranges[l] + (~t); - } - if (t <= 0x10ffff) { - return t; - } - switch (t - 0x200000) { - case 0: - return (code & -2); - case 1: - return (code | 1); - case 2: - return ((code - 1) | 1); - default: - LOG(FATAL) << code << " " << l << " " << r << " " << t; - return 0; - } -} - -uint32 prepare_search_character(uint32 code) { - if (code < TABLE_SIZE) { - return prepare_search_character_table[code]; - } else { - return binary_search_ranges(prepare_search_character_ranges, code); - } -} - -uint32 unicode_to_lower(uint32 code) { - if (code < TABLE_SIZE) { - return to_lower_table[code]; - } else { - return binary_search_ranges(to_lower_ranges, code); - } -} - -uint32 remove_diacritics(uint32 code) { - if (code < TABLE_SIZE) { - return without_diacritics_table[code]; - } else { - return binary_search_ranges(without_diacritics_ranges, code); - } -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/unicode.h b/submodules/ton/tonlib-src/tdutils/td/utils/unicode.h deleted file mode 100644 index dd96a980..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/unicode.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" - -namespace td { - -enum class UnicodeSimpleCategory { Unknown, Letter, DecimalNumber, Number, Separator }; - -UnicodeSimpleCategory get_unicode_simple_category(uint32 code); - -/** - * Prepares unicode character for search, leaving only digits and lowercased letters. - * Return code of replacing character or 0 if the character should be skipped. - */ -uint32 prepare_search_character(uint32 code); - -/** - * Converts unicode character to lower case. - */ -uint32 unicode_to_lower(uint32 code); - -/** - * Removes diacritics from a unicode character. - */ -uint32 remove_diacritics(uint32 code); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/unique_ptr.h b/submodules/ton/tonlib-src/tdutils/td/utils/unique_ptr.h deleted file mode 100644 index 1ec629a8..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/unique_ptr.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include -#include -#include - -namespace td { - -// const-correct and compiler-friendly (g++ RAM and CPU usage 10 times less than for std::unique_ptr) -// replacement for std::unique_ptr -template -class unique_ptr final { - public: - using pointer = T *; - using element_type = T; - - unique_ptr() noexcept = default; - unique_ptr(const unique_ptr &other) = delete; - unique_ptr &operator=(const unique_ptr &other) = delete; - unique_ptr(unique_ptr &&other) noexcept : ptr_(other.release()) { - } - unique_ptr &operator=(unique_ptr &&other) noexcept { - reset(other.release()); - return *this; - } - ~unique_ptr() { - reset(); - } - - unique_ptr(std::nullptr_t) noexcept { - } - explicit unique_ptr(T *ptr) noexcept : ptr_(ptr) { - } - template ::value>> - unique_ptr(unique_ptr &&other) noexcept : ptr_(static_cast(other.release())) { - } - template ::value>> - unique_ptr &operator=(unique_ptr &&other) noexcept { - reset(static_cast(other.release())); - return *this; - } - void reset(T *new_ptr = nullptr) noexcept { - delete ptr_; - ptr_ = new_ptr; - } - T *release() noexcept { - auto res = ptr_; - ptr_ = nullptr; - return res; - } - T *get() noexcept { - return ptr_; - } - const T *get() const noexcept { - return ptr_; - } - T *operator->() noexcept { - return ptr_; - } - const T *operator->() const noexcept { - return ptr_; - } - T &operator*() noexcept { - return *ptr_; - } - const T &operator*() const noexcept { - return *ptr_; - } - explicit operator bool() const noexcept { - return ptr_ != nullptr; - } - - private: - T *ptr_{nullptr}; -}; - -template -bool operator==(std::nullptr_t, const unique_ptr &p) { - return !p; -} -template -bool operator==(const unique_ptr &p, std::nullptr_t) { - return !p; -} -template -bool operator!=(std::nullptr_t, const unique_ptr &p) { - return static_cast(p); -} -template -bool operator!=(const unique_ptr &p, std::nullptr_t) { - return static_cast(p); -} - -template -unique_ptr make_unique(Args &&... args) { - return unique_ptr(new Type(std::forward(args)...)); -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/utf8.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/utf8.cpp deleted file mode 100644 index 9872143e..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/utf8.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/utf8.h" - -#include "td/utils/logging.h" // for UNREACHABLE -#include "td/utils/unicode.h" - -namespace td { - -bool check_utf8(CSlice str) { - const char *data = str.data(); - const char *data_end = data + str.size(); - do { - unsigned int a = static_cast(*data++); - if ((a & 0x80) == 0) { - if (data == data_end + 1) { - return true; - } - continue; - } - -#define ENSURE(condition) \ - if (!(condition)) { \ - return false; \ - } - - ENSURE((a & 0x40) != 0); - - unsigned int b = static_cast(*data++); - ENSURE((b & 0xc0) == 0x80); - if ((a & 0x20) == 0) { - ENSURE((a & 0x1e) > 0); - continue; - } - - unsigned int c = static_cast(*data++); - ENSURE((c & 0xc0) == 0x80); - if ((a & 0x10) == 0) { - int x = (((a & 0x0f) << 6) | (b & 0x20)); - ENSURE(x != 0 && x != 0x360); // surrogates - continue; - } - - unsigned int d = static_cast(*data++); - ENSURE((d & 0xc0) == 0x80); - if ((a & 0x08) == 0) { - int t = (((a & 0x07) << 6) | (b & 0x30)); - ENSURE(0 < t && t < 0x110); // end of unicode - continue; - } - - return false; -#undef ENSURE - } while (true); - - UNREACHABLE(); - return false; -} - -void append_utf8_character(string &str, uint32 ch) { - if (ch <= 0x7f) { - str.push_back(static_cast(ch)); - } else if (ch <= 0x7ff) { - str.push_back(static_cast(0xc0 | (ch >> 6))); // implementation-defined - str.push_back(static_cast(0x80 | (ch & 0x3f))); - } else if (ch <= 0xffff) { - str.push_back(static_cast(0xe0 | (ch >> 12))); // implementation-defined - str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3f))); - str.push_back(static_cast(0x80 | (ch & 0x3f))); - } else { - str.push_back(static_cast(0xf0 | (ch >> 18))); // implementation-defined - str.push_back(static_cast(0x80 | ((ch >> 12) & 0x3f))); - str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3f))); - str.push_back(static_cast(0x80 | (ch & 0x3f))); - } -} - -const unsigned char *next_utf8_unsafe(const unsigned char *ptr, uint32 *code, const char *source) { - uint32 a = ptr[0]; - if ((a & 0x80) == 0) { - if (code) { - *code = a; - } - return ptr + 1; - } else if ((a & 0x20) == 0) { - if (code) { - *code = ((a & 0x1f) << 6) | (ptr[1] & 0x3f); - } - return ptr + 2; - } else if ((a & 0x10) == 0) { - if (code) { - *code = ((a & 0x0f) << 12) | ((ptr[1] & 0x3f) << 6) | (ptr[2] & 0x3f); - } - return ptr + 3; - } else if ((a & 0x08) == 0) { - if (code) { - *code = ((a & 0x07) << 18) | ((ptr[1] & 0x3f) << 12) | ((ptr[2] & 0x3f) << 6) | (ptr[3] & 0x3f); - } - return ptr + 4; - } - LOG(FATAL) << a << " " << source; - if (code) { - *code = 0; - } - return ptr; -} - -string utf8_to_lower(Slice str) { - string result; - auto pos = str.ubegin(); - auto end = str.uend(); - while (pos != end) { - uint32 code; - pos = next_utf8_unsafe(pos, &code, "utf8_to_lower"); - append_utf8_character(result, unicode_to_lower(code)); - } - return result; -} - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/utf8.h b/submodules/ton/tonlib-src/tdutils/td/utils/utf8.h deleted file mode 100644 index 7dd7e379..00000000 --- a/submodules/ton/tonlib-src/tdutils/td/utils/utf8.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#pragma once - -#include "td/utils/common.h" -#include "td/utils/Slice.h" - -namespace td { - -/// checks UTF-8 string for correctness -bool check_utf8(CSlice str); - -/// checks if a code unit is a first code unit of a UTF-8 character -inline bool is_utf8_character_first_code_unit(unsigned char c) { - return (c & 0xC0) != 0x80; -} - -/// returns length of UTF-8 string in characters -inline size_t utf8_length(Slice str) { - size_t result = 0; - for (auto c : str) { - result += is_utf8_character_first_code_unit(c); - } - return result; -} - -/// appends a Unicode character using UTF-8 encoding -void append_utf8_character(string &str, uint32 ch); - -/// moves pointer one UTF-8 character back -inline const unsigned char *prev_utf8_unsafe(const unsigned char *ptr) { - while (!is_utf8_character_first_code_unit(*--ptr)) { - // pass - } - return ptr; -} - -/// moves pointer one UTF-8 character forward and saves code of the skipped character in *code -const unsigned char *next_utf8_unsafe(const unsigned char *ptr, uint32 *code, const char *source); - -/// truncates UTF-8 string to the given length in Unicode characters -template -T utf8_truncate(T str, size_t length) { - if (str.size() > length) { - for (size_t i = 0; i < str.size(); i++) { - if (is_utf8_character_first_code_unit(static_cast(str[i]))) { - if (length == 0) { - return str.substr(0, i); - } else { - length--; - } - } - } - } - return str; -} - -/// truncates UTF-8 string to the given length given in UTF-16 code units -template -T utf8_utf16_truncate(T str, size_t length) { - for (size_t i = 0; i < str.size(); i++) { - auto c = static_cast(str[i]); - if (is_utf8_character_first_code_unit(c)) { - if (length <= 0) { - return str.substr(0, i); - } else { - length--; - if (c >= 0xf0) { // >= 4 bytes in symbol => surrogaite pair - length--; - } - } - } - } - return str; -} - -template -T utf8_substr(T str, size_t offset) { - auto offset_pos = utf8_truncate(str, offset).size(); - return str.substr(offset_pos); -} - -template -T utf8_substr(T str, size_t offset, size_t length) { - return utf8_truncate(utf8_substr(str, offset), length); -} - -template -T utf8_utf16_substr(T str, size_t offset) { - auto offset_pos = utf8_utf16_truncate(str, offset).size(); - return str.substr(offset_pos); -} - -template -T utf8_utf16_substr(T str, size_t offset, size_t length) { - return utf8_utf16_truncate(utf8_utf16_substr(str, offset), length); -} - -/// Returns UTF-8 string converted to lower case. -string utf8_to_lower(Slice str); - -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/test/ConcurrentHashMap.cpp b/submodules/ton/tonlib-src/tdutils/test/ConcurrentHashMap.cpp deleted file mode 100644 index baceae6a..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/ConcurrentHashMap.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/benchmark.h" -#include "td/utils/ConcurrentHashTable.h" -#include "td/utils/port/thread.h" -#include "td/utils/SpinLock.h" -#include "td/utils/tests.h" - -#include -#include - -#if !TD_THREAD_UNSUPPORTED - -#if TD_HAVE_ABSL -#include -#else -#include -#endif - -#if TD_WITH_LIBCUCKOO -#include -#endif - -#if TD_WITH_JUNCTION -#include -#include -#include -#endif - -namespace td { - -// Non resizable HashMap. Just an example -template -class ArrayHashMap { - public: - explicit ArrayHashMap(size_t n) : array_(n) { - } - struct Node { - std::atomic key{KeyT{}}; - std::atomic value{ValueT{}}; - }; - static std::string get_name() { - return "ArrayHashMap"; - } - KeyT empty_key() const { - return KeyT{}; - } - - void insert(KeyT key, ValueT value) { - array_.with_value(key, true, [&](auto &node_value) { node_value.store(value, std::memory_order_release); }); - } - ValueT find(KeyT key, ValueT value) { - array_.with_value(key, false, [&](auto &node_value) { value = node_value.load(std::memory_order_acquire); }); - return value; - } - - private: - AtomicHashArray> array_; -}; - -template -class ConcurrentHashMapMutex { - public: - explicit ConcurrentHashMapMutex(size_t) { - } - static std::string get_name() { - return "ConcurrentHashMapMutex"; - } - void insert(KeyT key, ValueT value) { - std::unique_lock lock(mutex_); - hash_map_.emplace(key, value); - } - ValueT find(KeyT key, ValueT default_value) { - std::unique_lock lock(mutex_); - auto it = hash_map_.find(key); - if (it == hash_map_.end()) { - return default_value; - } - return it->second; - } - - private: - std::mutex mutex_; -#if TD_HAVE_ABSL - absl::flat_hash_map hash_map_; -#else - std::unordered_map hash_map_; -#endif -}; - -template -class ConcurrentHashMapSpinlock { - public: - explicit ConcurrentHashMapSpinlock(size_t) { - } - static std::string get_name() { - return "ConcurrentHashMapSpinlock"; - } - void insert(KeyT key, ValueT value) { - auto guard = spinlock_.lock(); - hash_map_.emplace(key, value); - } - ValueT find(KeyT key, ValueT default_value) { - auto guard = spinlock_.lock(); - auto it = hash_map_.find(key); - if (it == hash_map_.end()) { - return default_value; - } - return it->second; - } - - private: - SpinLock spinlock_; -#if TD_HAVE_ABSL - absl::flat_hash_map hash_map_; -#else - std::unordered_map hash_map_; -#endif -}; - -#if TD_WITH_LIBCUCKOO -template -class ConcurrentHashMapLibcuckoo { - public: - explicit ConcurrentHashMapLibcuckoo(size_t) { - } - static std::string get_name() { - return "ConcurrentHashMapLibcuckoo"; - } - void insert(KeyT key, ValueT value) { - hash_map_.insert(key, value); - } - ValueT find(KeyT key, ValueT default_value) { - hash_map_.find(key, default_value); - return default_value; - } - - private: - cuckoohash_map hash_map_; -}; -#endif - -#if TD_WITH_JUNCTION -template -class ConcurrentHashMapJunction { - public: - explicit ConcurrentHashMapJunction(size_t size) : hash_map_() { - } - static std::string get_name() { - return "ConcurrentHashMapJunction"; - } - void insert(KeyT key, ValueT value) { - hash_map_.assign(key, value); - } - ValueT find(KeyT key, ValueT default_value) { - return hash_map_.get(key); - } - - ConcurrentHashMapJunction(const ConcurrentHashMapJunction &) = delete; - ConcurrentHashMapJunction &operator=(const ConcurrentHashMapJunction &) = delete; - ConcurrentHashMapJunction(ConcurrentHashMapJunction &&other) = delete; - ConcurrentHashMapJunction &operator=(ConcurrentHashMapJunction &&) = delete; - ~ConcurrentHashMapJunction() { - junction::DefaultQSBR.flush(); - } - - private: - junction::ConcurrentMap_Leapfrog hash_map_; -}; -#endif - -} // namespace td - -template -class HashMapBenchmark : public td::Benchmark { - struct Query { - int key; - int value; - }; - std::vector queries; - td::unique_ptr hash_map; - - size_t threads_n = 16; - int mod_; - static constexpr size_t mul_ = 7273; //1000000000 + 7; - int n_; - - public: - explicit HashMapBenchmark(size_t threads_n) : threads_n(threads_n) { - } - std::string get_description() const override { - return hash_map->get_name(); - } - void start_up_n(int n) override { - n *= (int)threads_n; - n_ = n; - hash_map = td::make_unique(n * 2); - } - - void run(int n) override { - n = n_; - std::vector threads; - - for (size_t i = 0; i < threads_n; i++) { - size_t l = n * i / threads_n; - size_t r = n * (i + 1) / threads_n; - threads.emplace_back([l, r, this] { - for (size_t i = l; i < r; i++) { - auto x = int((i + 1) * mul_ % n_) + 3; - auto y = int(i + 2); - hash_map->insert(x, y); - } - }); - } - for (auto &thread : threads) { - thread.join(); - } - } - - void tear_down() override { - for (int i = 0; i < n_; i++) { - auto x = int((i + 1) * mul_ % n_) + 3; - auto y = int(i + 2); - ASSERT_EQ(y, hash_map->find(x, -1)); - } - queries.clear(); - hash_map.reset(); - } -}; - -template -static void bench_hash_map() { - td::bench(HashMapBenchmark(16)); - td::bench(HashMapBenchmark(1)); -} - -TEST(ConcurrentHashMap, Benchmark) { - bench_hash_map>(); - bench_hash_map>(); - bench_hash_map>(); - bench_hash_map>(); -#if TD_WITH_LIBCUCKOO - bench_hash_map>(); -#endif -#if TD_WITH_JUNCTION - bench_hash_map>(); -#endif -} - -#endif diff --git a/submodules/ton/tonlib-src/tdutils/test/Enumerator.cpp b/submodules/ton/tonlib-src/tdutils/test/Enumerator.cpp deleted file mode 100644 index 2bc8ea25..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/Enumerator.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/Enumerator.h" -#include "td/utils/tests.h" - -TEST(Enumerator, simple) { - td::Enumerator e; - auto b = e.add("b"); - auto a = e.add("a"); - auto d = e.add("d"); - auto c = e.add("c"); - ASSERT_STREQ(e.get(a), "a"); - ASSERT_STREQ(e.get(b), "b"); - ASSERT_STREQ(e.get(c), "c"); - ASSERT_STREQ(e.get(d), "d"); - ASSERT_EQ(a, e.add("a")); - ASSERT_EQ(b, e.add("b")); - ASSERT_EQ(c, e.add("c")); - ASSERT_EQ(d, e.add("d")); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/EpochBasedMemoryReclamation.cpp b/submodules/ton/tonlib-src/tdutils/test/EpochBasedMemoryReclamation.cpp deleted file mode 100644 index 5e8e2986..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/EpochBasedMemoryReclamation.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/common.h" -#include "td/utils/EpochBasedMemoryReclamation.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/tests.h" - -#include - -#if !TD_THREAD_UNSUPPORTED -TEST(EpochBaseMemoryReclamation, stress) { - struct Node { - std::atomic name_{nullptr}; - char pad[64]; - }; - - int threads_n = 10; - std::vector nodes(threads_n); - td::EpochBasedMemoryReclamation ebmr(threads_n + 1); - auto locker = ebmr.get_locker(threads_n); - locker.lock(); - locker.unlock(); - std::vector threads(threads_n); - int thread_id = 0; - for (auto &thread : threads) { - thread = td::thread([&, thread_id] { - auto locker = ebmr.get_locker(thread_id); - locker.lock(); - for (int i = 0; i < 1000000; i++) { - auto &node = nodes[td::Random::fast(0, threads_n - 1)]; - auto *str = node.name_.load(std::memory_order_acquire); - if (str) { - CHECK(*str == "one" || *str == "twotwo"); - } - if ((i + 1) % 100 == 0) { - locker.retire(); - } - if (td::Random::fast(0, 5) == 0) { - std::string *new_str = new std::string(td::Random::fast(0, 1) == 0 ? "one" : "twotwo"); - if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) { - locker.retire(str); - } else { - delete new_str; - } - } - } - locker.retire_sync(); - locker.unlock(); - }); - thread_id++; - } - for (auto &thread : threads) { - thread.join(); - } - LOG(ERROR) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe(); - //CHECK(static_cast(ebmr.to_delete_size_unsafe()) <= threads_n * threads_n); - for (int i = 0; i < threads_n; i++) { - ebmr.get_locker(i).retire_sync(); - } - CHECK(ebmr.to_delete_size_unsafe() == 0); -} -#endif //!TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdutils/test/HazardPointers.cpp b/submodules/ton/tonlib-src/tdutils/test/HazardPointers.cpp deleted file mode 100644 index 49e28819..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/HazardPointers.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/common.h" -#include "td/utils/HazardPointers.h" -#include "td/utils/logging.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/tests.h" - -#include - -#if !TD_THREAD_UNSUPPORTED -TEST(HazardPointers, stress) { - struct Node { - std::atomic name_{nullptr}; - char pad[64]; - }; - int threads_n = 10; - std::vector nodes(threads_n); - td::HazardPointers hazard_pointers(threads_n); - std::vector threads(threads_n); - int thread_id = 0; - for (auto &thread : threads) { - thread = td::thread([&, thread_id] { - std::remove_reference_t::Holder holder(hazard_pointers, thread_id, 0); - for (int i = 0; i < 1000000; i++) { - auto &node = nodes[td::Random::fast(0, threads_n - 1)]; - auto *str = holder.protect(node.name_); - if (str) { - CHECK(*str == td::Slice("one") || *str == td::Slice("twotwo")); - } - holder.clear(); - if (td::Random::fast(0, 5) == 0) { - std::string *new_str = new std::string(td::Random::fast(0, 1) == 0 ? "one" : "twotwo"); - if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) { - hazard_pointers.retire(thread_id, str); - } else { - delete new_str; - } - } - } - }); - thread_id++; - } - for (auto &thread : threads) { - thread.join(); - } - LOG(ERROR) << "Undeleted pointers: " << hazard_pointers.to_delete_size_unsafe(); - CHECK(static_cast(hazard_pointers.to_delete_size_unsafe()) <= threads_n * threads_n); - for (int i = 0; i < threads_n; i++) { - hazard_pointers.retire(i); - } - CHECK(hazard_pointers.to_delete_size_unsafe() == 0); -} -#endif //!TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdutils/test/MpmcQueue.cpp b/submodules/ton/tonlib-src/tdutils/test/MpmcQueue.cpp deleted file mode 100644 index 5ede9af5..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/MpmcQueue.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/MpmcQueue.h" -#include "td/utils/port/thread.h" -#include "td/utils/tests.h" - -#include -#include - -TEST(OneValue, simple) { - { - std::string x{"hello"}; - td::OneValue value; - auto status = value.set_value(x); - CHECK(status); - CHECK(x.empty()); - status = value.get_value(x); - CHECK(status); - CHECK(x == "hello"); - } - { - td::OneValue value; - std::string x; - auto status = value.get_value(x); - CHECK(!status); - CHECK(x.empty()); - std::string y{"hello"}; - status = value.set_value(y); - CHECK(!status); - CHECK(y == "hello"); - } -} - -#if !TD_THREAD_UNSUPPORTED -TEST(OneValue, stress) { - td::Stage run; - td::Stage check; - - std::string from; - bool set_status; - - std::string to; - bool get_status; - std::vector threads; - td::OneValue value; - for (size_t i = 0; i < 2; i++) { - threads.push_back(td::thread([&, id = i] { - for (td::uint64 round = 1; round < 100000; round++) { - if (id == 0) { - value.reset(); - to = ""; - from = ""; - } - run.wait(round * 2); - if (id == 0) { - from = "hello"; - set_status = value.set_value(from); - } else { - get_status = value.get_value(to); - } - check.wait(round * 2); - if (id == 0) { - if (set_status) { - CHECK(get_status); - CHECK(from.empty()); - LOG_CHECK(to == "hello") << to; - } else { - CHECK(!get_status); - CHECK(from == "hello"); - CHECK(to.empty()); - } - } - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} -#endif //!TD_THREAD_UNSUPPORTED - -TEST(MpmcQueueBlock, simple) { - // Test doesn't work now and it is ok, try_pop, logic changed - /* - td::MpmcQueueBlock block(2); - std::string x = "hello"; - using PushStatus = td::MpmcQueueBlock::PushStatus; - using PopStatus = td::MpmcQueueBlock::PopStatus; - auto push_status = block.push(x); - CHECK(push_status == PushStatus::Ok); - CHECK(x.empty()); - auto pop_status = block.pop(x); - CHECK(pop_status == PopStatus::Ok); - CHECK(x == "hello"); - pop_status = block.try_pop(x); - CHECK(pop_status == PopStatus::Empty); - x = "hello"; - push_status = block.push(x); - CHECK(push_status == PushStatus::Ok); - x = "hello"; - push_status = block.push(x); - CHECK(push_status == PushStatus::Closed); - CHECK(x == "hello"); - x = ""; - pop_status = block.try_pop(x); - CHECK(pop_status == PopStatus::Ok); - pop_status = block.try_pop(x); - CHECK(pop_status == PopStatus::Closed); - */ -} - -TEST(MpmcQueue, simple) { - td::MpmcQueue q(2, 1); - for (int t = 0; t < 2; t++) { - for (int i = 0; i < 100; i++) { - q.push(i, 0); - } - for (int i = 0; i < 100; i++) { - int x = q.pop(0); - LOG_CHECK(x == i) << x << " expected " << i; - } - } -} - -#if !TD_THREAD_UNSUPPORTED -TEST(MpmcQueue, multi_thread) { - size_t n = 10; - size_t m = 10; - struct Data { - size_t from{0}; - size_t value{0}; - }; - struct ThreadData { - std::vector v; - char pad[64]; - }; - td::MpmcQueue q(1024, n + m + 1); - std::vector n_threads(n); - std::vector m_threads(m); - std::vector thread_data(m); - size_t thread_id = 0; - for (auto &thread : m_threads) { - thread = td::thread([&, thread_id] { - while (true) { - auto data = q.pop(thread_id); - if (data.value == 0) { - return; - } - thread_data[thread_id].v.push_back(data); - } - }); - thread_id++; - } - size_t qn = 100000; - for (auto &thread : n_threads) { - thread = td::thread([&, thread_id] { - for (size_t i = 0; i < qn; i++) { - Data data; - data.from = thread_id - m; - data.value = i + 1; - q.push(data, thread_id); - } - }); - thread_id++; - } - for (auto &thread : n_threads) { - thread.join(); - } - for (size_t i = 0; i < m; i++) { - Data data; - data.from = 0; - data.value = 0; - q.push(data, thread_id); - } - for (auto &thread : m_threads) { - thread.join(); - } - std::vector all; - for (size_t i = 0; i < m; i++) { - std::vector from(n, 0); - for (auto &data : thread_data[i].v) { - all.push_back(data); - CHECK(data.value > from[data.from]); - from[data.from] = data.value; - } - } - LOG_CHECK(all.size() == n * qn) << all.size(); - std::sort(all.begin(), all.end(), - [](const auto &a, const auto &b) { return std::tie(a.from, a.value) < std::tie(b.from, b.value); }); - for (size_t i = 0; i < n * qn; i++) { - CHECK(all[i].from == i / qn); - CHECK(all[i].value == i % qn + 1); - } - LOG(INFO) << "Undeleted pointers: " << q.hazard_pointers_to_delele_size_unsafe(); - CHECK(q.hazard_pointers_to_delele_size_unsafe() <= (n + m + 1) * (n + m + 1)); - for (size_t id = 0; id < n + m + 1; id++) { - q.gc(id); - } - LOG_CHECK(q.hazard_pointers_to_delele_size_unsafe() == 0) << q.hazard_pointers_to_delele_size_unsafe(); -} -#endif //!TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdutils/test/MpmcWaiter.cpp b/submodules/ton/tonlib-src/tdutils/test/MpmcWaiter.cpp deleted file mode 100644 index 9cb5b363..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/MpmcWaiter.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/MpmcWaiter.h" -#include "td/utils/port/sleep.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/tests.h" - -#include - -#if !TD_THREAD_UNSUPPORTED -template -void test_waiter_stress_one_one() { - td::Stage run; - td::Stage check; - - std::vector threads; - std::atomic value{0}; - size_t write_cnt = 10; - td::unique_ptr waiter; - size_t threads_n = 2; - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = static_cast(i)] { - for (td::uint64 round = 1; round < 100000; round++) { - if (id == 0) { - value = 0; - waiter = td::make_unique(); - write_cnt = td::Random::fast(1, 10); - } - run.wait(round * threads_n); - if (id == 1) { - for (size_t i = 0; i < write_cnt; i++) { - value.store(i + 1, std::memory_order_relaxed); - waiter->notify(); - } - } else { - typename W::Slot slot; - waiter->init_slot(slot, id); - for (size_t i = 1; i <= write_cnt; i++) { - while (true) { - auto x = value.load(std::memory_order_relaxed); - if (x >= i) { - break; - } - waiter->wait(slot); - } - waiter->stop_wait(slot); - } - waiter->stop_wait(slot); - } - check.wait(round * threads_n); - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} -TEST(MpmcEagerWaiter, stress_one_one) { - test_waiter_stress_one_one(); -} -TEST(MpmcSleepyWaiter, stress_one_one) { - test_waiter_stress_one_one(); -} - -template -void test_waiter_stress() { - td::Stage run; - td::Stage check; - - std::vector threads; - size_t write_n; - size_t read_n; - std::atomic write_pos{0}; - std::atomic read_pos{0}; - size_t end_pos; - size_t write_cnt; - size_t threads_n = 20; - td::unique_ptr waiter; - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = static_cast(i)] { - for (td::uint64 round = 1; round < 1000; round++) { - if (id == 0) { - write_n = td::Random::fast(1, 10); - read_n = td::Random::fast(1, 10); - write_cnt = td::Random::fast(1, 50); - end_pos = write_n * write_cnt; - write_pos = 0; - read_pos = 0; - waiter = td::make_unique(); - } - run.wait(round * threads_n); - if (id <= write_n) { - for (size_t i = 0; i < write_cnt; i++) { - if (td::Random::fast(0, 20) == 0) { - td::usleep_for(td::Random::fast(1, 300)); - } - write_pos.fetch_add(1, std::memory_order_relaxed); - waiter->notify(); - } - } else if (id > 10 && id - 10 <= read_n) { - typename W::Slot slot; - waiter->init_slot(slot, id); - while (true) { - auto x = read_pos.load(std::memory_order_relaxed); - if (x == end_pos) { - waiter->stop_wait(slot); - break; - } - if (x == write_pos.load(std::memory_order_relaxed)) { - waiter->wait(slot); - continue; - } - waiter->stop_wait(slot); - read_pos.compare_exchange_strong(x, x + 1, std::memory_order_relaxed); - } - } - check.wait(round * threads_n); - if (id == 0) { - waiter->close(); - } - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} -TEST(MpmcEagerWaiter, stress_multi) { - test_waiter_stress(); -} -TEST(MpmcSleepyWaiter, stress_multi) { - test_waiter_stress(); -} -#endif // !TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdutils/test/MpscLinkQueue.cpp b/submodules/ton/tonlib-src/tdutils/test/MpscLinkQueue.cpp deleted file mode 100644 index e8f78802..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/MpscLinkQueue.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/MpscLinkQueue.h" -#include "td/utils/port/thread.h" -#include "td/utils/tests.h" - -class NodeX : public td::MpscLinkQueueImpl::Node { - public: - explicit NodeX(int value) : value_(value) { - } - td::MpscLinkQueueImpl::Node *to_mpsc_link_queue_node() { - return static_cast(this); - } - static NodeX *from_mpsc_link_queue_node(td::MpscLinkQueueImpl::Node *node) { - return static_cast(node); - } - int value() { - return value_; - } - - private: - int value_; -}; -using QueueNode = td::MpscLinkQueueUniquePtrNode; - -QueueNode create_node(int value) { - return QueueNode(td::make_unique(value)); -} - -TEST(MpscLinkQueue, one_thread) { - td::MpscLinkQueue queue; - - { - queue.push(create_node(1)); - queue.push(create_node(2)); - queue.push(create_node(3)); - td::MpscLinkQueue::Reader reader; - queue.pop_all(reader); - queue.push(create_node(4)); - queue.pop_all(reader); - std::vector v; - while (auto node = reader.read()) { - v.push_back(node.value().value()); - } - LOG_CHECK((v == std::vector{1, 2, 3, 4})) << td::format::as_array(v); - - v.clear(); - queue.push(create_node(5)); - queue.pop_all(reader); - while (auto node = reader.read()) { - v.push_back(node.value().value()); - } - LOG_CHECK((v == std::vector{5})) << td::format::as_array(v); - } - - { - queue.push_unsafe(create_node(3)); - queue.push_unsafe(create_node(2)); - queue.push_unsafe(create_node(1)); - queue.push_unsafe(create_node(0)); - td::MpscLinkQueue::Reader reader; - queue.pop_all_unsafe(reader); - std::vector v; - while (auto node = reader.read()) { - v.push_back(node.value().value()); - } - LOG_CHECK((v == std::vector{3, 2, 1, 0})) << td::format::as_array(v); - } -} - -#if !TD_THREAD_UNSUPPORTED -TEST(MpscLinkQueue, multi_thread) { - td::MpscLinkQueue queue; - int threads_n = 10; - int queries_n = 1000000; - std::vector next_value(threads_n); - std::vector threads(threads_n); - int thread_i = 0; - for (auto &thread : threads) { - thread = td::thread([&, id = thread_i] { - for (int i = 0; i < queries_n; i++) { - queue.push(create_node(i * threads_n + id)); - } - }); - thread_i++; - } - - int active_threads = threads_n; - - td::MpscLinkQueue::Reader reader; - while (active_threads) { - queue.pop_all(reader); - while (auto value = reader.read()) { - auto x = value.value().value(); - auto thread_id = x % threads_n; - x /= threads_n; - CHECK(next_value[thread_id] == x); - next_value[thread_id]++; - if (x + 1 == queries_n) { - active_threads--; - } - } - } - - for (auto &thread : threads) { - thread.join(); - } -} -#endif //!TD_THREAD_UNSUPPORTED diff --git a/submodules/ton/tonlib-src/tdutils/test/OrderedEventsProcessor.cpp b/submodules/ton/tonlib-src/tdutils/test/OrderedEventsProcessor.cpp deleted file mode 100644 index 434fcabe..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/OrderedEventsProcessor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/OrderedEventsProcessor.h" -#include "td/utils/Random.h" -#include "td/utils/tests.h" - -#include -#include -#include - -TEST(OrderedEventsProcessor, random) { - int d = 5001; - int n = 1000000; - int offset = 1000000; - std::vector> v; - for (int i = 0; i < n; i++) { - auto shift = td::Random::fast(0, 1) ? td::Random::fast(0, d) : td::Random::fast(0, 1) * d; - v.push_back({i + shift, i + offset}); - } - std::sort(v.begin(), v.end()); - - td::OrderedEventsProcessor processor(offset); - int next_pos = offset; - for (auto p : v) { - int seq_no = p.second; - processor.add(seq_no, seq_no, [&](auto seq_no, int x) { - ASSERT_EQ(x, next_pos); - next_pos++; - }); - } - ASSERT_EQ(next_pos, n + offset); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/SharedObjectPool.cpp b/submodules/ton/tonlib-src/tdutils/test/SharedObjectPool.cpp deleted file mode 100644 index 868438fb..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/SharedObjectPool.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/common.h" -#include "td/utils/SharedObjectPool.h" -#include "td/utils/tests.h" - -#include - -TEST(AtomicRefCnt, simple) { - td::detail::AtomicRefCnt cnt{0}; - cnt.inc(); - cnt.inc(); - CHECK(!cnt.dec()); - cnt.inc(); - CHECK(!cnt.dec()); - CHECK(cnt.dec()); - cnt.inc(); - CHECK(cnt.dec()); -} - -template -using Ptr = td::detail::SharedPtr; -class Deleter { - public: - template - void operator()(T *t) { - std::default_delete()(t); - was_delete() = true; - } - static bool &was_delete() { - static bool flag = false; - return flag; - } -}; - -TEST(SharedPtr, simple) { - CHECK(!Deleter::was_delete()); - Ptr ptr = Ptr::create("hello"); - auto ptr2 = ptr; - CHECK(*ptr == "hello"); - CHECK(*ptr2 == "hello"); - ptr.reset(); - CHECK(*ptr2 == "hello"); - CHECK(ptr.empty()); - Ptr ptr3 = std::move(ptr2); - CHECK(ptr2.empty()); - CHECK(*ptr3 == "hello"); - ptr = ptr3; - CHECK(*ptr3 == "hello"); - ptr3.reset(); - CHECK(*ptr == "hello"); - ptr2 = std::move(ptr); - CHECK(ptr.empty()); - CHECK(*ptr2 == "hello"); -#if TD_CLANG -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wunknown-warning-option" -#pragma clang diagnostic ignored "-Wself-assign-overloaded" -#endif - ptr2 = ptr2; -#if TD_CLANG -#pragma clang diagnostic pop -#endif - CHECK(*ptr2 == "hello"); - CHECK(!Deleter::was_delete()); - ptr2.reset(); - CHECK(Deleter::was_delete()); - CHECK(ptr2.empty()); -} - -TEST(SharedObjectPool, simple) { - class Node { - public: - Node() { - cnt()++; - }; - ~Node() { - cnt()--; - } - static int &cnt() { - static int cnt_ = 0; - return cnt_; - } - }; - { - td::SharedObjectPool pool; - { auto ptr1 = pool.alloc(); } - { auto ptr2 = pool.alloc(); } - { auto ptr3 = pool.alloc(); } - { auto ptr4 = pool.alloc(); } - { auto ptr5 = pool.alloc(); } - CHECK(Node::cnt() == 0); - CHECK(pool.total_size() == 1); - CHECK(pool.calc_free_size() == 1); - { auto ptr6 = pool.alloc(), ptr7 = pool.alloc(), ptr8 = pool.alloc(); } - CHECK(pool.total_size() == 3); - CHECK(pool.calc_free_size() == 3); - } - CHECK(Node::cnt() == 0); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/SharedSlice.cpp b/submodules/ton/tonlib-src/tdutils/test/SharedSlice.cpp deleted file mode 100644 index b9b6ea3f..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/SharedSlice.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" -#include "td/utils/SharedSlice.h" - -using namespace td; - -TEST(SharedSlice, Hands) { - { - SharedSlice h("hello"); - ASSERT_EQ("hello", h.as_slice()); - // auto g = h; // CE - auto g = h.clone(); - ASSERT_EQ("hello", g.as_slice()); - } - - { - SharedSlice h("hello"); - UniqueSharedSlice g(std::move(h)); - ASSERT_EQ("", h.as_slice()); - ASSERT_EQ("hello", g.as_slice()); - } - { - SharedSlice h("hello"); - SharedSlice t = h.clone(); - UniqueSharedSlice g(std::move(h)); - ASSERT_EQ("", h.as_slice()); - ASSERT_EQ("hello", g.as_slice()); - ASSERT_EQ("hello", t.as_slice()); - } - - { - UniqueSharedSlice g(5); - g.as_mutable_slice().copy_from("hello"); - SharedSlice h(std::move(g)); - ASSERT_EQ("hello", h); - ASSERT_EQ("", g); - } - - { - UniqueSlice h("hello"); - UniqueSlice g(std::move(h)); - ASSERT_EQ("", h.as_slice()); - ASSERT_EQ("hello", g.as_slice()); - } - - { - SecureString h("hello"); - SecureString g(std::move(h)); - ASSERT_EQ("", h.as_slice()); - ASSERT_EQ("hello", g.as_slice()); - } - - { - Stage stage; - SharedSlice a, b; - std::vector threads(2); - for (int i = 0; i < 2; i++) { - threads[i] = td::thread([i, &stage, &a, &b] { - for (int j = 0; j < 10000; j++) { - if (i == 0) { - a = SharedSlice("hello"); - b = a.clone(); - } - stage.wait((2 * j + 1) * 2); - if (i == 0) { - ASSERT_EQ('h', a[0]); - a.clear(); - } else { - UniqueSharedSlice c(std::move(b)); - c.as_mutable_slice()[0] = '!'; - } - stage.wait((2 * j + 2) * 2); - } - }); - } - for (auto &thread : threads) { - thread.join(); - } - } -} diff --git a/submodules/ton/tonlib-src/tdutils/test/StealingQueue.cpp b/submodules/ton/tonlib-src/tdutils/test/StealingQueue.cpp deleted file mode 100644 index c5ff8b51..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/StealingQueue.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - TON Blockchain is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2019-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" -#include "td/utils/benchmark.h" - -#include "td/utils/AtomicRead.h" -#include "td/utils/StealingQueue.h" -#include "td/utils/MpmcQueue.h" - -namespace td { -TEST(StealingQueue, very_simple) { - StealingQueue q; - q.local_push(1, [](auto x) { UNREACHABLE(); }); - int x; - CHECK(q.local_pop(x)); - ASSERT_EQ(1, x); -} -TEST(AtomicRead, simple) { - td::Stage run; - td::Stage check; - - size_t threads_n = 10; - std::vector threads; - - int x{0}; - std::atomic version{0}; - - int64 res = 0; - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = static_cast(i)] { - for (uint64 round = 1; round < 10000; round++) { - if (id == 0) { - } - run.wait(round * threads_n); - if (id == 0) { - version++; - x++; - version++; - } else { - int y = 0; - auto v1 = version.load(); - y = x; - auto v2 = version.load(); - if (v1 == v2 && v1 % 2 == 0) { - res += y; - } - } - - check.wait(round * threads_n); - } - })); - } - td::do_not_optimize_away(res); - for (auto &thread : threads) { - thread.join(); - } -} -TEST(AtomicRead, simple2) { - td::Stage run; - td::Stage check; - - size_t threads_n = 10; - std::vector threads; - - struct Value { - td::uint64 value = 0; - char str[50] = "0 0 0 0"; - }; - AtomicRead value; - - auto to_str = [](size_t i) { return PSTRING() << i << " " << i << " " << i << " " << i; }; - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = static_cast(i)] { - for (uint64 round = 1; round < 10000; round++) { - if (id == 0) { - } - run.wait(round * threads_n); - if (id == 0) { - auto x = value.lock(); - x->value = round; - auto str = to_str(round); - memcpy(x->str, str.c_str(), str.size() + 1); - } else { - Value x; - value.read(x); - LOG_CHECK(x.value == round || x.value == round - 1) << x.value << " " << round; - CHECK(x.str == to_str(x.value)); - } - check.wait(round * threads_n); - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} - -TEST(StealingQueue, simple) { - uint64 sum; - std::atomic got_sum; - - td::Stage run; - td::Stage check; - - size_t threads_n = 10; - std::vector threads; - std::vector> lq(threads_n); - MpmcQueue gq(threads_n); - - constexpr uint64 XN = 20; - uint64 x_sum[XN]; - x_sum[0] = 0; - x_sum[1] = 1; - for (uint64 i = 2; i < XN; i++) { - x_sum[i] = i + x_sum[i - 1] + x_sum[i - 2]; - } - - td::Random::Xorshift128plus rnd(123); - for (size_t i = 0; i < threads_n; i++) { - threads.push_back(td::thread([&, id = static_cast(i)] { - for (uint64 round = 1; round < 10000; round++) { - if (id == 0) { - sum = 0; - int n = rnd() % 5; - for (int j = 0; j < n; j++) { - int x = rand() % XN; - sum += x_sum[x]; - gq.push(x, id); - } - got_sum = 0; - } - run.wait(round * threads_n); - while (got_sum.load() != sum) { - auto x = [&] { - int res; - if (lq[id].local_pop(res)) { - return res; - } - if (gq.try_pop(res, id)) { - return res; - } - if (lq[id].steal(res, lq[rand() % threads_n])) { - //LOG(ERROR) << "STEAL"; - return res; - } - return 0; - }(); - if (x == 0) { - continue; - } - //LOG(ERROR) << x << " " << got_sum.load() << " " << sum; - got_sum.fetch_add(x, std::memory_order_relaxed); - lq[id].local_push(x - 1, [&](auto y) { - //LOG(ERROR) << "OVERFLOW"; - gq.push(y, id); - }); - if (x > 1) { - lq[id].local_push(x - 2, [&](auto y) { gq.push(y, id); }); - } - } - check.wait(round * threads_n); - } - })); - } - for (auto &thread : threads) { - thread.join(); - } -} -} // namespace td diff --git a/submodules/ton/tonlib-src/tdutils/test/buffer.cpp b/submodules/ton/tonlib-src/tdutils/test/buffer.cpp deleted file mode 100644 index 0d691da3..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/buffer.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/utils/buffer.h" -#include "td/utils/Random.h" - -using namespace td; - -TEST(Buffer, buffer_builder) { - { - BufferBuilder builder; - builder.append("b"); - builder.prepend("a"); - builder.append("c"); - ASSERT_EQ(builder.extract().as_slice(), "abc"); - } - { - BufferBuilder builder{"hello", 0, 0}; - ASSERT_EQ(builder.extract().as_slice(), "hello"); - } - { - BufferBuilder builder{"hello", 1, 1}; - builder.prepend("A "); - builder.append(" B"); - ASSERT_EQ(builder.extract().as_slice(), "A hello B"); - } - { - std::string str = rand_string('a', 'z', 10000); - auto splitted_str = rand_split(str); - - int l = Random::fast(0, static_cast(splitted_str.size() - 1)); - int r = l; - BufferBuilder builder(splitted_str[l], 123, 1000); - while (l != 0 || r != static_cast(splitted_str.size()) - 1) { - if (l == 0 || (Random::fast(0, 1) == 1 && r != static_cast(splitted_str.size() - 1))) { - r++; - if (Random::fast(0, 1) == 1) { - builder.append(splitted_str[r]); - } else { - builder.append(BufferSlice(splitted_str[r])); - } - } else { - l--; - if (Random::fast(0, 1) == 1) { - builder.prepend(splitted_str[l]); - } else { - builder.prepend(BufferSlice(splitted_str[l])); - } - } - } - ASSERT_EQ(builder.extract().as_slice(), str); - } -} diff --git a/submodules/ton/tonlib-src/tdutils/test/crypto.cpp b/submodules/ton/tonlib-src/tdutils/test/crypto.cpp deleted file mode 100644 index e958878b..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/crypto.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/base64.h" -#include "td/utils/benchmark.h" -#include "td/utils/common.h" -#include "td/utils/crypto.h" -#include "td/utils/logging.h" -#include "td/utils/Slice.h" -#include "td/utils/tests.h" -#include "td/utils/UInt.h" - -#include - -static td::vector strings{"", "1", "short test string", td::string(1000000, 'a')}; - -#if TD_HAVE_OPENSSL -TEST(Crypto, AesCtrState) { - td::vector answers1{0u, 1141589763u, 596296607u, 3673001485u, 2302125528u, - 330967191u, 2047392231u, 3537459563u, 307747798u, 2149598133u}; - td::vector answers2{0u, 2053451992u, 1384063362u, 3266188502u, 2893295118u, - 780356167u, 1904947434u, 2043402406u, 472080809u, 1807109488u}; - - std::size_t i = 0; - for (auto length : {0, 1, 31, 32, 33, 9999, 10000, 10001, 999999, 1000001}) { - td::uint32 seed = length; - td::string s(length, '\0'); - for (auto &c : s) { - seed = seed * 123457567u + 987651241u; - c = static_cast((seed >> 23) & 255); - } - - td::UInt256 key; - for (auto &c : key.raw) { - seed = seed * 123457567u + 987651241u; - c = (seed >> 23) & 255; - } - td::UInt128 iv; - for (auto &c : iv.raw) { - seed = seed * 123457567u + 987651241u; - c = (seed >> 23) & 255; - } - - td::AesCtrState state; - state.init(as_slice(key), as_slice(iv)); - td::string t(length, '\0'); - state.encrypt(s, t); - ASSERT_EQ(answers1[i], td::crc32(t)); - state.init(as_slice(key), as_slice(iv)); - state.decrypt(t, t); - ASSERT_STREQ(s, t); - - for (auto &c : iv.raw) { - c = 0xFF; - } - state.init(as_slice(key), as_slice(iv)); - state.encrypt(s, t); - ASSERT_EQ(answers2[i], td::crc32(t)); - - i++; - } -} - -TEST(Crypto, Sha256State) { - for (auto length : {0, 1, 31, 32, 33, 9999, 10000, 10001, 999999, 1000001}) { - auto s = td::rand_string(std::numeric_limits::min(), std::numeric_limits::max(), length); - td::UInt256 baseline; - td::sha256(s, as_slice(baseline)); - - td::Sha256State state; - state.init(); - td::Sha256State state2 = std::move(state); - auto v = td::rand_split(s); - for (auto &x : v) { - state2.feed(x); - } - state = std::move(state2); - td::UInt256 result; - state.extract(as_slice(result)); - ASSERT_TRUE(baseline == result); - } -} - -TEST(Crypto, PBKDF) { - td::vector passwords{"", "qwerty", std::string(1000, 'a')}; - td::vector salts{"", "qwerty", std::string(1000, 'a')}; - td::vector iteration_counts{1, 2, 1000}; - td::vector answers{ - "984LZT0tcqQQjPWr6RL/3Xd2Ftu7J6cOggTzri0Pb60=", "lzmEEdaupDp3rO+SImq4J41NsGaL0denanJfdoCsRcU=", - "T8WKIcEAzhg1uPmZHXOLVpZdFLJOF2H73/xprF4LZno=", "NHxAnMhPOATsb1wV0cGDlAIs+ofzI6I4I8eGJeWN9Qw=", - "fjYi7waEPjbVYEuZ61/Nm2hbk/vRdShoJoXg4Ygnqe4=", "GhW6e95hGJSf+ID5IrSbvzWyBZ1l35A+UoL55Uh/njk=", - "BueLDpqSCEc0GWk83WgMwz3UsWwfvVKcvllETSB/Yq8=", "hgHgJZNWRh78PyPdVJsK8whgHOHQbNQiyaTuGDX2IFo=", - "T2xdyNT1GlcA4+MVNzOe7NCgSAAzNkanNsmuoSr+4xQ=", "/f6t++GUPE+e63+0TrlInL+UsmzRSAAFopa8BBBmb2w=", - "8Zn98QEAKS9wPOUlN09+pfm0SWs1IGeQxQkNMT/1k48=", "sURLQ/6UX/KVYedyQB21oAtMJ+STZ4iwpxfQtqmWkLw=", - "T9t/EJXFpPs2Lhca7IVGphTC/OdEloPMHw1UhDnXcyQ=", "TIrtN05E9KQL6Lp/wjtbsFS+KkWZ8jlGK0ErtaoitOg=", - "+1KcMBjyUNz5VMaIfE5wkGwS6I+IQ5FhK+Ou2HgtVoQ=", "h36ci1T0vGllCl/xJxq6vI7n28Bg40dilzWOKg6Jt8k=", - "9uwsHJsotTiTqqCYftN729Dg7QI2BijIjV2MvSEUAeE=", "/l+vd/XYgbioh1SfLMaGRr13udmY6TLSlG4OYmytwGU=", - "7qfZZBbMRLtgjqq7GHgWa/UfXPajW8NXpJ6/T3P1rxI=", "ufwz94p28WnoOFdbrb1oyQEzm/v0CV2b0xBVxeEPJGA=", - "T/PUUBX2vGMUsI6httlhbMHlGPMvqFBNzayU5voVlaw=", "viMvsvTg9GfQymF3AXZ8uFYTDa3qLrqJJk9w/74iZfg=", - "HQF+rOZMW4DAdgZz8kAMe28eyIi0rs3a3u/mUeGPNfs=", "7lBVA+GnSxWF/eOo+tyyTB7niMDl1MqP8yzo+xnHTyw=", - "aTWb7HQAxaTKhSiRPY3GuM1GVmq/FPuwWBU/TUpdy70=", "fbg8M/+Ht/oU+UAZ4dQcGPo+wgCCHaA+GM4tm5jnWcY=", - "DJbCGFMIR/5neAlpda8Td5zftK4NGekVrg2xjrKW/4c="}; - - std::size_t pos = 0; - for (auto &password : passwords) { - for (auto &salt : salts) { - for (auto &iteration_count : iteration_counts) { - char result[32]; - td::pbkdf2_sha256(password, salt, iteration_count, {result, 32}); - ASSERT_STREQ(answers[pos], td::base64_encode({result, 32})); - pos++; - } - } - } -} - -TEST(Crypto, sha1) { - td::vector answers{"2jmj7l5rSw0yVb/vlWAYkK/YBwk=", "NWoZK3kTsExUV00Ywo1G5jlUKKs=", - "uRysQwoax0pNJeBC3+zpQzJy1rA=", "NKqXPNTE2qT2Husr260nMWU0AW8="}; - - for (std::size_t i = 0; i < strings.size(); i++) { - unsigned char output[20]; - td::sha1(strings[i], output); - ASSERT_STREQ(answers[i], td::base64_encode(td::Slice(output, 20))); - } -} - -TEST(Crypto, sha256) { - td::vector answers{ - "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", "a4ayc/80/OGda4BO/1o/V0etpOqiLx1JwB5S3beHW0s=", - "yPMaY7Q8PKPwCsw64UnDD5mhRcituEJgzLZMvr0O8pY=", "zcduXJkU+5KBocfihNc+Z/GAmkiklyAOBG05zMcRLNA="}; - - for (std::size_t i = 0; i < strings.size(); i++) { - td::string output(32, '\0'); - td::sha256(strings[i], output); - ASSERT_STREQ(answers[i], td::base64_encode(output)); - } -} - -TEST(Crypto, md5) { - td::vector answers{ - "1B2M2Y8AsgTpgAmY7PhCfg==", "xMpCOKC5I4INzFCab3WEmw==", "vwBninYbDRkgk+uA7GMiIQ==", "dwfWrk4CfHDuoqk1wilvIQ=="}; - - for (std::size_t i = 0; i < strings.size(); i++) { - td::string output(16, '\0'); - td::md5(strings[i], output); - ASSERT_STREQ(answers[i], td::base64_encode(output)); - } -} -#endif - -#if TD_HAVE_ZLIB -TEST(Crypto, crc32) { - td::vector answers{0u, 2212294583u, 3013144151u, 3693461436u}; - - for (std::size_t i = 0; i < strings.size(); i++) { - ASSERT_EQ(answers[i], td::crc32(strings[i])); - } -} -#endif - -#if TD_HAVE_CRC32C -TEST(Crypto, crc32c) { - td::vector answers{0u, 2432014819u, 1077264849u, 1131405888u}; - - for (std::size_t i = 0; i < strings.size(); i++) { - ASSERT_EQ(answers[i], td::crc32c(strings[i])); - - auto v = td::rand_split(strings[i]); - td::uint32 a = 0; - td::uint32 b = 0; - for (auto &x : v) { - a = td::crc32c_extend(a, x); - auto x_crc = td::crc32c(x); - b = td::crc32c_extend(b, x_crc, x.size()); - } - ASSERT_EQ(answers[i], a); - ASSERT_EQ(answers[i], b); - } -} - -TEST(Crypto, crc32c_benchmark) { - class Crc32cExtendBenchmark : public td::Benchmark { - public: - explicit Crc32cExtendBenchmark(size_t chunk_size) : chunk_size_(chunk_size) { - } - std::string get_description() const override { - return PSTRING() << "Crc32c with chunk_size=" << chunk_size_; - } - void start_up_n(int n) override { - if (n > (1 << 20)) { - cnt_ = n / (1 << 20); - n = (1 << 20); - } else { - cnt_ = 1; - } - data_ = std::string(n, 'a'); - } - void run(int n) override { - td::uint32 res = 0; - for (int i = 0; i < cnt_; i++) { - td::Slice data(data_); - while (!data.empty()) { - auto head = data.substr(0, chunk_size_); - data = data.substr(head.size()); - res = td::crc32c_extend(res, head); - } - } - td::do_not_optimize_away(res); - } - - private: - size_t chunk_size_; - std::string data_; - int cnt_; - }; - bench(Crc32cExtendBenchmark(2)); - bench(Crc32cExtendBenchmark(8)); - bench(Crc32cExtendBenchmark(32)); - bench(Crc32cExtendBenchmark(128)); - bench(Crc32cExtendBenchmark(65536)); -} -#endif - -TEST(Crypto, crc64) { - td::vector answers{0ull, 3039664240384658157ull, 17549519902062861804ull, 8794730974279819706ull}; - - for (std::size_t i = 0; i < strings.size(); i++) { - ASSERT_EQ(answers[i], td::crc64(strings[i])); - } -} - -TEST(Crypto, crc16) { - td::vector answers{0, 9842, 25046, 37023}; - - for (std::size_t i = 0; i < strings.size(); i++) { - ASSERT_EQ(answers[i], td::crc16(strings[i])); - } -} - -static td::Slice rsa_private_key = R"ABCD( ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDeYT5/prmLEa2Q -tZND+UwTmif8kl2VlXaMCjj1k1lJJq8BqS8cVM2vPnOPzFoiC2LYykhm4kk7goCC -ZH6wez9yakg28fcq0Ycv0x8DL1K+VKHJuwIhVfQs//IY1/cBOrMESc+NQowPbv1t -TIFxBO2gebnpLuseht8ix7XtpGC4qAaHN2aEvT2cRsnA76TAK1RVxf1OYGUFBDzY -318WpVZfVIjcQ7K9+eU6b2Yb84VLlvJXw3e1rvw+fBzx2EjpD4zhXy11YppWDyV6 -HEb2hs3cGS/LbHfHvdcSfil2omaJP97MDEEY2HFxjR/E5CEf2suvPzX4XS3RE+S3 -2aEJaaQbAgMBAAECggEAKo3XRNwls0wNt5xXcvF4smOUdUuY5u/0AHZQUgYBVvM1 -GA9E+ZnsxjUgLgs/0DX3k16aHj39H4sohksuxxy+lmlqKkGBN8tioC85RwW+Qre1 -QgIsNS7ai+XqcQCavrx51z88nV53qNhnXIwAVR1JT6Ubg1i8G1pZxrEKyk/jRlJd -mGjf6vjitH//PPkghPJ/D42k93YRcy+duOgqYDQpLZp8DiEGfYrX10B1H7HrWLV+ -Wp5KO1YXtKgQUplj6kYy72bVajbxYTvzgjaaKsh74jBO0uT3tHTtXG0dcKGb0VR/ -cqP/1H/lC9bAnAqAGefNusGJQZIElvTsrpIQXOeZsQKBgQD2W04S+FjqYYFjnEFX -6eL4it01afs5M3/C6CcI5JQtN6p+Na4NCSILol33xwhakn87zqdADHawBYQVQ8Uw -dPurl805wfkzN3AbfdDmtx0IJ8vK4HFpktRjfpwBVhlVtm1doAYFqqsuCF2vWW1t -mM2YOSq4AnRHCeBb/P6kRIW0MwKBgQDnFawKKqiC4tuyBOkkEhexlm7x9he0md7D -3Z2hc3Bmdcq1niw4wBq3HUxGLReGCcSr5epKSQwkunlTn5ZSC6Rmbe4zxsGIwbb3 -5W3342swBaoxEIuBokBvZ/xUOXVwiqKj+S/NzVkZcnT6K9V/HnUCQR+JBbQxFQaX -iiezcjKoeQKBgCIVUcDoIQ0UPl10ocmy7xbpx177calhSZzCl5vwW9vBptHdRV5C -VDZ92ThNjgdR205/8b23u7fwm2yBusdQd/0ufFMwVfTTB6yWBI/W56pYLya7VJWB -nebB/n1k1w53tbvNRugDy7kLqUJ4Qd521ILp7dIVbNbjM+omH2jEnibnAoGBAIM5 -a1jaoJay/M86uqohHBNcuePtO8jzF+1iDAGC7HFCsrov+CzB6mnR2V6AfLtBEM4M -4d8NXDf/LKawGUy+D72a74m3dG+UkbJ0Nt5t5pB+pwb1vkL/QFgDVOb/OhGOqI01 -FFBqLA6nUIZAHhzxzsBY+u90rb6xkey8J49faiUBAoGAaMgOgEvQB5H19ZL5tMkl -A/DKtTz/NFzN4Zw/vNPVb7eNn4jg9M25d9xqvL4acOa+nuV3nLHbcUWE1/7STXw1 -gT58CvoEmD1AiP95nup+HKHENJ1DWMgF5MDfVQwGCvWP5/Qy89ybr0eG8HjbldbN -MpSmzz2wOz152oGdOd3syT4= ------END PRIVATE KEY----- -)ABCD"; - -static td::Slice rsa_public_key = R"ABCD( ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3mE+f6a5ixGtkLWTQ/lM -E5on/JJdlZV2jAo49ZNZSSavAakvHFTNrz5zj8xaIgti2MpIZuJJO4KAgmR+sHs/ -cmpINvH3KtGHL9MfAy9SvlShybsCIVX0LP/yGNf3ATqzBEnPjUKMD279bUyBcQTt -oHm56S7rHobfIse17aRguKgGhzdmhL09nEbJwO+kwCtUVcX9TmBlBQQ82N9fFqVW -X1SI3EOyvfnlOm9mG/OFS5byV8N3ta78Pnwc8dhI6Q+M4V8tdWKaVg8lehxG9obN -3Bkvy2x3x73XEn4pdqJmiT/ezAxBGNhxcY0fxOQhH9rLrz81+F0t0RPkt9mhCWmk -GwIDAQAB ------END PUBLIC KEY----- -)ABCD"; - -TEST(Crypto, rsa) { - auto value = td::rand_string('a', 'z', 200); - auto encrypted_value = td::rsa_encrypt_pkcs1_oaep(rsa_public_key, value).move_as_ok(); - auto decrypted_value = td::rsa_decrypt_pkcs1_oaep(rsa_private_key, encrypted_value.as_slice()).move_as_ok(); - ASSERT_TRUE(decrypted_value.as_slice().truncate(value.size()) == value); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/filesystem.cpp b/submodules/ton/tonlib-src/tdutils/test/filesystem.cpp deleted file mode 100644 index ab9b2d84..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/filesystem.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/filesystem.h" -#include "td/utils/tests.h" - -TEST(Misc, clean_filename) { - using td::clean_filename; - ASSERT_STREQ(clean_filename("-1234567"), "-1234567"); - ASSERT_STREQ(clean_filename(".git"), "git"); - ASSERT_STREQ(clean_filename("../../.git"), "git"); - ASSERT_STREQ(clean_filename(".././.."), ""); - ASSERT_STREQ(clean_filename("../"), ""); - ASSERT_STREQ(clean_filename(".."), ""); - ASSERT_STREQ(clean_filename("test/git/ as dsa . a"), "as dsa.a"); - ASSERT_STREQ(clean_filename(" . "), ""); - ASSERT_STREQ(clean_filename("!@#$%^&*()_+-=[]{;|:\"}'<>?,.`~"), "!@#$%^ ()_+-=[]{; } ,.~"); - ASSERT_STREQ(clean_filename("!@#$%^&*()_+-=[]{}\\|:\";'<>?,.`~"), "; ,.~"); - ASSERT_STREQ(clean_filename("عرفها بعد قد. هذا مع تاريخ اليميني واندونيسيا،, لعدم تاريخ لهيمنة الى"), - "عرفها بعد قد.هذا مع تاريخ اليميني"); - ASSERT_STREQ( - clean_filename( - "012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd"), - "012345678901234567890123456789012345678901234567890123456789.01234567890123456789"); - ASSERT_STREQ(clean_filename("01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. " - "0123456789`<><<>><><>0123456789asdasdasdasd"), - "01234567890123456789012345678901234567890123456789.0123456789"); - ASSERT_STREQ(clean_filename("01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. " - "0123456789`<><><>0123456789asdasdasdasd"), - "01234567890123456789012345678901234567890123456789.0123456789 012"); - ASSERT_STREQ(clean_filename("C:/document.tar.gz"), "document.tar.gz"); - ASSERT_STREQ(clean_filename("test...."), "test"); - ASSERT_STREQ(clean_filename("....test"), "test"); - ASSERT_STREQ(clean_filename("test.exe...."), "test.exe"); // extension has changed - ASSERT_STREQ(clean_filename("test.exe01234567890123456789...."), - "test.exe01234567890123456789"); // extension may be more then 20 characters - ASSERT_STREQ(clean_filename("....test....asdf"), "test.asdf"); - ASSERT_STREQ(clean_filename("കറുപ്പ്.txt"), "കറപപ.txt"); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/gzip.cpp b/submodules/ton/tonlib-src/tdutils/test/gzip.cpp deleted file mode 100644 index 3e27ae67..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/gzip.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/buffer.h" -#include "td/utils/ByteFlow.h" -#include "td/utils/Gzip.h" -#include "td/utils/GzipByteFlow.h" -#include "td/utils/logging.h" -#include "td/utils/Status.h" -#include "td/utils/tests.h" - -static void encode_decode(td::string s) { - auto r = td::gzencode(s, 2); - ASSERT_TRUE(!r.empty()); - if (r.empty()) { - return; - } - auto new_s = td::gzdecode(r.as_slice()); - ASSERT_TRUE(!new_s.empty()); - if (new_s.empty()) { - return; - } - ASSERT_EQ(s, new_s.as_slice().str()); -} - -TEST(Gzip, gzencode_gzdecode) { - auto str = td::rand_string(0, 127, 1000); - encode_decode(str); - str = td::rand_string('a', 'z', 1000000); - encode_decode(str); - str = td::string(1000000, 'a'); - encode_decode(str); -} - -TEST(Gzip, flow) { - auto str = td::rand_string('a', 'z', 1000000); - auto parts = td::rand_split(str); - - td::ChainBufferWriter input_writer; - auto input = input_writer.extract_reader(); - td::ByteFlowSource source(&input); - td::GzipByteFlow gzip_flow(td::Gzip::Encode); - gzip_flow = td::GzipByteFlow(td::Gzip::Encode); - td::ByteFlowSink sink; - - source >> gzip_flow >> sink; - - ASSERT_TRUE(!sink.is_ready()); - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - ASSERT_TRUE(!sink.is_ready()); - source.close_input(td::Status::OK()); - ASSERT_TRUE(sink.is_ready()); - ASSERT_TRUE(sink.status().is_ok()); - auto res = sink.result()->move_as_buffer_slice().as_slice().str(); - ASSERT_TRUE(!res.empty()); - ASSERT_EQ(td::gzencode(str, 2).as_slice().str(), res); -} -TEST(Gzip, flow_error) { - auto str = td::rand_string('a', 'z', 1000000); - auto zip = td::gzencode(str).as_slice().str(); - zip.resize(zip.size() - 1); - auto parts = td::rand_split(zip); - - auto input_writer = td::ChainBufferWriter(); - auto input = input_writer.extract_reader(); - td::ByteFlowSource source(&input); - td::GzipByteFlow gzip_flow(td::Gzip::Decode); - td::ByteFlowSink sink; - - source >> gzip_flow >> sink; - - ASSERT_TRUE(!sink.is_ready()); - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - ASSERT_TRUE(!sink.is_ready()); - source.close_input(td::Status::OK()); - ASSERT_TRUE(sink.is_ready()); - ASSERT_TRUE(!sink.status().is_ok()); -} - -TEST(Gzip, encode_decode_flow) { - auto str = td::rand_string('a', 'z', 1000000); - auto parts = td::rand_split(str); - td::ChainBufferWriter input_writer; - auto input = input_writer.extract_reader(); - td::ByteFlowSource source(&input); - td::GzipByteFlow gzip_encode_flow(td::Gzip::Encode); - td::GzipByteFlow gzip_decode_flow(td::Gzip::Decode); - td::GzipByteFlow gzip_encode_flow2(td::Gzip::Encode); - td::GzipByteFlow gzip_decode_flow2(td::Gzip::Decode); - td::ByteFlowSink sink; - source >> gzip_encode_flow >> gzip_decode_flow >> gzip_encode_flow2 >> gzip_decode_flow2 >> sink; - - ASSERT_TRUE(!sink.is_ready()); - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - ASSERT_TRUE(!sink.is_ready()); - source.close_input(td::Status::OK()); - ASSERT_TRUE(sink.is_ready()); - LOG_IF(ERROR, sink.status().is_error()) << sink.status(); - ASSERT_TRUE(sink.status().is_ok()); - ASSERT_EQ(str, sink.result()->move_as_buffer_slice().as_slice().str()); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/heap.cpp b/submodules/ton/tonlib-src/tdutils/test/heap.cpp deleted file mode 100644 index 8a20216b..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/heap.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/utils/common.h" -#include "td/utils/Heap.h" -#include "td/utils/Random.h" - -#include -#include -#include -#include -#include - -REGISTER_TESTS(heap) - -using namespace td; - -TEST(Heap, sort_random_perm) { - int n = 1000000; - std::vector v(n); - for (int i = 0; i < n; i++) { - v[i] = i; - } - std::srand(123); - std::random_shuffle(v.begin(), v.end()); - std::vector nodes(n); - KHeap kheap; - for (int i = 0; i < n; i++) { - kheap.insert(v[i], &nodes[i]); - } - for (int i = 0; i < n; i++) { - ASSERT_EQ(i, kheap.top_key()); - kheap.pop(); - } -}; - -class CheckedHeap { - public: - void set_max_size(int max_size) { - nodes.resize(max_size); - free_ids.resize(max_size); - rev_ids.resize(max_size); - for (int i = 0; i < max_size; i++) { - free_ids[i] = max_size - i - 1; - nodes[i].value = i; - } - } - static void xx(int key, const HeapNode *heap_node) { - const Node *node = static_cast(heap_node); - std::fprintf(stderr, "(%d;%d)", node->key, node->value); - } - void check() const { - for (auto p : set_heap) { - std::fprintf(stderr, "(%d;%d)", p.first, p.second); - } - std::fprintf(stderr, "\n"); - kheap.for_each(xx); - std::fprintf(stderr, "\n"); - kheap.check(); - } - int random_id() const { - CHECK(!empty()); - return ids[Random::fast(0, static_cast(ids.size() - 1))]; - } - size_t size() const { - return ids.size(); - } - bool empty() const { - return ids.empty(); - } - - int top_key() const { - CHECK(!empty()); - int res = set_heap.begin()->first; - ASSERT_EQ(set_heap.size(), kheap.size()); - ASSERT_EQ(res, kheap.top_key()); - return res; - } - int insert(int key) { - // std::fprintf(stderr, "insert %d\n", key); - int id; - if (free_ids.empty()) { - UNREACHABLE(); - id = static_cast(nodes.size()); - nodes.emplace_back(key, id); - rev_ids.push_back(-1); - } else { - id = free_ids.back(); - free_ids.pop_back(); - nodes[id].key = key; - } - rev_ids[id] = static_cast(ids.size()); - ids.push_back(id); - kheap.insert(key, &nodes[id]); - set_heap.emplace(key, id); - return id; - } - void fix_key(int new_key, int id) { - // std::fprintf(stderr, "fix key %d %d (old_key = %d)\n", new_key, id, nodes[id].key); - set_heap.erase(std::make_pair(nodes[id].key, id)); - nodes[id].key = new_key; - kheap.fix(new_key, &nodes[id]); - set_heap.emplace(new_key, id); - } - void erase(int id) { - // std::fprintf(stderr, "erase %d\n", id); - int pos = rev_ids[id]; - CHECK(pos != -1); - ids[pos] = ids.back(); - rev_ids[ids[pos]] = pos; - ids.pop_back(); - rev_ids[id] = -1; - free_ids.push_back(id); - - kheap.erase(&nodes[id]); - set_heap.erase(std::make_pair(nodes[id].key, id)); - } - void pop() { - // std::fprintf(stderr, "pop\n"); - CHECK(!empty()); - Node *node = static_cast(kheap.pop()); - int id = node->value; - ASSERT_EQ(node->key, set_heap.begin()->first); - - int pos = rev_ids[id]; - CHECK(pos != -1); - ids[pos] = ids.back(); - rev_ids[ids[pos]] = pos; - ids.pop_back(); - rev_ids[id] = -1; - free_ids.push_back(id); - - set_heap.erase(std::make_pair(nodes[id].key, id)); - } - - private: - struct Node : public HeapNode { - Node() = default; - Node(int key, int value) : key(key), value(value) { - } - int key = 0; - int value = 0; - }; - vector ids; - vector rev_ids; - vector free_ids; - vector nodes; - std::set> set_heap; - KHeap kheap; -}; - -TEST(Heap, random_events) { - CheckedHeap heap; - heap.set_max_size(1000); - for (int i = 0; i < 300000; i++) { - if (!heap.empty()) { - heap.top_key(); - } - - int x = Random::fast(0, 4); - if (heap.empty() || (x < 2 && heap.size() < 1000)) { - heap.insert(Random::fast(0, 99)); - } else if (x < 3) { - heap.fix_key(Random::fast(0, 99), heap.random_id()); - } else if (x < 4) { - heap.erase(heap.random_id()); - } else if (x < 5) { - heap.pop(); - } - // heap.check(); - } -} diff --git a/submodules/ton/tonlib-src/tdutils/test/json.cpp b/submodules/ton/tonlib-src/tdutils/test/json.cpp deleted file mode 100644 index c7f34688..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/json.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" - -#include "td/utils/JsonBuilder.h" -#include "td/utils/logging.h" -#include "td/utils/Slice.h" -#include "td/utils/StringBuilder.h" - -#include -#include - -REGISTER_TESTS(json) - -using namespace td; - -static void decode_encode(string str, string result = "") { - auto str_copy = str; - auto r_value = json_decode(str_copy); - ASSERT_TRUE(r_value.is_ok()); - if (r_value.is_error()) { - LOG(INFO) << r_value.error(); - return; - } - auto new_str = json_encode(r_value.ok()); - if (result.empty()) { - result = str; - } - ASSERT_EQ(result, new_str); -} - -TEST(JSON, array) { - char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); - jb.enter_value().enter_array() << "Hello" << -123; - ASSERT_EQ(jb.string_builder().is_error(), false); - auto encoded = jb.string_builder().as_cslice().str(); - ASSERT_EQ("[\"Hello\",-123]", encoded); - decode_encode(encoded); -} -TEST(JSON, object) { - char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); - auto c = jb.enter_object(); - c << std::tie("key", "value"); - c << std::make_pair("1", 2); - c.leave(); - ASSERT_EQ(jb.string_builder().is_error(), false); - auto encoded = jb.string_builder().as_cslice().str(); - ASSERT_EQ("{\"key\":\"value\",\"1\":2}", encoded); - decode_encode(encoded); -} - -TEST(JSON, nested) { - char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); - { - auto a = jb.enter_array(); - a << 1; - { a.enter_value().enter_array() << 2; } - a << 3; - } - ASSERT_EQ(jb.string_builder().is_error(), false); - auto encoded = jb.string_builder().as_cslice().str(); - ASSERT_EQ("[1,[2],3]", encoded); - decode_encode(encoded); -} - -TEST(JSON, kphp) { - decode_encode("[]"); - decode_encode("[[]]"); - decode_encode("{}"); - decode_encode("{}"); - decode_encode("\"\\n\""); - decode_encode( - "\"" - "some long string \\t \\r \\\\ \\n \\f \\\" " - "\\u1234" - "\""); - decode_encode( - "{\"keyboard\":[[\"\\u2022 abcdefg\"],[\"\\u2022 hijklmnop\"],[\"\\u2022 " - "qrstuvwxyz\"]],\"one_time_keyboard\":true}"); - decode_encode( - " \n { \"keyboard\" : \n [[ \"\\u2022 abcdefg\" ] , \n [ \"\\u2022 hijklmnop\" \n ],[ \n \"\\u2022 " - "qrstuvwxyz\"]], \n \"one_time_keyboard\"\n:\ntrue\n}\n \n", - "{\"keyboard\":[[\"\\u2022 abcdefg\"],[\"\\u2022 hijklmnop\"],[\"\\u2022 " - "qrstuvwxyz\"]],\"one_time_keyboard\":true}"); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/log.cpp b/submodules/ton/tonlib-src/tdutils/test/log.cpp deleted file mode 100644 index 04d99dee..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/log.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/tests.h" -#include "td/utils/FileLog.h" -#include "td/utils/TsFileLog.h" -#include "td/utils/logging.h" -#include "td/utils/port/path.h" -#include "td/utils/benchmark.h" - -#include - -// Thread safe logging with tests -// -// LOG uses thread local LogInterface -// void append(CSlice slice, int log_level); -// - -template -class LogBenchmark : public td::Benchmark { - public: - explicit LogBenchmark(std::string name, int threads_n, std::function()> creator) - : name_(std::move(name)), threads_n_(threads_n), creator_(std::move(creator)) { - } - std::string get_description() const override { - return PSTRING() << name_ << " " << td::tag("threads_n", threads_n_); - } - void start_up() override { - log_ = creator_(); - threads_.resize(threads_n_); - } - void tear_down() override { - for (auto path : log_->get_file_paths()) { - td::unlink(path).ignore(); - } - log_.reset(); - } - void run(int n) override { - for (auto &thread : threads_) { - thread = td::thread([this, n] { this->run_thread(n); }); - } - for (auto &thread : threads_) { - thread.join(); - } - } - - void run_thread(int n) { - auto str = PSTRING() << "#" << n << " : fsjklfdjsklfjdsklfjdksl\n"; - for (int i = 0; i < n; i++) { - if (i % 10000 == 0) { - log_->rotate(); - } - log_->append(str); - } - } - - private: - std::string name_; - td::unique_ptr log_; - int threads_n_{0}; - std::function()> creator_; - std::vector threads_; -}; - -template -void bench_log(std::string name, int threads_n, F &&f) { - bench(LogBenchmark(std::move(name), threads_n, std::move(f))); -}; - -TEST(Log, TsLogger) { - bench_log("NewTsFileLog", 4, - [] { return td::TsFileLog::create("tmplog", std::numeric_limits::max(), false).move_as_ok(); }); - bench_log("TsFileLog", 8, [] { - class FileLog : public td::LogInterface { - public: - FileLog() { - file_log_.init("tmplog", std::numeric_limits::max(), false); - ts_log_.init(&file_log_); - } - ~FileLog() { - } - void append(td::CSlice slice) override { - ts_log_.append(slice, -1); - } - std::vector get_file_paths() override { - return file_log_.get_file_paths(); - } - - private: - td::FileLog file_log_; - td::TsLog ts_log_{nullptr}; - }; - return td::make_unique(); - }); - - bench_log("noop", 4, [] { - class NoopLog : public td::LogInterface { - public: - void append(td::CSlice slice) override { - } - }; - return td::make_unique(); - }); - - bench_log("FileLog", 4, [] { - class FileLog : public td::LogInterface { - public: - FileLog() { - file_log_.init("tmplog", std::numeric_limits::max(), false); - } - ~FileLog() { - } - void append(td::CSlice slice) override { - file_log_.append(slice, -1); - } - std::vector get_file_paths() override { - return file_log_.get_file_paths(); - } - - private: - td::FileLog file_log_; - }; - return td::make_unique(); - }); -} diff --git a/submodules/ton/tonlib-src/tdutils/test/misc.cpp b/submodules/ton/tonlib-src/tdutils/test/misc.cpp deleted file mode 100644 index 768aebd3..00000000 --- a/submodules/ton/tonlib-src/tdutils/test/misc.cpp +++ /dev/null @@ -1,972 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "td/utils/as.h" -#include "td/utils/base64.h" -#include "td/utils/BigNum.h" -#include "td/utils/bits.h" -#include "td/utils/CancellationToken.h" -#include "td/utils/common.h" -#include "td/utils/Hash.h" -#include "td/utils/HashMap.h" -#include "td/utils/HashSet.h" -#include "td/utils/HttpUrl.h" -#include "td/utils/invoke.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/EventFd.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/IPAddress.h" -#include "td/utils/port/path.h" -#include "td/utils/port/sleep.h" -#include "td/utils/port/Stat.h" -#include "td/utils/port/thread.h" -#include "td/utils/port/wstring_convert.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" -#include "td/utils/tests.h" -#include "td/utils/Time.h" -#include "td/utils/translit.h" -#include "td/utils/uint128.h" -#include "td/utils/unicode.h" -#include "td/utils/utf8.h" - -#include -#include -#include -#include -#include -#include - -#if TD_HAVE_ABSL -#include -#endif - -using namespace td; - -#if TD_LINUX || TD_DARWIN -TEST(Misc, update_atime_saves_mtime) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - std::string name = "test_file"; - unlink(name).ignore(); - auto r_file = FileFd::open(name, FileFd::Read | FileFd::Flags::Create | FileFd::Flags::Truncate); - LOG_IF(ERROR, r_file.is_error()) << r_file.error(); - ASSERT_TRUE(r_file.is_ok()); - r_file.move_as_ok().close(); - - auto info = stat(name).ok(); - int32 tests_ok = 0; - int32 tests_wa = 0; - for (int i = 0; i < 10000; i++) { - update_atime(name).ensure(); - auto new_info = stat(name).ok(); - if (info.mtime_nsec_ == new_info.mtime_nsec_) { - tests_ok++; - } else { - tests_wa++; - info.mtime_nsec_ = new_info.mtime_nsec_; - } - ASSERT_EQ(info.mtime_nsec_, new_info.mtime_nsec_); - usleep_for(Random::fast(0, 1000)); - } - if (tests_wa > 0) { - LOG(ERROR) << "Access time was unexpectedly updated " << tests_wa << " times"; - } - unlink(name).ensure(); -} - -TEST(Misc, update_atime_change_atime) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - std::string name = "test_file"; - unlink(name).ignore(); - auto r_file = FileFd::open(name, FileFd::Read | FileFd::Flags::Create | FileFd::Flags::Truncate); - LOG_IF(ERROR, r_file.is_error()) << r_file.error(); - ASSERT_TRUE(r_file.is_ok()); - r_file.move_as_ok().close(); - auto info = stat(name).ok(); - // not enough for fat and e.t.c. - usleep_for(5000000); - update_atime(name).ensure(); - auto new_info = stat(name).ok(); - if (info.atime_nsec_ == new_info.atime_nsec_) { - LOG(ERROR) << "Access time was unexpectedly not changed"; - } - unlink(name).ensure(); -} -#endif - -TEST(Misc, errno_tls_bug) { - // That's a problem that should be avoided - // errno = 0; - // impl_.alloc(123); - // CHECK(errno == 0); - -#if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED - EventFd test_event_fd; - test_event_fd.init(); - std::atomic s{0}; - s = 1; - td::thread th([&] { - while (s != 1) { - } - test_event_fd.acquire(); - }); - th.join(); - - for (int i = 0; i < 1000; i++) { - vector events(10); - vector threads; - for (auto &event : events) { - event.init(); - event.release(); - } - for (auto &event : events) { - threads.push_back(td::thread([&] { - { - EventFd tmp; - tmp.init(); - tmp.acquire(); - } - event.acquire(); - })); - } - for (auto &thread : threads) { - thread.join(); - } - } -#endif -} - -TEST(Misc, get_last_argument) { - auto a = make_unique(5); - ASSERT_EQ(*get_last_argument(std::move(a)), 5); - ASSERT_EQ(*get_last_argument(1, 2, 3, 4, a), 5); - ASSERT_EQ(*get_last_argument(a), 5); - auto b = get_last_argument(1, 2, 3, std::move(a)); - ASSERT_TRUE(!a); - ASSERT_EQ(*b, 5); -} - -TEST(Misc, call_n_arguments) { - auto f = [](int, int) {}; - call_n_arguments<2>(f, 1, 3, 4); -} - -TEST(Misc, base64) { - ASSERT_TRUE(is_base64("dGVzdA==") == true); - ASSERT_TRUE(is_base64("dGVzdB==") == false); - ASSERT_TRUE(is_base64("dGVzdA=") == false); - ASSERT_TRUE(is_base64("dGVzdA") == false); - ASSERT_TRUE(is_base64("dGVz") == true); - ASSERT_TRUE(is_base64("") == true); - ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == true); - ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") == false); - ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/") == false); - ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") == false); - ASSERT_TRUE(is_base64("====") == false); - - ASSERT_TRUE(is_base64url("dGVzdA==") == true); - ASSERT_TRUE(is_base64url("dGVzdB==") == false); - ASSERT_TRUE(is_base64url("dGVzdA=") == false); - ASSERT_TRUE(is_base64url("dGVzdA") == true); - ASSERT_TRUE(is_base64url("dGVz") == true); - ASSERT_TRUE(is_base64url("") == true); - ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") == true); - ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=") == false); - ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/") == false); - ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == false); - ASSERT_TRUE(is_base64url("====") == false); - - for (int l = 0; l < 300000; l += l / 20 + l / 1000 * 500 + 1) { - for (int t = 0; t < 10; t++) { - string s = rand_string(std::numeric_limits::min(), std::numeric_limits::max(), l); - string encoded = base64url_encode(s); - auto decoded = base64url_decode(encoded); - ASSERT_TRUE(decoded.is_ok()); - ASSERT_TRUE(decoded.ok() == s); - - encoded = base64_encode(s); - decoded = base64_decode(encoded); - ASSERT_TRUE(decoded.is_ok()); - ASSERT_TRUE(decoded.ok() == s); - } - } - - ASSERT_TRUE(base64url_decode("dGVzdA").is_ok()); - ASSERT_TRUE(base64url_decode("dGVzdB").is_error()); - ASSERT_TRUE(base64_encode(base64url_decode("dGVzdA").ok()) == "dGVzdA=="); - ASSERT_TRUE(base64_encode("any carnal pleas") == "YW55IGNhcm5hbCBwbGVhcw=="); - ASSERT_TRUE(base64_encode("any carnal pleasu") == "YW55IGNhcm5hbCBwbGVhc3U="); - ASSERT_TRUE(base64_encode("any carnal pleasur") == "YW55IGNhcm5hbCBwbGVhc3Vy"); - ASSERT_TRUE(base64_encode(" /'.;.';≤.];,].',[.;/,.;/]/..;!@#!*(%?::;!%\";") == - "ICAgICAgLycuOy4nO+KJpC5dOyxdLicsWy47LywuOy9dLy4uOyFAIyEqKCU/" - "Ojo7ISUiOw=="); -} - -TEST(Misc, base32) { - ASSERT_EQ("", base32_encode("")); - ASSERT_EQ("me", base32_encode("a")); - base32_decode("me").ensure(); - ASSERT_EQ("mfra", base32_encode("ab")); - ASSERT_EQ("mfrgg", base32_encode("abc")); - ASSERT_EQ("mfrggza", base32_encode("abcd")); - ASSERT_EQ("mfrggzdg", base32_encode("abcdf")); - ASSERT_EQ("mfrggzdgm4", base32_encode("abcdfg")); - for (int l = 0; l < 300000; l += l / 20 + l / 1000 * 500 + 1) { - for (int t = 0; t < 10; t++) { - string s = rand_string(std::numeric_limits::min(), std::numeric_limits::max(), l); - auto encoded = base32_encode(s); - auto decoded = base32_decode(encoded); - ASSERT_TRUE(decoded.is_ok()); - ASSERT_TRUE(decoded.ok() == s); - } - } -} - -TEST(Misc, to_integer) { - ASSERT_EQ(to_integer("-1234567"), -1234567); - ASSERT_EQ(to_integer("-1234567"), -1234567); - ASSERT_EQ(to_integer("-1234567"), 0u); - ASSERT_EQ(to_integer("-1234567"), 10617); - ASSERT_EQ(to_integer("-1234567"), 0u); - ASSERT_EQ(to_integer("-1254567"), -9383); - ASSERT_EQ(to_integer("1254567"), 9383u); - ASSERT_EQ(to_integer("-12345678910111213"), -12345678910111213); - ASSERT_EQ(to_integer("12345678910111213"), 12345678910111213ull); - - ASSERT_EQ(to_integer_safe("-1234567").ok(), -1234567); - ASSERT_EQ(to_integer_safe("-1234567").ok(), -1234567); - ASSERT_TRUE(to_integer_safe("-1234567").is_error()); - ASSERT_TRUE(to_integer_safe("-1234567").is_error()); - ASSERT_TRUE(to_integer_safe("-1234567").is_error()); - ASSERT_TRUE(to_integer_safe("-1254567").is_error()); - ASSERT_TRUE(to_integer_safe("1254567").is_error()); - ASSERT_EQ(to_integer_safe("-12345678910111213").ok(), -12345678910111213); - ASSERT_EQ(to_integer_safe("12345678910111213").ok(), 12345678910111213ull); - ASSERT_TRUE(to_integer_safe("-12345678910111213").is_error()); -} - -static void test_to_double_one(CSlice str, Slice expected, int precision = 6) { - auto result = PSTRING() << td::StringBuilder::FixedDouble(to_double(str), precision); - if (expected != result) { - LOG(ERROR) << "To double conversion failed: have " << str << ", expected " << expected << ", parsed " - << to_double(str) << ", got " << result; - } -} - -static void test_to_double() { - test_to_double_one("0", "0.000000"); - test_to_double_one("1", "1.000000"); - test_to_double_one("-10", "-10.000000"); - test_to_double_one("1.234", "1.234000"); - test_to_double_one("-1.234e2", "-123.400000"); - test_to_double_one("inf", "inf"); - test_to_double_one(" inF asdasd", "inf"); - test_to_double_one(" inFasdasd", "0.000000"); - test_to_double_one(" NaN", "nan"); - test_to_double_one(" 12345678910111213141516171819 asdasd", "12345678910111213670658736128.000000"); - test_to_double_one("1.234567891011121314E123", - "1234567891011121363209105003376291141757777526749278953577304234065881343284952489418916814035346" - "625663604561924259911303168.000000"); - test_to_double_one("1.234567891011121314E-9", "0.000000"); - test_to_double_one("123456789", "123456789.000000"); - test_to_double_one("-1,234567891011121314E123", "-1.000000"); - test_to_double_one("123456789", "123456789", 0); - test_to_double_one("1.23456789", "1", 0); - test_to_double_one("1.23456789", "1.2", 1); - test_to_double_one("1.23456789", "1.23", 2); - test_to_double_one("1.23456789", "1.235", 3); - test_to_double_one("1.23456789", "1.2346", 4); - test_to_double_one("1.23456789", "1.23457", 5); - test_to_double_one("1.23456789", "1.234568", 6); - test_to_double_one("1.23456789", "1.2345679", 7); - test_to_double_one("1.23456789", "1.23456789", 8); - test_to_double_one("1.23456789", "1.234567890", 9); - test_to_double_one("1.23456789", "1.2345678900", 10); -} - -TEST(Misc, to_double) { - test_to_double(); - const char *locale_name = (std::setlocale(LC_ALL, "fr-FR") == nullptr ? "" : "fr-FR"); - std::locale new_locale(locale_name); - auto host_locale = std::locale::global(new_locale); - test_to_double(); - new_locale = std::locale::global(std::locale::classic()); - test_to_double(); - auto classic_locale = std::locale::global(host_locale); - test_to_double(); -} - -TEST(Misc, print_int) { - ASSERT_STREQ("-9223372036854775808", PSLICE() << -9223372036854775807 - 1); - ASSERT_STREQ("-2147483649", PSLICE() << -2147483649ll); - ASSERT_STREQ("-2147483648", PSLICE() << -2147483647 - 1); - ASSERT_STREQ("-2147483647", PSLICE() << -2147483647); - ASSERT_STREQ("-123456789", PSLICE() << -123456789); - ASSERT_STREQ("-1", PSLICE() << -1); - ASSERT_STREQ("0", PSLICE() << 0); - ASSERT_STREQ("1", PSLICE() << 1); - ASSERT_STREQ("9", PSLICE() << 9); - ASSERT_STREQ("10", PSLICE() << 10); - ASSERT_STREQ("2147483647", PSLICE() << 2147483647); - ASSERT_STREQ("2147483648", PSLICE() << 2147483648ll); - ASSERT_STREQ("2147483649", PSLICE() << 2147483649ll); - ASSERT_STREQ("9223372036854775807", PSLICE() << 9223372036854775807ll); -} - -TEST(Misc, print_uint) { - ASSERT_STREQ("0", PSLICE() << 0u); - ASSERT_STREQ("1", PSLICE() << 1u); - ASSERT_STREQ("9", PSLICE() << 9u); - ASSERT_STREQ("10", PSLICE() << 10u); - ASSERT_STREQ("2147483647", PSLICE() << 2147483647u); - ASSERT_STREQ("2147483648", PSLICE() << 2147483648u); - ASSERT_STREQ("2147483649", PSLICE() << 2147483649u); - ASSERT_STREQ("9223372036854775807", PSLICE() << 9223372036854775807u); -} - -static void test_get_url_query_file_name_one(const char *prefix, const char *suffix, const char *file_name) { - auto path = string(prefix) + string(file_name) + string(suffix); - ASSERT_STREQ(file_name, get_url_query_file_name(path)); - ASSERT_STREQ(file_name, get_url_file_name("http://telegram.org" + path)); - ASSERT_STREQ(file_name, get_url_file_name("http://telegram.org:80" + path)); - ASSERT_STREQ(file_name, get_url_file_name("telegram.org" + path)); -} - -TEST(Misc, get_url_query_file_name) { - for (auto suffix : {"?t=1#test", "#test?t=1", "#?t=1", "?t=1#", "#test", "?t=1", "#", "?", ""}) { - test_get_url_query_file_name_one("", suffix, ""); - test_get_url_query_file_name_one("/", suffix, ""); - test_get_url_query_file_name_one("/a/adasd/", suffix, ""); - test_get_url_query_file_name_one("/a/lklrjetn/", suffix, "adasd.asdas"); - test_get_url_query_file_name_one("/", suffix, "a123asadas"); - test_get_url_query_file_name_one("/", suffix, "\\a\\1\\2\\3\\a\\s\\a\\das"); - } -} - -static void test_idn_to_ascii_one(string host, string result) { - if (result != idn_to_ascii(host).ok()) { - LOG(ERROR) << "Failed to convert " << host << " to " << result << ", got \"" << idn_to_ascii(host).ok() << "\""; - } -} - -TEST(Misc, idn_to_ascii) { - test_idn_to_ascii_one("::::::::::::::::::::::::::::::::::::::@/", "::::::::::::::::::::::::::::::::::::::@/"); - test_idn_to_ascii_one("", ""); - test_idn_to_ascii_one("%30", "%30"); - test_idn_to_ascii_one("127.0.0.1", "127.0.0.1"); - test_idn_to_ascii_one("fe80::", "fe80::"); - test_idn_to_ascii_one("fe80:0:0:0:200:f8ff:fe21:67cf", "fe80:0:0:0:200:f8ff:fe21:67cf"); - test_idn_to_ascii_one("2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d", "2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d"); - test_idn_to_ascii_one("::ffff:192.0.2.1", "::ffff:192.0.2.1"); - test_idn_to_ascii_one("ABCDEF", "abcdef"); - test_idn_to_ascii_one("abcdef", "abcdef"); - test_idn_to_ascii_one("abæcdöef", "xn--abcdef-qua4k"); - test_idn_to_ascii_one("schön", "xn--schn-7qa"); - test_idn_to_ascii_one("ยจฆฟคฏข", "xn--22cdfh1b8fsa"); - test_idn_to_ascii_one("☺", "xn--74h"); - test_idn_to_ascii_one("правда", "xn--80aafi6cg"); - test_idn_to_ascii_one("büücher", "xn--bcher-kvaa"); - test_idn_to_ascii_one("BüüCHER", "xn--bcher-kvaa"); - test_idn_to_ascii_one("bücüher", "xn--bcher-kvab"); - test_idn_to_ascii_one("bücherü", "xn--bcher-kvae"); - test_idn_to_ascii_one("ýbücher", "xn--bcher-kvaf"); - test_idn_to_ascii_one("übücher", "xn--bcher-jvab"); - test_idn_to_ascii_one("bücher.tld", "xn--bcher-kva.tld"); - test_idn_to_ascii_one("кто.рф", "xn--j1ail.xn--p1ai"); - test_idn_to_ascii_one("wіkіреdіа.org", "xn--wkd-8cdx9d7hbd.org"); - test_idn_to_ascii_one("cnwin2k8中国.avol.com", "xn--cnwin2k8-sd0mx14e.avol.com"); - test_idn_to_ascii_one("win-2k12r2-addc.阿伯测阿伯测ad.hai.com", "win-2k12r2-addc.xn--ad-tl3ca3569aba8944eca.hai.com"); - test_idn_to_ascii_one("✌.ws", "xn--7bi.ws"); - // test_idn_to_ascii_one("✌️.ws", "xn--7bi.ws"); // needs nameprep to succeed - test_idn_to_ascii_one("⛧", "xn--59h"); - test_idn_to_ascii_one("--рф.рф", "xn-----mmcq.xn--p1ai"); - ASSERT_TRUE(idn_to_ascii("\xc0").is_error()); -} - -#if TD_WINDOWS -static void test_to_wstring_one(string str) { - ASSERT_STREQ(str, from_wstring(to_wstring(str).ok()).ok()); -} - -TEST(Misc, to_wstring) { - test_to_wstring_one(""); - for (int i = 0; i < 10; i++) { - test_to_wstring_one("test"); - test_to_wstring_one("тест"); - } - string str; - for (uint32 i = 0; i <= 0xD7FF; i++) { - append_utf8_character(str, i); - } - for (uint32 i = 0xE000; i <= 0x10FFFF; i++) { - append_utf8_character(str, i); - } - test_to_wstring_one(str); - ASSERT_TRUE(to_wstring("\xc0").is_error()); - auto emoji = to_wstring("🏟").ok(); - ASSERT_TRUE(from_wstring(emoji).ok() == "🏟"); - ASSERT_TRUE(emoji.size() == 2); - auto emoji2 = emoji; - emoji[0] = emoji[1]; - emoji2[1] = emoji2[0]; - ASSERT_TRUE(from_wstring(emoji).is_error()); - ASSERT_TRUE(from_wstring(emoji2).is_error()); - emoji2[0] = emoji[0]; - ASSERT_TRUE(from_wstring(emoji2).is_error()); -} -#endif - -static void test_translit(string word, vector result, bool allow_partial = true) { - ASSERT_EQ(result, get_word_transliterations(word, allow_partial)); -} - -TEST(Misc, translit) { - test_translit("word", {"word", "ворд"}); - test_translit("", {}); - test_translit("ььььььььь", {"ььььььььь"}); - test_translit("крыло", {"krylo", "крыло"}); - test_translit("krylo", {"krylo", "крило"}); - test_translit("crylo", {"crylo", "крило"}); - test_translit("cheiia", {"cheiia", "кхеииа", "чейия"}); - test_translit("cheii", {"cheii", "кхеии", "чейи", "чейий", "чейия"}); - test_translit("s", {"s", "с", "ш", "щ"}); - test_translit("y", {"e", "y", "е", "и", "ю", "я"}); - test_translit("j", {"e", "j", "е", "й", "ю", "я"}); - test_translit("yo", {"e", "yo", "е", "ио"}); - test_translit("artjom", {"artem", "artjom", "артем", "артйом"}); - test_translit("artyom", {"artem", "artyom", "артем", "артиом"}); - test_translit("arty", {"arte", "arty", "арте", "арти", "артю", "артя"}); - test_translit("льи", {"li", "lia", "ly", "льи"}); - test_translit("y", {"y", "и"}, false); - test_translit("yo", {"e", "yo", "е", "ио"}, false); -} - -static void test_unicode(uint32 (*func)(uint32)) { - for (uint32 i = 0; i <= 0x110000; i++) { - auto res = func(i); - CHECK(res <= 0x10ffff); - } -} - -TEST(Misc, unicode) { - test_unicode(prepare_search_character); - test_unicode(unicode_to_lower); - test_unicode(remove_diacritics); -} - -TEST(BigNum, from_decimal) { - ASSERT_TRUE(BigNum::from_decimal("").is_error()); - ASSERT_TRUE(BigNum::from_decimal("a").is_error()); - ASSERT_TRUE(BigNum::from_decimal("123a").is_error()); - ASSERT_TRUE(BigNum::from_decimal("-123a").is_error()); - // ASSERT_TRUE(BigNum::from_decimal("-").is_error()); - ASSERT_TRUE(BigNum::from_decimal("123").is_ok()); - ASSERT_TRUE(BigNum::from_decimal("-123").is_ok()); - ASSERT_TRUE(BigNum::from_decimal("0").is_ok()); - ASSERT_TRUE(BigNum::from_decimal("-0").is_ok()); - ASSERT_TRUE(BigNum::from_decimal("-999999999999999999999999999999999999999999999999").is_ok()); - ASSERT_TRUE(BigNum::from_decimal("999999999999999999999999999999999999999999999999").is_ok()); -} - -static void test_get_ipv4(uint32 ip) { - td::IPAddress ip_address; - ip_address.init_ipv4_port(td::IPAddress::ipv4_to_str(ip), 80).ensure(); - ASSERT_EQ(ip_address.get_ipv4(), ip); -} - -TEST(Misc, IPAddress_get_ipv4) { - test_get_ipv4(0x00000000); - test_get_ipv4(0x010000FF); - test_get_ipv4(0xFF000001); - test_get_ipv4(0x01020304); - test_get_ipv4(0x04030201); - test_get_ipv4(0xFFFFFFFF); -} - -static void test_is_reserved(string ip, bool is_reserved) { - IPAddress ip_address; - ip_address.init_ipv4_port(ip, 80).ensure(); - ASSERT_EQ(is_reserved, ip_address.is_reserved()); -} - -TEST(Misc, IPAddress_is_reserved) { - test_is_reserved("0.0.0.0", true); - test_is_reserved("0.255.255.255", true); - test_is_reserved("1.0.0.0", false); - test_is_reserved("5.0.0.0", false); - test_is_reserved("9.255.255.255", false); - test_is_reserved("10.0.0.0", true); - test_is_reserved("10.255.255.255", true); - test_is_reserved("11.0.0.0", false); - test_is_reserved("100.63.255.255", false); - test_is_reserved("100.64.0.0", true); - test_is_reserved("100.127.255.255", true); - test_is_reserved("100.128.0.0", false); - test_is_reserved("126.255.255.255", false); - test_is_reserved("127.0.0.0", true); - test_is_reserved("127.255.255.255", true); - test_is_reserved("128.0.0.0", false); - test_is_reserved("169.253.255.255", false); - test_is_reserved("169.254.0.0", true); - test_is_reserved("169.254.255.255", true); - test_is_reserved("169.255.0.0", false); - test_is_reserved("172.15.255.255", false); - test_is_reserved("172.16.0.0", true); - test_is_reserved("172.31.255.255", true); - test_is_reserved("172.32.0.0", false); - test_is_reserved("191.255.255.255", false); - test_is_reserved("192.0.0.0", true); - test_is_reserved("192.0.0.255", true); - test_is_reserved("192.0.1.0", false); - test_is_reserved("192.0.1.255", false); - test_is_reserved("192.0.2.0", true); - test_is_reserved("192.0.2.255", true); - test_is_reserved("192.0.3.0", false); - test_is_reserved("192.88.98.255", false); - test_is_reserved("192.88.99.0", true); - test_is_reserved("192.88.99.255", true); - test_is_reserved("192.88.100.0", false); - test_is_reserved("192.167.255.255", false); - test_is_reserved("192.168.0.0", true); - test_is_reserved("192.168.255.255", true); - test_is_reserved("192.169.0.0", false); - test_is_reserved("198.17.255.255", false); - test_is_reserved("198.18.0.0", true); - test_is_reserved("198.19.255.255", true); - test_is_reserved("198.20.0.0", false); - test_is_reserved("198.51.99.255", false); - test_is_reserved("198.51.100.0", true); - test_is_reserved("198.51.100.255", true); - test_is_reserved("198.51.101.0", false); - test_is_reserved("203.0.112.255", false); - test_is_reserved("203.0.113.0", true); - test_is_reserved("203.0.113.255", true); - test_is_reserved("203.0.114.0", false); - test_is_reserved("223.255.255.255", false); - test_is_reserved("224.0.0.0", true); - test_is_reserved("239.255.255.255", true); - test_is_reserved("240.0.0.0", true); - test_is_reserved("255.255.255.254", true); - test_is_reserved("255.255.255.255", true); -} - -static void test_split(Slice str, std::pair expected) { - ASSERT_EQ(expected, td::split(str)); -} - -TEST(Misc, split) { - test_split("", {"", ""}); - test_split(" ", {"", ""}); - test_split("abcdef", {"abcdef", ""}); - test_split("abc def", {"abc", "def"}); - test_split("a bcdef", {"a", "bcdef"}); - test_split(" abcdef", {"", "abcdef"}); - test_split("abcdef ", {"abcdef", ""}); - test_split("ab cd ef", {"ab", "cd ef"}); - test_split("ab cdef ", {"ab", "cdef "}); - test_split(" abcd ef", {"", "abcd ef"}); - test_split(" abcdef ", {"", "abcdef "}); -} - -static void test_full_split(Slice str, vector expected) { - ASSERT_EQ(expected, td::full_split(str)); -} - -static void test_full_split(Slice str, char c, size_t max_parts, vector expected) { - ASSERT_EQ(expected, td::full_split(str, c, max_parts)); -} - -TEST(Misc, full_split) { - test_full_split("", {}); - test_full_split(" ", {"", ""}); - test_full_split(" ", {"", "", ""}); - test_full_split("abcdef", {"abcdef"}); - test_full_split("abc def", {"abc", "def"}); - test_full_split("a bcdef", {"a", "bcdef"}); - test_full_split(" abcdef", {"", "abcdef"}); - test_full_split("abcdef ", {"abcdef", ""}); - test_full_split("ab cd ef", {"ab", "cd", "ef"}); - test_full_split("ab cdef ", {"ab", "cdef", ""}); - test_full_split(" abcd ef", {"", "abcd", "ef"}); - test_full_split(" abcdef ", {"", "abcdef", ""}); - test_full_split(" ab cd ef ", {"", "ab", "cd", "ef", ""}); - test_full_split(" ab cd ef ", {"", "", "ab", "", "cd", "", "ef", "", ""}); - test_full_split("ab cd ef gh", ' ', 3, {"ab", "cd", "ef gh"}); -} - -TEST(Misc, StringBuilder) { - auto small_str = std::string{"abcdefghij"}; - auto big_str = std::string(1000, 'a'); - using V = std::vector; - for (auto use_buf : {false, true}) { - for (size_t initial_buffer_size : {0, 1, 5, 10, 100, 1000, 2000}) { - for (auto test : {V{small_str}, V{small_str, big_str, big_str, small_str}, V{big_str, small_str, big_str}}) { - std::string buf(initial_buffer_size, '\0'); - td::StringBuilder sb(buf, use_buf); - std::string res; - for (auto x : test) { - res += x; - sb << x; - } - if (use_buf) { - ASSERT_EQ(res, sb.as_cslice()); - } else { - auto got = sb.as_cslice(); - res.resize(got.size()); - ASSERT_EQ(res, got); - } - } - } - } -} - -TEST(Misc, As) { - char buf[100]; - as(buf) = 123; - ASSERT_EQ(123, as((const char *)buf)); - ASSERT_EQ(123, as((char *)buf)); - char buf2[100]; - as(buf2) = as(buf); - ASSERT_EQ(123, as((const char *)buf2)); - ASSERT_EQ(123, as((char *)buf2)); -} - -TEST(Misc, Regression) { - string name = "regression_db"; - RegressionTester::destroy(name); - - { - auto tester = RegressionTester::create(name); - tester->save_db(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("two_plus_one", "three").ensure(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("two_plus_one", "three").ensure(); - tester->save_db(); - } - { - auto tester = RegressionTester::create(name); - tester->save_db(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("two_plus_one", "three").ensure(); - tester->verify_test("one_plus_one", "two").ensure(); - tester->verify_test("two_plus_one", "three").ensure(); - tester->save_db(); - tester->verify_test("one_plus_one", "three").ensure_error(); - tester->verify_test("two_plus_one", "two").ensure_error(); - } - { - auto tester = RegressionTester::create(name); - tester->verify_test("one_plus_one", "three").ensure_error(); - tester->verify_test("two_plus_one", "two").ensure_error(); - } -} - -TEST(Misc, Bits) { - ASSERT_EQ(32, count_leading_zeroes32(0)); - ASSERT_EQ(64, count_leading_zeroes64(0)); - ASSERT_EQ(32, count_trailing_zeroes32(0)); - ASSERT_EQ(64, count_trailing_zeroes64(0)); - - for (int i = 0; i < 32; i++) { - ASSERT_EQ(31 - i, count_leading_zeroes32(1u << i)); - ASSERT_EQ(i, count_trailing_zeroes32(1u << i)); - ASSERT_EQ(31 - i, count_leading_zeroes_non_zero32(1u << i)); - ASSERT_EQ(i, count_trailing_zeroes_non_zero32(1u << i)); - } - for (int i = 0; i < 64; i++) { - ASSERT_EQ(63 - i, count_leading_zeroes64(1ull << i)); - ASSERT_EQ(i, count_trailing_zeroes64(1ull << i)); - ASSERT_EQ(63 - i, count_leading_zeroes_non_zero64(1ull << i)); - ASSERT_EQ(i, count_trailing_zeroes_non_zero64(1ull << i)); - } - - ASSERT_EQ(0x12345678u, td::bswap32(0x78563412u)); - ASSERT_EQ(0x12345678abcdef67ull, td::bswap64(0x67efcdab78563412ull)); - - ASSERT_EQ(0, count_bits32(0)); - ASSERT_EQ(0, count_bits64(0)); - ASSERT_EQ(4, count_bits32((1u << 31) | 7)); - ASSERT_EQ(4, count_bits64((1ull << 63) | 7)); -} - -#if !TD_THREAD_UNSUPPORTED -TEST(Misc, Time) { - Stage run; - Stage check; - Stage finish; - - size_t threads_n = 3; - std::vector threads; - std::vector> ts(threads_n); - for (size_t i = 0; i < threads_n; i++) { - threads.emplace_back([&, thread_id = i] { - for (uint64 round = 1; round < 100000; round++) { - ts[thread_id] = 0; - run.wait(round * threads_n); - ts[thread_id] = Time::now(); - check.wait(round * threads_n); - for (auto &ts_ref : ts) { - auto other_ts = ts_ref.load(); - if (other_ts != 0) { - ASSERT_TRUE(other_ts <= Time::now_cached()); - } - } - - finish.wait(round * threads_n); - } - }); - } - for (auto &thread : threads) { - thread.join(); - } -} -#endif - -TEST(Misc, uint128) { - std::vector parts = {0, - 1, - 2000, - 2001, - std::numeric_limits::max(), - std::numeric_limits::max() - 1, - std::numeric_limits::max(), - static_cast(std::numeric_limits::max()) + 1}; - std::vector signed_parts = {0, - 1, - 2000, - 2001, - -1, - -2000, - -2001, - std::numeric_limits::max(), - std::numeric_limits::max() - 1, - std::numeric_limits::min(), - std::numeric_limits::min() + 1, - std::numeric_limits::max(), - static_cast(std::numeric_limits::max()) + 1, - std::numeric_limits::max() - 1, - std::numeric_limits::min(), - std::numeric_limits::min() + 1, - static_cast(std::numeric_limits::min()) - 1}; - -#if TD_HAVE_INT128 - auto to_intrinsic = [](uint128_emulated num) { return uint128_intrinsic(num.hi(), num.lo()); }; - auto eq = [](uint128_emulated a, uint128_intrinsic b) { return a.hi() == b.hi() && a.lo() == b.lo(); }; - auto ensure_eq = [&](uint128_emulated a, uint128_intrinsic b) { - if (!eq(a, b)) { - LOG(FATAL) << "[" << a.hi() << ";" << a.lo() << "] vs [" << b.hi() << ";" << b.lo() << "]"; - } - }; -#endif - - std::vector nums; - for (auto hi : parts) { - for (auto lo : parts) { - auto a = uint128_emulated(hi, lo); -#if TD_HAVE_INT128 - auto ia = uint128_intrinsic(hi, lo); - ensure_eq(a, ia); -#endif - nums.push_back(a); - nums.pop_back(); - nums.push_back({hi, lo}); - } - } - -#if TD_HAVE_INT128 - for (auto a : nums) { - auto ia = to_intrinsic(a); - ensure_eq(a, ia); - CHECK(a.is_zero() == ia.is_zero()); - for (int i = 0; i <= 130; i++) { - ensure_eq(a.shl(i), ia.shl(i)); - ensure_eq(a.shr(i), ia.shr(i)); - } - for (auto b : parts) { - ensure_eq(a.mult(b), ia.mult(b)); - } - for (auto b : signed_parts) { - ensure_eq(a.mult_signed(b), ia.mult_signed(b)); - if (b == 0) { - continue; - } - int64 q, r; - a.divmod_signed(b, &q, &r); - int64 iq, ir; - ia.divmod_signed(b, &iq, &ir); - ASSERT_EQ(q, iq); - ASSERT_EQ(r, ir); - } - for (auto b : nums) { - auto ib = to_intrinsic(b); - //LOG(ERROR) << ia.hi() << ";" << ia.lo() << " " << ib.hi() << ";" << ib.lo(); - ensure_eq(a.mult(b), ia.mult(ib)); - ensure_eq(a.add(b), ia.add(ib)); - ensure_eq(a.sub(b), ia.sub(ib)); - if (!b.is_zero()) { - ensure_eq(a.div(b), ia.div(ib)); - ensure_eq(a.mod(b), ia.mod(ib)); - } - } - } - - for (auto signed_part : signed_parts) { - auto a = uint128_emulated::from_signed(signed_part); - auto ia = uint128_intrinsic::from_signed(signed_part); - ensure_eq(a, ia); - } -#endif -} - -template